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