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