src/compiler/Parser.cpp
author David Anderson <dvander@alliedmods.net>
Sun Jan 27 17:34:30 2013 -0800 (2013-01-27)
changeset 261 219b49bf4a03
parent 258 241d082d6d89
child 263 ba85a47ee414
permissions -rw-r--r--
Add support for importing enum types and enum values (as constexprs).
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@117
     5
 * This file is part of SourcePawn.
dvander@0
     6
 *
dvander@117
     7
 * SourcePawn 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@117
    12
 * SourcePawn 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@117
    17
 * SourcePawn. If not, see http://www.gnu.org/licenses/.
dvander@0
    18
 */
danderson@92
    19
#include <string.h>
dvander@195
    20
#include "../Zone.h"
dvander@195
    21
#include "../FixedArray.h"
dvander@195
    22
#include "../Heap.h"
dvander@195
    23
#include "../Strings.h"
dvander@195
    24
#include "../TypeManager.h"
dvander@0
    25
#include "Parser.h"
dvander@195
    26
#include "../Heap-inl.h"
dvander@0
    27
dvander@59
    28
using namespace ke;
dvander@0
    29
dvander@54
    30
Parser::Parser(Zone *zone, CompileContext &cc, const char *stream, size_t length)
dvander@54
    31
  : zone_(zone),
dvander@54
    32
    cc_(cc),
dvander@54
    33
    pool_(zone_->pool()),
dvander@25
    34
    scanner_(cc, stream, length),
dvander@0
    35
    unbound_(NULL)
dvander@0
    36
{
dvander@57
    37
    unbound_ = new (pool_) PoolList<NameProxy *>();
dvander@195
    38
    imports_ = new (pool_) PoolList<ImportStatement *>();
dvander@0
    39
}
dvander@0
    40
dvander@0
    41
bool
dvander@145
    42
Parser::peek(TokenKind kind)
dvander@145
    43
{
dvander@145
    44
    return scanner_.peek() == kind;
dvander@145
    45
}
dvander@145
    46
dvander@145
    47
bool
dvander@0
    48
Parser::match(TokenKind kind)
dvander@0
    49
{
dvander@145
    50
    if (!peek(kind))
dvander@0
    51
        return false;
dvander@0
    52
    scanner_.scan();
dvander@0
    53
    return true;
dvander@0
    54
}
dvander@0
    55
dvander@0
    56
bool
dvander@63
    57
Parser::matchSemicolon()
dvander@63
    58
{
dvander@63
    59
    return expect(TOK_SEMICOLON);
dvander@63
    60
}
dvander@63
    61
dvander@63
    62
bool
dvander@0
    63
Parser::expect(TokenKind kind)
dvander@0
    64
{
dvander@0
    65
    TokenKind got = scanner_.scan();
dvander@0
    66
    if (got == kind)
dvander@0
    67
        return true;
dvander@25
    68
    cc_.reportError(scanner_.begin(), Message_WrongToken, TokenNames[kind], TokenNames[got]);
dvander@0
    69
    return false;
dvander@0
    70
}
dvander@0
    71
dvander@4
    72
bool
dvander@54
    73
Parser::matchName(String **name, TokenKind kind)
dvander@4
    74
{
dvander@4
    75
    assert(kind == TOK_NAME || kind == TOK_LABEL);
dvander@4
    76
    *name = NULL;
dvander@4
    77
    if (!match(kind))
dvander@4
    78
        return false;
dvander@54
    79
    *name = zone_->makeSymbol(scanner_.literal(), scanner_.literal_length());
dvander@4
    80
    return true;
dvander@4
    81
}
dvander@4
    82
dvander@54
    83
String *
dvander@4
    84
Parser::expectName()
dvander@4
    85
{
dvander@4
    86
    if (!expect(TOK_NAME))
dvander@4
    87
        return NULL;
dvander@54
    88
    return zone_->makeSymbol(scanner_.literal(), scanner_.literal_length());
dvander@4
    89
}
dvander@4
    90
dvander@0
    91
Expression *
dvander@0
    92
Parser::primitive()
dvander@0
    93
{
dvander@25
    94
    TokenKind kind = scanner_.peek();
dvander@25
    95
    switch (kind) {
dvander@4
    96
      case TOK_FLOAT_LITERAL:
dvander@4
    97
      {
dvander@4
    98
        scanner_.scan();
dvander@4
    99
        double value = Scanner::ParseDouble(scanner_.literal());
dvander@25
   100
        return new (pool_) FloatLiteral(scanner_.begin(), value);
dvander@4
   101
      }
dvander@4
   102
dvander@176
   103
      case TOK_HEX_LITERAL:
dvander@176
   104
      {
dvander@176
   105
        scanner_.scan();
dvander@176
   106
        int value = strtol(scanner_.literal(), NULL, 16);
dvander@176
   107
        return new (pool_) IntegerLiteral(scanner_.begin(), value);
dvander@176
   108
      }
dvander@176
   109
dvander@0
   110
      case TOK_INTEGER_LITERAL:
dvander@0
   111
      {
dvander@0
   112
        scanner_.scan();
dvander@0
   113
        int value = atoi(scanner_.literal());
dvander@25
   114
        return new (pool_) IntegerLiteral(scanner_.begin(), value);
dvander@0
   115
      }
dvander@0
   116
dvander@143
   117
      case TOK_TRUE:
dvander@143
   118
      case TOK_FALSE:
dvander@143
   119
        scanner_.scan();
dvander@143
   120
        return new (pool_) BooleanLiteral(scanner_.begin(), kind);
dvander@143
   121
dvander@21
   122
      case TOK_STRING_LITERAL:
dvander@21
   123
      {
dvander@21
   124
        scanner_.scan();
dvander@234
   125
        Local<String> string(zone_, zone_->makeSymbol(scanner_.literal(), scanner_.literal_length()));
dvander@234
   126
        return new (pool_) StringLiteral(scanner_.begin(), string);
dvander@21
   127
      }
dvander@21
   128
dvander@0
   129
      default:
dvander@0
   130
      {
dvander@25
   131
        if (kind != TOK_ERROR)
dvander@25
   132
            cc_.reportError(scanner_.begin(), Message_ExpectedExpression, TokenNames[kind]);
dvander@0
   133
        return NULL;
dvander@0
   134
      }
dvander@0
   135
    }
dvander@0
   136
}
dvander@0
   137
dvander@0
   138
Expression *
dvander@212
   139
Parser::fixedArrayLiteral()
dvander@187
   140
{
dvander@187
   141
    SourcePosition pos = scanner_.begin();
dvander@187
   142
dvander@187
   143
    ExpressionList *list = new (pool_) ExpressionList();
dvander@187
   144
    do {
dvander@212
   145
        // { } is an illegal array literal.
dvander@212
   146
        if (list->length() > 0 && match(TOK_LBRACE))
dvander@187
   147
            break;
dvander@187
   148
dvander@187
   149
        Expression *expr = NULL;
dvander@212
   150
        if (peek(TOK_LBRACE))
dvander@212
   151
            expr = fixedArrayLiteral();
dvander@212
   152
        else
dvander@212
   153
            expr = primitive();
dvander@187
   154
        if (!expr)
dvander@187
   155
            return NULL;
dvander@187
   156
dvander@187
   157
        if (!list->append(expr))
dvander@187
   158
            return NULL;
dvander@187
   159
dvander@187
   160
        if (!match(TOK_COMMA)) {
dvander@212
   161
            if (!expect(TOK_RBRACE))
dvander@187
   162
                return NULL;
dvander@187
   163
            break;
dvander@187
   164
        }
dvander@187
   165
    } while (true);
dvander@187
   166
dvander@212
   167
    return new (pool_) ArrayLiteral(pos, TOK_LBRACE, list);
dvander@187
   168
}
dvander@187
   169
dvander@187
   170
Expression *
dvander@0
   171
Parser::prefix()
dvander@0
   172
{
dvander@0
   173
    switch (scanner_.peek()) {
dvander@0
   174
      case TOK_LPAREN:
dvander@0
   175
      {
dvander@0
   176
        scanner_.scan();
dvander@0
   177
        Expression *expr = expression();
dvander@0
   178
        if (!expr)
dvander@0
   179
            return NULL;
dvander@0
   180
        if (!expect(TOK_RPAREN))
dvander@0
   181
            return NULL;
dvander@0
   182
        return expr;
dvander@0
   183
      }
dvander@0
   184
dvander@187
   185
      case TOK_NAME:
dvander@187
   186
      {
dvander@187
   187
        Local<String> name(zone_, expectName());
dvander@187
   188
        if (!name)
dvander@187
   189
            return NULL;
dvander@195
   190
        return new (pool_) NameProxy(scanner_.begin(), name);
dvander@187
   191
      }
dvander@187
   192
dvander@0
   193
      default:
dvander@0
   194
        return primitive();
dvander@0
   195
    }
dvander@0
   196
}
dvander@0
   197
dvander@195
   198
// Parses only old-style declarations.
dvander@195
   199
bool
dvander@195
   200
Parser::typeAndName(Expression **type, String **namep)
dvander@195
   201
{
dvander@195
   202
    if (match(TOK_LABEL)) {
dvander@195
   203
        // Old-style declaration:
dvander@195
   204
        //   new X:type
dvander@195
   205
        Local<String> name(zone_, zone_->makeSymbol(scanner_.literal(), scanner_.literal_length()));
dvander@195
   206
        if (!name)
dvander@195
   207
            return false;
dvander@195
   208
dvander@195
   209
        *type = new (pool_) NameProxy(scanner_.begin(), name);
dvander@195
   210
        *namep = expectName();
dvander@195
   211
        return !!*namep;
dvander@195
   212
    }
dvander@195
   213
    
dvander@195
   214
    *type = NULL;
dvander@195
   215
    *namep = expectName();
dvander@195
   216
dvander@195
   217
    return !!*namep;
dvander@195
   218
}
dvander@195
   219
dvander@195
   220
// Parses both old and new style declarations.
dvander@195
   221
bool
dvander@195
   222
Parser::fullTypeAndName(Expression **type, String **namep, DeclKind kind)
dvander@195
   223
{
dvander@251
   224
    //   decl    ::= newdecl | olddecl
dvander@251
   225
    //   newdecl ::= Type Ident
dvander@251
   226
    //   olddecl ::= Label? (Ident | "...")
dvander@251
   227
    //   type    ::= Ident
dvander@251
   228
    //   label   ::= Ident ":"
dvander@195
   229
    //
dvander@195
   230
    if (match(TOK_LABEL)) {
dvander@195
   231
        // We something of the form:
dvander@195
   232
        //     Label Ident
dvander@195
   233
        // or: Label "..."
dvander@195
   234
        Local<String> name(zone_, zone_->makeSymbol(scanner_.literal(), scanner_.literal_length()));
dvander@195
   235
        if (!name)
dvander@195
   236
            return false;
dvander@195
   237
dvander@195
   238
        *type = new (pool_) NameProxy(scanner_.begin(), name);
dvander@195
   239
        if (kind == DeclArg && match(TOK_ELLIPSES)) {
dvander@195
   240
            *namep = NULL;
dvander@195
   241
        } else {
dvander@195
   242
            if ((*namep = expectName()) == NULL)
dvander@195
   243
                return false;
dvander@195
   244
        }
dvander@195
   245
        return true;
dvander@195
   246
    }
dvander@195
   247
dvander@195
   248
    Local<String> name(zone_, expectName());
dvander@195
   249
    if (!name)
dvander@195
   250
        return false;
dvander@195
   251
dvander@195
   252
    if (peek(TOK_NAME) || (kind == DeclArg && peek(TOK_ELLIPSES))) {
dvander@195
   253
        // We got something of the form:
dvander@195
   254
        //    Ident Ident
dvander@195
   255
        *type = new (pool_) NameProxy(scanner_.begin(), name);
dvander@195
   256
        if (peek(TOK_NAME)) {
dvander@195
   257
            if ((*namep = expectName()) == NULL)
dvander@195
   258
                return false;
dvander@195
   259
        } else {
dvander@195
   260
            *namep = NULL;
dvander@195
   261
        }
dvander@195
   262
        return true;
dvander@195
   263
    }
dvander@195
   264
dvander@195
   265
    // We got something of the form:
dvander@195
   266
    //    Ident
dvander@195
   267
    *type = NULL;
dvander@195
   268
    *namep = name;
dvander@195
   269
    return true;
dvander@195
   270
}
dvander@195
   271
dvander@0
   272
Expression *
dvander@0
   273
Parser::call(Expression *callee)
dvander@0
   274
{
dvander@56
   275
    ExpressionList *arguments = new (pool_) ExpressionList();
dvander@0
   276
dvander@25
   277
    SourcePosition pos = scanner_.begin();
dvander@0
   278
    expect(TOK_LPAREN);
dvander@0
   279
    
dvander@0
   280
    if (!match(TOK_RPAREN)) {
dvander@0
   281
        while (true) {
dvander@0
   282
            Expression *expr = expression();
dvander@0
   283
            if (!expr)
dvander@0
   284
                return NULL;
dvander@0
   285
dvander@55
   286
            if (!arguments->append(expr))
dvander@55
   287
                return NULL;
dvander@0
   288
dvander@0
   289
            if (!match(TOK_COMMA))
dvander@0
   290
                break;
dvander@0
   291
        }
dvander@0
   292
dvander@0
   293
        if (!expect(TOK_RPAREN))
dvander@0
   294
            return NULL;
dvander@0
   295
    }
dvander@0
   296
dvander@25
   297
    return new (pool_) CallExpression(pos, callee, arguments);
dvander@0
   298
}
dvander@0
   299
dvander@0
   300
Expression *
dvander@0
   301
Parser::index(Expression *left)
dvander@0
   302
{
dvander@0
   303
    expect(TOK_LBRACKET);
dvander@0
   304
    
dvander@25
   305
    SourcePosition pos = scanner_.begin();
dvander@0
   306
    Expression *expr = expression();
dvander@0
   307
    if (!expr)
dvander@0
   308
        return NULL;
dvander@0
   309
dvander@0
   310
    if (!expect(TOK_RBRACKET))
dvander@0
   311
        return NULL;
dvander@0
   312
dvander@25
   313
    return new (pool_) IndexExpression(pos, left, expr);
dvander@0
   314
}
dvander@0
   315
dvander@0
   316
Expression *
dvander@148
   317
Parser::field(Expression *left)
dvander@148
   318
{
dvander@148
   319
    expect(TOK_DOT);
dvander@148
   320
dvander@148
   321
    SourcePosition pos = scanner_.begin();
dvander@148
   322
    Local<String> name(zone_, expectName());
dvander@148
   323
    if (!name)
dvander@148
   324
        return NULL;
dvander@148
   325
dvander@148
   326
    return new (pool_) FieldExpression(pos, left, name);
dvander@148
   327
}
dvander@148
   328
dvander@148
   329
Expression *
dvander@0
   330
Parser::primary()
dvander@0
   331
{
dvander@0
   332
    Expression *expr = prefix();
dvander@0
   333
    if (!expr)
dvander@0
   334
        return NULL;
dvander@0
   335
dvander@0
   336
    for (;;) {
dvander@0
   337
        switch (scanner_.peek()) {
dvander@0
   338
          case TOK_LPAREN:
dvander@148
   339
            if ((expr = call(expr)) == NULL)
dvander@0
   340
                return NULL;
dvander@0
   341
            break;
dvander@0
   342
dvander@0
   343
          case TOK_LBRACKET:
dvander@148
   344
            if ((expr = index(expr)) == NULL)
dvander@148
   345
                return NULL;
dvander@148
   346
            break;
dvander@148
   347
dvander@148
   348
          case TOK_DOT:
dvander@148
   349
            if ((expr = field(expr)) == NULL)
dvander@0
   350
                return NULL;
dvander@0
   351
            break;
dvander@0
   352
dvander@0
   353
          default:
dvander@0
   354
            return expr;
dvander@0
   355
        }
dvander@0
   356
    }
dvander@0
   357
}
dvander@0
   358
dvander@0
   359
Expression *
dvander@0
   360
Parser::unary()
dvander@0
   361
{
dvander@23
   362
    TokenKind token = scanner_.peek();
dvander@23
   363
dvander@25
   364
    SourcePosition pos = scanner_.begin();
dvander@23
   365
    switch (token) {
dvander@23
   366
      case TOK_INCREMENT:
dvander@23
   367
      case TOK_DECREMENT:
dvander@23
   368
      {
dvander@23
   369
        scanner_.scan();
dvander@141
   370
        Expression *expr = unary();
dvander@23
   371
        if (!expr)
dvander@23
   372
            return NULL;
dvander@25
   373
        return new (pool_) IncDecExpression(pos, token, expr, false);
dvander@23
   374
      }
dvander@78
   375
dvander@80
   376
      case TOK_MINUS:
dvander@79
   377
      case TOK_NOT:
dvander@78
   378
      case TOK_TILDE:
dvander@78
   379
      {
dvander@78
   380
        scanner_.scan();
dvander@141
   381
        Expression *expr = unary();
dvander@78
   382
        if (!expr)
dvander@78
   383
            return NULL;
dvander@78
   384
        return new (pool_) UnaryExpression(pos, token, expr);
dvander@78
   385
      }
dvander@78
   386
dvander@194
   387
      case TOK_SIZEOF:
dvander@194
   388
      {
dvander@194
   389
        scanner_.scan();
dvander@194
   390
        if (!expect(TOK_LPAREN))
dvander@194
   391
            return NULL;
dvander@194
   392
        Expression *expr = unary();
dvander@194
   393
        if (!expr)
dvander@194
   394
            return NULL;
dvander@194
   395
        if (!expect(TOK_RPAREN))
dvander@194
   396
            return NULL;
dvander@194
   397
        return new (pool_) UnaryExpression(pos, token, expr);
dvander@194
   398
      }
dvander@194
   399
dvander@141
   400
      case TOK_LABEL:
dvander@141
   401
      {
dvander@141
   402
        scanner_.scan();
dvander@141
   403
        Local<String> tag(zone_, zone_->makeSymbol(scanner_.literal(), scanner_.literal_length()));
dvander@141
   404
        if (!tag)
dvander@141
   405
            return NULL;
dvander@141
   406
dvander@195
   407
        NameProxy *proxy = new (pool_) NameProxy(scanner_.begin(), tag);
dvander@145
   408
dvander@141
   409
        Expression *expr = unary();
dvander@141
   410
        if (!expr)
dvander@141
   411
            return NULL;
dvander@141
   412
dvander@195
   413
        return new (pool_) UnaryExpression(pos, TOK_LABEL, expr, proxy);
dvander@141
   414
      }
dvander@141
   415
dvander@28
   416
      default:
dvander@28
   417
        break;
dvander@23
   418
    }
dvander@23
   419
dvander@23
   420
    Expression *expr = primary();
dvander@23
   421
dvander@23
   422
    token = scanner_.peek();
dvander@23
   423
    if (token == TOK_INCREMENT || token == TOK_DECREMENT) {
dvander@23
   424
        scanner_.scan();
dvander@25
   425
        return new (pool_) IncDecExpression(pos, token, expr, true);
dvander@23
   426
    }
dvander@23
   427
dvander@23
   428
    return expr;
dvander@0
   429
}
dvander@0
   430
dvander@0
   431
Expression *
dvander@0
   432
Parser::multiplication()
dvander@0
   433
{
dvander@0
   434
    Expression *left = unary();
dvander@0
   435
    do {
dvander@82
   436
        if (!match(TOK_SLASH) && !match(TOK_STAR) && !match(TOK_PERCENT))
dvander@0
   437
            break;
dvander@25
   438
        SourcePosition pos = scanner_.begin();
dvander@0
   439
        TokenKind kind = scanner_.last();
dvander@0
   440
        Expression *right = unary();
dvander@0
   441
        if (!right)
dvander@0
   442
            return NULL;
dvander@25
   443
        left = new (pool_) BinaryExpression(pos, kind, left, right);
dvander@0
   444
    } while (left);
dvander@0
   445
    return left;
dvander@0
   446
}
dvander@0
   447
dvander@0
   448
Expression *
dvander@0
   449
Parser::addition()
dvander@0
   450
{
dvander@0
   451
    Expression *left = multiplication();
dvander@0
   452
    while (left) {
dvander@0
   453
        if (!match(TOK_PLUS) && !match(TOK_MINUS))
dvander@0
   454
            break;
dvander@25
   455
        SourcePosition pos = scanner_.begin();
dvander@0
   456
        TokenKind kind = scanner_.last();
dvander@0
   457
        Expression *right = multiplication();
dvander@0
   458
        if (!right)
dvander@0
   459
            return NULL;
dvander@25
   460
        left = new (pool_) BinaryExpression(pos, kind, left, right);
dvander@0
   461
    }
dvander@0
   462
    return left;
dvander@0
   463
}
dvander@0
   464
dvander@0
   465
Expression *
dvander@2
   466
Parser::shift()
dvander@2
   467
{
dvander@2
   468
    Expression *left = addition();
dvander@2
   469
    while (left) {
dvander@8
   470
        if (!match(TOK_SHL) && !match(TOK_SHR) && !match(TOK_USHR))
dvander@2
   471
            break;
dvander@25
   472
        SourcePosition pos = scanner_.begin();
dvander@2
   473
        TokenKind kind = scanner_.last();
dvander@2
   474
        Expression *right = addition();
dvander@2
   475
        if (!right)
dvander@2
   476
            return NULL;
dvander@25
   477
        left = new (pool_) BinaryExpression(pos, kind, left, right);
dvander@2
   478
    }
dvander@2
   479
    return left;
dvander@2
   480
}
dvander@2
   481
dvander@2
   482
Expression *
dvander@28
   483
Parser::bitand_()
dvander@8
   484
{
dvander@8
   485
    Expression *left = shift();
dvander@8
   486
    while (left) {
dvander@8
   487
        if (!match(TOK_BITAND))
dvander@8
   488
            break;
dvander@25
   489
        SourcePosition pos = scanner_.begin();
dvander@8
   490
        Expression *right = shift();
dvander@8
   491
        if (!right)
dvander@8
   492
            return NULL;
dvander@25
   493
        left = new (pool_) BinaryExpression(pos, TOK_BITAND, left, right);
dvander@8
   494
    }
dvander@8
   495
    return left;
dvander@8
   496
}
dvander@8
   497
dvander@8
   498
Expression *
dvander@8
   499
Parser::bitxor()
dvander@8
   500
{
dvander@28
   501
    Expression *left = bitand_();
dvander@8
   502
    while (left) {
dvander@8
   503
        if (!match(TOK_BITXOR))
dvander@8
   504
            break;
dvander@25
   505
        SourcePosition pos = scanner_.begin();
dvander@8
   506
        Expression *right = shift();
dvander@8
   507
        if (!right)
dvander@8
   508
            return NULL;
dvander@25
   509
        left = new (pool_) BinaryExpression(pos, TOK_BITXOR, left, right);
dvander@8
   510
    }
dvander@8
   511
    return left;
dvander@8
   512
}
dvander@8
   513
dvander@8
   514
Expression *
dvander@28
   515
Parser::bitor_()
dvander@8
   516
{
dvander@8
   517
    Expression *left = bitxor();
dvander@8
   518
    while (left) {
dvander@8
   519
        if (!match(TOK_BITOR))
dvander@8
   520
            break;
dvander@25
   521
        SourcePosition pos = scanner_.begin();
dvander@75
   522
        Expression *right = bitxor();
dvander@8
   523
        if (!right)
dvander@8
   524
            return NULL;
dvander@25
   525
        left = new (pool_) BinaryExpression(pos, TOK_BITOR, left, right);
dvander@8
   526
    }
dvander@8
   527
    return left;
dvander@8
   528
}
dvander@8
   529
dvander@8
   530
Expression *
dvander@0
   531
Parser::relational()
dvander@0
   532
{
dvander@28
   533
    Expression *left = bitor_();
dvander@0
   534
    while (left) {
dvander@0
   535
        TokenKind kind = scanner_.peek();
dvander@0
   536
        if (kind < TOK_LT || kind > TOK_GE)
dvander@0
   537
            break;
dvander@0
   538
        scanner_.scan();
dvander@25
   539
        SourcePosition pos = scanner_.begin();
dvander@2
   540
        Expression *right = shift();
dvander@0
   541
        if (!right)
dvander@0
   542
            return NULL;
dvander@25
   543
        left = new (pool_) BinaryExpression(pos, kind, left, right);
dvander@0
   544
    }
dvander@0
   545
    return left;
dvander@0
   546
}
dvander@0
   547
dvander@0
   548
Expression *
dvander@0
   549
Parser::equals()
dvander@0
   550
{
dvander@0
   551
    Expression *left = relational();
dvander@0
   552
    while (left) {
dvander@0
   553
        if (!match(TOK_EQUALS) && !match(TOK_NOTEQUALS))
dvander@0
   554
            break;
dvander@0
   555
        TokenKind kind = scanner_.last();
dvander@25
   556
        SourcePosition pos = scanner_.begin();
dvander@0
   557
        Expression *right = relational();
dvander@0
   558
        if (!right)
dvander@0
   559
            return NULL;
dvander@25
   560
        left = new (pool_) BinaryExpression(pos, kind, left, right);
dvander@0
   561
    }
dvander@0
   562
    return left;
dvander@0
   563
}
dvander@0
   564
dvander@0
   565
Expression *
dvander@75
   566
Parser::and_()
dvander@75
   567
{
dvander@75
   568
    Expression *left = equals();
dvander@75
   569
    while (left) {
dvander@75
   570
        if (!match(TOK_AND))
dvander@75
   571
            break;
dvander@75
   572
        SourcePosition pos = scanner_.begin();
dvander@75
   573
        Expression *right = equals();
dvander@75
   574
        if (!right)
dvander@75
   575
            return NULL;
dvander@75
   576
        left = new (pool_) BinaryExpression(pos, TOK_AND, left, right);
dvander@75
   577
    }
dvander@75
   578
    return left;
dvander@75
   579
}
dvander@75
   580
dvander@75
   581
Expression *
dvander@75
   582
Parser::or_()
dvander@75
   583
{
dvander@75
   584
    Expression *left = and_();
dvander@75
   585
    while (left) {
dvander@75
   586
        if (!match(TOK_OR))
dvander@75
   587
            break;
dvander@75
   588
        SourcePosition pos = scanner_.begin();
dvander@75
   589
        Expression *right = and_();
dvander@75
   590
        if (!right)
dvander@75
   591
            return NULL;
dvander@75
   592
        left = new (pool_) BinaryExpression(pos, TOK_OR, left, right);
dvander@75
   593
    }
dvander@75
   594
    return left;
dvander@75
   595
}
dvander@75
   596
dvander@75
   597
Expression *
dvander@83
   598
Parser::ternary()
dvander@83
   599
{
dvander@83
   600
    Expression *cond = or_();
dvander@83
   601
    if (!cond)
dvander@83
   602
        return NULL;
dvander@83
   603
    
dvander@83
   604
    if (!match(TOK_QMARK))
dvander@83
   605
        return cond;
dvander@83
   606
dvander@172
   607
    Expression *left;
dvander@83
   608
    SourcePosition pos = scanner_.begin();
dvander@172
   609
    AutoAllowTags<false> disableTags(scanner_);
dvander@172
   610
    {
dvander@172
   611
        if ((left = expression()) == NULL)
dvander@172
   612
            return NULL;
dvander@172
   613
    }
dvander@83
   614
dvander@83
   615
    if (!expect(TOK_COLON))
dvander@83
   616
        return NULL;
dvander@83
   617
dvander@83
   618
    Expression *right = expression();
dvander@83
   619
    if (!right)
dvander@83
   620
        return NULL;
dvander@83
   621
dvander@83
   622
    return new (pool_) TernaryExpression(pos, cond, left, right);
dvander@83
   623
}
dvander@83
   624
dvander@83
   625
Expression *
dvander@22
   626
Parser::assignment()
dvander@22
   627
{
dvander@83
   628
    Expression *left = ternary();
dvander@22
   629
    while (left) {
dvander@22
   630
        TokenKind token = scanner_.peek();
dvander@22
   631
        if (token != TOK_ASSIGN && (token < TOK_ASSIGN_ADD || token > TOK_ASSIGN_SHL))
dvander@22
   632
            break;
dvander@22
   633
        scanner_.scan();
dvander@25
   634
        SourcePosition pos = scanner_.begin();
dvander@83
   635
        Expression *expr = ternary();
dvander@22
   636
        if (!expr)
dvander@22
   637
            return NULL;
dvander@22
   638
dvander@25
   639
        left = new (pool_) Assignment(pos, token, left, expr);
dvander@22
   640
    }
dvander@22
   641
    return left;
dvander@22
   642
}
dvander@22
   643
dvander@22
   644
Expression *
dvander@0
   645
Parser::expression()
dvander@0
   646
{
dvander@22
   647
    return assignment();
dvander@0
   648
}
dvander@0
   649
dvander@0
   650
Statement *
dvander@9
   651
Parser::while_()
dvander@9
   652
{
dvander@251
   653
    // while ::= "while" "(" expr ")" statement
dvander@25
   654
    SourcePosition pos = scanner_.begin();
dvander@9
   655
    scanner_.scan();
dvander@9
   656
dvander@9
   657
    if (!expect(TOK_LPAREN))
dvander@9
   658
        return NULL;
dvander@25
   659
dvander@9
   660
    Expression *condition = expression();
dvander@9
   661
    if (!condition)
dvander@9
   662
        return NULL;
dvander@25
   663
dvander@9
   664
    if (!expect(TOK_RPAREN))
dvander@9
   665
        return NULL;
dvander@9
   666
dvander@48
   667
    Statement *body;
dvander@48
   668
    if (scanner_.peek() == TOK_LBRACE)
dvander@195
   669
        body = block();
dvander@48
   670
    else
dvander@48
   671
        body = localStatement();
dvander@9
   672
    if (!body)
dvander@9
   673
        return NULL;
dvander@9
   674
dvander@25
   675
    return new (pool_) WhileStatement(pos, TOK_WHILE, condition, body);
dvander@9
   676
}
dvander@9
   677
dvander@9
   678
Statement *
dvander@9
   679
Parser::do_()
dvander@9
   680
{
dvander@251
   681
    // do ::= "do" block "while" "(" expr ")"
dvander@25
   682
    SourcePosition pos = scanner_.begin();
dvander@9
   683
    scanner_.scan();
dvander@9
   684
dvander@251
   685
    Statement *body = block();
dvander@9
   686
    if (!body)
dvander@9
   687
        return NULL;
dvander@9
   688
dvander@9
   689
    if (!expect(TOK_WHILE))
dvander@9
   690
        return NULL;
dvander@9
   691
dvander@9
   692
    if (!expect(TOK_LPAREN))
dvander@9
   693
        return NULL;
dvander@9
   694
    Expression *condition = expression();
dvander@9
   695
    if (!condition)
dvander@9
   696
        return NULL;
dvander@9
   697
    if (!expect(TOK_RPAREN))
dvander@9
   698
        return NULL;
dvander@9
   699
dvander@25
   700
    return new (pool_) WhileStatement(pos, TOK_DO, condition, body);
dvander@9
   701
}
dvander@9
   702
dvander@9
   703
Statement *
dvander@172
   704
Parser::switch_()
dvander@172
   705
{
dvander@251
   706
    // switch ::= "switch" "(" expr ")" "{" case* defaultcase? "}"
dvander@251
   707
    // case ::= "case" casevals ":" statement
dvander@251
   708
    // defaultcase ::= "default" ":" statement
dvander@251
   709
    //
dvander@172
   710
    expect(TOK_SWITCH);
dvander@172
   711
dvander@172
   712
    SourcePosition pos = scanner_.begin();
dvander@172
   713
dvander@172
   714
    if (!expect(TOK_LPAREN))
dvander@172
   715
        return NULL;
dvander@172
   716
    Expression *expr = expression();
dvander@172
   717
    if (!expr)
dvander@172
   718
        return NULL;
dvander@172
   719
    if (!expect(TOK_RPAREN))
dvander@172
   720
        return NULL;
dvander@172
   721
dvander@172
   722
    if (!expect(TOK_LBRACE))
dvander@172
   723
        return NULL;
dvander@172
   724
dvander@172
   725
    SourcePosition defaultPos;
dvander@172
   726
    PoolList<Case *> *cases = new (pool_) PoolList<Case *>();
dvander@172
   727
dvander@172
   728
    Statement *defaultCase = NULL;
dvander@172
   729
dvander@172
   730
    while (!peek(TOK_RBRACE)) {
dvander@172
   731
        Expression *expr = NULL;
dvander@172
   732
        ExpressionList *others = NULL;
dvander@172
   733
        if (match(TOK_DEFAULT)) {
dvander@172
   734
            if (defaultCase) {
dvander@172
   735
                cc_.reportError(scanner_.begin(), Message_OneDefaultPerSwitch);
dvander@172
   736
                return NULL;
dvander@172
   737
            }
dvander@172
   738
dvander@172
   739
            defaultPos = scanner_.begin();
dvander@172
   740
        } else {
dvander@172
   741
            if (defaultCase) {
dvander@172
   742
                cc_.reportError(defaultPos, Message_DefaultMustBeLastCase);
dvander@172
   743
                return NULL;
dvander@172
   744
            }
dvander@172
   745
dvander@172
   746
            if (!expect(TOK_CASE))
dvander@172
   747
                return NULL;
dvander@172
   748
dvander@172
   749
            // A limitation in the grammar is that |case <NAME>:| will be
dvander@172
   750
            // detected as a label.
dvander@172
   751
            AutoAllowTags<false> disableTags(scanner_);
dvander@172
   752
dvander@172
   753
            if ((expr = expression()) == NULL)
dvander@172
   754
                return NULL;
dvander@172
   755
dvander@172
   756
            if (peek(TOK_COMMA)) {
dvander@172
   757
                others = new (pool_) ExpressionList();
dvander@172
   758
                while (match(TOK_COMMA)) {
dvander@172
   759
                    Expression *other = expression();
dvander@172
   760
                    if (!other)
dvander@172
   761
                        return NULL;
dvander@172
   762
                    if (!others->append(other))
dvander@172
   763
                        return NULL;
dvander@172
   764
                }
dvander@172
   765
            }
dvander@172
   766
        }
dvander@172
   767
dvander@172
   768
        if (!expect(TOK_COLON))
dvander@172
   769
            return NULL;
dvander@172
   770
dvander@172
   771
        Statement *statement = localStatement();
dvander@172
   772
        if (!statement)
dvander@172
   773
            return NULL;
dvander@172
   774
dvander@172
   775
        if (!peek(TOK_CASE) &&
dvander@172
   776
            !peek(TOK_DEFAULT) &&
dvander@172
   777
            !peek(TOK_RBRACE))
dvander@172
   778
        {
dvander@172
   779
            cc_.reportError(scanner_.begin(), Message_SingleStatementPerCase);
dvander@172
   780
            return NULL;
dvander@172
   781
        }
dvander@172
   782
dvander@172
   783
        if (expr) {
dvander@172
   784
            Case *caze = new (pool_) Case(expr, others, statement);
dvander@172
   785
            if (!cases->append(caze))
dvander@172
   786
                return NULL;
dvander@172
   787
        } else {
dvander@172
   788
            defaultCase = statement;
dvander@172
   789
        }
dvander@172
   790
    }
dvander@172
   791
dvander@172
   792
    if (!expect(TOK_RBRACE))
dvander@172
   793
        return NULL;
dvander@172
   794
dvander@172
   795
    return new (pool_) SwitchStatement(pos, expr, cases, defaultCase);
dvander@172
   796
}
dvander@172
   797
dvander@172
   798
Statement *
dvander@0
   799
Parser::forStatement()
dvander@0
   800
{
dvander@251
   801
    // for ::= "for" "(" forinit? ";" forcond? ";" forstep ")" statement
dvander@251
   802
    // forint ::= "new" vardecl |
dvander@251
   803
    //            exprstmt
dvander@251
   804
    // forcond ::= expr
dvander@251
   805
    // forstep ::= exprstmt
dvander@251
   806
    //
dvander@25
   807
    SourcePosition pos = scanner_.begin();
dvander@0
   808
    scanner_.scan();
dvander@0
   809
    if (!expect(TOK_LPAREN))
dvander@0
   810
        return NULL;
dvander@0
   811
dvander@22
   812
    Statement *decl = NULL;
dvander@0
   813
    if (!match(TOK_SEMICOLON)) {
dvander@135
   814
        if (match(TOK_NEW)) {
dvander@238
   815
            if ((decl = vars(TypeQual_None)) == NULL)
dvander@22
   816
                return NULL;
dvander@22
   817
        } else {
dvander@22
   818
            if ((decl = expressionStatement()) == NULL)
dvander@22
   819
                return NULL;
dvander@22
   820
        }
dvander@0
   821
        if (!expect(TOK_SEMICOLON))
dvander@0
   822
            return NULL;
dvander@0
   823
    }
dvander@0
   824
dvander@0
   825
    Expression *condition = NULL;
dvander@0
   826
    if (!match(TOK_SEMICOLON)) {
dvander@0
   827
        if ((condition = expression()) == NULL)
dvander@0
   828
            return NULL;
dvander@0
   829
        if (!expect(TOK_SEMICOLON))
dvander@0
   830
            return NULL;
dvander@0
   831
    }
dvander@0
   832
dvander@0
   833
    Statement *update = NULL;
dvander@0
   834
    if (!match(TOK_RPAREN)) {
dvander@0
   835
        if ((update = expressionStatement()) == NULL)
dvander@0
   836
            return NULL;
dvander@0
   837
        if (!expect(TOK_RPAREN))
dvander@0
   838
            return NULL;
dvander@0
   839
    }
dvander@0
   840
dvander@48
   841
    Statement *body;
dvander@48
   842
    if (scanner_.peek() == TOK_LBRACE)
dvander@195
   843
        body = block();
dvander@48
   844
    else
dvander@48
   845
        body = localStatement();
dvander@0
   846
    if (!body)
dvander@0
   847
        return NULL;
dvander@0
   848
dvander@195
   849
    return new (pool_) ForStatement(pos, decl, condition, update, body);
dvander@0
   850
}
dvander@0
   851
dvander@145
   852
ExpressionList *
dvander@145
   853
Parser::dimensions()
dvander@145
   854
{
dvander@251
   855
    // dimensions ::= ("[" expr? "]")*
dvander@251
   856
dvander@145
   857
    ExpressionList *postDimensions = new (pool_) ExpressionList();
dvander@145
   858
    while (match(TOK_LBRACKET)) {
dvander@145
   859
        Expression *dim = NULL;
dvander@145
   860
        if (!match(TOK_RBRACKET)) {
dvander@145
   861
            if ((dim = expression()) == NULL)
dvander@145
   862
                return NULL;
dvander@145
   863
            if (!expect(TOK_RBRACKET))
dvander@145
   864
                return NULL;
dvander@145
   865
        }
dvander@145
   866
dvander@145
   867
        if (!postDimensions->append(dim))
dvander@145
   868
            return NULL;
dvander@145
   869
    }
dvander@145
   870
    return postDimensions;
dvander@145
   871
}
dvander@145
   872
dvander@0
   873
VariableDeclaration *
dvander@195
   874
Parser::var(TypeQualifiers qual)
dvander@0
   875
{
dvander@251
   876
    // vardecl ::= decl ("=" expr)?
dvander@251
   877
dvander@195
   878
    Expression *type;
dvander@195
   879
    Local<String> name(zone_);
dvander@251
   880
dvander@195
   881
    if (!typeAndName(&type, name.ref()))
dvander@4
   882
        return NULL;
dvander@0
   883
dvander@209
   884
    ExpressionList *dims = NULL;
dvander@212
   885
    if (peek(TOK_LBRACKET)) {
dvander@209
   886
        if ((dims = dimensions()) == NULL)
dvander@209
   887
            return NULL;;
dvander@209
   888
    }
dvander@209
   889
dvander@189
   890
    SourcePosition pos = scanner_.begin();
dvander@0
   891
    
dvander@0
   892
    Expression *expr = NULL;
dvander@0
   893
    if (match(TOK_ASSIGN)) {
dvander@187
   894
        switch (scanner_.peek()) {
dvander@187
   895
          // Note: we don't support [] literals yet.
dvander@187
   896
          case TOK_LBRACE:
dvander@212
   897
            scanner_.scan();
dvander@212
   898
            if ((expr = fixedArrayLiteral()) == NULL)
dvander@187
   899
                return NULL;
dvander@187
   900
            break;
dvander@187
   901
dvander@187
   902
          default:
dvander@187
   903
            if ((expr = expression()) == NULL)
dvander@187
   904
                return NULL;
dvander@187
   905
            break;
dvander@187
   906
        }
dvander@0
   907
    }
dvander@0
   908
dvander@209
   909
    return new (pool_) VariableDeclaration(pos, qual, name, type, dims, expr);
dvander@0
   910
}
dvander@0
   911
dvander@0
   912
Statement *
dvander@195
   913
Parser::vars(TypeQualifiers qual)
dvander@165
   914
{
dvander@251
   915
    // localvars ::= ("new" | "const" | "decl") vardecl ("," vardecl)*
dvander@251
   916
    // globalvars ::= ("public" | "const" | "new" | "public" "const") vardecl
dvander@195
   917
    VariableDeclaration *decl = var(qual);
dvander@165
   918
    if (!decl)
dvander@165
   919
        return NULL;
dvander@165
   920
dvander@165
   921
    if (!peek(TOK_COMMA))
dvander@165
   922
        return decl;
dvander@165
   923
dvander@165
   924
    StatementList *statements = new (pool_) StatementList();
dvander@165
   925
    if (!statements->append(decl))
dvander@165
   926
        return NULL;
dvander@165
   927
dvander@165
   928
    while (match(TOK_COMMA)) {
dvander@195
   929
        Statement *decl = var(qual);
dvander@165
   930
        if (!decl)
dvander@165
   931
            return NULL;
dvander@165
   932
        if (!statements->append(decl))
dvander@165
   933
            return NULL;
dvander@165
   934
    }
dvander@165
   935
dvander@165
   936
    // Create a fake-o block with no scope to create a statement list.
dvander@247
   937
    return new (pool_) BlockStatement(decl->pos(), statements, TOK_NEW);
dvander@165
   938
}
dvander@165
   939
dvander@165
   940
Statement *
dvander@0
   941
Parser::returnStatement()
dvander@0
   942
{
dvander@251
   943
    // return ::= "return" term |
dvander@251
   944
    //            "return" "expr"
dvander@251
   945
dvander@25
   946
    SourcePosition pos = scanner_.begin();
dvander@0
   947
    if (!expect(TOK_RETURN))
dvander@0
   948
        return NULL;
dvander@0
   949
dvander@72
   950
    Expression *expr = NULL;
dvander@72
   951
    if (scanner_.peek() != TOK_SEMICOLON) {
dvander@72
   952
        if ((expr = expression()) == NULL)
dvander@72
   953
            return NULL;
dvander@0
   954
dvander@72
   955
        // We only care about non-void returns when determining whether a
dvander@72
   956
        // tagless function is non-void.
dvander@72
   957
        encounteredReturn_ = true;
dvander@72
   958
    }
dvander@71
   959
dvander@25
   960
    return new (pool_) ReturnStatement(pos, expr);
dvander@0
   961
}
dvander@0
   962
dvander@0
   963
Statement *
dvander@0
   964
Parser::expressionStatement()
dvander@0
   965
{
dvander@251
   966
    // exprstmt ::= expr
dvander@22
   967
    Expression *left = assignment();
dvander@21
   968
    if (!left)
dvander@0
   969
        return NULL;
dvander@0
   970
dvander@0
   971
    return new (pool_) ExpressionStatement(left);
dvander@0
   972
}
dvander@0
   973
dvander@0
   974
Statement *
dvander@195
   975
Parser::block()
dvander@0
   976
{
dvander@251
   977
    // block ::= "{" statement* "}"
dvander@251
   978
dvander@0
   979
    if (!expect(TOK_LBRACE))
dvander@0
   980
        return NULL;
dvander@0
   981
dvander@25
   982
    SourcePosition pos = scanner_.begin();
dvander@0
   983
dvander@0
   984
    StatementList *statements = new (pool_) StatementList();
dvander@0
   985
    while (!match(TOK_RBRACE)) {
dvander@0
   986
        Statement *statement = localStatement();
dvander@0
   987
        if (statement == NULL)
dvander@0
   988
            return NULL;
dvander@56
   989
        if (!statements->append(statement))
dvander@56
   990
            return NULL;
dvander@0
   991
    }
dvander@0
   992
dvander@247
   993
    BlockStatement *block = new (pool_) BlockStatement(pos, statements, TOK_LBRACE);
dvander@0
   994
    return block;
dvander@0
   995
}
dvander@0
   996
dvander@0
   997
Statement *
dvander@0
   998
Parser::if_()
dvander@0
   999
{
dvander@251
  1000
    // if ::= "if" "(" expr ")" statement elseif* else?
dvander@251
  1001
    // elseif ::= "elseif" "(" expr ")" statement
dvander@251
  1002
    // else ::= "else" statement
dvander@0
  1003
    expect(TOK_IF);
dvander@251
  1004
  
dvander@25
  1005
    SourcePosition pos = scanner_.begin();
dvander@0
  1006
    if (!expect(TOK_LPAREN))
dvander@0
  1007
        return NULL;
dvander@0
  1008
dvander@0
  1009
    Expression *cond = expression();
dvander@0
  1010
    if (!cond)
dvander@0
  1011
        return NULL;
dvander@0
  1012
dvander@0
  1013
    if (!expect(TOK_RPAREN))
dvander@0
  1014
        return NULL;
dvander@0
  1015
dvander@0
  1016
    Statement *ifTrue = localStatement();
dvander@0
  1017
    if (!ifTrue)
dvander@0
  1018
        return NULL;
dvander@0
  1019
dvander@25
  1020
    IfStatement *outer = new (pool_) IfStatement(pos, cond, ifTrue);
dvander@0
  1021
dvander@0
  1022
    IfStatement *last = outer;
dvander@0
  1023
    while (match(TOK_ELSE)) {
dvander@0
  1024
        if (!match(TOK_IF)) {
dvander@0
  1025
            Statement *ifFalse = localStatement();
dvander@0
  1026
            if (!ifFalse)
dvander@0
  1027
                return NULL;
dvander@0
  1028
dvander@0
  1029
            last->setIfFalse(ifFalse);
dvander@0
  1030
            break;
dvander@0
  1031
        }
dvander@0
  1032
dvander@25
  1033
        SourcePosition pos = scanner_.begin();
dvander@0
  1034
        if (!expect(TOK_LPAREN))
dvander@0
  1035
            return NULL;
dvander@0
  1036
dvander@0
  1037
        Expression *otherCond = expression();
dvander@0
  1038
        if (!otherCond)
dvander@0
  1039
            return NULL;
dvander@0
  1040
dvander@0
  1041
        if (!expect(TOK_RPAREN))
dvander@0
  1042
            return NULL;
dvander@0
  1043
dvander@0
  1044
        Statement *otherIfTrue = localStatement();
dvander@0
  1045
        if (!otherIfTrue)
dvander@0
  1046
            return NULL;
dvander@0
  1047
dvander@25
  1048
        IfStatement *inner = new (pool_) IfStatement(pos, otherCond, otherIfTrue);
dvander@0
  1049
        last->setIfFalse(inner);
dvander@0
  1050
        last = inner;
dvander@0
  1051
    }
dvander@0
  1052
dvander@0
  1053
    return outer;
dvander@0
  1054
}
dvander@0
  1055
dvander@0
  1056
Statement *
dvander@0
  1057
Parser::localStatement()
dvander@0
  1058
{
dvander@251
  1059
    // statement ::= stmt term
dvander@251
  1060
    // stmt ::= do | for | if | while | struct | enum |
dvander@251
  1061
    //          localvars | return | switch | break | continue
dvander@251
  1062
dvander@0
  1063
    Statement *statement = NULL;
dvander@0
  1064
dvander@0
  1065
    // Statements which must be followed by a semicolon will break out of the
dvander@0
  1066
    // switch. If they may end in BlockStatements, they'll immediately return.
dvander@0
  1067
dvander@135
  1068
    TokenKind kind = scanner_.peek();
dvander@135
  1069
    switch (kind) {
dvander@135
  1070
      case TOK_CONST:
dvander@131
  1071
      case TOK_NEW:
dvander@195
  1072
      {
dvander@195
  1073
        TypeQualifiers quals = (kind == TOK_CONST)
dvander@241
  1074
                              ? TypeQual_Const
dvander@238
  1075
                              : TypeQual_None;
dvander@135
  1076
        scanner_.scan();
dvander@195
  1077
        if ((statement = vars(quals)) == NULL)
dvander@172
  1078
          return NULL;
dvander@131
  1079
        break;
dvander@195
  1080
      }
dvander@0
  1081
dvander@131
  1082
      case TOK_FOR:
dvander@131
  1083
        return forStatement();
dvander@0
  1084
dvander@131
  1085
      case TOK_WHILE:
dvander@131
  1086
        return while_();
dvander@9
  1087
dvander@131
  1088
      case TOK_BREAK:
dvander@131
  1089
        scanner_.scan();
dvander@131
  1090
        statement = new (pool_) BreakStatement(scanner_.begin());
dvander@131
  1091
        break;
dvander@10
  1092
dvander@131
  1093
      case TOK_CONTINUE:
dvander@131
  1094
        scanner_.scan();
dvander@131
  1095
        statement = new (pool_) ContinueStatement(scanner_.begin());
dvander@131
  1096
        break;
dvander@10
  1097
dvander@131
  1098
      case TOK_DO:
dvander@131
  1099
        if ((statement = do_()) == NULL)
dvander@131
  1100
            return NULL;
dvander@131
  1101
        break;
dvander@9
  1102
dvander@131
  1103
      case TOK_RETURN:
dvander@131
  1104
        if ((statement = returnStatement()) == NULL)
dvander@172
  1105
          return NULL;
dvander@131
  1106
        break;
dvander@0
  1107
dvander@131
  1108
      case TOK_ENUM:
dvander@261
  1109
        if ((statement = enum_(TOK_NONE)) == NULL)
dvander@172
  1110
          return NULL;
dvander@131
  1111
        break;
dvander@2
  1112
dvander@146
  1113
      case TOK_STRUCT:
dvander@146
  1114
        if ((statement = struct_()) == NULL)
dvander@172
  1115
          return NULL;
dvander@146
  1116
        break;
dvander@146
  1117
dvander@172
  1118
      case TOK_SWITCH:
dvander@172
  1119
        return switch_();
dvander@172
  1120
dvander@131
  1121
      case TOK_IF:
dvander@131
  1122
        return if_();
dvander@0
  1123
dvander@131
  1124
      case TOK_LBRACE:
dvander@131
  1125
        return block();
dvander@28
  1126
dvander@131
  1127
      default:
dvander@131
  1128
        break;
dvander@0
  1129
    }
dvander@0
  1130
dvander@0
  1131
    if (!statement) {
dvander@0
  1132
        if ((statement = expressionStatement()) == NULL)
dvander@0
  1133
            return NULL;
dvander@0
  1134
    }
dvander@0
  1135
dvander@0
  1136
    if (!expect(TOK_SEMICOLON))
dvander@0
  1137
        return NULL;
dvander@0
  1138
dvander@0
  1139
    return statement;
dvander@0
  1140
}
dvander@0
  1141
dvander@0
  1142
Statement *
dvander@146
  1143
Parser::struct_()
dvander@146
  1144
{
dvander@251
  1145
    // struct ::= "struct" name { struct_fields }
dvander@251
  1146
    // struct_fields ::= struct_field |
dvander@251
  1147
    //                   struct_field struct_fields
dvander@251
  1148
    // struct_field ::= label? name term
dvander@146
  1149
    expect(TOK_STRUCT);
dvander@146
  1150
dvander@146
  1151
    Local<String> name(zone_, expectName());
dvander@146
  1152
    if (!name)
dvander@146
  1153
        return NULL;
dvander@146
  1154
dvander@146
  1155
    SourcePosition pos = scanner_.begin();
dvander@146
  1156
dvander@146
  1157
    if (!expect(TOK_LBRACE))
dvander@146
  1158
        return NULL;
dvander@146
  1159
dvander@146
  1160
    FieldList *fields = new (pool_) FieldList();
dvander@146
  1161
dvander@146
  1162
    while (!peek(TOK_RBRACE)) {
dvander@195
  1163
        Expression *type;
dvander@195
  1164
        Local<String> fieldName(zone_);
dvander@146
  1165
dvander@195
  1166
        if (!fullTypeAndName(&type, fieldName.ref(), DeclField))
dvander@146
  1167
            return NULL;
dvander@146
  1168
dvander@146
  1169
        SourcePosition pos = scanner_.begin();
dvander@146
  1170
dvander@146
  1171
        if (!matchSemicolon())
dvander@146
  1172
            return NULL;
dvander@146
  1173
dvander@146
  1174
        StructureStatement::Field *field =
dvander@195
  1175
            new (pool_) StructureStatement::Field(pos, type, fieldName);
dvander@146
  1176
        if (!field || !fields->append(field))
dvander@146
  1177
            return NULL;
dvander@146
  1178
    }
dvander@146
  1179
dvander@146
  1180
    if (!expect(TOK_RBRACE))
dvander@146
  1181
        return NULL;
dvander@146
  1182
mibusby@180
  1183
    if (fields->empty()) {
mibusby@180
  1184
        cc_.reportError(pos, Message_StructCantBeEmpty);
mibusby@180
  1185
        return NULL;
mibusby@180
  1186
    }
mibusby@180
  1187
dvander@195
  1188
    return new (pool_) StructureStatement(pos, name, fields);
dvander@146
  1189
}
dvander@146
  1190
dvander@146
  1191
Statement *
dvander@261
  1192
Parser::enum_(TokenKind kind)
dvander@2
  1193
{
dvander@251
  1194
    // enum ::= "enum" name? { enum_members? }
dvander@251
  1195
    // enum_members ::= enum_member ","? |
dvander@251
  1196
    //                  enum_member "," enum_members
dvander@251
  1197
    // enum_member ::= ident ("=" constexpr)?
dvander@2
  1198
    expect(TOK_ENUM);
dvander@2
  1199
dvander@25
  1200
    SourcePosition pos = scanner_.begin();
dvander@25
  1201
dvander@54
  1202
    Local<String> name(zone_);
dvander@195
  1203
    if (matchName(name.ref()) && !name)
dvander@195
  1204
        return NULL;
dvander@2
  1205
dvander@57
  1206
    EnumStatement::EntryList *entries = new (pool_) EnumStatement::EntryList();
dvander@2
  1207
dvander@2
  1208
    if (!expect(TOK_LBRACE))
dvander@2
  1209
        return NULL;
dvander@2
  1210
dvander@2
  1211
    do {
dvander@2
  1212
        if (scanner_.peek() == TOK_RBRACE)
dvander@2
  1213
            break;
dvander@2
  1214
dvander@243
  1215
        SourcePosition pos = scanner_.begin();
dvander@54
  1216
        Local<String> name(zone_, expectName());
dvander@2
  1217
        if (!name)
dvander@2
  1218
            return NULL;
dvander@2
  1219
dvander@2
  1220
        Expression *expr = NULL;
dvander@2
  1221
        if (match(TOK_ASSIGN)) {
dvander@2
  1222
            if ((expr = expression()) == NULL)
dvander@2
  1223
                return NULL;
dvander@2
  1224
        }
dvander@2
  1225
dvander@233
  1226
        if (!entries->append(EnumStatement::Entry(name, expr, pos)))
dvander@57
  1227
            return NULL;
dvander@2
  1228
    } while (match(TOK_COMMA));
dvander@2
  1229
    if (!expect(TOK_RBRACE))
dvander@2
  1230
        return NULL;
dvander@2
  1231
dvander@261
  1232
    return new (pool_) EnumStatement(pos, kind, name, entries);
dvander@195
  1233
}
dvander@195
  1234
dvander@195
  1235
template <class T>
dvander@195
  1236
static inline ScopedRoot<T> *
dvander@195
  1237
NewScopedRoot(PoolAllocator &pool, Handle<T> obj)
dvander@195
  1238
{
dvander@256
  1239
    return new (pool) ScopedRoot<T>(obj);
dvander@195
  1240
}
dvander@195
  1241
dvander@195
  1242
ImportStatement *
dvander@258
  1243
Parser::import(TokenKind kind)
dvander@195
  1244
{
dvander@195
  1245
    SourcePosition pos = scanner_.begin();
dvander@195
  1246
dvander@258
  1247
    // import       ::= "from" import_path "import" import_names
dvander@258
  1248
    //                | "import" import_path
dvander@258
  1249
    //                | "import" import_path ".*"
dvander@258
  1250
    // import_path  ::= name
dvander@258
  1251
    //                | name "." import_path
dvander@258
  1252
    // import_names ::= "*"
dvander@258
  1253
    //                | import_name_list
dvander@258
  1254
    // import_name_list ::= name
dvander@258
  1255
    //                    | name "," import_name_list
dvander@251
  1256
dvander@195
  1257
    Local<String> name(zone_, expectName());
dvander@251
  1258
    if (!name)
dvander@195
  1259
        return NULL;
dvander@195
  1260
dvander@251
  1261
    PathComponent *root = new (pool_) PathComponent(NewScopedRoot<String>(pool_, name), NULL);
dvander@251
  1262
    PathComponent *current = root;
dvander@251
  1263
dvander@258
  1264
    // NULL namelist means that we do not import any names. An empty namelist
dvander@258
  1265
    // means we import all names.
dvander@258
  1266
    NameList *names = NULL;
dvander@258
  1267
dvander@195
  1268
    while (match(TOK_DOT)) {
dvander@258
  1269
        if (kind == TOK_IMPORT && match(TOK_STAR)) {
dvander@258
  1270
            names = new (pool_) NameList();
dvander@258
  1271
            break;
dvander@258
  1272
        }
dvander@258
  1273
dvander@195
  1274
        if ((name = expectName()) == NULL)
dvander@195
  1275
            return NULL;
dvander@195
  1276
dvander@251
  1277
        current->next = new (pool_) PathComponent(NewScopedRoot<String>(pool_, name), NULL);
dvander@251
  1278
        current = current->next;
dvander@195
  1279
    }
dvander@195
  1280
dvander@258
  1281
    if (kind == TOK_FROM) {
dvander@258
  1282
        if (!expect(TOK_IMPORT))
dvander@258
  1283
            return NULL;
dvander@258
  1284
dvander@258
  1285
        names = new (pool_) NameList();
dvander@258
  1286
dvander@258
  1287
        if (!match(TOK_STAR)) {
dvander@258
  1288
            if (!matchName(name.address())) {
dvander@258
  1289
                cc_.reportError(scanner_.begin(), Message_BadImportFrom);
dvander@258
  1290
                return NULL;
dvander@258
  1291
            }
dvander@258
  1292
dvander@258
  1293
            if (!name || !names->append(NewScopedRoot<String>(pool_, name)))
dvander@258
  1294
                return NULL;
dvander@258
  1295
dvander@258
  1296
            while (match(TOK_COMMA)) {
dvander@258
  1297
                if ((name = expectName()) == NULL)
dvander@258
  1298
                    return NULL;
dvander@258
  1299
                if (!names->append(NewScopedRoot<String>(pool_, name)))
dvander@258
  1300
                    return NULL;
dvander@258
  1301
            }
dvander@258
  1302
        }
dvander@258
  1303
    }
dvander@258
  1304
dvander@258
  1305
    return new (pool_) ImportStatement(pos, root, names);
dvander@2
  1306
}
dvander@2
  1307
dvander@2
  1308
Statement *
dvander@63
  1309
Parser::function(TokenKind token)
dvander@0
  1310
{
dvander@195
  1311
    Expression *returnType;
dvander@191
  1312
    Local<String> name(zone_);
dvander@191
  1313
dvander@195
  1314
    if (!fullTypeAndName(&returnType, name.ref(), DeclFun))
dvander@195
  1315
        return NULL;
dvander@132
  1316
dvander@25
  1317
    SourcePosition pos = scanner_.begin();
dvander@57
  1318
    ParameterList *parameters = new (pool_) ParameterList();
dvander@14
  1319
dvander@0
  1320
    if (!expect(TOK_LPAREN))
dvander@0
  1321
        return NULL;
dvander@133
  1322
dvander@195
  1323
    bool variadic = false;
dvander@195
  1324
dvander@0
  1325
    if (!match(TOK_RPAREN)) {
dvander@0
  1326
        while (true) {
dvander@241
  1327
            TypeQualifiers quals = TypeQual_None;
dvander@241
  1328
            if (match(TOK_CONST))
dvander@241
  1329
                quals = TypeQualifiers(quals | TypeQual_Const);
dvander@241
  1330
dvander@14
  1331
            bool ref = match(TOK_AMPERSAND);
dvander@14
  1332
dvander@66
  1333
            SourcePosition begin = scanner_.begin();
dvander@195
  1334
            Expression *type;
dvander@195
  1335
            Local<String> name(zone_);
dvander@195
  1336
            if (!fullTypeAndName(&type, name.ref(), DeclArg))
dvander@66
  1337
                return NULL;
dvander@66
  1338
dvander@195
  1339
            if (!name) {
dvander@241
  1340
                if ((quals & TypeQual_Const) || ref) {
dvander@68
  1341
                    cc_.reportError(begin, Message_InvalidVarArgs);
dvander@68
  1342
                    return NULL;
dvander@68
  1343
                }
dvander@68
  1344
dvander@68
  1345
                if (token != TOK_NATIVE) {
dvander@68
  1346
                    cc_.reportError(begin, Message_VarArgsOutsideNative);
dvander@68
  1347
                    return NULL;
dvander@68
  1348
                }
dvander@68
  1349
dvander@195
  1350
                variadic = true;
dvander@68
  1351
                break;
dvander@68
  1352
            }
dvander@68
  1353
dvander@220
  1354
            ExpressionList *dims = NULL;
dvander@220
  1355
            if (peek(TOK_LBRACKET)) {
dvander@220
  1356
                if ((dims = dimensions()) == NULL)
dvander@220
  1357
                    return NULL;
dvander@220
  1358
            }
dvander@220
  1359
dvander@133
  1360
            Expression *expr = NULL;
dvander@133
  1361
            if (match(TOK_ASSIGN)) {
dvander@133
  1362
                if ((expr = expression()) == NULL)
dvander@133
  1363
                    return NULL;
dvander@133
  1364
            }
dvander@133
  1365
dvander@241
  1366
            Parameter *parameter = new (pool_) Parameter(name, type, ref, quals, dims, expr, begin);
dvander@57
  1367
            if (!parameters->append(parameter))
dvander@57
  1368
                return NULL;
dvander@14
  1369
dvander@0
  1370
            if (!match(TOK_COMMA))
dvander@0
  1371
                break;
dvander@0
  1372
        }
dvander@0
  1373
        if (!expect(TOK_RPAREN))
dvander@0
  1374
            return NULL;
dvander@0
  1375
    }
dvander@0
  1376
dvander@71
  1377
    encounteredReturn_ = false;
dvander@71
  1378
dvander@63
  1379
    Statement *body = NULL;
dvander@174
  1380
    if (token != TOK_FORWARD && token != TOK_NATIVE && token != TOK_TYPEDEF) {
dvander@63
  1381
        body = block();
dvander@63
  1382
        if (!body)
dvander@63
  1383
            return NULL;
dvander@63
  1384
    }
dvander@0
  1385
dvander@195
  1386
    FunctionSignature signature(returnType, parameters, variadic);
dvander@174
  1387
    if (token == TOK_TYPEDEF)
dvander@195
  1388
        return new (pool_) FunctionTypeStatement(pos, name, signature);
dvander@174
  1389
dvander@195
  1390
    return new (pool_) FunctionStatement(pos, name, token, body, signature, encounteredReturn_);
dvander@0
  1391
}
dvander@0
  1392
dvander@145
  1393
static inline bool
dvander@167
  1394
DeclareIntrinsicType(Zone *zone, Scope *scope, const char *name, Handle<Type> type)
dvander@145
  1395
{
dvander@145
  1396
    Local<String> tag(zone, zone->makeSymbol(name));
dvander@145
  1397
    if (!tag)
dvander@145
  1398
        return false;
dvander@145
  1399
dvander@195
  1400
    assert(false);
dvander@195
  1401
    return false; //return !!scope->declareType(tag, type);
dvander@167
  1402
}
dvander@167
  1403
dvander@167
  1404
static inline bool
dvander@167
  1405
DeclareIntrinsicType(Zone *zone, Scope *scope, const char *name, PrimitiveType type)
dvander@167
  1406
{
dvander@145
  1407
    Local<Type> primitive(zone, zone->types()->getPrimitive(type));
dvander@145
  1408
    assert(primitive);
dvander@167
  1409
    return DeclareIntrinsicType(zone, scope, name, primitive);
dvander@145
  1410
}
dvander@145
  1411
dvander@0
  1412
ParseTree *
dvander@0
  1413
Parser::parse()
dvander@0
  1414
{
dvander@0
  1415
    StatementList *statements = new (pool_) StatementList();
dvander@0
  1416
dvander@0
  1417
    for (;;) {
dvander@0
  1418
        Statement *statement = NULL;
dvander@0
  1419
dvander@135
  1420
        TokenKind kind = scanner_.peek();
dvander@135
  1421
        switch (kind) {
dvander@0
  1422
          case TOK_ERROR:
dvander@0
  1423
            return NULL;
dvander@0
  1424
dvander@0
  1425
          case TOK_EOF:
dvander@0
  1426
            break;
dvander@0
  1427
dvander@0
  1428
          case TOK_NAME:
dvander@63
  1429
            if ((statement = function(TOK_NAME)) == NULL)
dvander@0
  1430
                return NULL;
dvander@0
  1431
            break;
dvander@0
  1432
dvander@258
  1433
          case TOK_FROM:
dvander@195
  1434
          case TOK_IMPORT:
dvander@195
  1435
          {
dvander@195
  1436
            scanner_.scan();
dvander@195
  1437
            if (statements->length())
dvander@195
  1438
                cc_.reportError(scanner_.begin(), Message_ImportsMustBeFirst);
dvander@258
  1439
            ImportStatement *stmt = import(kind);
dvander@195
  1440
            if (!stmt)
dvander@195
  1441
                return NULL;
dvander@195
  1442
            if (!imports_->append(stmt))
dvander@195
  1443
                return NULL;
dvander@195
  1444
            if (!matchSemicolon())
dvander@195
  1445
                return NULL;
dvander@195
  1446
            continue;
dvander@195
  1447
          }
dvander@195
  1448
dvander@63
  1449
          case TOK_FORWARD:
dvander@63
  1450
          case TOK_PUBLIC:
dvander@68
  1451
          case TOK_NATIVE:
dvander@134
  1452
          case TOK_STOCK:
dvander@145
  1453
          case TOK_LABEL:
dvander@174
  1454
          case TOK_TYPEDEF:
dvander@63
  1455
          {
dvander@195
  1456
            if (kind != TOK_LABEL)
dvander@195
  1457
                scanner_.scan();
dvander@170
  1458
            if (kind == TOK_PUBLIC && peek(TOK_CONST)) {
dvander@241
  1459
                if ((statement = var(TypeQual_Const)) == NULL)
dvander@170
  1460
                    return NULL;
dvander@170
  1461
                if (!matchSemicolon())
dvander@170
  1462
                    return NULL;
dvander@261
  1463
            } else if (kind == TOK_PUBLIC && peek(TOK_ENUM)) {
dvander@261
  1464
                if ((statement = enum_(kind)) == NULL)
dvander@261
  1465
                    return NULL;
dvander@261
  1466
                if (!matchSemicolon())
dvander@261
  1467
                    return NULL;
dvander@170
  1468
            } else {
dvander@170
  1469
                if ((statement = function(kind)) == NULL)
dvander@170
  1470
                    return NULL;
dvander@174
  1471
                if ((kind == TOK_FORWARD || kind == TOK_NATIVE || kind == TOK_TYPEDEF) && !matchSemicolon())
dvander@170
  1472
                    return NULL;
dvander@170
  1473
            }
dvander@63
  1474
            break;
dvander@63
  1475
          }
dvander@63
  1476
dvander@135
  1477
          case TOK_CONST:
dvander@85
  1478
          case TOK_NEW:
dvander@85
  1479
          {
dvander@241
  1480
            TypeQualifiers quals = (kind == TOK_CONST) ? TypeQual_Const : TypeQual_None;
dvander@165
  1481
            // Note: at global scope, we don't accept comma-delimited
dvander@165
  1482
            // declarations yet, to see if we can get away with forcing
dvander@165
  1483
            // a nicer top-level style.
dvander@135
  1484
            scanner_.scan();
dvander@195
  1485
            if ((statement = var(quals)) == NULL)
dvander@170
  1486
                return NULL;
dvander@85
  1487
            if (!matchSemicolon())
dvander@85
  1488
                return NULL;
dvander@85
  1489
            break;
dvander@85
  1490
          }
dvander@74
  1491
dvander@2
  1492
          case TOK_ENUM:
dvander@261
  1493
            if ((statement = enum_(TOK_NONE)) == NULL)
dvander@2
  1494
                return NULL;
dvander@63
  1495
            if (!matchSemicolon())
dvander@63
  1496
                return NULL;
dvander@2
  1497
            break;
dvander@2
  1498
dvander@146
  1499
          case TOK_STRUCT:
dvander@146
  1500
            if ((statement = struct_()) == NULL)
dvander@146
  1501
                return NULL;
dvander@146
  1502
            if (!matchSemicolon())
dvander@146
  1503
                return NULL;
dvander@146
  1504
            break;
dvander@146
  1505
dvander@0
  1506
          default:
dvander@63
  1507
            cc_.reportError(scanner_.begin(), Message_ExpectedGlobal);
dvander@0
  1508
            return NULL;
dvander@0
  1509
        }
dvander@0
  1510
dvander@0
  1511
        if (!statement)
dvander@0
  1512
            break;
dvander@0
  1513
dvander@56
  1514
        if (!statements->append(statement))
dvander@56
  1515
            return NULL;
dvander@0
  1516
    }
dvander@0
  1517
dvander@195
  1518
    return new (pool_) ParseTree(statements, unbound_, imports_);
dvander@0
  1519
}
dvander@0
  1520
dvander@0
  1521
class AstPrinter : public AstVisitor
dvander@0
  1522
{
dvander@0
  1523
    FILE *fp_;
dvander@0
  1524
    size_t level_;
dvander@0
  1525
dvander@0
  1526
  private:
dvander@0
  1527
    void prefix() {
dvander@0
  1528
        for (size_t i = 0; i < level_; i++)
dvander@0
  1529
            fprintf(fp_, "  ");
dvander@0
  1530
    }
dvander@0
  1531
    void indent() {
dvander@0
  1532
        level_++;
dvander@0
  1533
    }
dvander@0
  1534
    void unindent() {
dvander@0
  1535
        level_--;
dvander@0
  1536
    }
dvander@0
  1537
dvander@0
  1538
  public:
dvander@0
  1539
    AstPrinter(FILE *fp)
dvander@0
  1540
      : fp_(fp),
dvander@0
  1541
        level_(0)
dvander@0
  1542
    {
dvander@0
  1543
    }
dvander@0
  1544
dvander@191
  1545
    void dump(const FunctionSignature &sig) {
dvander@191
  1546
        prefix();
dvander@191
  1547
        fprintf(fp_, "()\n");
dvander@191
  1548
    }
dvander@195
  1549
    void visitNameProxy(NameProxy *name) {
dvander@0
  1550
        prefix();
dvander@195
  1551
        fprintf(fp_, "[ NameProxy (%s)\n", name->name()->chars());
dvander@0
  1552
    }
dvander@195
  1553
    void visitCallExpression(CallExpression *node) {
dvander@0
  1554
        prefix();
dvander@0
  1555
        fprintf(fp_, "[ CallExpression\n");
dvander@0
  1556
        indent();
dvander@0
  1557
        node->callee()->accept(this);
dvander@55
  1558
        for (size_t i = 0; i < node->arguments()->length(); i++)
dvander@0
  1559
            node->arguments()->at(i)->accept(this);
dvander@0
  1560
        unindent();
dvander@0
  1561
    }
dvander@195
  1562
    void visitFunctionTypeStatement(FunctionTypeStatement *node) {
dvander@174
  1563
        prefix();
dvander@195
  1564
        fprintf(fp_, "[ FunctionTypeStatement (%s)\n", node->name()->chars());
dvander@191
  1565
        indent();
dvander@191
  1566
        dump(node->signature());
dvander@191
  1567
        unindent();
dvander@174
  1568
    }
dvander@195
  1569
    void visitFunctionStatement(FunctionStatement *node) {
dvander@0
  1570
        prefix();
dvander@195
  1571
        fprintf(fp_, "[ FunctionStatement (%s)\n", node->name()->chars());
dvander@0
  1572
        indent();
dvander@191
  1573
        dump(node->signature());
dvander@63
  1574
        if (node->body())
dvander@63
  1575
            node->body()->accept(this);
dvander@0
  1576
        unindent();
dvander@0
  1577
    }
dvander@195
  1578
    void visitExpressionStatement(ExpressionStatement *node) {
dvander@0
  1579
        prefix();
dvander@0
  1580
        fprintf(fp_, "[ ExpressionStatement\n");
dvander@0
  1581
        indent();
dvander@0
  1582
        node->expression()->accept(this);
dvander@0
  1583
        unindent();
dvander@0
  1584
    }
dvander@195
  1585
    void visitAssignment(Assignment *node) {
dvander@0
  1586
        prefix();
dvander@0
  1587
        fprintf(fp_, "[ Assignment\n");
dvander@0
  1588
        indent();
dvander@0
  1589
        node->lvalue()->accept(this);
dvander@0
  1590
        node->expression()->accept(this);
dvander@0
  1591
        unindent();
dvander@0
  1592
    }
dvander@195
  1593
    void visitTernaryExpression(TernaryExpression *node) {
dvander@83
  1594
        prefix();
dvander@83
  1595
        fprintf(fp_, "[ TernaryExpression\n");
dvander@83
  1596
        indent();
dvander@83
  1597
        node->condition()->accept(this);
dvander@83
  1598
        node->left()->accept(this);
dvander@83
  1599
        node->right()->accept(this);
dvander@83
  1600
        unindent();
dvander@83
  1601
    }
dvander@195
  1602
    void visitBinaryExpression(BinaryExpression *node) {
dvander@0
  1603
        prefix();
dvander@0
  1604
        fprintf(fp_, "[ BinaryExpression (%s)\n", TokenNames[node->token()]);
dvander@0
  1605
        indent();
dvander@0
  1606
        node->left()->accept(this);
dvander@0
  1607
        node->right()->accept(this);
dvander@0
  1608
        unindent();
dvander@0
  1609
    }
dvander@195
  1610
    void visitUnaryExpression(UnaryExpression *node) {
dvander@78
  1611
        prefix();
dvander@78
  1612
        fprintf(fp_, "[ UnaryExpression (%s)\n", TokenNames[node->token()]);
dvander@78
  1613
        indent();
dvander@78
  1614
        node->expression()->accept(this);
dvander@78
  1615
        unindent();
dvander@78
  1616
    }
dvander@195
  1617
    void visitReturnStatement(ReturnStatement *node) {
dvander@0
  1618
        prefix();
dvander@0
  1619
        fprintf(fp_, "[ ReturnStatement\n");
dvander@0
  1620
        indent();
dvander@72
  1621
        if (node->expression())
dvander@72
  1622
            node->expression()->accept(this);
dvander@0
  1623
        unindent();
dvander@0
  1624
    }
dvander@195
  1625
    void visitForStatement(ForStatement *node) {
dvander@0
  1626
        prefix();
dvander@0
  1627
        fprintf(fp_, "[ ForStatement\n");
dvander@0
  1628
        indent();
dvander@22
  1629
        if (node->initialization())
dvander@22
  1630
            node->initialization()->accept(this);
dvander@0
  1631
        if (node->condition())
dvander@0
  1632
            node->condition()->accept(this);
dvander@0
  1633
        if (node->update())
dvander@0
  1634
            node->update()->accept(this);
dvander@0
  1635
        node->body()->accept(this);
dvander@0
  1636
        unindent();
dvander@0
  1637
    }
dvander@195
  1638
    void visitBlockStatement(BlockStatement *node) {
dvander@0
  1639
        prefix();
dvander@0
  1640
        fprintf(fp_, "[ BlockStatement\n");
dvander@0
  1641
        indent();
dvander@0
  1642
        for (size_t i = 0; i < node->statements()->length(); i++)
dvander@0
  1643
            node->statements()->at(i)->accept(this);
dvander@0
  1644
        unindent();
dvander@0
  1645
    }
dvander@195
  1646
    void visitVariableDeclaration(VariableDeclaration *node) {
dvander@0
  1647
        prefix();
dvander@195
  1648
        fprintf(fp_, "[ VariableDeclaration (%s)\n", node->name()->chars());
dvander@0
  1649
        indent();
dvander@0
  1650
        if (node->initialization())
dvander@0
  1651
            node->initialization()->accept(this);
dvander@0
  1652
        unindent();
dvander@0
  1653
    }
dvander@195
  1654
    void visitIntegerLiteral(IntegerLiteral *node) {
dvander@0
  1655
        prefix();
dvander@4
  1656
        fprintf(fp_, "[ IntegerLiteral (%d)\n", node->value());
dvander@4
  1657
    }
dvander@195
  1658
    void visitBooleanLiteral(BooleanLiteral *node) {
dvander@143
  1659
        prefix();
dvander@143
  1660
        fprintf(fp_, "[ BooleanLiteral (%s)\n",
dvander@143
  1661
                (node->token() == TOK_TRUE) ? "true" : "false");
dvander@143
  1662
    }
dvander@195
  1663
    void visitFloatLiteral(FloatLiteral *node) {
dvander@4
  1664
        prefix();
dvander@4
  1665
        fprintf(fp_, "[ FloatLiteral (%f)\n", node->value());
dvander@0
  1666
    }
dvander@195
  1667
    void visitIfStatement(IfStatement *node) {
dvander@0
  1668
        prefix();
dvander@0
  1669
        fprintf(fp_, "[ IfStatement\n");
dvander@0
  1670
        indent();
dvander@0
  1671
        node->ifTrue()->accept(this);
dvander@0
  1672
        if (node->ifFalse())
dvander@0
  1673
            node->ifFalse()->accept(this);
dvander@0
  1674
        unindent();
dvander@0
  1675
    }
dvander@195
  1676
    void visitIndexExpression(IndexExpression *node) {
dvander@0
  1677
        prefix();
dvander@0
  1678
        fprintf(fp_, "[ IndexExpression\n");
dvander@0
  1679
        indent();
dvander@0
  1680
        node->left()->accept(this);
dvander@0
  1681
        node->right()->accept(this);
dvander@0
  1682
        unindent();
dvander@0
  1683
    }
dvander@195
  1684
    void visitEnumStatement(EnumStatement *node) {
dvander@2
  1685
        prefix();
dvander@54
  1686
        fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name()->chars() : "<anonymous>");
dvander@2
  1687
        indent();
dvander@57
  1688
        for (size_t i = 0; i < node->entries()->length(); i++) {
dvander@2
  1689
            prefix();
dvander@195
  1690
            fprintf(fp_, "%s =\n", node->entries()->at(i).name->chars());
dvander@2
  1691
            if (node->entries()->at(i).expr) {
dvander@2
  1692
                indent();
dvander@2
  1693
                node->entries()->at(i).expr->accept(this);
dvander@2
  1694
                unindent();
dvander@2
  1695
            }
dvander@2
  1696
        }
dvander@2
  1697
        unindent();
dvander@2
  1698
    }
dvander@195
  1699
    void visitWhileStatement(WhileStatement *node) {
dvander@9
  1700
        prefix();
dvander@9
  1701
        fprintf(fp_, "[ WhileStatement (%s)\n",
dvander@9
  1702
                (node->token() == TOK_DO) ? "do" : "while");
dvander@9
  1703
        indent();
dvander@9
  1704
        if (node->token() == TOK_DO) {
dvander@9
  1705
            node->condition()->accept(this);
dvander@9
  1706
            node->body()->accept(this);
dvander@9
  1707
        } else {
dvander@9
  1708
            node->condition()->accept(this);
dvander@9
  1709
            node->body()->accept(this);
dvander@9
  1710
        }
dvander@9
  1711
        unindent();
dvander@9
  1712
    }
dvander@195
  1713
    void visitBreakStatement(BreakStatement *node) {
dvander@10
  1714
        prefix();
dvander@10
  1715
        fprintf(fp_, "[ BreakStatement\n");
dvander@10
  1716
    }
dvander@195
  1717
    void visitContinueStatement(ContinueStatement *node) {
dvander@10
  1718
        prefix();
dvander@10
  1719
        fprintf(fp_, "[ ContinueStatement\n");
dvander@10
  1720
    }
dvander@195
  1721
    void visitStringLiteral(StringLiteral *node) {
dvander@21
  1722
        prefix();
dvander@21
  1723
        fprintf(fp_, "[ StringLiteral\n");
dvander@21
  1724
    }
dvander@195
  1725
    void visitIncDecExpression(IncDecExpression *node) {
dvander@23
  1726
        prefix();
dvander@23
  1727
        fprintf(fp_, "[ IncDecExpression (postfix=%d)\n", node->postfix());
dvander@23
  1728
        indent();
dvander@23
  1729
        node->expression()->accept(this);
dvander@23
  1730
        unindent();
dvander@23
  1731
    }
dvander@195
  1732
    void visitStructureStatement(StructureStatement *node) {
dvander@146
  1733
        prefix();
dvander@195
  1734
        fprintf(fp_, "[ StructureStatement %s\n", node->name()->chars());
dvander@148
  1735
    }
dvander@195
  1736
    void visitFieldExpression(FieldExpression *node) {
dvander@148
  1737
        prefix();
dvander@148
  1738
        fprintf(fp_, "[ FieldExpression %s\n", node->field()->chars());
dvander@148
  1739
        indent();
dvander@148
  1740
        node->left()->accept(this);
dvander@148
  1741
        unindent();
dvander@146
  1742
    }
dvander@195
  1743
    void visitSwitchStatement(SwitchStatement *node) {
dvander@172
  1744
        prefix();
dvander@172
  1745
        fprintf(fp_, "[ SwitchStatement\n");
dvander@172
  1746
        indent();
dvander@172
  1747
        node->expression()->accept(this);
dvander@172
  1748
        for (size_t i = 0; i < node->cases()->length(); i++) {
dvander@172
  1749
            Case *c = node->cases()->at(i);
dvander@172
  1750
            c->expression()->accept(this);
dvander@172
  1751
            if (c->others()) {
dvander@172
  1752
                for (size_t j = 0; j < c->others()->length(); j++)
dvander@172
  1753
                    c->others()->at(j)->accept(this);
dvander@172
  1754
            }
dvander@172
  1755
            indent();
dvander@172
  1756
            c->statement()->accept(this);
dvander@172
  1757
            unindent();
dvander@172
  1758
        }
dvander@172
  1759
        if (node->defaultCase())
dvander@172
  1760
            node->defaultCase()->accept(this);
dvander@172
  1761
        unindent();
dvander@172
  1762
    }
dvander@195
  1763
    void visitArrayLiteral(ArrayLiteral *node) {
dvander@187
  1764
        prefix();
dvander@187
  1765
        fprintf(fp_, "[ ArrayLiteral\n");
dvander@187
  1766
        indent();
dvander@187
  1767
        for (size_t i = 0; i < node->expressions()->length(); i++) {
dvander@187
  1768
            Expression *expr = node->expressions()->at(i);
dvander@187
  1769
            indent();
dvander@187
  1770
            expr->accept(this);
dvander@187
  1771
            unindent();
dvander@187
  1772
        }
dvander@187
  1773
    }
dvander@195
  1774
    void visitImportStatement(ImportStatement *node) {
dvander@195
  1775
        prefix();
dvander@195
  1776
        fprintf(fp_, "[ ImportStatement\n");
dvander@195
  1777
    }
dvander@0
  1778
};
dvander@0
  1779
dvander@0
  1780
void
dvander@0
  1781
ParseTree::dump(FILE *fp)
dvander@0
  1782
{
dvander@0
  1783
    AstPrinter printer(fp);
dvander@0
  1784
dvander@0
  1785
    for (size_t i = 0; i < statements_->length(); i++)
dvander@0
  1786
        statements_->at(i)->accept(&printer);
dvander@0
  1787
}