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