jitcraft/Parser.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jul 04 19:54:53 2012 -0400 (2012-07-04)
changeset 48 2b6904506469
parent 38 88049d677e3f
child 54 8e22792a3921
permissions -rw-r--r--
Fix a bug where we might not unwind the lifo stack in empty scopes.
dvander@48
     1
/* vim: set ts=4 sw=4 tw=99 et:
dvander@48
     2
 *
dvander@0
     3
 * Copyright (C) 2012 David Anderson
dvander@0
     4
 *
dvander@0
     5
 * This file is part of JITCraft.
dvander@0
     6
 *
dvander@0
     7
 * JITCraft is free software: you can redistribute it and/or modify it under
dvander@0
     8
 * the terms of the GNU General Public License as published by the Free
dvander@0
     9
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@0
    10
 * any later version.
dvander@0
    11
 * 
dvander@0
    12
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@0
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@0
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@0
    15
 *
dvander@0
    16
 * You should have received a copy of the GNU General Public License along with
dvander@0
    17
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@0
    18
 */
dvander@0
    19
#include "Zone.h"
dvander@0
    20
#include "Parser.h"
dvander@21
    21
#include "FixedArray.h"
dvander@21
    22
#include "Heap.h"
dvander@21
    23
#include "Heap-inl.h"
dvander@0
    24
dvander@0
    25
using namespace jc;
dvander@0
    26
dvander@25
    27
Parser::Parser(CompileContext &cc, const char *stream, size_t length)
dvander@25
    28
  : cc_(cc),
dvander@25
    29
    pool_(ZONE()->pool()),
dvander@0
    30
    strings_(pool_),
dvander@25
    31
    scanner_(cc, stream, length),
dvander@0
    32
    scope_(NULL),
dvander@0
    33
    unbound_(NULL)
dvander@0
    34
{
dvander@0
    35
    unbound_ = new std::vector<NameProxy *>();
dvander@0
    36
}
dvander@0
    37
dvander@0
    38
bool
dvander@0
    39
Parser::match(TokenKind kind)
dvander@0
    40
{
dvander@0
    41
    if (scanner_.peek() != kind)
dvander@0
    42
        return false;
dvander@0
    43
    scanner_.scan();
dvander@0
    44
    return true;
dvander@0
    45
}
dvander@0
    46
dvander@0
    47
bool
dvander@0
    48
Parser::expect(TokenKind kind)
dvander@0
    49
{
dvander@0
    50
    TokenKind got = scanner_.scan();
dvander@0
    51
    if (got == kind)
dvander@0
    52
        return true;
dvander@25
    53
    cc_.reportError(scanner_.begin(), Message_WrongToken, TokenNames[kind], TokenNames[got]);
dvander@0
    54
    return false;
dvander@0
    55
}
dvander@0
    56
dvander@0
    57
Scope *
dvander@0
    58
Parser::enterScope(Scope::Kind kind)
dvander@0
    59
{
dvander@0
    60
    scope_ = new (pool_) Scope(pool_, kind, scope_);
dvander@0
    61
    if (!scope_->initialize())
dvander@0
    62
        return NULL;
dvander@0
    63
    return scope_;
dvander@0
    64
}
dvander@0
    65
dvander@0
    66
NameProxy *
dvander@0
    67
Parser::bind(Name *name)
dvander@0
    68
{
dvander@0
    69
    BoundName *bound = scope_->lookup(name);
dvander@25
    70
    NameProxy *proxy = new (pool_) NameProxy(scanner_.begin(), name, bound);
dvander@0
    71
    if (!bound)
dvander@0
    72
        unbound_->push_back(proxy);
dvander@0
    73
    return proxy;
dvander@0
    74
}
dvander@0
    75
dvander@4
    76
bool
dvander@4
    77
Parser::matchName(Name **name, TokenKind kind)
dvander@4
    78
{
dvander@4
    79
    assert(kind == TOK_NAME || kind == TOK_LABEL);
dvander@4
    80
    *name = NULL;
dvander@4
    81
    if (!match(kind))
dvander@4
    82
        return false;
dvander@4
    83
    *name = strings_.add(scanner_.literal());
dvander@4
    84
    return true;
dvander@4
    85
}
dvander@4
    86
dvander@4
    87
Name *
dvander@4
    88
Parser::expectName()
dvander@4
    89
{
dvander@4
    90
    if (!expect(TOK_NAME))
dvander@4
    91
        return NULL;
dvander@4
    92
    return strings_.add(scanner_.literal());
dvander@4
    93
}
dvander@4
    94
dvander@25
    95
void
dvander@25
    96
Parser::redeclarationError(BoundName *other)
dvander@25
    97
{
dvander@25
    98
    cc_.reportError(scanner_.begin(), Message_RedeclaredName, other->pos().line, other->pos().col);
dvander@25
    99
}
dvander@25
   100
dvander@0
   101
Expression *
dvander@0
   102
Parser::primitive()
dvander@0
   103
{
dvander@25
   104
    TokenKind kind = scanner_.peek();
dvander@25
   105
    switch (kind) {
dvander@0
   106
      case TOK_NAME:
dvander@0
   107
      {
dvander@0
   108
        scanner_.scan();
dvander@0
   109
        Name *name = strings_.add(scanner_.literal());
dvander@0
   110
        return bind(name);
dvander@0
   111
      }
dvander@0
   112
dvander@4
   113
      case TOK_FLOAT_LITERAL:
dvander@4
   114
      {
dvander@4
   115
        scanner_.scan();
dvander@4
   116
        double value = Scanner::ParseDouble(scanner_.literal());
dvander@25
   117
        return new (pool_) FloatLiteral(scanner_.begin(), value);
dvander@4
   118
      }
dvander@4
   119
dvander@0
   120
      case TOK_INTEGER_LITERAL:
dvander@0
   121
      {
dvander@0
   122
        scanner_.scan();
dvander@0
   123
        int value = atoi(scanner_.literal());
dvander@25
   124
        return new (pool_) IntegerLiteral(scanner_.begin(), value);
dvander@0
   125
      }
dvander@0
   126
dvander@21
   127
      case TOK_STRING_LITERAL:
dvander@21
   128
      {
dvander@21
   129
        scanner_.scan();
dvander@38
   130
        Local<ByteArray> array(ZONE(), ByteArray::New(ZONE(), scanner_.literal_length()));
dvander@21
   131
        if (!array)
dvander@21
   132
            return NULL;
dvander@21
   133
        memcpy(array->raw(), scanner_.literal(), scanner_.literal_length());
dvander@25
   134
        return new (pool_) StringLiteral(scanner_.begin(), array);
dvander@21
   135
      }
dvander@21
   136
dvander@0
   137
      default:
dvander@0
   138
      {
dvander@25
   139
        if (kind != TOK_ERROR)
dvander@25
   140
            cc_.reportError(scanner_.begin(), Message_ExpectedExpression, TokenNames[kind]);
dvander@0
   141
        return NULL;
dvander@0
   142
      }
dvander@0
   143
    }
dvander@0
   144
}
dvander@0
   145
dvander@0
   146
Expression *
dvander@0
   147
Parser::prefix()
dvander@0
   148
{
dvander@0
   149
    switch (scanner_.peek()) {
dvander@0
   150
      case TOK_LPAREN:
dvander@0
   151
      {
dvander@0
   152
        scanner_.scan();
dvander@0
   153
        Expression *expr = expression();
dvander@0
   154
        if (!expr)
dvander@0
   155
            return NULL;
dvander@0
   156
        if (!expect(TOK_RPAREN))
dvander@0
   157
            return NULL;
dvander@0
   158
        return expr;
dvander@0
   159
      }
dvander@0
   160
dvander@0
   161
      default:
dvander@0
   162
        return primitive();
dvander@0
   163
    }
dvander@0
   164
}
dvander@0
   165
dvander@0
   166
Expression *
dvander@0
   167
Parser::call(Expression *callee)
dvander@0
   168
{
dvander@0
   169
    ExpressionList *arguments = new ExpressionList();
dvander@0
   170
dvander@25
   171
    SourcePosition pos = scanner_.begin();
dvander@0
   172
    expect(TOK_LPAREN);
dvander@0
   173
    
dvander@0
   174
    if (!match(TOK_RPAREN)) {
dvander@0
   175
        while (true) {
dvander@0
   176
            Expression *expr = expression();
dvander@0
   177
            if (!expr)
dvander@0
   178
                return NULL;
dvander@0
   179
dvander@0
   180
            arguments->push_back(expr);
dvander@0
   181
dvander@0
   182
            if (!match(TOK_COMMA))
dvander@0
   183
                break;
dvander@0
   184
        }
dvander@0
   185
dvander@0
   186
        if (!expect(TOK_RPAREN))
dvander@0
   187
            return NULL;
dvander@0
   188
    }
dvander@0
   189
dvander@25
   190
    return new (pool_) CallExpression(pos, callee, arguments);
dvander@0
   191
}
dvander@0
   192
dvander@0
   193
Expression *
dvander@0
   194
Parser::index(Expression *left)
dvander@0
   195
{
dvander@0
   196
    expect(TOK_LBRACKET);
dvander@0
   197
    
dvander@25
   198
    SourcePosition pos = scanner_.begin();
dvander@0
   199
    Expression *expr = expression();
dvander@0
   200
    if (!expr)
dvander@0
   201
        return NULL;
dvander@0
   202
dvander@0
   203
    if (!expect(TOK_RBRACKET))
dvander@0
   204
        return NULL;
dvander@0
   205
dvander@25
   206
    return new (pool_) IndexExpression(pos, left, expr);
dvander@0
   207
}
dvander@0
   208
dvander@0
   209
Expression *
dvander@0
   210
Parser::primary()
dvander@0
   211
{
dvander@0
   212
    Expression *expr = prefix();
dvander@0
   213
    if (!expr)
dvander@0
   214
        return NULL;
dvander@0
   215
dvander@0
   216
    for (;;) {
dvander@0
   217
        switch (scanner_.peek()) {
dvander@0
   218
          case TOK_LPAREN:
dvander@0
   219
            expr = call(expr);
dvander@0
   220
            if (!expr)
dvander@0
   221
                return NULL;
dvander@0
   222
            break;
dvander@0
   223
dvander@0
   224
          case TOK_LBRACKET:
dvander@0
   225
            expr = index(expr);
dvander@0
   226
            if (!expr)
dvander@0
   227
                return NULL;
dvander@0
   228
            break;
dvander@0
   229
dvander@0
   230
          default:
dvander@0
   231
            return expr;
dvander@0
   232
        }
dvander@0
   233
    }
dvander@0
   234
}
dvander@0
   235
dvander@0
   236
Expression *
dvander@0
   237
Parser::unary()
dvander@0
   238
{
dvander@23
   239
    TokenKind token = scanner_.peek();
dvander@23
   240
dvander@25
   241
    SourcePosition pos = scanner_.begin();
dvander@23
   242
    switch (token) {
dvander@23
   243
      case TOK_INCREMENT:
dvander@23
   244
      case TOK_DECREMENT:
dvander@23
   245
      {
dvander@23
   246
        scanner_.scan();
dvander@23
   247
        Expression *expr = expression();
dvander@23
   248
        if (!expr)
dvander@23
   249
            return NULL;
dvander@23
   250
dvander@25
   251
        return new (pool_) IncDecExpression(pos, token, expr, false);
dvander@23
   252
      }
dvander@28
   253
      default:
dvander@28
   254
        break;
dvander@23
   255
    }
dvander@23
   256
dvander@25
   257
dvander@23
   258
    Expression *expr = primary();
dvander@23
   259
dvander@23
   260
    token = scanner_.peek();
dvander@23
   261
    if (token == TOK_INCREMENT || token == TOK_DECREMENT) {
dvander@23
   262
        scanner_.scan();
dvander@25
   263
        return new (pool_) IncDecExpression(pos, token, expr, true);
dvander@23
   264
    }
dvander@23
   265
dvander@23
   266
    return expr;
dvander@0
   267
}
dvander@0
   268
dvander@0
   269
Expression *
dvander@0
   270
Parser::multiplication()
dvander@0
   271
{
dvander@0
   272
    Expression *left = unary();
dvander@0
   273
    do {
dvander@0
   274
        if (!match(TOK_SLASH) && !match(TOK_STAR))
dvander@0
   275
            break;
dvander@25
   276
        SourcePosition pos = scanner_.begin();
dvander@0
   277
        TokenKind kind = scanner_.last();
dvander@0
   278
        Expression *right = unary();
dvander@0
   279
        if (!right)
dvander@0
   280
            return NULL;
dvander@25
   281
        left = new (pool_) BinaryExpression(pos, kind, left, right);
dvander@0
   282
    } while (left);
dvander@0
   283
    return left;
dvander@0
   284
}
dvander@0
   285
dvander@0
   286
Expression *
dvander@0
   287
Parser::addition()
dvander@0
   288
{
dvander@0
   289
    Expression *left = multiplication();
dvander@0
   290
    while (left) {
dvander@0
   291
        if (!match(TOK_PLUS) && !match(TOK_MINUS))
dvander@0
   292
            break;
dvander@25
   293
        SourcePosition pos = scanner_.begin();
dvander@0
   294
        TokenKind kind = scanner_.last();
dvander@0
   295
        Expression *right = multiplication();
dvander@0
   296
        if (!right)
dvander@0
   297
            return NULL;
dvander@25
   298
        left = new (pool_) BinaryExpression(pos, kind, left, right);
dvander@0
   299
    }
dvander@0
   300
    return left;
dvander@0
   301
}
dvander@0
   302
dvander@0
   303
Expression *
dvander@2
   304
Parser::shift()
dvander@2
   305
{
dvander@2
   306
    Expression *left = addition();
dvander@2
   307
    while (left) {
dvander@8
   308
        if (!match(TOK_SHL) && !match(TOK_SHR) && !match(TOK_USHR))
dvander@2
   309
            break;
dvander@25
   310
        SourcePosition pos = scanner_.begin();
dvander@2
   311
        TokenKind kind = scanner_.last();
dvander@2
   312
        Expression *right = addition();
dvander@2
   313
        if (!right)
dvander@2
   314
            return NULL;
dvander@25
   315
        left = new (pool_) BinaryExpression(pos, kind, left, right);
dvander@2
   316
    }
dvander@2
   317
    return left;
dvander@2
   318
}
dvander@2
   319
dvander@2
   320
Expression *
dvander@28
   321
Parser::bitand_()
dvander@8
   322
{
dvander@8
   323
    Expression *left = shift();
dvander@8
   324
    while (left) {
dvander@8
   325
        if (!match(TOK_BITAND))
dvander@8
   326
            break;
dvander@25
   327
        SourcePosition pos = scanner_.begin();
dvander@8
   328
        Expression *right = shift();
dvander@8
   329
        if (!right)
dvander@8
   330
            return NULL;
dvander@25
   331
        left = new (pool_) BinaryExpression(pos, TOK_BITAND, left, right);
dvander@8
   332
    }
dvander@8
   333
    return left;
dvander@8
   334
}
dvander@8
   335
dvander@8
   336
Expression *
dvander@8
   337
Parser::bitxor()
dvander@8
   338
{
dvander@28
   339
    Expression *left = bitand_();
dvander@8
   340
    while (left) {
dvander@8
   341
        if (!match(TOK_BITXOR))
dvander@8
   342
            break;
dvander@25
   343
        SourcePosition pos = scanner_.begin();
dvander@8
   344
        Expression *right = shift();
dvander@8
   345
        if (!right)
dvander@8
   346
            return NULL;
dvander@25
   347
        left = new (pool_) BinaryExpression(pos, TOK_BITXOR, left, right);
dvander@8
   348
    }
dvander@8
   349
    return left;
dvander@8
   350
}
dvander@8
   351
dvander@8
   352
Expression *
dvander@28
   353
Parser::bitor_()
dvander@8
   354
{
dvander@8
   355
    Expression *left = bitxor();
dvander@8
   356
    while (left) {
dvander@8
   357
        if (!match(TOK_BITOR))
dvander@8
   358
            break;
dvander@25
   359
        SourcePosition pos = scanner_.begin();
dvander@8
   360
        Expression *right = shift();
dvander@8
   361
        if (!right)
dvander@8
   362
            return NULL;
dvander@25
   363
        left = new (pool_) BinaryExpression(pos, TOK_BITOR, left, right);
dvander@8
   364
    }
dvander@8
   365
    return left;
dvander@8
   366
}
dvander@8
   367
dvander@8
   368
Expression *
dvander@0
   369
Parser::relational()
dvander@0
   370
{
dvander@28
   371
    Expression *left = bitor_();
dvander@0
   372
    while (left) {
dvander@0
   373
        TokenKind kind = scanner_.peek();
dvander@0
   374
        if (kind < TOK_LT || kind > TOK_GE)
dvander@0
   375
            break;
dvander@0
   376
        scanner_.scan();
dvander@25
   377
        SourcePosition pos = scanner_.begin();
dvander@2
   378
        Expression *right = shift();
dvander@0
   379
        if (!right)
dvander@0
   380
            return NULL;
dvander@25
   381
        left = new (pool_) BinaryExpression(pos, kind, left, right);
dvander@0
   382
    }
dvander@0
   383
    return left;
dvander@0
   384
}
dvander@0
   385
dvander@0
   386
Expression *
dvander@0
   387
Parser::equals()
dvander@0
   388
{
dvander@0
   389
    Expression *left = relational();
dvander@0
   390
    while (left) {
dvander@0
   391
        if (!match(TOK_EQUALS) && !match(TOK_NOTEQUALS))
dvander@0
   392
            break;
dvander@0
   393
        TokenKind kind = scanner_.last();
dvander@25
   394
        SourcePosition pos = scanner_.begin();
dvander@0
   395
        Expression *right = relational();
dvander@0
   396
        if (!right)
dvander@0
   397
            return NULL;
dvander@25
   398
        left = new (pool_) BinaryExpression(pos, kind, left, right);
dvander@0
   399
    }
dvander@0
   400
    return left;
dvander@0
   401
}
dvander@0
   402
dvander@0
   403
Expression *
dvander@22
   404
Parser::assignment()
dvander@22
   405
{
dvander@22
   406
    Expression *left = equals();
dvander@22
   407
    while (left) {
dvander@22
   408
        TokenKind token = scanner_.peek();
dvander@22
   409
        if (token != TOK_ASSIGN && (token < TOK_ASSIGN_ADD || token > TOK_ASSIGN_SHL))
dvander@22
   410
            break;
dvander@22
   411
        scanner_.scan();
dvander@25
   412
        SourcePosition pos = scanner_.begin();
dvander@22
   413
        Expression *expr = equals();
dvander@22
   414
        if (!expr)
dvander@22
   415
            return NULL;
dvander@22
   416
dvander@25
   417
        left = new (pool_) Assignment(pos, token, left, expr);
dvander@22
   418
    }
dvander@22
   419
    return left;
dvander@22
   420
}
dvander@22
   421
dvander@22
   422
Expression *
dvander@0
   423
Parser::expression()
dvander@0
   424
{
dvander@22
   425
    return assignment();
dvander@0
   426
}
dvander@0
   427
dvander@0
   428
Statement *
dvander@9
   429
Parser::while_()
dvander@9
   430
{
dvander@25
   431
    SourcePosition pos = scanner_.begin();
dvander@9
   432
    scanner_.scan();
dvander@9
   433
dvander@9
   434
    if (!expect(TOK_LPAREN))
dvander@9
   435
        return NULL;
dvander@25
   436
dvander@9
   437
    Expression *condition = expression();
dvander@9
   438
    if (!condition)
dvander@9
   439
        return NULL;
dvander@25
   440
dvander@9
   441
    if (!expect(TOK_RPAREN))
dvander@9
   442
        return NULL;
dvander@9
   443
dvander@48
   444
    // Inside a loop, we force the creation of a scope object. Normally, we
dvander@48
   445
    // will cull scopes if they have no variables. However inside a loop,
dvander@48
   446
    // function calls that take references may compute a LIFO object, and to
dvander@48
   447
    // avoid temporarily leaking many such objects, we ensure that a scope
dvander@48
   448
    // is present so a LIFO slot can be allocated.
dvander@48
   449
    if (!enterScope(Scope::BLOCK))
dvander@48
   450
        return NULL;
dvander@48
   451
dvander@48
   452
    Statement *body;
dvander@48
   453
    if (scanner_.peek() == TOK_LBRACE)
dvander@48
   454
        body = block(scope_);
dvander@48
   455
    else
dvander@48
   456
        body = localStatement();
dvander@9
   457
    if (!body)
dvander@9
   458
        return NULL;
dvander@9
   459
dvander@48
   460
    scope_ = scope_->enclosing();
dvander@25
   461
    return new (pool_) WhileStatement(pos, TOK_WHILE, condition, body);
dvander@9
   462
}
dvander@9
   463
dvander@9
   464
Statement *
dvander@9
   465
Parser::do_()
dvander@9
   466
{
dvander@25
   467
    SourcePosition pos = scanner_.begin();
dvander@9
   468
    scanner_.scan();
dvander@9
   469
dvander@48
   470
    // See the comment in ::while_() as to why we force a scope.
dvander@48
   471
    if (!enterScope(Scope::BLOCK))
dvander@48
   472
        return NULL;
dvander@48
   473
dvander@48
   474
    Statement *body;
dvander@48
   475
    if (scanner_.peek() == TOK_LBRACE)
dvander@48
   476
        body = block(scope_);
dvander@48
   477
    else
dvander@48
   478
        body = localStatement();
dvander@9
   479
    if (!body)
dvander@9
   480
        return NULL;
dvander@9
   481
dvander@48
   482
    scope_ = scope_->enclosing();
dvander@48
   483
dvander@9
   484
    if (!expect(TOK_WHILE))
dvander@9
   485
        return NULL;
dvander@9
   486
dvander@9
   487
    if (!expect(TOK_LPAREN))
dvander@9
   488
        return NULL;
dvander@9
   489
    Expression *condition = expression();
dvander@9
   490
    if (!condition)
dvander@9
   491
        return NULL;
dvander@9
   492
    if (!expect(TOK_RPAREN))
dvander@9
   493
        return NULL;
dvander@9
   494
dvander@25
   495
    return new (pool_) WhileStatement(pos, TOK_DO, condition, body);
dvander@9
   496
}
dvander@9
   497
dvander@9
   498
Statement *
dvander@0
   499
Parser::forStatement()
dvander@0
   500
{
dvander@25
   501
    SourcePosition pos = scanner_.begin();
dvander@0
   502
    scanner_.scan();
dvander@0
   503
    if (!expect(TOK_LPAREN))
dvander@0
   504
        return NULL;
dvander@0
   505
dvander@22
   506
    Statement *decl = NULL;
dvander@0
   507
    if (!match(TOK_SEMICOLON)) {
dvander@22
   508
        if (scanner_.peek() == TOK_NEW) {
dvander@22
   509
            if (!enterScope(Scope::BLOCK))
dvander@22
   510
                return NULL;
dvander@22
   511
            if ((decl = variableDeclaration()) == NULL)
dvander@22
   512
                return NULL;
dvander@22
   513
        } else {
dvander@22
   514
            if ((decl = expressionStatement()) == NULL)
dvander@22
   515
                return NULL;
dvander@22
   516
        }
dvander@0
   517
        if (!expect(TOK_SEMICOLON))
dvander@0
   518
            return NULL;
dvander@0
   519
    }
dvander@0
   520
dvander@0
   521
    Expression *condition = NULL;
dvander@0
   522
    if (!match(TOK_SEMICOLON)) {
dvander@0
   523
        if ((condition = expression()) == NULL)
dvander@0
   524
            return NULL;
dvander@0
   525
        if (!expect(TOK_SEMICOLON))
dvander@0
   526
            return NULL;
dvander@0
   527
    }
dvander@0
   528
dvander@0
   529
    Statement *update = NULL;
dvander@0
   530
    if (!match(TOK_RPAREN)) {
dvander@0
   531
        if ((update = expressionStatement()) == NULL)
dvander@0
   532
            return NULL;
dvander@0
   533
        if (!expect(TOK_RPAREN))
dvander@0
   534
            return NULL;
dvander@0
   535
    }
dvander@0
   536
dvander@48
   537
    // See the comment in ::while_() as to why we force a scope.
dvander@48
   538
    if (!enterScope(Scope::BLOCK))
dvander@48
   539
        return NULL;
dvander@48
   540
dvander@48
   541
    Statement *body;
dvander@48
   542
    if (scanner_.peek() == TOK_LBRACE)
dvander@48
   543
        body = block(scope_);
dvander@48
   544
    else
dvander@48
   545
        body = localStatement();
dvander@0
   546
    if (!body)
dvander@0
   547
        return NULL;
dvander@0
   548
dvander@48
   549
    scope_ = scope_->enclosing();
dvander@48
   550
dvander@48
   551
    Scope *declScope = NULL;
dvander@22
   552
    if (decl && decl->isVariableDeclaration()) {
dvander@48
   553
        declScope = scope_->unlinkIfEmpty();
dvander@0
   554
        scope_ = scope_->enclosing();
dvander@0
   555
    }
dvander@48
   556
    return new (pool_) ForStatement(pos, declScope, decl, condition, update, body);
dvander@0
   557
}
dvander@0
   558
dvander@0
   559
VariableDeclaration *
dvander@0
   560
Parser::variableDeclaration()
dvander@0
   561
{
dvander@0
   562
    if (!expect(TOK_NEW))
dvander@0
   563
        return NULL;
dvander@0
   564
dvander@4
   565
    Name *tag;
dvander@4
   566
    if (matchName(&tag, TOK_LABEL) && !tag)
dvander@0
   567
        return NULL;
dvander@4
   568
dvander@4
   569
    Name *name = expectName();
dvander@4
   570
    if (!name)
dvander@4
   571
        return NULL;
dvander@0
   572
dvander@25
   573
    if (BoundName *other = scope_->localLookup(name)) {
dvander@25
   574
        redeclarationError(other);
dvander@25
   575
        return NULL;
dvander@25
   576
    }
dvander@25
   577
dvander@25
   578
    Variable *var = scope_->declareVariable(name, scanner_.begin());
dvander@25
   579
    if (!var)
dvander@25
   580
        return NULL;
dvander@25
   581
dvander@0
   582
    ExpressionList *postDimensions = NULL;
dvander@0
   583
    if (scanner_.peek() == TOK_LBRACKET) {
dvander@0
   584
        postDimensions = new ExpressionList();
dvander@0
   585
        while (match(TOK_LBRACKET)) {
dvander@0
   586
            Expression *dim = expression();
dvander@0
   587
            if (!dim)
dvander@0
   588
                return NULL;
dvander@0
   589
dvander@0
   590
            if (!expect(TOK_RBRACKET))
dvander@0
   591
                return NULL;
dvander@0
   592
dvander@0
   593
            postDimensions->push_back(dim);
dvander@0
   594
        }
dvander@0
   595
    }
dvander@0
   596
    
dvander@0
   597
    Expression *expr = NULL;
dvander@0
   598
    if (match(TOK_ASSIGN)) {
dvander@0
   599
        if ((expr = expression()) == NULL)
dvander@0
   600
            return NULL;
dvander@0
   601
    }
dvander@0
   602
dvander@25
   603
    return new (pool_) VariableDeclaration(var->pos(), var, tag, postDimensions, expr);
dvander@0
   604
}
dvander@0
   605
dvander@0
   606
Statement *
dvander@0
   607
Parser::returnStatement()
dvander@0
   608
{
dvander@25
   609
    SourcePosition pos = scanner_.begin();
dvander@0
   610
    if (!expect(TOK_RETURN))
dvander@0
   611
        return NULL;
dvander@0
   612
dvander@0
   613
    Expression *expr = expression();
dvander@0
   614
    if (!expr)
dvander@0
   615
        return NULL;
dvander@0
   616
dvander@25
   617
    return new (pool_) ReturnStatement(pos, expr);
dvander@0
   618
}
dvander@0
   619
dvander@0
   620
Statement *
dvander@0
   621
Parser::expressionStatement()
dvander@0
   622
{
dvander@22
   623
    Expression *left = assignment();
dvander@21
   624
    if (!left)
dvander@0
   625
        return NULL;
dvander@0
   626
dvander@0
   627
    return new (pool_) ExpressionStatement(left);
dvander@0
   628
}
dvander@0
   629
dvander@0
   630
Statement *
dvander@48
   631
Parser::block(Scope *scope)
dvander@0
   632
{
dvander@0
   633
    if (!expect(TOK_LBRACE))
dvander@0
   634
        return NULL;
dvander@0
   635
dvander@25
   636
    SourcePosition pos = scanner_.begin();
dvander@48
   637
    if (!scope && !enterScope(Scope::BLOCK))
dvander@0
   638
        return NULL;
dvander@0
   639
dvander@0
   640
    StatementList *statements = new (pool_) StatementList();
dvander@0
   641
    while (!match(TOK_RBRACE)) {
dvander@0
   642
        Statement *statement = localStatement();
dvander@0
   643
        if (statement == NULL)
dvander@0
   644
            return NULL;
dvander@0
   645
        statements->append(pool_, statement);
dvander@0
   646
    }
dvander@0
   647
dvander@48
   648
    if (!scope) {
dvander@48
   649
    	scope = scope_->unlinkIfEmpty();
dvander@48
   650
        scope_ = scope_->enclosing();
dvander@48
   651
    }
dvander@48
   652
    BlockStatement *block = new (pool_) BlockStatement(pos, scope, statements);
dvander@0
   653
    return block;
dvander@0
   654
}
dvander@0
   655
dvander@0
   656
Statement *
dvander@0
   657
Parser::if_()
dvander@0
   658
{
dvander@0
   659
    expect(TOK_IF);
dvander@25
   660
    
dvander@25
   661
    SourcePosition pos = scanner_.begin();
dvander@0
   662
    if (!expect(TOK_LPAREN))
dvander@0
   663
        return NULL;
dvander@0
   664
dvander@0
   665
    Expression *cond = expression();
dvander@0
   666
    if (!cond)
dvander@0
   667
        return NULL;
dvander@0
   668
dvander@0
   669
    if (!expect(TOK_RPAREN))
dvander@0
   670
        return NULL;
dvander@0
   671
dvander@0
   672
    Statement *ifTrue = localStatement();
dvander@0
   673
    if (!ifTrue)
dvander@0
   674
        return NULL;
dvander@0
   675
dvander@25
   676
    IfStatement *outer = new (pool_) IfStatement(pos, cond, ifTrue);
dvander@0
   677
dvander@0
   678
    IfStatement *last = outer;
dvander@0
   679
    while (match(TOK_ELSE)) {
dvander@0
   680
        if (!match(TOK_IF)) {
dvander@0
   681
            Statement *ifFalse = localStatement();
dvander@0
   682
            if (!ifFalse)
dvander@0
   683
                return NULL;
dvander@0
   684
dvander@0
   685
            last->setIfFalse(ifFalse);
dvander@0
   686
            break;
dvander@0
   687
        }
dvander@0
   688
dvander@0
   689
        if (!expect(TOK_IF))
dvander@28
   690
            return NULL;
dvander@0
   691
dvander@25
   692
        SourcePosition pos = scanner_.begin();
dvander@0
   693
        if (!expect(TOK_LPAREN))
dvander@0
   694
            return NULL;
dvander@0
   695
dvander@0
   696
        Expression *otherCond = expression();
dvander@0
   697
        if (!otherCond)
dvander@0
   698
            return NULL;
dvander@0
   699
dvander@0
   700
        if (!expect(TOK_RPAREN))
dvander@0
   701
            return NULL;
dvander@0
   702
dvander@0
   703
        Statement *otherIfTrue = localStatement();
dvander@0
   704
        if (!otherIfTrue)
dvander@0
   705
            return NULL;
dvander@0
   706
dvander@25
   707
        IfStatement *inner = new (pool_) IfStatement(pos, otherCond, otherIfTrue);
dvander@0
   708
        last->setIfFalse(inner);
dvander@0
   709
        last = inner;
dvander@0
   710
    }
dvander@0
   711
dvander@0
   712
    return outer;
dvander@0
   713
}
dvander@0
   714
dvander@0
   715
Statement *
dvander@0
   716
Parser::localStatement()
dvander@0
   717
{
dvander@0
   718
    Statement *statement = NULL;
dvander@0
   719
dvander@0
   720
    // Statements which must be followed by a semicolon will break out of the
dvander@0
   721
    // switch. If they may end in BlockStatements, they'll immediately return.
dvander@0
   722
dvander@0
   723
    switch (scanner_.peek()) {
dvander@0
   724
        case TOK_NEW:
dvander@21
   725
          if ((statement = variableDeclaration()) == NULL)
dvander@21
   726
              return NULL;
dvander@0
   727
          break;
dvander@0
   728
dvander@0
   729
        case TOK_FOR:
dvander@0
   730
          return forStatement();
dvander@0
   731
dvander@9
   732
        case TOK_WHILE:
dvander@9
   733
          return while_();
dvander@9
   734
dvander@10
   735
        case TOK_BREAK:
dvander@10
   736
          scanner_.scan();
dvander@25
   737
          statement = new (pool_) BreakStatement(scanner_.begin());
dvander@10
   738
          break;
dvander@10
   739
dvander@10
   740
        case TOK_CONTINUE:
dvander@10
   741
          scanner_.scan();
dvander@25
   742
          statement = new (pool_) ContinueStatement(scanner_.begin());
dvander@10
   743
          break;
dvander@10
   744
dvander@9
   745
        case TOK_DO:
dvander@9
   746
          if ((statement = do_()) == NULL)
dvander@9
   747
              return NULL;
dvander@9
   748
          break;
dvander@9
   749
dvander@0
   750
        case TOK_RETURN:
dvander@21
   751
          if ((statement = returnStatement()) == NULL)
dvander@21
   752
              return NULL;
dvander@0
   753
          break;
dvander@0
   754
dvander@2
   755
        case TOK_ENUM:
dvander@21
   756
          if ((statement = enum_()) == NULL)
dvander@21
   757
              return NULL;
dvander@2
   758
          break;
dvander@2
   759
dvander@0
   760
        case TOK_IF:
dvander@0
   761
          return if_();
dvander@0
   762
dvander@0
   763
        case TOK_LBRACE:
dvander@0
   764
          return block();
dvander@28
   765
dvander@28
   766
	default:
dvander@28
   767
	  break;
dvander@0
   768
    }
dvander@0
   769
dvander@0
   770
    if (!statement) {
dvander@0
   771
        if ((statement = expressionStatement()) == NULL)
dvander@0
   772
            return NULL;
dvander@0
   773
    }
dvander@0
   774
dvander@0
   775
    if (!expect(TOK_SEMICOLON))
dvander@0
   776
        return NULL;
dvander@0
   777
dvander@0
   778
    return statement;
dvander@0
   779
}
dvander@0
   780
dvander@0
   781
Statement *
dvander@2
   782
Parser::enum_()
dvander@2
   783
{
dvander@2
   784
    expect(TOK_ENUM);
dvander@2
   785
dvander@25
   786
    SourcePosition pos = scanner_.begin();
dvander@25
   787
dvander@2
   788
    Name *name = NULL;
dvander@2
   789
    if (match(TOK_NAME)) {
dvander@2
   790
        if ((name = strings_.add(scanner_.literal())) == NULL)
dvander@2
   791
            return NULL;
dvander@2
   792
dvander@25
   793
        if (BoundName *other = scope_->localLookup(name)) {
dvander@25
   794
            redeclarationError(other);
dvander@2
   795
            return NULL;
dvander@2
   796
        }
dvander@2
   797
dvander@25
   798
        if (!scope_->declareEnum(name, scanner_.begin()))
dvander@2
   799
            return NULL;
dvander@2
   800
    }
dvander@2
   801
dvander@2
   802
    EnumStatement::EntryList *entries = new EnumStatement::EntryList();
dvander@2
   803
dvander@2
   804
    if (!expect(TOK_LBRACE))
dvander@2
   805
        return NULL;
dvander@2
   806
dvander@2
   807
    do {
dvander@2
   808
        if (scanner_.peek() == TOK_RBRACE)
dvander@2
   809
            break;
dvander@2
   810
dvander@4
   811
        Name *name = expectName();
dvander@2
   812
        if (!name)
dvander@2
   813
            return NULL;
dvander@2
   814
dvander@25
   815
        if (BoundName *other = scope_->localLookup(name)) {
dvander@25
   816
            redeclarationError(other);
dvander@2
   817
            return NULL;
dvander@2
   818
        }
dvander@2
   819
dvander@25
   820
        NamedConstant *constant = scope_->declareConstant(name, scanner_.begin());
dvander@2
   821
        if (!constant)
dvander@2
   822
            return NULL;
dvander@2
   823
dvander@2
   824
        Expression *expr = NULL;
dvander@2
   825
        if (match(TOK_ASSIGN)) {
dvander@2
   826
            if ((expr = expression()) == NULL)
dvander@2
   827
                return NULL;
dvander@2
   828
        }
dvander@2
   829
dvander@2
   830
        entries->push_back(EnumStatement::Entry(constant, expr));
dvander@2
   831
    } while (match(TOK_COMMA));
dvander@2
   832
    if (!expect(TOK_RBRACE))
dvander@2
   833
        return NULL;
dvander@2
   834
dvander@25
   835
    return new (pool_) EnumStatement(pos, name, entries);
dvander@2
   836
}
dvander@2
   837
dvander@2
   838
Statement *
dvander@0
   839
Parser::function()
dvander@0
   840
{
dvander@4
   841
    Name *name = expectName();
dvander@0
   842
    if (!name)
dvander@0
   843
        return NULL;
dvander@0
   844
dvander@25
   845
    SourcePosition pos = scanner_.begin();
dvander@25
   846
dvander@0
   847
    // The function name goes into the outer (global) scope.
dvander@0
   848
    assert(!scope_->enclosing());
dvander@0
   849
dvander@25
   850
    if (BoundName *other = scope_->localLookup(name)) {
dvander@25
   851
        redeclarationError(other);
dvander@0
   852
        return NULL;
dvander@0
   853
    }
dvander@25
   854
    NamedFunction *fun = scope_->declareFunction(name, scanner_.begin());
dvander@0
   855
    if (!fun)
dvander@0
   856
        return NULL;
dvander@0
   857
dvander@0
   858
    Scope *scope = enterScope(Scope::FUNCTION);
dvander@0
   859
    if (!scope)
dvander@0
   860
        return NULL;
dvander@0
   861
dvander@14
   862
    ParameterList *parameters = new ParameterList();
dvander@14
   863
dvander@0
   864
    if (!expect(TOK_LPAREN))
dvander@0
   865
        return NULL;
dvander@0
   866
    if (!match(TOK_RPAREN)) {
dvander@0
   867
        while (true) {
dvander@14
   868
            bool ref = match(TOK_AMPERSAND);
dvander@14
   869
dvander@4
   870
            Name *name = expectName();
dvander@0
   871
            if (!name)
dvander@0
   872
                return NULL;
dvander@0
   873
dvander@25
   874
            if (BoundName *other = scope_->localLookup(name)) {
dvander@25
   875
                redeclarationError(other);
dvander@0
   876
                return NULL;
dvander@0
   877
            }
dvander@25
   878
            Variable *arg = scope_->declareArgument(name, scanner_.begin());
dvander@14
   879
            if (!arg)
dvander@0
   880
                return NULL;
dvander@0
   881
dvander@14
   882
            Parameter *parameter = new (pool_) Parameter(arg, NULL, ref);
dvander@14
   883
            parameters->push_back(parameter);
dvander@14
   884
dvander@0
   885
            if (!match(TOK_COMMA))
dvander@0
   886
                break;
dvander@0
   887
        }
dvander@0
   888
        if (!expect(TOK_RPAREN))
dvander@0
   889
            return NULL;
dvander@0
   890
    }
dvander@0
   891
dvander@0
   892
    Statement *body = block();
dvander@0
   893
    if (!body)
dvander@0
   894
        return NULL;
dvander@0
   895
dvander@0
   896
    scope_ = scope_->enclosing();
dvander@25
   897
    return new (pool_) FunctionStatement(pos, scope, fun, body, parameters);
dvander@0
   898
}
dvander@0
   899
dvander@0
   900
ParseTree *
dvander@0
   901
Parser::parse()
dvander@0
   902
{
dvander@0
   903
    StatementList *statements = new (pool_) StatementList();
dvander@0
   904
dvander@0
   905
    if (!enterScope(Scope::GLOBAL))
dvander@0
   906
        return NULL;
dvander@0
   907
dvander@0
   908
    for (;;) {
dvander@0
   909
        Statement *statement = NULL;
dvander@0
   910
dvander@0
   911
        switch (scanner_.peek()) {
dvander@0
   912
          case TOK_ERROR:
dvander@0
   913
            return NULL;
dvander@0
   914
dvander@0
   915
          case TOK_EOF:
dvander@0
   916
            break;
dvander@0
   917
dvander@0
   918
          case TOK_NAME:
dvander@0
   919
            if ((statement = function()) == NULL)
dvander@0
   920
                return NULL;
dvander@0
   921
            break;
dvander@0
   922
dvander@2
   923
          case TOK_ENUM:
dvander@2
   924
            if ((statement = enum_()) == NULL)
dvander@2
   925
                return NULL;
dvander@2
   926
            // :TODO: require semicolon
dvander@2
   927
            break;
dvander@2
   928
dvander@0
   929
          default:
dvander@0
   930
            fprintf(stderr, "expected function or global variable\n");
dvander@0
   931
            return NULL;
dvander@0
   932
        }
dvander@0
   933
dvander@0
   934
        if (!statement)
dvander@0
   935
            break;
dvander@0
   936
dvander@0
   937
        statements->append(pool_, statement);
dvander@0
   938
    }
dvander@0
   939
dvander@0
   940
    return new (pool_) ParseTree(scope_, statements, unbound_);
dvander@0
   941
}
dvander@0
   942
dvander@0
   943
class AstPrinter : public AstVisitor
dvander@0
   944
{
dvander@0
   945
    FILE *fp_;
dvander@0
   946
    size_t level_;
dvander@0
   947
dvander@0
   948
  private:
dvander@0
   949
    void prefix() {
dvander@0
   950
        for (size_t i = 0; i < level_; i++)
dvander@0
   951
            fprintf(fp_, "  ");
dvander@0
   952
    }
dvander@0
   953
    void indent() {
dvander@0
   954
        level_++;
dvander@0
   955
    }
dvander@0
   956
    void unindent() {
dvander@0
   957
        level_--;
dvander@0
   958
    }
dvander@0
   959
dvander@0
   960
  public:
dvander@0
   961
    AstPrinter(FILE *fp)
dvander@0
   962
      : fp_(fp),
dvander@0
   963
        level_(0)
dvander@0
   964
    {
dvander@0
   965
    }
dvander@0
   966
dvander@0
   967
    void visit(NameProxy *name) {
dvander@0
   968
        prefix();
dvander@0
   969
        fprintf(fp_, "[ NameProxy (%s)%s\n", name->name(),
dvander@0
   970
                (name->binding() ? "" : " unbound"));
dvander@0
   971
    }
dvander@0
   972
    void visit(CallExpression *node) {
dvander@0
   973
        prefix();
dvander@0
   974
        fprintf(fp_, "[ CallExpression\n");
dvander@0
   975
        indent();
dvander@0
   976
        node->callee()->accept(this);
dvander@0
   977
        for (size_t i = 0; i < node->arguments()->size(); i++)
dvander@0
   978
            node->arguments()->at(i)->accept(this);
dvander@0
   979
        unindent();
dvander@0
   980
    }
dvander@0
   981
    void visit(FunctionStatement *node) {
dvander@0
   982
        prefix();
dvander@0
   983
        fprintf(fp_, "[ FunctionStatement (%s)\n", node->fun()->name());
dvander@0
   984
        indent();
dvander@0
   985
        node->body()->accept(this);
dvander@0
   986
        unindent();
dvander@0
   987
    }
dvander@0
   988
    void visit(ExpressionStatement *node) {
dvander@0
   989
        prefix();
dvander@0
   990
        fprintf(fp_, "[ ExpressionStatement\n");
dvander@0
   991
        indent();
dvander@0
   992
        node->expression()->accept(this);
dvander@0
   993
        unindent();
dvander@0
   994
    }
dvander@0
   995
    void visit(Assignment *node) {
dvander@0
   996
        prefix();
dvander@0
   997
        fprintf(fp_, "[ Assignment\n");
dvander@0
   998
        indent();
dvander@0
   999
        node->lvalue()->accept(this);
dvander@0
  1000
        node->expression()->accept(this);
dvander@0
  1001
        unindent();
dvander@0
  1002
    }
dvander@0
  1003
    void visit(BinaryExpression *node) {
dvander@0
  1004
        prefix();
dvander@0
  1005
        fprintf(fp_, "[ BinaryExpression (%s)\n", TokenNames[node->token()]);
dvander@0
  1006
        indent();
dvander@0
  1007
        node->left()->accept(this);
dvander@0
  1008
        node->right()->accept(this);
dvander@0
  1009
        unindent();
dvander@0
  1010
    }
dvander@0
  1011
    void visit(ReturnStatement *node) {
dvander@0
  1012
        prefix();
dvander@0
  1013
        fprintf(fp_, "[ ReturnStatement\n");
dvander@0
  1014
        indent();
dvander@0
  1015
        node->expression()->accept(this);
dvander@0
  1016
        unindent();
dvander@0
  1017
    }
dvander@0
  1018
    void visit(ForStatement *node) {
dvander@0
  1019
        prefix();
dvander@0
  1020
        fprintf(fp_, "[ ForStatement\n");
dvander@0
  1021
        indent();
dvander@22
  1022
        if (node->initialization())
dvander@22
  1023
            node->initialization()->accept(this);
dvander@0
  1024
        if (node->condition())
dvander@0
  1025
            node->condition()->accept(this);
dvander@0
  1026
        if (node->update())
dvander@0
  1027
            node->update()->accept(this);
dvander@0
  1028
        node->body()->accept(this);
dvander@0
  1029
        unindent();
dvander@0
  1030
    }
dvander@0
  1031
    void visit(BlockStatement *node) {
dvander@0
  1032
        prefix();
dvander@0
  1033
        fprintf(fp_, "[ BlockStatement\n");
dvander@0
  1034
        indent();
dvander@0
  1035
        for (size_t i = 0; i < node->statements()->length(); i++)
dvander@0
  1036
            node->statements()->at(i)->accept(this);
dvander@0
  1037
        unindent();
dvander@0
  1038
    }
dvander@0
  1039
    void visit(VariableDeclaration *node) {
dvander@0
  1040
        prefix();
dvander@0
  1041
        fprintf(fp_, "[ VariableDeclaration (%s)\n", node->variable()->name());
dvander@0
  1042
        indent();
dvander@0
  1043
        if (node->initialization())
dvander@0
  1044
            node->initialization()->accept(this);
dvander@0
  1045
        unindent();
dvander@0
  1046
    }
dvander@4
  1047
    void visit(IntegerLiteral *node) {
dvander@0
  1048
        prefix();
dvander@4
  1049
        fprintf(fp_, "[ IntegerLiteral (%d)\n", node->value());
dvander@4
  1050
    }
dvander@4
  1051
    void visit(FloatLiteral *node) {
dvander@4
  1052
        prefix();
dvander@4
  1053
        fprintf(fp_, "[ FloatLiteral (%f)\n", node->value());
dvander@0
  1054
    }
dvander@0
  1055
    void visit(IfStatement *node) {
dvander@0
  1056
        prefix();
dvander@0
  1057
        fprintf(fp_, "[ IfStatement\n");
dvander@0
  1058
        indent();
dvander@0
  1059
        node->ifTrue()->accept(this);
dvander@0
  1060
        if (node->ifFalse())
dvander@0
  1061
            node->ifFalse()->accept(this);
dvander@0
  1062
        unindent();
dvander@0
  1063
    }
dvander@0
  1064
    void visit(IndexExpression *node) {
dvander@0
  1065
        prefix();
dvander@0
  1066
        fprintf(fp_, "[ IndexExpression\n");
dvander@0
  1067
        indent();
dvander@0
  1068
        node->left()->accept(this);
dvander@0
  1069
        node->right()->accept(this);
dvander@0
  1070
        unindent();
dvander@0
  1071
    }
dvander@2
  1072
    void visit(EnumStatement *node) {
dvander@2
  1073
        prefix();
dvander@2
  1074
        fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name() : "<anonymous>");
dvander@2
  1075
        indent();
dvander@2
  1076
        for (size_t i = 0; i < node->entries()->size(); i++) {
dvander@2
  1077
            prefix();
dvander@2
  1078
            fprintf(fp_, "%s =\n", node->entries()->at(i).name->name());
dvander@2
  1079
            if (node->entries()->at(i).expr) {
dvander@2
  1080
                indent();
dvander@2
  1081
                node->entries()->at(i).expr->accept(this);
dvander@2
  1082
                unindent();
dvander@2
  1083
            }
dvander@2
  1084
        }
dvander@2
  1085
        unindent();
dvander@2
  1086
    }
dvander@9
  1087
    void visit(WhileStatement *node) {
dvander@9
  1088
        prefix();
dvander@9
  1089
        fprintf(fp_, "[ WhileStatement (%s)\n",
dvander@9
  1090
                (node->token() == TOK_DO) ? "do" : "while");
dvander@9
  1091
        indent();
dvander@9
  1092
        if (node->token() == TOK_DO) {
dvander@9
  1093
            node->condition()->accept(this);
dvander@9
  1094
            node->body()->accept(this);
dvander@9
  1095
        } else {
dvander@9
  1096
            node->condition()->accept(this);
dvander@9
  1097
            node->body()->accept(this);
dvander@9
  1098
        }
dvander@9
  1099
        unindent();
dvander@9
  1100
    }
dvander@10
  1101
    void visit(BreakStatement *node) {
dvander@10
  1102
        prefix();
dvander@10
  1103
        fprintf(fp_, "[ BreakStatement\n");
dvander@10
  1104
    }
dvander@10
  1105
    void visit(ContinueStatement *node) {
dvander@10
  1106
        prefix();
dvander@10
  1107
        fprintf(fp_, "[ ContinueStatement\n");
dvander@10
  1108
    }
dvander@21
  1109
    void visit(StringLiteral *node) {
dvander@21
  1110
        prefix();
dvander@21
  1111
        fprintf(fp_, "[ StringLiteral\n");
dvander@21
  1112
    }
dvander@23
  1113
    void visit(IncDecExpression *node) {
dvander@23
  1114
        prefix();
dvander@23
  1115
        fprintf(fp_, "[ IncDecExpression (postfix=%d)\n", node->postfix());
dvander@23
  1116
        indent();
dvander@23
  1117
        node->expression()->accept(this);
dvander@23
  1118
        unindent();
dvander@23
  1119
    }
dvander@0
  1120
};
dvander@0
  1121
dvander@0
  1122
void
dvander@0
  1123
ParseTree::dump(FILE *fp)
dvander@0
  1124
{
dvander@0
  1125
    AstPrinter printer(fp);
dvander@0
  1126
dvander@0
  1127
    for (size_t i = 0; i < statements_->length(); i++)
dvander@0
  1128
        statements_->at(i)->accept(&printer);
dvander@0
  1129
}