src/compiler/Parser.cpp
author David Anderson <dvander@alliedmods.net>
Fri Dec 28 17:13:51 2012 -0800 (2012-12-28)
changeset 247 7721042bdb67
parent 243 3d94c73a824c
child 251 ca99a81745fe
permissions -rw-r--r--
Implement dependent char arrays.
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@195
   224
    // Declaration:
dvander@195
   225
    //   NewDecl ::= Type Ident
dvander@195
   226
    //   OldDecl ::= Label? (Ident | "...")
dvander@195
   227
    //   Type    ::= Ident
dvander@195
   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@25
   653
    SourcePosition pos = scanner_.begin();
dvander@9
   654
    scanner_.scan();
dvander@9
   655
dvander@9
   656
    if (!expect(TOK_LPAREN))
dvander@9
   657
        return NULL;
dvander@25
   658
dvander@9
   659
    Expression *condition = expression();
dvander@9
   660
    if (!condition)
dvander@9
   661
        return NULL;
dvander@25
   662
dvander@9
   663
    if (!expect(TOK_RPAREN))
dvander@9
   664
        return NULL;
dvander@9
   665
dvander@48
   666
    Statement *body;
dvander@48
   667
    if (scanner_.peek() == TOK_LBRACE)
dvander@195
   668
        body = block();
dvander@48
   669
    else
dvander@48
   670
        body = localStatement();
dvander@9
   671
    if (!body)
dvander@9
   672
        return NULL;
dvander@9
   673
dvander@25
   674
    return new (pool_) WhileStatement(pos, TOK_WHILE, condition, body);
dvander@9
   675
}
dvander@9
   676
dvander@9
   677
Statement *
dvander@9
   678
Parser::do_()
dvander@9
   679
{
dvander@25
   680
    SourcePosition pos = scanner_.begin();
dvander@9
   681
    scanner_.scan();
dvander@9
   682
dvander@48
   683
    Statement *body;
dvander@48
   684
    if (scanner_.peek() == TOK_LBRACE)
dvander@195
   685
        body = block();
dvander@48
   686
    else
dvander@48
   687
        body = localStatement();
dvander@9
   688
    if (!body)
dvander@9
   689
        return NULL;
dvander@9
   690
dvander@9
   691
    if (!expect(TOK_WHILE))
dvander@9
   692
        return NULL;
dvander@9
   693
dvander@9
   694
    if (!expect(TOK_LPAREN))
dvander@9
   695
        return NULL;
dvander@9
   696
    Expression *condition = expression();
dvander@9
   697
    if (!condition)
dvander@9
   698
        return NULL;
dvander@9
   699
    if (!expect(TOK_RPAREN))
dvander@9
   700
        return NULL;
dvander@9
   701
dvander@25
   702
    return new (pool_) WhileStatement(pos, TOK_DO, condition, body);
dvander@9
   703
}
dvander@9
   704
dvander@9
   705
Statement *
dvander@172
   706
Parser::switch_()
dvander@172
   707
{
dvander@172
   708
    expect(TOK_SWITCH);
dvander@172
   709
dvander@172
   710
    SourcePosition pos = scanner_.begin();
dvander@172
   711
dvander@172
   712
    if (!expect(TOK_LPAREN))
dvander@172
   713
        return NULL;
dvander@172
   714
    Expression *expr = expression();
dvander@172
   715
    if (!expr)
dvander@172
   716
        return NULL;
dvander@172
   717
    if (!expect(TOK_RPAREN))
dvander@172
   718
        return NULL;
dvander@172
   719
dvander@172
   720
    if (!expect(TOK_LBRACE))
dvander@172
   721
        return NULL;
dvander@172
   722
dvander@172
   723
    SourcePosition defaultPos;
dvander@172
   724
    PoolList<Case *> *cases = new (pool_) PoolList<Case *>();
dvander@172
   725
dvander@172
   726
    Statement *defaultCase = NULL;
dvander@172
   727
dvander@172
   728
    while (!peek(TOK_RBRACE)) {
dvander@172
   729
        Expression *expr = NULL;
dvander@172
   730
        ExpressionList *others = NULL;
dvander@172
   731
        if (match(TOK_DEFAULT)) {
dvander@172
   732
            if (defaultCase) {
dvander@172
   733
                cc_.reportError(scanner_.begin(), Message_OneDefaultPerSwitch);
dvander@172
   734
                return NULL;
dvander@172
   735
            }
dvander@172
   736
dvander@172
   737
            defaultPos = scanner_.begin();
dvander@172
   738
        } else {
dvander@172
   739
            if (defaultCase) {
dvander@172
   740
                cc_.reportError(defaultPos, Message_DefaultMustBeLastCase);
dvander@172
   741
                return NULL;
dvander@172
   742
            }
dvander@172
   743
dvander@172
   744
            if (!expect(TOK_CASE))
dvander@172
   745
                return NULL;
dvander@172
   746
dvander@172
   747
            // A limitation in the grammar is that |case <NAME>:| will be
dvander@172
   748
            // detected as a label.
dvander@172
   749
            AutoAllowTags<false> disableTags(scanner_);
dvander@172
   750
dvander@172
   751
            if ((expr = expression()) == NULL)
dvander@172
   752
                return NULL;
dvander@172
   753
dvander@172
   754
            if (peek(TOK_COMMA)) {
dvander@172
   755
                others = new (pool_) ExpressionList();
dvander@172
   756
                while (match(TOK_COMMA)) {
dvander@172
   757
                    Expression *other = expression();
dvander@172
   758
                    if (!other)
dvander@172
   759
                        return NULL;
dvander@172
   760
                    if (!others->append(other))
dvander@172
   761
                        return NULL;
dvander@172
   762
                }
dvander@172
   763
            }
dvander@172
   764
        }
dvander@172
   765
dvander@172
   766
        if (!expect(TOK_COLON))
dvander@172
   767
            return NULL;
dvander@172
   768
dvander@172
   769
        Statement *statement = localStatement();
dvander@172
   770
        if (!statement)
dvander@172
   771
            return NULL;
dvander@172
   772
dvander@172
   773
        if (!peek(TOK_CASE) &&
dvander@172
   774
            !peek(TOK_DEFAULT) &&
dvander@172
   775
            !peek(TOK_RBRACE))
dvander@172
   776
        {
dvander@172
   777
            cc_.reportError(scanner_.begin(), Message_SingleStatementPerCase);
dvander@172
   778
            return NULL;
dvander@172
   779
        }
dvander@172
   780
dvander@172
   781
        if (expr) {
dvander@172
   782
            Case *caze = new (pool_) Case(expr, others, statement);
dvander@172
   783
            if (!cases->append(caze))
dvander@172
   784
                return NULL;
dvander@172
   785
        } else {
dvander@172
   786
            defaultCase = statement;
dvander@172
   787
        }
dvander@172
   788
    }
dvander@172
   789
dvander@172
   790
    if (!expect(TOK_RBRACE))
dvander@172
   791
        return NULL;
dvander@172
   792
dvander@172
   793
    return new (pool_) SwitchStatement(pos, expr, cases, defaultCase);
dvander@172
   794
}
dvander@172
   795
dvander@172
   796
Statement *
dvander@0
   797
Parser::forStatement()
dvander@0
   798
{
dvander@25
   799
    SourcePosition pos = scanner_.begin();
dvander@0
   800
    scanner_.scan();
dvander@0
   801
    if (!expect(TOK_LPAREN))
dvander@0
   802
        return NULL;
dvander@0
   803
dvander@22
   804
    Statement *decl = NULL;
dvander@0
   805
    if (!match(TOK_SEMICOLON)) {
dvander@135
   806
        if (match(TOK_NEW)) {
dvander@238
   807
            if ((decl = vars(TypeQual_None)) == NULL)
dvander@22
   808
                return NULL;
dvander@22
   809
        } else {
dvander@22
   810
            if ((decl = expressionStatement()) == NULL)
dvander@22
   811
                return NULL;
dvander@22
   812
        }
dvander@0
   813
        if (!expect(TOK_SEMICOLON))
dvander@0
   814
            return NULL;
dvander@0
   815
    }
dvander@0
   816
dvander@0
   817
    Expression *condition = NULL;
dvander@0
   818
    if (!match(TOK_SEMICOLON)) {
dvander@0
   819
        if ((condition = expression()) == NULL)
dvander@0
   820
            return NULL;
dvander@0
   821
        if (!expect(TOK_SEMICOLON))
dvander@0
   822
            return NULL;
dvander@0
   823
    }
dvander@0
   824
dvander@0
   825
    Statement *update = NULL;
dvander@0
   826
    if (!match(TOK_RPAREN)) {
dvander@0
   827
        if ((update = expressionStatement()) == NULL)
dvander@0
   828
            return NULL;
dvander@0
   829
        if (!expect(TOK_RPAREN))
dvander@0
   830
            return NULL;
dvander@0
   831
    }
dvander@0
   832
dvander@48
   833
    Statement *body;
dvander@48
   834
    if (scanner_.peek() == TOK_LBRACE)
dvander@195
   835
        body = block();
dvander@48
   836
    else
dvander@48
   837
        body = localStatement();
dvander@0
   838
    if (!body)
dvander@0
   839
        return NULL;
dvander@0
   840
dvander@195
   841
    return new (pool_) ForStatement(pos, decl, condition, update, body);
dvander@0
   842
}
dvander@0
   843
dvander@145
   844
ExpressionList *
dvander@145
   845
Parser::dimensions()
dvander@145
   846
{
dvander@145
   847
    ExpressionList *postDimensions = new (pool_) ExpressionList();
dvander@145
   848
    while (match(TOK_LBRACKET)) {
dvander@145
   849
        Expression *dim = NULL;
dvander@145
   850
        if (!match(TOK_RBRACKET)) {
dvander@145
   851
            if ((dim = expression()) == NULL)
dvander@145
   852
                return NULL;
dvander@145
   853
            if (!expect(TOK_RBRACKET))
dvander@145
   854
                return NULL;
dvander@145
   855
        }
dvander@145
   856
dvander@145
   857
        if (!postDimensions->append(dim))
dvander@145
   858
            return NULL;
dvander@145
   859
    }
dvander@145
   860
    return postDimensions;
dvander@145
   861
}
dvander@145
   862
dvander@0
   863
VariableDeclaration *
dvander@195
   864
Parser::var(TypeQualifiers qual)
dvander@0
   865
{
dvander@195
   866
    Expression *type;
dvander@195
   867
    Local<String> name(zone_);
dvander@195
   868
    
dvander@195
   869
    if (!typeAndName(&type, name.ref()))
dvander@4
   870
        return NULL;
dvander@0
   871
dvander@209
   872
    ExpressionList *dims = NULL;
dvander@212
   873
    if (peek(TOK_LBRACKET)) {
dvander@209
   874
        if ((dims = dimensions()) == NULL)
dvander@209
   875
            return NULL;;
dvander@209
   876
    }
dvander@209
   877
dvander@189
   878
    SourcePosition pos = scanner_.begin();
dvander@0
   879
    
dvander@0
   880
    Expression *expr = NULL;
dvander@0
   881
    if (match(TOK_ASSIGN)) {
dvander@187
   882
        switch (scanner_.peek()) {
dvander@187
   883
          // Note: we don't support [] literals yet.
dvander@187
   884
          case TOK_LBRACE:
dvander@212
   885
            scanner_.scan();
dvander@212
   886
            if ((expr = fixedArrayLiteral()) == NULL)
dvander@187
   887
                return NULL;
dvander@187
   888
            break;
dvander@187
   889
dvander@187
   890
          default:
dvander@187
   891
            if ((expr = expression()) == NULL)
dvander@187
   892
                return NULL;
dvander@187
   893
            break;
dvander@187
   894
        }
dvander@0
   895
    }
dvander@0
   896
dvander@209
   897
    return new (pool_) VariableDeclaration(pos, qual, name, type, dims, expr);
dvander@0
   898
}
dvander@0
   899
dvander@0
   900
Statement *
dvander@195
   901
Parser::vars(TypeQualifiers qual)
dvander@165
   902
{
dvander@195
   903
    VariableDeclaration *decl = var(qual);
dvander@165
   904
    if (!decl)
dvander@165
   905
        return NULL;
dvander@165
   906
dvander@165
   907
    if (!peek(TOK_COMMA))
dvander@165
   908
        return decl;
dvander@165
   909
dvander@165
   910
    StatementList *statements = new (pool_) StatementList();
dvander@165
   911
    if (!statements->append(decl))
dvander@165
   912
        return NULL;
dvander@165
   913
dvander@165
   914
    while (match(TOK_COMMA)) {
dvander@195
   915
        Statement *decl = var(qual);
dvander@165
   916
        if (!decl)
dvander@165
   917
            return NULL;
dvander@165
   918
        if (!statements->append(decl))
dvander@165
   919
            return NULL;
dvander@165
   920
    }
dvander@165
   921
dvander@165
   922
    // Create a fake-o block with no scope to create a statement list.
dvander@247
   923
    return new (pool_) BlockStatement(decl->pos(), statements, TOK_NEW);
dvander@165
   924
}
dvander@165
   925
dvander@165
   926
Statement *
dvander@0
   927
Parser::returnStatement()
dvander@0
   928
{
dvander@25
   929
    SourcePosition pos = scanner_.begin();
dvander@0
   930
    if (!expect(TOK_RETURN))
dvander@0
   931
        return NULL;
dvander@0
   932
dvander@72
   933
    Expression *expr = NULL;
dvander@72
   934
    if (scanner_.peek() != TOK_SEMICOLON) {
dvander@72
   935
        if ((expr = expression()) == NULL)
dvander@72
   936
            return NULL;
dvander@0
   937
dvander@72
   938
        // We only care about non-void returns when determining whether a
dvander@72
   939
        // tagless function is non-void.
dvander@72
   940
        encounteredReturn_ = true;
dvander@72
   941
    }
dvander@71
   942
dvander@25
   943
    return new (pool_) ReturnStatement(pos, expr);
dvander@0
   944
}
dvander@0
   945
dvander@0
   946
Statement *
dvander@0
   947
Parser::expressionStatement()
dvander@0
   948
{
dvander@22
   949
    Expression *left = assignment();
dvander@21
   950
    if (!left)
dvander@0
   951
        return NULL;
dvander@0
   952
dvander@0
   953
    return new (pool_) ExpressionStatement(left);
dvander@0
   954
}
dvander@0
   955
dvander@0
   956
Statement *
dvander@195
   957
Parser::block()
dvander@0
   958
{
dvander@0
   959
    if (!expect(TOK_LBRACE))
dvander@0
   960
        return NULL;
dvander@0
   961
dvander@25
   962
    SourcePosition pos = scanner_.begin();
dvander@0
   963
dvander@0
   964
    StatementList *statements = new (pool_) StatementList();
dvander@0
   965
    while (!match(TOK_RBRACE)) {
dvander@0
   966
        Statement *statement = localStatement();
dvander@0
   967
        if (statement == NULL)
dvander@0
   968
            return NULL;
dvander@56
   969
        if (!statements->append(statement))
dvander@56
   970
            return NULL;
dvander@0
   971
    }
dvander@0
   972
dvander@247
   973
    BlockStatement *block = new (pool_) BlockStatement(pos, statements, TOK_LBRACE);
dvander@0
   974
    return block;
dvander@0
   975
}
dvander@0
   976
dvander@0
   977
Statement *
dvander@0
   978
Parser::if_()
dvander@0
   979
{
dvander@0
   980
    expect(TOK_IF);
dvander@25
   981
    
dvander@25
   982
    SourcePosition pos = scanner_.begin();
dvander@0
   983
    if (!expect(TOK_LPAREN))
dvander@0
   984
        return NULL;
dvander@0
   985
dvander@0
   986
    Expression *cond = expression();
dvander@0
   987
    if (!cond)
dvander@0
   988
        return NULL;
dvander@0
   989
dvander@0
   990
    if (!expect(TOK_RPAREN))
dvander@0
   991
        return NULL;
dvander@0
   992
dvander@0
   993
    Statement *ifTrue = localStatement();
dvander@0
   994
    if (!ifTrue)
dvander@0
   995
        return NULL;
dvander@0
   996
dvander@25
   997
    IfStatement *outer = new (pool_) IfStatement(pos, cond, ifTrue);
dvander@0
   998
dvander@0
   999
    IfStatement *last = outer;
dvander@0
  1000
    while (match(TOK_ELSE)) {
dvander@0
  1001
        if (!match(TOK_IF)) {
dvander@0
  1002
            Statement *ifFalse = localStatement();
dvander@0
  1003
            if (!ifFalse)
dvander@0
  1004
                return NULL;
dvander@0
  1005
dvander@0
  1006
            last->setIfFalse(ifFalse);
dvander@0
  1007
            break;
dvander@0
  1008
        }
dvander@0
  1009
dvander@25
  1010
        SourcePosition pos = scanner_.begin();
dvander@0
  1011
        if (!expect(TOK_LPAREN))
dvander@0
  1012
            return NULL;
dvander@0
  1013
dvander@0
  1014
        Expression *otherCond = expression();
dvander@0
  1015
        if (!otherCond)
dvander@0
  1016
            return NULL;
dvander@0
  1017
dvander@0
  1018
        if (!expect(TOK_RPAREN))
dvander@0
  1019
            return NULL;
dvander@0
  1020
dvander@0
  1021
        Statement *otherIfTrue = localStatement();
dvander@0
  1022
        if (!otherIfTrue)
dvander@0
  1023
            return NULL;
dvander@0
  1024
dvander@25
  1025
        IfStatement *inner = new (pool_) IfStatement(pos, otherCond, otherIfTrue);
dvander@0
  1026
        last->setIfFalse(inner);
dvander@0
  1027
        last = inner;
dvander@0
  1028
    }
dvander@0
  1029
dvander@0
  1030
    return outer;
dvander@0
  1031
}
dvander@0
  1032
dvander@0
  1033
Statement *
dvander@0
  1034
Parser::localStatement()
dvander@0
  1035
{
dvander@0
  1036
    Statement *statement = NULL;
dvander@0
  1037
dvander@0
  1038
    // Statements which must be followed by a semicolon will break out of the
dvander@0
  1039
    // switch. If they may end in BlockStatements, they'll immediately return.
dvander@0
  1040
dvander@135
  1041
    TokenKind kind = scanner_.peek();
dvander@135
  1042
    switch (kind) {
dvander@135
  1043
      case TOK_CONST:
dvander@131
  1044
      case TOK_NEW:
dvander@195
  1045
      {
dvander@195
  1046
        TypeQualifiers quals = (kind == TOK_CONST)
dvander@241
  1047
                              ? TypeQual_Const
dvander@238
  1048
                              : TypeQual_None;
dvander@135
  1049
        scanner_.scan();
dvander@195
  1050
        if ((statement = vars(quals)) == NULL)
dvander@172
  1051
          return NULL;
dvander@131
  1052
        break;
dvander@195
  1053
      }
dvander@0
  1054
dvander@131
  1055
      case TOK_FOR:
dvander@131
  1056
        return forStatement();
dvander@0
  1057
dvander@131
  1058
      case TOK_WHILE:
dvander@131
  1059
        return while_();
dvander@9
  1060
dvander@131
  1061
      case TOK_BREAK:
dvander@131
  1062
        scanner_.scan();
dvander@131
  1063
        statement = new (pool_) BreakStatement(scanner_.begin());
dvander@131
  1064
        break;
dvander@10
  1065
dvander@131
  1066
      case TOK_CONTINUE:
dvander@131
  1067
        scanner_.scan();
dvander@131
  1068
        statement = new (pool_) ContinueStatement(scanner_.begin());
dvander@131
  1069
        break;
dvander@10
  1070
dvander@131
  1071
      case TOK_DO:
dvander@131
  1072
        if ((statement = do_()) == NULL)
dvander@131
  1073
            return NULL;
dvander@131
  1074
        break;
dvander@9
  1075
dvander@131
  1076
      case TOK_RETURN:
dvander@131
  1077
        if ((statement = returnStatement()) == NULL)
dvander@172
  1078
          return NULL;
dvander@131
  1079
        break;
dvander@0
  1080
dvander@131
  1081
      case TOK_ENUM:
dvander@131
  1082
        if ((statement = enum_()) == NULL)
dvander@172
  1083
          return NULL;
dvander@131
  1084
        break;
dvander@2
  1085
dvander@146
  1086
      case TOK_STRUCT:
dvander@146
  1087
        if ((statement = struct_()) == NULL)
dvander@172
  1088
          return NULL;
dvander@146
  1089
        break;
dvander@146
  1090
dvander@172
  1091
      case TOK_SWITCH:
dvander@172
  1092
        return switch_();
dvander@172
  1093
dvander@131
  1094
      case TOK_IF:
dvander@131
  1095
        return if_();
dvander@0
  1096
dvander@131
  1097
      case TOK_LBRACE:
dvander@131
  1098
        return block();
dvander@28
  1099
dvander@131
  1100
      default:
dvander@131
  1101
        break;
dvander@0
  1102
    }
dvander@0
  1103
dvander@0
  1104
    if (!statement) {
dvander@0
  1105
        if ((statement = expressionStatement()) == NULL)
dvander@0
  1106
            return NULL;
dvander@0
  1107
    }
dvander@0
  1108
dvander@0
  1109
    if (!expect(TOK_SEMICOLON))
dvander@0
  1110
        return NULL;
dvander@0
  1111
dvander@0
  1112
    return statement;
dvander@0
  1113
}
dvander@0
  1114
dvander@0
  1115
Statement *
dvander@146
  1116
Parser::struct_()
dvander@146
  1117
{
dvander@146
  1118
    expect(TOK_STRUCT);
dvander@146
  1119
dvander@146
  1120
    Local<String> name(zone_, expectName());
dvander@146
  1121
    if (!name)
dvander@146
  1122
        return NULL;
dvander@146
  1123
dvander@146
  1124
    SourcePosition pos = scanner_.begin();
dvander@146
  1125
dvander@146
  1126
    if (!expect(TOK_LBRACE))
dvander@146
  1127
        return NULL;
dvander@146
  1128
dvander@146
  1129
    FieldList *fields = new (pool_) FieldList();
dvander@146
  1130
dvander@146
  1131
    while (!peek(TOK_RBRACE)) {
dvander@195
  1132
        Expression *type;
dvander@195
  1133
        Local<String> fieldName(zone_);
dvander@146
  1134
dvander@195
  1135
        if (!fullTypeAndName(&type, fieldName.ref(), DeclField))
dvander@146
  1136
            return NULL;
dvander@146
  1137
dvander@146
  1138
        SourcePosition pos = scanner_.begin();
dvander@146
  1139
dvander@146
  1140
        if (!matchSemicolon())
dvander@146
  1141
            return NULL;
dvander@146
  1142
dvander@146
  1143
        StructureStatement::Field *field =
dvander@195
  1144
            new (pool_) StructureStatement::Field(pos, type, fieldName);
dvander@146
  1145
        if (!field || !fields->append(field))
dvander@146
  1146
            return NULL;
dvander@146
  1147
    }
dvander@146
  1148
dvander@146
  1149
    if (!expect(TOK_RBRACE))
dvander@146
  1150
        return NULL;
dvander@146
  1151
mibusby@180
  1152
    if (fields->empty()) {
mibusby@180
  1153
        cc_.reportError(pos, Message_StructCantBeEmpty);
mibusby@180
  1154
        return NULL;
mibusby@180
  1155
    }
mibusby@180
  1156
dvander@195
  1157
    return new (pool_) StructureStatement(pos, name, fields);
dvander@146
  1158
}
dvander@146
  1159
dvander@146
  1160
Statement *
dvander@2
  1161
Parser::enum_()
dvander@2
  1162
{
dvander@2
  1163
    expect(TOK_ENUM);
dvander@2
  1164
dvander@25
  1165
    SourcePosition pos = scanner_.begin();
dvander@25
  1166
dvander@54
  1167
    Local<String> name(zone_);
dvander@195
  1168
    if (matchName(name.ref()) && !name)
dvander@195
  1169
        return NULL;
dvander@2
  1170
dvander@57
  1171
    EnumStatement::EntryList *entries = new (pool_) EnumStatement::EntryList();
dvander@2
  1172
dvander@2
  1173
    if (!expect(TOK_LBRACE))
dvander@2
  1174
        return NULL;
dvander@2
  1175
dvander@2
  1176
    do {
dvander@2
  1177
        if (scanner_.peek() == TOK_RBRACE)
dvander@2
  1178
            break;
dvander@2
  1179
dvander@243
  1180
        SourcePosition pos = scanner_.begin();
dvander@54
  1181
        Local<String> name(zone_, expectName());
dvander@2
  1182
        if (!name)
dvander@2
  1183
            return NULL;
dvander@2
  1184
dvander@2
  1185
        Expression *expr = NULL;
dvander@2
  1186
        if (match(TOK_ASSIGN)) {
dvander@2
  1187
            if ((expr = expression()) == NULL)
dvander@2
  1188
                return NULL;
dvander@2
  1189
        }
dvander@2
  1190
dvander@233
  1191
        if (!entries->append(EnumStatement::Entry(name, expr, pos)))
dvander@57
  1192
            return NULL;
dvander@2
  1193
    } while (match(TOK_COMMA));
dvander@2
  1194
    if (!expect(TOK_RBRACE))
dvander@2
  1195
        return NULL;
dvander@2
  1196
dvander@195
  1197
    return new (pool_) EnumStatement(pos, name, entries);
dvander@195
  1198
}
dvander@195
  1199
dvander@195
  1200
template <class T>
dvander@195
  1201
static inline ScopedRoot<T> *
dvander@195
  1202
NewScopedRoot(PoolAllocator &pool, Handle<T> obj)
dvander@195
  1203
{
dvander@195
  1204
    ScopedRoot<T> *root = pool.alloc<ScopedRoot<T> >();
dvander@195
  1205
    new (root) ScopedRoot<T>(obj);
dvander@195
  1206
    return root;
dvander@195
  1207
}
dvander@195
  1208
dvander@195
  1209
ImportStatement *
dvander@195
  1210
Parser::import()
dvander@195
  1211
{
dvander@195
  1212
    NameList *names = new (pool_) NameList();
dvander@195
  1213
dvander@195
  1214
    SourcePosition pos = scanner_.begin();
dvander@195
  1215
dvander@195
  1216
    Local<String> name(zone_, expectName());
dvander@195
  1217
    if (!name || !names->append(NewScopedRoot<String>(pool_, name)))
dvander@195
  1218
        return NULL;
dvander@195
  1219
dvander@195
  1220
    TokenKind suffix = TOK_NONE;
dvander@195
  1221
    while (match(TOK_DOT)) {
dvander@195
  1222
        if (match(TOK_STAR)) {
dvander@195
  1223
            suffix = TOK_STAR;
dvander@195
  1224
            break;
dvander@195
  1225
        }
dvander@195
  1226
dvander@195
  1227
        if ((name = expectName()) == NULL)
dvander@195
  1228
            return NULL;
dvander@195
  1229
dvander@195
  1230
        if (!names->append(NewScopedRoot<String>(pool_, name)))
dvander@195
  1231
            return NULL;
dvander@195
  1232
    }
dvander@195
  1233
dvander@195
  1234
    return new (pool_) ImportStatement(pos, names, suffix);
dvander@2
  1235
}
dvander@2
  1236
dvander@2
  1237
Statement *
dvander@63
  1238
Parser::function(TokenKind token)
dvander@0
  1239
{
dvander@195
  1240
    Expression *returnType;
dvander@191
  1241
    Local<String> name(zone_);
dvander@191
  1242
dvander@195
  1243
    if (!fullTypeAndName(&returnType, name.ref(), DeclFun))
dvander@195
  1244
        return NULL;
dvander@132
  1245
dvander@25
  1246
    SourcePosition pos = scanner_.begin();
dvander@57
  1247
    ParameterList *parameters = new (pool_) ParameterList();
dvander@14
  1248
dvander@0
  1249
    if (!expect(TOK_LPAREN))
dvander@0
  1250
        return NULL;
dvander@133
  1251
dvander@195
  1252
    bool variadic = false;
dvander@195
  1253
dvander@0
  1254
    if (!match(TOK_RPAREN)) {
dvander@0
  1255
        while (true) {
dvander@241
  1256
            TypeQualifiers quals = TypeQual_None;
dvander@241
  1257
            if (match(TOK_CONST))
dvander@241
  1258
                quals = TypeQualifiers(quals | TypeQual_Const);
dvander@241
  1259
dvander@14
  1260
            bool ref = match(TOK_AMPERSAND);
dvander@14
  1261
dvander@66
  1262
            SourcePosition begin = scanner_.begin();
dvander@195
  1263
            Expression *type;
dvander@195
  1264
            Local<String> name(zone_);
dvander@195
  1265
            if (!fullTypeAndName(&type, name.ref(), DeclArg))
dvander@66
  1266
                return NULL;
dvander@66
  1267
dvander@195
  1268
            if (!name) {
dvander@241
  1269
                if ((quals & TypeQual_Const) || ref) {
dvander@68
  1270
                    cc_.reportError(begin, Message_InvalidVarArgs);
dvander@68
  1271
                    return NULL;
dvander@68
  1272
                }
dvander@68
  1273
dvander@68
  1274
                if (token != TOK_NATIVE) {
dvander@68
  1275
                    cc_.reportError(begin, Message_VarArgsOutsideNative);
dvander@68
  1276
                    return NULL;
dvander@68
  1277
                }
dvander@68
  1278
dvander@195
  1279
                variadic = true;
dvander@68
  1280
                break;
dvander@68
  1281
            }
dvander@68
  1282
dvander@220
  1283
            ExpressionList *dims = NULL;
dvander@220
  1284
            if (peek(TOK_LBRACKET)) {
dvander@220
  1285
                if ((dims = dimensions()) == NULL)
dvander@220
  1286
                    return NULL;
dvander@220
  1287
            }
dvander@220
  1288
dvander@133
  1289
            Expression *expr = NULL;
dvander@133
  1290
            if (match(TOK_ASSIGN)) {
dvander@133
  1291
                if ((expr = expression()) == NULL)
dvander@133
  1292
                    return NULL;
dvander@133
  1293
            }
dvander@133
  1294
dvander@241
  1295
            Parameter *parameter = new (pool_) Parameter(name, type, ref, quals, dims, expr, begin);
dvander@57
  1296
            if (!parameters->append(parameter))
dvander@57
  1297
                return NULL;
dvander@14
  1298
dvander@0
  1299
            if (!match(TOK_COMMA))
dvander@0
  1300
                break;
dvander@0
  1301
        }
dvander@0
  1302
        if (!expect(TOK_RPAREN))
dvander@0
  1303
            return NULL;
dvander@0
  1304
    }
dvander@0
  1305
dvander@71
  1306
    encounteredReturn_ = false;
dvander@71
  1307
dvander@63
  1308
    Statement *body = NULL;
dvander@174
  1309
    if (token != TOK_FORWARD && token != TOK_NATIVE && token != TOK_TYPEDEF) {
dvander@63
  1310
        body = block();
dvander@63
  1311
        if (!body)
dvander@63
  1312
            return NULL;
dvander@63
  1313
    }
dvander@0
  1314
dvander@195
  1315
    FunctionSignature signature(returnType, parameters, variadic);
dvander@174
  1316
    if (token == TOK_TYPEDEF)
dvander@195
  1317
        return new (pool_) FunctionTypeStatement(pos, name, signature);
dvander@174
  1318
dvander@195
  1319
    return new (pool_) FunctionStatement(pos, name, token, body, signature, encounteredReturn_);
dvander@0
  1320
}
dvander@0
  1321
dvander@145
  1322
static inline bool
dvander@167
  1323
DeclareIntrinsicType(Zone *zone, Scope *scope, const char *name, Handle<Type> type)
dvander@145
  1324
{
dvander@145
  1325
    Local<String> tag(zone, zone->makeSymbol(name));
dvander@145
  1326
    if (!tag)
dvander@145
  1327
        return false;
dvander@145
  1328
dvander@195
  1329
    assert(false);
dvander@195
  1330
    return false; //return !!scope->declareType(tag, type);
dvander@167
  1331
}
dvander@167
  1332
dvander@167
  1333
static inline bool
dvander@167
  1334
DeclareIntrinsicType(Zone *zone, Scope *scope, const char *name, PrimitiveType type)
dvander@167
  1335
{
dvander@145
  1336
    Local<Type> primitive(zone, zone->types()->getPrimitive(type));
dvander@145
  1337
    assert(primitive);
dvander@167
  1338
    return DeclareIntrinsicType(zone, scope, name, primitive);
dvander@145
  1339
}
dvander@145
  1340
dvander@0
  1341
ParseTree *
dvander@0
  1342
Parser::parse()
dvander@0
  1343
{
dvander@0
  1344
    StatementList *statements = new (pool_) StatementList();
dvander@0
  1345
dvander@0
  1346
    for (;;) {
dvander@0
  1347
        Statement *statement = NULL;
dvander@0
  1348
dvander@135
  1349
        TokenKind kind = scanner_.peek();
dvander@135
  1350
        switch (kind) {
dvander@0
  1351
          case TOK_ERROR:
dvander@0
  1352
            return NULL;
dvander@0
  1353
dvander@0
  1354
          case TOK_EOF:
dvander@0
  1355
            break;
dvander@0
  1356
dvander@0
  1357
          case TOK_NAME:
dvander@63
  1358
            if ((statement = function(TOK_NAME)) == NULL)
dvander@0
  1359
                return NULL;
dvander@0
  1360
            break;
dvander@0
  1361
dvander@195
  1362
          case TOK_IMPORT:
dvander@195
  1363
          {
dvander@195
  1364
            scanner_.scan();
dvander@195
  1365
            if (statements->length())
dvander@195
  1366
                cc_.reportError(scanner_.begin(), Message_ImportsMustBeFirst);
dvander@195
  1367
            ImportStatement *stmt = import();
dvander@195
  1368
            if (!stmt)
dvander@195
  1369
                return NULL;
dvander@195
  1370
            if (!imports_->append(stmt))
dvander@195
  1371
                return NULL;
dvander@195
  1372
            if (!matchSemicolon())
dvander@195
  1373
                return NULL;
dvander@195
  1374
            continue;
dvander@195
  1375
          }
dvander@195
  1376
dvander@63
  1377
          case TOK_FORWARD:
dvander@63
  1378
          case TOK_PUBLIC:
dvander@68
  1379
          case TOK_NATIVE:
dvander@134
  1380
          case TOK_STOCK:
dvander@145
  1381
          case TOK_LABEL:
dvander@174
  1382
          case TOK_TYPEDEF:
dvander@63
  1383
          {
dvander@195
  1384
            if (kind != TOK_LABEL)
dvander@195
  1385
                scanner_.scan();
dvander@170
  1386
            if (kind == TOK_PUBLIC && peek(TOK_CONST)) {
dvander@241
  1387
                if ((statement = var(TypeQual_Const)) == NULL)
dvander@170
  1388
                    return NULL;
dvander@170
  1389
                if (!matchSemicolon())
dvander@170
  1390
                    return NULL;
dvander@170
  1391
            } else {
dvander@170
  1392
                if ((statement = function(kind)) == NULL)
dvander@170
  1393
                    return NULL;
dvander@174
  1394
                if ((kind == TOK_FORWARD || kind == TOK_NATIVE || kind == TOK_TYPEDEF) && !matchSemicolon())
dvander@170
  1395
                    return NULL;
dvander@170
  1396
            }
dvander@63
  1397
            break;
dvander@63
  1398
          }
dvander@63
  1399
dvander@135
  1400
          case TOK_CONST:
dvander@85
  1401
          case TOK_NEW:
dvander@85
  1402
          {
dvander@241
  1403
            TypeQualifiers quals = (kind == TOK_CONST) ? TypeQual_Const : TypeQual_None;
dvander@165
  1404
            // Note: at global scope, we don't accept comma-delimited
dvander@165
  1405
            // declarations yet, to see if we can get away with forcing
dvander@165
  1406
            // a nicer top-level style.
dvander@135
  1407
            scanner_.scan();
dvander@195
  1408
            if ((statement = var(quals)) == NULL)
dvander@170
  1409
                return NULL;
dvander@85
  1410
            if (!matchSemicolon())
dvander@85
  1411
                return NULL;
dvander@85
  1412
            break;
dvander@85
  1413
          }
dvander@74
  1414
dvander@2
  1415
          case TOK_ENUM:
dvander@2
  1416
            if ((statement = enum_()) == NULL)
dvander@2
  1417
                return NULL;
dvander@63
  1418
            if (!matchSemicolon())
dvander@63
  1419
                return NULL;
dvander@2
  1420
            break;
dvander@2
  1421
dvander@146
  1422
          case TOK_STRUCT:
dvander@146
  1423
            if ((statement = struct_()) == NULL)
dvander@146
  1424
                return NULL;
dvander@146
  1425
            if (!matchSemicolon())
dvander@146
  1426
                return NULL;
dvander@146
  1427
            break;
dvander@146
  1428
dvander@0
  1429
          default:
dvander@63
  1430
            cc_.reportError(scanner_.begin(), Message_ExpectedGlobal);
dvander@0
  1431
            return NULL;
dvander@0
  1432
        }
dvander@0
  1433
dvander@0
  1434
        if (!statement)
dvander@0
  1435
            break;
dvander@0
  1436
dvander@56
  1437
        if (!statements->append(statement))
dvander@56
  1438
            return NULL;
dvander@0
  1439
    }
dvander@0
  1440
dvander@195
  1441
    return new (pool_) ParseTree(statements, unbound_, imports_);
dvander@0
  1442
}
dvander@0
  1443
dvander@0
  1444
class AstPrinter : public AstVisitor
dvander@0
  1445
{
dvander@0
  1446
    FILE *fp_;
dvander@0
  1447
    size_t level_;
dvander@0
  1448
dvander@0
  1449
  private:
dvander@0
  1450
    void prefix() {
dvander@0
  1451
        for (size_t i = 0; i < level_; i++)
dvander@0
  1452
            fprintf(fp_, "  ");
dvander@0
  1453
    }
dvander@0
  1454
    void indent() {
dvander@0
  1455
        level_++;
dvander@0
  1456
    }
dvander@0
  1457
    void unindent() {
dvander@0
  1458
        level_--;
dvander@0
  1459
    }
dvander@0
  1460
dvander@0
  1461
  public:
dvander@0
  1462
    AstPrinter(FILE *fp)
dvander@0
  1463
      : fp_(fp),
dvander@0
  1464
        level_(0)
dvander@0
  1465
    {
dvander@0
  1466
    }
dvander@0
  1467
dvander@191
  1468
    void dump(const FunctionSignature &sig) {
dvander@191
  1469
        prefix();
dvander@191
  1470
        fprintf(fp_, "()\n");
dvander@191
  1471
    }
dvander@195
  1472
    void visitNameProxy(NameProxy *name) {
dvander@0
  1473
        prefix();
dvander@195
  1474
        fprintf(fp_, "[ NameProxy (%s)\n", name->name()->chars());
dvander@0
  1475
    }
dvander@195
  1476
    void visitCallExpression(CallExpression *node) {
dvander@0
  1477
        prefix();
dvander@0
  1478
        fprintf(fp_, "[ CallExpression\n");
dvander@0
  1479
        indent();
dvander@0
  1480
        node->callee()->accept(this);
dvander@55
  1481
        for (size_t i = 0; i < node->arguments()->length(); i++)
dvander@0
  1482
            node->arguments()->at(i)->accept(this);
dvander@0
  1483
        unindent();
dvander@0
  1484
    }
dvander@195
  1485
    void visitFunctionTypeStatement(FunctionTypeStatement *node) {
dvander@174
  1486
        prefix();
dvander@195
  1487
        fprintf(fp_, "[ FunctionTypeStatement (%s)\n", node->name()->chars());
dvander@191
  1488
        indent();
dvander@191
  1489
        dump(node->signature());
dvander@191
  1490
        unindent();
dvander@174
  1491
    }
dvander@195
  1492
    void visitFunctionStatement(FunctionStatement *node) {
dvander@0
  1493
        prefix();
dvander@195
  1494
        fprintf(fp_, "[ FunctionStatement (%s)\n", node->name()->chars());
dvander@0
  1495
        indent();
dvander@191
  1496
        dump(node->signature());
dvander@63
  1497
        if (node->body())
dvander@63
  1498
            node->body()->accept(this);
dvander@0
  1499
        unindent();
dvander@0
  1500
    }
dvander@195
  1501
    void visitExpressionStatement(ExpressionStatement *node) {
dvander@0
  1502
        prefix();
dvander@0
  1503
        fprintf(fp_, "[ ExpressionStatement\n");
dvander@0
  1504
        indent();
dvander@0
  1505
        node->expression()->accept(this);
dvander@0
  1506
        unindent();
dvander@0
  1507
    }
dvander@195
  1508
    void visitAssignment(Assignment *node) {
dvander@0
  1509
        prefix();
dvander@0
  1510
        fprintf(fp_, "[ Assignment\n");
dvander@0
  1511
        indent();
dvander@0
  1512
        node->lvalue()->accept(this);
dvander@0
  1513
        node->expression()->accept(this);
dvander@0
  1514
        unindent();
dvander@0
  1515
    }
dvander@195
  1516
    void visitTernaryExpression(TernaryExpression *node) {
dvander@83
  1517
        prefix();
dvander@83
  1518
        fprintf(fp_, "[ TernaryExpression\n");
dvander@83
  1519
        indent();
dvander@83
  1520
        node->condition()->accept(this);
dvander@83
  1521
        node->left()->accept(this);
dvander@83
  1522
        node->right()->accept(this);
dvander@83
  1523
        unindent();
dvander@83
  1524
    }
dvander@195
  1525
    void visitBinaryExpression(BinaryExpression *node) {
dvander@0
  1526
        prefix();
dvander@0
  1527
        fprintf(fp_, "[ BinaryExpression (%s)\n", TokenNames[node->token()]);
dvander@0
  1528
        indent();
dvander@0
  1529
        node->left()->accept(this);
dvander@0
  1530
        node->right()->accept(this);
dvander@0
  1531
        unindent();
dvander@0
  1532
    }
dvander@195
  1533
    void visitUnaryExpression(UnaryExpression *node) {
dvander@78
  1534
        prefix();
dvander@78
  1535
        fprintf(fp_, "[ UnaryExpression (%s)\n", TokenNames[node->token()]);
dvander@78
  1536
        indent();
dvander@78
  1537
        node->expression()->accept(this);
dvander@78
  1538
        unindent();
dvander@78
  1539
    }
dvander@195
  1540
    void visitReturnStatement(ReturnStatement *node) {
dvander@0
  1541
        prefix();
dvander@0
  1542
        fprintf(fp_, "[ ReturnStatement\n");
dvander@0
  1543
        indent();
dvander@72
  1544
        if (node->expression())
dvander@72
  1545
            node->expression()->accept(this);
dvander@0
  1546
        unindent();
dvander@0
  1547
    }
dvander@195
  1548
    void visitForStatement(ForStatement *node) {
dvander@0
  1549
        prefix();
dvander@0
  1550
        fprintf(fp_, "[ ForStatement\n");
dvander@0
  1551
        indent();
dvander@22
  1552
        if (node->initialization())
dvander@22
  1553
            node->initialization()->accept(this);
dvander@0
  1554
        if (node->condition())
dvander@0
  1555
            node->condition()->accept(this);
dvander@0
  1556
        if (node->update())
dvander@0
  1557
            node->update()->accept(this);
dvander@0
  1558
        node->body()->accept(this);
dvander@0
  1559
        unindent();
dvander@0
  1560
    }
dvander@195
  1561
    void visitBlockStatement(BlockStatement *node) {
dvander@0
  1562
        prefix();
dvander@0
  1563
        fprintf(fp_, "[ BlockStatement\n");
dvander@0
  1564
        indent();
dvander@0
  1565
        for (size_t i = 0; i < node->statements()->length(); i++)
dvander@0
  1566
            node->statements()->at(i)->accept(this);
dvander@0
  1567
        unindent();
dvander@0
  1568
    }
dvander@195
  1569
    void visitVariableDeclaration(VariableDeclaration *node) {
dvander@0
  1570
        prefix();
dvander@195
  1571
        fprintf(fp_, "[ VariableDeclaration (%s)\n", node->name()->chars());
dvander@0
  1572
        indent();
dvander@0
  1573
        if (node->initialization())
dvander@0
  1574
            node->initialization()->accept(this);
dvander@0
  1575
        unindent();
dvander@0
  1576
    }
dvander@195
  1577
    void visitIntegerLiteral(IntegerLiteral *node) {
dvander@0
  1578
        prefix();
dvander@4
  1579
        fprintf(fp_, "[ IntegerLiteral (%d)\n", node->value());
dvander@4
  1580
    }
dvander@195
  1581
    void visitBooleanLiteral(BooleanLiteral *node) {
dvander@143
  1582
        prefix();
dvander@143
  1583
        fprintf(fp_, "[ BooleanLiteral (%s)\n",
dvander@143
  1584
                (node->token() == TOK_TRUE) ? "true" : "false");
dvander@143
  1585
    }
dvander@195
  1586
    void visitFloatLiteral(FloatLiteral *node) {
dvander@4
  1587
        prefix();
dvander@4
  1588
        fprintf(fp_, "[ FloatLiteral (%f)\n", node->value());
dvander@0
  1589
    }
dvander@195
  1590
    void visitIfStatement(IfStatement *node) {
dvander@0
  1591
        prefix();
dvander@0
  1592
        fprintf(fp_, "[ IfStatement\n");
dvander@0
  1593
        indent();
dvander@0
  1594
        node->ifTrue()->accept(this);
dvander@0
  1595
        if (node->ifFalse())
dvander@0
  1596
            node->ifFalse()->accept(this);
dvander@0
  1597
        unindent();
dvander@0
  1598
    }
dvander@195
  1599
    void visitIndexExpression(IndexExpression *node) {
dvander@0
  1600
        prefix();
dvander@0
  1601
        fprintf(fp_, "[ IndexExpression\n");
dvander@0
  1602
        indent();
dvander@0
  1603
        node->left()->accept(this);
dvander@0
  1604
        node->right()->accept(this);
dvander@0
  1605
        unindent();
dvander@0
  1606
    }
dvander@195
  1607
    void visitEnumStatement(EnumStatement *node) {
dvander@2
  1608
        prefix();
dvander@54
  1609
        fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name()->chars() : "<anonymous>");
dvander@2
  1610
        indent();
dvander@57
  1611
        for (size_t i = 0; i < node->entries()->length(); i++) {
dvander@2
  1612
            prefix();
dvander@195
  1613
            fprintf(fp_, "%s =\n", node->entries()->at(i).name->chars());
dvander@2
  1614
            if (node->entries()->at(i).expr) {
dvander@2
  1615
                indent();
dvander@2
  1616
                node->entries()->at(i).expr->accept(this);
dvander@2
  1617
                unindent();
dvander@2
  1618
            }
dvander@2
  1619
        }
dvander@2
  1620
        unindent();
dvander@2
  1621
    }
dvander@195
  1622
    void visitWhileStatement(WhileStatement *node) {
dvander@9
  1623
        prefix();
dvander@9
  1624
        fprintf(fp_, "[ WhileStatement (%s)\n",
dvander@9
  1625
                (node->token() == TOK_DO) ? "do" : "while");
dvander@9
  1626
        indent();
dvander@9
  1627
        if (node->token() == TOK_DO) {
dvander@9
  1628
            node->condition()->accept(this);
dvander@9
  1629
            node->body()->accept(this);
dvander@9
  1630
        } else {
dvander@9
  1631
            node->condition()->accept(this);
dvander@9
  1632
            node->body()->accept(this);
dvander@9
  1633
        }
dvander@9
  1634
        unindent();
dvander@9
  1635
    }
dvander@195
  1636
    void visitBreakStatement(BreakStatement *node) {
dvander@10
  1637
        prefix();
dvander@10
  1638
        fprintf(fp_, "[ BreakStatement\n");
dvander@10
  1639
    }
dvander@195
  1640
    void visitContinueStatement(ContinueStatement *node) {
dvander@10
  1641
        prefix();
dvander@10
  1642
        fprintf(fp_, "[ ContinueStatement\n");
dvander@10
  1643
    }
dvander@195
  1644
    void visitStringLiteral(StringLiteral *node) {
dvander@21
  1645
        prefix();
dvander@21
  1646
        fprintf(fp_, "[ StringLiteral\n");
dvander@21
  1647
    }
dvander@195
  1648
    void visitIncDecExpression(IncDecExpression *node) {
dvander@23
  1649
        prefix();
dvander@23
  1650
        fprintf(fp_, "[ IncDecExpression (postfix=%d)\n", node->postfix());
dvander@23
  1651
        indent();
dvander@23
  1652
        node->expression()->accept(this);
dvander@23
  1653
        unindent();
dvander@23
  1654
    }
dvander@195
  1655
    void visitStructureStatement(StructureStatement *node) {
dvander@146
  1656
        prefix();
dvander@195
  1657
        fprintf(fp_, "[ StructureStatement %s\n", node->name()->chars());
dvander@148
  1658
    }
dvander@195
  1659
    void visitFieldExpression(FieldExpression *node) {
dvander@148
  1660
        prefix();
dvander@148
  1661
        fprintf(fp_, "[ FieldExpression %s\n", node->field()->chars());
dvander@148
  1662
        indent();
dvander@148
  1663
        node->left()->accept(this);
dvander@148
  1664
        unindent();
dvander@146
  1665
    }
dvander@195
  1666
    void visitSwitchStatement(SwitchStatement *node) {
dvander@172
  1667
        prefix();
dvander@172
  1668
        fprintf(fp_, "[ SwitchStatement\n");
dvander@172
  1669
        indent();
dvander@172
  1670
        node->expression()->accept(this);
dvander@172
  1671
        for (size_t i = 0; i < node->cases()->length(); i++) {
dvander@172
  1672
            Case *c = node->cases()->at(i);
dvander@172
  1673
            c->expression()->accept(this);
dvander@172
  1674
            if (c->others()) {
dvander@172
  1675
                for (size_t j = 0; j < c->others()->length(); j++)
dvander@172
  1676
                    c->others()->at(j)->accept(this);
dvander@172
  1677
            }
dvander@172
  1678
            indent();
dvander@172
  1679
            c->statement()->accept(this);
dvander@172
  1680
            unindent();
dvander@172
  1681
        }
dvander@172
  1682
        if (node->defaultCase())
dvander@172
  1683
            node->defaultCase()->accept(this);
dvander@172
  1684
        unindent();
dvander@172
  1685
    }
dvander@195
  1686
    void visitArrayLiteral(ArrayLiteral *node) {
dvander@187
  1687
        prefix();
dvander@187
  1688
        fprintf(fp_, "[ ArrayLiteral\n");
dvander@187
  1689
        indent();
dvander@187
  1690
        for (size_t i = 0; i < node->expressions()->length(); i++) {
dvander@187
  1691
            Expression *expr = node->expressions()->at(i);
dvander@187
  1692
            indent();
dvander@187
  1693
            expr->accept(this);
dvander@187
  1694
            unindent();
dvander@187
  1695
        }
dvander@187
  1696
    }
dvander@195
  1697
    void visitImportStatement(ImportStatement *node) {
dvander@195
  1698
        prefix();
dvander@195
  1699
        fprintf(fp_, "[ ImportStatement\n");
dvander@195
  1700
    }
dvander@0
  1701
};
dvander@0
  1702
dvander@0
  1703
void
dvander@0
  1704
ParseTree::dump(FILE *fp)
dvander@0
  1705
{
dvander@0
  1706
    AstPrinter printer(fp);
dvander@0
  1707
dvander@0
  1708
    for (size_t i = 0; i < statements_->length(); i++)
dvander@0
  1709
        statements_->at(i)->accept(&printer);
dvander@0
  1710
}