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