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