src/compiler/Parser.cpp
author David Anderson <dvander@alliedmods.net>
Sat Nov 17 18:41:01 2012 -0800 (2012-11-17)
changeset 195 c1ba166f3fc4
parent 194 src/Parser.cpp@b029d63565a2
child 209 5cbec15fadfe
permissions -rw-r--r--
Massive SemA/BC refactoring to support better type systems. Read on for more.

The previous compiler had a simple pipeline, best outlined as:
(1) Parsing and name binding -> AST
(2) Storage allocation -> AST
(3) Semantic Analysis (SemA) -> AST
(4) Bytecode Compilation (BC) -> Code

This pipeline, unfortunately, had two problems. First, name binding cannot be performed in one pass if we wish to have multi-file support in the form of modules. Name binding must be two-pass.

Second, because SemA was only capable of annotating AST nodes with a single type, most coercion work had to be duplicated in the BC phase, as coercion was not explicit in the SemA output. This made introducing new type rules extremely difficult, and all but precluded concepts like operator overloading (or overloading at all).

This patch rewrites most of Keima's backend. Of interest are the following changes:
(1) CompileContext has been refactored around future multi-file support.
(2) Parsing no longer performs any name binding.
(3) The grammar for type-and-name has been changed from:
(Label | Identifier)? Identifier
to:
Type? Identifier
where:
Type ::= OldType | NewType
OldType ::= Label
NewType ::= Identifier (. NewType)*


Although we do not implement the full production for Type yet, this
distinction is important. A type identifier is now affixed to the AST
as an Expression (right now, always a NameProxy), so it can fully
participate in name binding.

(4) Immediately after parsing, the AST goes through a NamePopulation phase.
This phase creates Scope objects for every scope which declares a name,
and if those names are declaring types or functions, a Symbol is created
and entered into the scope. Symbols entirely replace the old BoundName
classes.

(5) After NamePopulation comes NameBinding. This phase performs three steps:
(a) Links Scope objects together, to form a tree.
(b) Binds any free name to an existing name in the scope chain.
(c) Creates and registers any Symbols for names which have not yet been
added to the scope (for example, local variables).

In accordance, all "allocation" and "binding" concepts have been removed
from Scopes, which are now lightweight container classes.

(6) SemA now generates bytecode for each statement in the AST. Expression
compilation is performed via a separate mechanism called HIR (High-level
Intermediate Representation). To analyze an expression, SemA will walk
the AST, and produce a HIR object for each node. HIR is typed, and SemA
may insert coercion nodes, or even expand an AST node into multiple HIR
nodes. The result of evaluating an expression in SemA is therefore the
the root of a HIR tree, which SemA then sends to the HIRTranslator, which
performs bytecode generation.

As before, SemA still performs full semantic analysis. However, not it
also produces each function's bytecode.

This split allows us to decompose potentially complex semantics into
a more fine-grained, AST-like structure, which can have very simple
code-generation logic. For example, (1.0 + 5) might look like:

HAdd(HFloat(1.0), HConvert(HInteger(5), <Float>))

As part of this decomposition, many opcodes have been removed. Rather than
using typed jumps, we now expand jumps into longer tests. For example:
jge.f <label>
becomes:
ge.f
cvt.f2b
jt <label>

This simplifies the pipeline, and JITs should be able to melt the added
work away.

HIR is not used at a statement level, and HIR does not have any concept
of control-flow.

(7) The old BytecodeCompiler has been removed, as its work is now split
between SemA and HIRTranslator.


In addition, some minor refactorings have taken place:

(1) Opcodes.tbl no longer hardcodes numbers (aaah).
(2) Type has been split into smaller, typed structs.
(3) BytecodeEmitter no longer relies on Pools or RootScopes.
(4) SemA is now responsible for variable/storage allocation.
(5) Native table are now global, rather than per-module. As such, native
declarations now result in a Native object (which still requires a
CALLNATIVE opcode), which is an index into the global table. Natives
must be bound globally. This is in preparation for module support.
(6) Publics are no longer tracked, but rather registered via a global
callback upon module load. This callback can be set by embedders. This
is in preparation for multi-file support.
(7) The BytecodeEmitter now performs Symbol allocations itself, and it
also generates Code objects itself, which removes a good deal of
complexity.

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