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