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