jitcraft/Parser.cpp
author David Anderson <dvander@alliedmods.net>
Sat Jun 30 22:45:25 2012 -0700 (2012-06-30)
changeset 16 23627f8bc421
parent 14 0784ac5cc347
child 21 af5d8e985502
permissions -rw-r--r--
Added support for arbitrary expression references.
dvander@0
     1
/*
dvander@0
     2
 * Copyright (C) 2012 David Anderson
dvander@0
     3
 *
dvander@0
     4
 * This file is part of JITCraft.
dvander@0
     5
 *
dvander@0
     6
 * JITCraft is free software: you can redistribute it and/or modify it under
dvander@0
     7
 * the terms of the GNU General Public License as published by the Free
dvander@0
     8
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@0
     9
 * any later version.
dvander@0
    10
 * 
dvander@0
    11
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@0
    12
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@0
    13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@0
    14
 *
dvander@0
    15
 * You should have received a copy of the GNU General Public License along with
dvander@0
    16
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@0
    17
 */
dvander@0
    18
#include "Zone.h"
dvander@0
    19
#include "Parser.h"
dvander@0
    20
dvander@0
    21
using namespace jc;
dvander@0
    22
dvander@0
    23
Parser::Parser(const char *stream, size_t length)
dvander@0
    24
  : pool_(ZONE()->pool()),
dvander@0
    25
    strings_(pool_),
dvander@0
    26
    scanner_(stream, length),
dvander@0
    27
    scope_(NULL),
dvander@0
    28
    unbound_(NULL)
dvander@0
    29
{
dvander@0
    30
    unbound_ = new std::vector<NameProxy *>();
dvander@0
    31
}
dvander@0
    32
dvander@0
    33
bool
dvander@0
    34
Parser::match(TokenKind kind)
dvander@0
    35
{
dvander@0
    36
    if (scanner_.peek() != kind)
dvander@0
    37
        return false;
dvander@0
    38
    scanner_.scan();
dvander@0
    39
    return true;
dvander@0
    40
}
dvander@0
    41
dvander@0
    42
bool
dvander@0
    43
Parser::expect(TokenKind kind)
dvander@0
    44
{
dvander@0
    45
    TokenKind got = scanner_.scan();
dvander@0
    46
    if (got == kind)
dvander@0
    47
        return true;
dvander@0
    48
    fprintf(stderr, "error: expected %s, got %s\n", TokenNames[kind], TokenNames[got]);
dvander@0
    49
    return false;
dvander@0
    50
}
dvander@0
    51
dvander@0
    52
Scope *
dvander@0
    53
Parser::enterScope(Scope::Kind kind)
dvander@0
    54
{
dvander@0
    55
    scope_ = new (pool_) Scope(pool_, kind, scope_);
dvander@0
    56
    if (!scope_->initialize())
dvander@0
    57
        return NULL;
dvander@0
    58
    return scope_;
dvander@0
    59
}
dvander@0
    60
dvander@0
    61
NameProxy *
dvander@0
    62
Parser::bind(Name *name)
dvander@0
    63
{
dvander@0
    64
    BoundName *bound = scope_->lookup(name);
dvander@0
    65
    NameProxy *proxy = new (pool_) NameProxy(name, bound);
dvander@0
    66
    if (!bound)
dvander@0
    67
        unbound_->push_back(proxy);
dvander@0
    68
    return proxy;
dvander@0
    69
}
dvander@0
    70
dvander@4
    71
bool
dvander@4
    72
Parser::matchName(Name **name, TokenKind kind)
dvander@4
    73
{
dvander@4
    74
    assert(kind == TOK_NAME || kind == TOK_LABEL);
dvander@4
    75
    *name = NULL;
dvander@4
    76
    if (!match(kind))
dvander@4
    77
        return false;
dvander@4
    78
    *name = strings_.add(scanner_.literal());
dvander@4
    79
    return true;
dvander@4
    80
}
dvander@4
    81
dvander@4
    82
Name *
dvander@4
    83
Parser::expectName()
dvander@4
    84
{
dvander@4
    85
    if (!expect(TOK_NAME))
dvander@4
    86
        return NULL;
dvander@4
    87
    return strings_.add(scanner_.literal());
dvander@4
    88
}
dvander@4
    89
dvander@0
    90
Expression *
dvander@0
    91
Parser::primitive()
dvander@0
    92
{
dvander@0
    93
    switch (scanner_.peek()) {
dvander@0
    94
      case TOK_NAME:
dvander@0
    95
      {
dvander@0
    96
        scanner_.scan();
dvander@0
    97
        Name *name = strings_.add(scanner_.literal());
dvander@0
    98
        return bind(name);
dvander@0
    99
      }
dvander@0
   100
dvander@4
   101
      case TOK_FLOAT_LITERAL:
dvander@4
   102
      {
dvander@4
   103
        scanner_.scan();
dvander@4
   104
        double value = Scanner::ParseDouble(scanner_.literal());
dvander@4
   105
        return new (pool_) FloatLiteral(value);
dvander@4
   106
      }
dvander@4
   107
dvander@0
   108
      case TOK_INTEGER_LITERAL:
dvander@0
   109
      {
dvander@0
   110
        scanner_.scan();
dvander@0
   111
        int value = atoi(scanner_.literal());
dvander@4
   112
        return new (pool_) IntegerLiteral(value);
dvander@0
   113
      }
dvander@0
   114
dvander@0
   115
      default:
dvander@0
   116
      {
dvander@0
   117
        fprintf(stderr, "error: expected expression!\n");
dvander@0
   118
        return NULL;
dvander@0
   119
      }
dvander@0
   120
    }
dvander@0
   121
}
dvander@0
   122
dvander@0
   123
Expression *
dvander@0
   124
Parser::prefix()
dvander@0
   125
{
dvander@0
   126
    switch (scanner_.peek()) {
dvander@0
   127
      case TOK_LPAREN:
dvander@0
   128
      {
dvander@0
   129
        scanner_.scan();
dvander@0
   130
        Expression *expr = expression();
dvander@0
   131
        if (!expr)
dvander@0
   132
            return NULL;
dvander@0
   133
        if (!expect(TOK_RPAREN))
dvander@0
   134
            return NULL;
dvander@0
   135
        return expr;
dvander@0
   136
      }
dvander@0
   137
dvander@0
   138
      default:
dvander@0
   139
        return primitive();
dvander@0
   140
    }
dvander@0
   141
}
dvander@0
   142
dvander@0
   143
Expression *
dvander@0
   144
Parser::call(Expression *callee)
dvander@0
   145
{
dvander@0
   146
    ExpressionList *arguments = new ExpressionList();
dvander@0
   147
dvander@0
   148
    expect(TOK_LPAREN);
dvander@0
   149
    
dvander@0
   150
    if (!match(TOK_RPAREN)) {
dvander@0
   151
        while (true) {
dvander@0
   152
            Expression *expr = expression();
dvander@0
   153
            if (!expr)
dvander@0
   154
                return NULL;
dvander@0
   155
dvander@0
   156
            arguments->push_back(expr);
dvander@0
   157
dvander@0
   158
            if (!match(TOK_COMMA))
dvander@0
   159
                break;
dvander@0
   160
        }
dvander@0
   161
dvander@0
   162
        if (!expect(TOK_RPAREN))
dvander@0
   163
            return NULL;
dvander@0
   164
    }
dvander@0
   165
dvander@0
   166
    return new (pool_) CallExpression(callee, arguments);
dvander@0
   167
}
dvander@0
   168
dvander@0
   169
Expression *
dvander@0
   170
Parser::index(Expression *left)
dvander@0
   171
{
dvander@0
   172
    expect(TOK_LBRACKET);
dvander@0
   173
    
dvander@0
   174
    Expression *expr = expression();
dvander@0
   175
    if (!expr)
dvander@0
   176
        return NULL;
dvander@0
   177
dvander@0
   178
    if (!expect(TOK_RBRACKET))
dvander@0
   179
        return NULL;
dvander@0
   180
dvander@0
   181
    return new (pool_) IndexExpression(left, expr);
dvander@0
   182
}
dvander@0
   183
dvander@0
   184
Expression *
dvander@0
   185
Parser::primary()
dvander@0
   186
{
dvander@0
   187
    Expression *expr = prefix();
dvander@0
   188
    if (!expr)
dvander@0
   189
        return NULL;
dvander@0
   190
dvander@0
   191
    for (;;) {
dvander@0
   192
        switch (scanner_.peek()) {
dvander@0
   193
          case TOK_LPAREN:
dvander@0
   194
            expr = call(expr);
dvander@0
   195
            if (!expr)
dvander@0
   196
                return NULL;
dvander@0
   197
            break;
dvander@0
   198
dvander@0
   199
          case TOK_LBRACKET:
dvander@0
   200
            expr = index(expr);
dvander@0
   201
            if (!expr)
dvander@0
   202
                return NULL;
dvander@0
   203
            break;
dvander@0
   204
dvander@0
   205
          default:
dvander@0
   206
            return expr;
dvander@0
   207
        }
dvander@0
   208
    }
dvander@0
   209
}
dvander@0
   210
dvander@0
   211
Expression *
dvander@0
   212
Parser::unary()
dvander@0
   213
{
dvander@0
   214
    return primary();
dvander@0
   215
}
dvander@0
   216
dvander@0
   217
Expression *
dvander@0
   218
Parser::multiplication()
dvander@0
   219
{
dvander@0
   220
    Expression *left = unary();
dvander@0
   221
    do {
dvander@0
   222
        if (!match(TOK_SLASH) && !match(TOK_STAR))
dvander@0
   223
            break;
dvander@0
   224
        TokenKind kind = scanner_.last();
dvander@0
   225
        Expression *right = unary();
dvander@0
   226
        if (!right)
dvander@0
   227
            return NULL;
dvander@0
   228
        left = new (pool_) BinaryExpression(kind, left, right);
dvander@0
   229
    } while (left);
dvander@0
   230
    return left;
dvander@0
   231
}
dvander@0
   232
dvander@0
   233
Expression *
dvander@0
   234
Parser::addition()
dvander@0
   235
{
dvander@0
   236
    Expression *left = multiplication();
dvander@0
   237
    while (left) {
dvander@0
   238
        if (!match(TOK_PLUS) && !match(TOK_MINUS))
dvander@0
   239
            break;
dvander@0
   240
        TokenKind kind = scanner_.last();
dvander@0
   241
        Expression *right = multiplication();
dvander@0
   242
        if (!right)
dvander@0
   243
            return NULL;
dvander@0
   244
        left = new (pool_) BinaryExpression(kind, left, right);
dvander@0
   245
    }
dvander@0
   246
    return left;
dvander@0
   247
}
dvander@0
   248
dvander@0
   249
Expression *
dvander@2
   250
Parser::shift()
dvander@2
   251
{
dvander@2
   252
    Expression *left = addition();
dvander@2
   253
    while (left) {
dvander@8
   254
        if (!match(TOK_SHL) && !match(TOK_SHR) && !match(TOK_USHR))
dvander@2
   255
            break;
dvander@2
   256
        TokenKind kind = scanner_.last();
dvander@2
   257
        Expression *right = addition();
dvander@2
   258
        if (!right)
dvander@2
   259
            return NULL;
dvander@2
   260
        left = new (pool_) BinaryExpression(kind, left, right);
dvander@2
   261
    }
dvander@2
   262
    return left;
dvander@2
   263
}
dvander@2
   264
dvander@2
   265
Expression *
dvander@8
   266
Parser::bitand()
dvander@8
   267
{
dvander@8
   268
    Expression *left = shift();
dvander@8
   269
    while (left) {
dvander@8
   270
        if (!match(TOK_BITAND))
dvander@8
   271
            break;
dvander@8
   272
        Expression *right = shift();
dvander@8
   273
        if (!right)
dvander@8
   274
            return NULL;
dvander@8
   275
        left = new (pool_) BinaryExpression(TOK_BITAND, left, right);
dvander@8
   276
    }
dvander@8
   277
    return left;
dvander@8
   278
}
dvander@8
   279
dvander@8
   280
Expression *
dvander@8
   281
Parser::bitxor()
dvander@8
   282
{
dvander@8
   283
    Expression *left = bitand();
dvander@8
   284
    while (left) {
dvander@8
   285
        if (!match(TOK_BITXOR))
dvander@8
   286
            break;
dvander@8
   287
        Expression *right = shift();
dvander@8
   288
        if (!right)
dvander@8
   289
            return NULL;
dvander@8
   290
        left = new (pool_) BinaryExpression(TOK_BITXOR, left, right);
dvander@8
   291
    }
dvander@8
   292
    return left;
dvander@8
   293
}
dvander@8
   294
dvander@8
   295
Expression *
dvander@8
   296
Parser::bitor()
dvander@8
   297
{
dvander@8
   298
    Expression *left = bitxor();
dvander@8
   299
    while (left) {
dvander@8
   300
        if (!match(TOK_BITOR))
dvander@8
   301
            break;
dvander@8
   302
        Expression *right = shift();
dvander@8
   303
        if (!right)
dvander@8
   304
            return NULL;
dvander@8
   305
        left = new (pool_) BinaryExpression(TOK_BITOR, left, right);
dvander@8
   306
    }
dvander@8
   307
    return left;
dvander@8
   308
}
dvander@8
   309
dvander@8
   310
Expression *
dvander@0
   311
Parser::relational()
dvander@0
   312
{
dvander@8
   313
    Expression *left = bitor();
dvander@0
   314
    while (left) {
dvander@0
   315
        TokenKind kind = scanner_.peek();
dvander@0
   316
        if (kind < TOK_LT || kind > TOK_GE)
dvander@0
   317
            break;
dvander@0
   318
        scanner_.scan();
dvander@2
   319
        Expression *right = shift();
dvander@0
   320
        if (!right)
dvander@0
   321
            return NULL;
dvander@0
   322
        left = new (pool_) BinaryExpression(kind, left, right);
dvander@0
   323
    }
dvander@0
   324
    return left;
dvander@0
   325
}
dvander@0
   326
dvander@0
   327
Expression *
dvander@0
   328
Parser::equals()
dvander@0
   329
{
dvander@0
   330
    Expression *left = relational();
dvander@0
   331
    while (left) {
dvander@0
   332
        if (!match(TOK_EQUALS) && !match(TOK_NOTEQUALS))
dvander@0
   333
            break;
dvander@0
   334
        TokenKind kind = scanner_.last();
dvander@0
   335
        Expression *right = relational();
dvander@0
   336
        if (!right)
dvander@0
   337
            return NULL;
dvander@0
   338
        left = new (pool_) BinaryExpression(kind, left, right);
dvander@0
   339
    }
dvander@0
   340
    return left;
dvander@0
   341
}
dvander@0
   342
dvander@0
   343
Expression *
dvander@0
   344
Parser::expression()
dvander@0
   345
{
dvander@0
   346
    return equals();
dvander@0
   347
}
dvander@0
   348
dvander@0
   349
Statement *
dvander@9
   350
Parser::while_()
dvander@9
   351
{
dvander@9
   352
    scanner_.scan();
dvander@9
   353
dvander@9
   354
    if (!expect(TOK_LPAREN))
dvander@9
   355
        return NULL;
dvander@9
   356
    Expression *condition = expression();
dvander@9
   357
    if (!condition)
dvander@9
   358
        return NULL;
dvander@9
   359
    if (!expect(TOK_RPAREN))
dvander@9
   360
        return NULL;
dvander@9
   361
dvander@9
   362
    Statement *body = localStatement();
dvander@9
   363
    if (!body)
dvander@9
   364
        return NULL;
dvander@9
   365
dvander@9
   366
    return new (pool_) WhileStatement(TOK_WHILE, condition, body);
dvander@9
   367
}
dvander@9
   368
dvander@9
   369
Statement *
dvander@9
   370
Parser::do_()
dvander@9
   371
{
dvander@9
   372
    scanner_.scan();
dvander@9
   373
dvander@9
   374
    Statement *body = block();
dvander@9
   375
    if (!body)
dvander@9
   376
        return NULL;
dvander@9
   377
dvander@9
   378
    if (!expect(TOK_WHILE))
dvander@9
   379
        return NULL;
dvander@9
   380
dvander@9
   381
    if (!expect(TOK_LPAREN))
dvander@9
   382
        return NULL;
dvander@9
   383
    Expression *condition = expression();
dvander@9
   384
    if (!condition)
dvander@9
   385
        return NULL;
dvander@9
   386
    if (!expect(TOK_RPAREN))
dvander@9
   387
        return NULL;
dvander@9
   388
dvander@9
   389
    return new (pool_) WhileStatement(TOK_DO, condition, body);
dvander@9
   390
}
dvander@9
   391
dvander@9
   392
Statement *
dvander@0
   393
Parser::forStatement()
dvander@0
   394
{
dvander@0
   395
    scanner_.scan();
dvander@0
   396
    if (!expect(TOK_LPAREN))
dvander@0
   397
        return NULL;
dvander@0
   398
dvander@0
   399
    VariableDeclaration *decl = NULL;
dvander@0
   400
    if (!match(TOK_SEMICOLON)) {
dvander@0
   401
        if (!enterScope(Scope::BLOCK))
dvander@0
   402
            return NULL;
dvander@0
   403
        if ((decl = variableDeclaration()) == NULL)
dvander@0
   404
            return NULL;
dvander@0
   405
        if (!expect(TOK_SEMICOLON))
dvander@0
   406
            return NULL;
dvander@0
   407
    }
dvander@0
   408
dvander@0
   409
    Expression *condition = NULL;
dvander@0
   410
    if (!match(TOK_SEMICOLON)) {
dvander@0
   411
        if ((condition = expression()) == NULL)
dvander@0
   412
            return NULL;
dvander@0
   413
        if (!expect(TOK_SEMICOLON))
dvander@0
   414
            return NULL;
dvander@0
   415
    }
dvander@0
   416
dvander@0
   417
    Statement *update = NULL;
dvander@0
   418
    if (!match(TOK_RPAREN)) {
dvander@0
   419
        if ((update = expressionStatement()) == NULL)
dvander@0
   420
            return NULL;
dvander@0
   421
        if (!expect(TOK_RPAREN))
dvander@0
   422
            return NULL;
dvander@0
   423
    }
dvander@0
   424
dvander@0
   425
    Statement *body = localStatement();
dvander@0
   426
    if (!body)
dvander@0
   427
        return NULL;
dvander@0
   428
dvander@0
   429
    Scope *blockScope = NULL;
dvander@0
   430
    if (decl) {
dvander@0
   431
        blockScope = scope_->unlinkIfEmpty();
dvander@0
   432
        scope_ = scope_->enclosing();
dvander@0
   433
    }
dvander@0
   434
    return new (pool_) ForStatement(blockScope, decl, condition, update, body);
dvander@0
   435
}
dvander@0
   436
dvander@0
   437
VariableDeclaration *
dvander@0
   438
Parser::variableDeclaration()
dvander@0
   439
{
dvander@0
   440
    if (!expect(TOK_NEW))
dvander@0
   441
        return NULL;
dvander@0
   442
dvander@4
   443
    Name *tag;
dvander@4
   444
    if (matchName(&tag, TOK_LABEL) && !tag)
dvander@0
   445
        return NULL;
dvander@4
   446
dvander@4
   447
    Name *name = expectName();
dvander@4
   448
    if (!name)
dvander@4
   449
        return NULL;
dvander@0
   450
dvander@0
   451
    ExpressionList *postDimensions = NULL;
dvander@0
   452
    if (scanner_.peek() == TOK_LBRACKET) {
dvander@0
   453
        postDimensions = new ExpressionList();
dvander@0
   454
        while (match(TOK_LBRACKET)) {
dvander@0
   455
            Expression *dim = expression();
dvander@0
   456
            if (!dim)
dvander@0
   457
                return NULL;
dvander@0
   458
dvander@0
   459
            if (!expect(TOK_RBRACKET))
dvander@0
   460
                return NULL;
dvander@0
   461
dvander@0
   462
            postDimensions->push_back(dim);
dvander@0
   463
        }
dvander@0
   464
    }
dvander@0
   465
    
dvander@0
   466
    Expression *expr = NULL;
dvander@0
   467
    if (match(TOK_ASSIGN)) {
dvander@0
   468
        if ((expr = expression()) == NULL)
dvander@0
   469
            return NULL;
dvander@0
   470
    }
dvander@0
   471
    
dvander@0
   472
    if (scope_->localLookup(name)) {
dvander@0
   473
        redeclarationError();
dvander@0
   474
        return NULL;
dvander@0
   475
    }
dvander@0
   476
dvander@0
   477
    Variable *var = scope_->declareVariable(name);
dvander@4
   478
    VariableDeclaration *decl = new (pool_) VariableDeclaration(var, tag, postDimensions, expr);
dvander@0
   479
dvander@0
   480
    return decl;
dvander@0
   481
}
dvander@0
   482
dvander@0
   483
Statement *
dvander@0
   484
Parser::returnStatement()
dvander@0
   485
{
dvander@0
   486
    if (!expect(TOK_RETURN))
dvander@0
   487
        return NULL;
dvander@0
   488
dvander@0
   489
    Expression *expr = expression();
dvander@0
   490
    if (!expr)
dvander@0
   491
        return NULL;
dvander@0
   492
dvander@0
   493
    return new (pool_) ReturnStatement(expr);
dvander@0
   494
}
dvander@0
   495
dvander@0
   496
Statement *
dvander@0
   497
Parser::expressionStatement()
dvander@0
   498
{
dvander@0
   499
    Expression *left = primary();
dvander@0
   500
    if (!left) {
dvander@0
   501
        fprintf(stderr, "expected expression or statement\n");
dvander@0
   502
        return NULL;
dvander@0
   503
    }
dvander@0
   504
dvander@0
   505
    if (match(TOK_ASSIGN)) {
dvander@0
   506
        Expression *expr = expression();
dvander@0
   507
        if (!expr)
dvander@0
   508
            return NULL;
dvander@0
   509
dvander@0
   510
        left = new (pool_) Assignment(left, expr);
dvander@0
   511
    }
dvander@0
   512
dvander@0
   513
    return new (pool_) ExpressionStatement(left);
dvander@0
   514
}
dvander@0
   515
dvander@0
   516
Statement *
dvander@0
   517
Parser::block()
dvander@0
   518
{
dvander@0
   519
    if (!expect(TOK_LBRACE))
dvander@0
   520
        return NULL;
dvander@0
   521
dvander@0
   522
    if (!enterScope(Scope::BLOCK))
dvander@0
   523
        return NULL;
dvander@0
   524
dvander@0
   525
    StatementList *statements = new (pool_) StatementList();
dvander@0
   526
    while (!match(TOK_RBRACE)) {
dvander@0
   527
        Statement *statement = localStatement();
dvander@0
   528
        if (statement == NULL)
dvander@0
   529
            return NULL;
dvander@0
   530
        statements->append(pool_, statement);
dvander@0
   531
    }
dvander@0
   532
dvander@0
   533
    Scope *blockScope = scope_->unlinkIfEmpty();
dvander@0
   534
    BlockStatement *block = new (pool_) BlockStatement(blockScope, statements);
dvander@0
   535
dvander@0
   536
    scope_ = scope_->enclosing();
dvander@0
   537
    return block;
dvander@0
   538
}
dvander@0
   539
dvander@0
   540
Statement *
dvander@0
   541
Parser::if_()
dvander@0
   542
{
dvander@0
   543
    expect(TOK_IF);
dvander@0
   544
dvander@0
   545
    if (!expect(TOK_LPAREN))
dvander@0
   546
        return NULL;
dvander@0
   547
dvander@0
   548
    Expression *cond = expression();
dvander@0
   549
    if (!cond)
dvander@0
   550
        return NULL;
dvander@0
   551
dvander@0
   552
    if (!expect(TOK_RPAREN))
dvander@0
   553
        return NULL;
dvander@0
   554
dvander@0
   555
    Statement *ifTrue = localStatement();
dvander@0
   556
    if (!ifTrue)
dvander@0
   557
        return NULL;
dvander@0
   558
dvander@0
   559
    IfStatement *outer = new (pool_) IfStatement(cond, ifTrue);
dvander@0
   560
dvander@0
   561
    IfStatement *last = outer;
dvander@0
   562
    while (match(TOK_ELSE)) {
dvander@0
   563
        if (!match(TOK_IF)) {
dvander@0
   564
            Statement *ifFalse = localStatement();
dvander@0
   565
            if (!ifFalse)
dvander@0
   566
                return NULL;
dvander@0
   567
dvander@0
   568
            last->setIfFalse(ifFalse);
dvander@0
   569
            break;
dvander@0
   570
        }
dvander@0
   571
dvander@0
   572
        if (!expect(TOK_IF))
dvander@0
   573
            return false;
dvander@0
   574
dvander@0
   575
        if (!expect(TOK_LPAREN))
dvander@0
   576
            return NULL;
dvander@0
   577
dvander@0
   578
        Expression *otherCond = expression();
dvander@0
   579
        if (!otherCond)
dvander@0
   580
            return NULL;
dvander@0
   581
dvander@0
   582
        if (!expect(TOK_RPAREN))
dvander@0
   583
            return NULL;
dvander@0
   584
dvander@0
   585
        Statement *otherIfTrue = localStatement();
dvander@0
   586
        if (!otherIfTrue)
dvander@0
   587
            return NULL;
dvander@0
   588
dvander@0
   589
        IfStatement *inner = new (pool_) IfStatement(otherCond, otherIfTrue);
dvander@0
   590
        last->setIfFalse(inner);
dvander@0
   591
        last = inner;
dvander@0
   592
    }
dvander@0
   593
dvander@0
   594
    return outer;
dvander@0
   595
}
dvander@0
   596
dvander@0
   597
Statement *
dvander@0
   598
Parser::localStatement()
dvander@0
   599
{
dvander@0
   600
    Statement *statement = NULL;
dvander@0
   601
dvander@0
   602
    // Statements which must be followed by a semicolon will break out of the
dvander@0
   603
    // switch. If they may end in BlockStatements, they'll immediately return.
dvander@0
   604
dvander@0
   605
    switch (scanner_.peek()) {
dvander@0
   606
        case TOK_NEW:
dvander@0
   607
          statement = variableDeclaration();
dvander@0
   608
          break;
dvander@0
   609
dvander@0
   610
        case TOK_FOR:
dvander@0
   611
          return forStatement();
dvander@0
   612
dvander@9
   613
        case TOK_WHILE:
dvander@9
   614
          return while_();
dvander@9
   615
dvander@10
   616
        case TOK_BREAK:
dvander@10
   617
          scanner_.scan();
dvander@10
   618
          statement = new (pool_) BreakStatement();
dvander@10
   619
          break;
dvander@10
   620
dvander@10
   621
        case TOK_CONTINUE:
dvander@10
   622
          scanner_.scan();
dvander@10
   623
          statement = new (pool_) ContinueStatement();
dvander@10
   624
          break;
dvander@10
   625
dvander@9
   626
        case TOK_DO:
dvander@9
   627
          if ((statement = do_()) == NULL)
dvander@9
   628
              return NULL;
dvander@9
   629
          break;
dvander@9
   630
dvander@0
   631
        case TOK_RETURN:
dvander@0
   632
          statement = returnStatement();
dvander@0
   633
          break;
dvander@0
   634
dvander@2
   635
        case TOK_ENUM:
dvander@2
   636
          statement = enum_();
dvander@2
   637
          break;
dvander@2
   638
dvander@0
   639
        case TOK_IF:
dvander@0
   640
          return if_();
dvander@0
   641
dvander@0
   642
        case TOK_LBRACE:
dvander@0
   643
          return block();
dvander@0
   644
    }
dvander@0
   645
dvander@0
   646
    if (!statement) {
dvander@0
   647
        if ((statement = expressionStatement()) == NULL)
dvander@0
   648
            return NULL;
dvander@0
   649
    }
dvander@0
   650
dvander@0
   651
    if (!expect(TOK_SEMICOLON))
dvander@0
   652
        return NULL;
dvander@0
   653
dvander@0
   654
    return statement;
dvander@0
   655
}
dvander@0
   656
dvander@0
   657
Statement *
dvander@2
   658
Parser::enum_()
dvander@2
   659
{
dvander@2
   660
    expect(TOK_ENUM);
dvander@2
   661
dvander@2
   662
    Name *name = NULL;
dvander@2
   663
    if (match(TOK_NAME)) {
dvander@2
   664
        if ((name = strings_.add(scanner_.literal())) == NULL)
dvander@2
   665
            return NULL;
dvander@2
   666
dvander@2
   667
        if (scope_->localLookup(name)) {
dvander@2
   668
            redeclarationError();
dvander@2
   669
            return NULL;
dvander@2
   670
        }
dvander@2
   671
dvander@2
   672
        NamedEnum *e = scope_->declareEnum(name);
dvander@2
   673
        if (!e)
dvander@2
   674
            return NULL;
dvander@2
   675
    }
dvander@2
   676
dvander@2
   677
    EnumStatement::EntryList *entries = new EnumStatement::EntryList();
dvander@2
   678
dvander@2
   679
    if (!expect(TOK_LBRACE))
dvander@2
   680
        return NULL;
dvander@2
   681
dvander@2
   682
    do {
dvander@2
   683
        if (scanner_.peek() == TOK_RBRACE)
dvander@2
   684
            break;
dvander@2
   685
dvander@4
   686
        Name *name = expectName();
dvander@2
   687
        if (!name)
dvander@2
   688
            return NULL;
dvander@2
   689
dvander@2
   690
        if (scope_->localLookup(name)) {
dvander@2
   691
            redeclarationError();
dvander@2
   692
            return NULL;
dvander@2
   693
        }
dvander@2
   694
dvander@2
   695
        NamedConstant *constant = scope_->declareConstant(name);
dvander@2
   696
        if (!constant)
dvander@2
   697
            return NULL;
dvander@2
   698
dvander@2
   699
        Expression *expr = NULL;
dvander@2
   700
        if (match(TOK_ASSIGN)) {
dvander@2
   701
            if ((expr = expression()) == NULL)
dvander@2
   702
                return NULL;
dvander@2
   703
        }
dvander@2
   704
dvander@2
   705
        entries->push_back(EnumStatement::Entry(constant, expr));
dvander@2
   706
    } while (match(TOK_COMMA));
dvander@2
   707
    if (!expect(TOK_RBRACE))
dvander@2
   708
        return NULL;
dvander@2
   709
dvander@2
   710
    return new (pool_) EnumStatement(name, entries);
dvander@2
   711
}
dvander@2
   712
dvander@2
   713
Statement *
dvander@0
   714
Parser::function()
dvander@0
   715
{
dvander@4
   716
    Name *name = expectName();
dvander@0
   717
    if (!name)
dvander@0
   718
        return NULL;
dvander@0
   719
dvander@0
   720
    // The function name goes into the outer (global) scope.
dvander@0
   721
    assert(!scope_->enclosing());
dvander@0
   722
dvander@0
   723
    if (scope_->localLookup(name)) {
dvander@0
   724
        redeclarationError();
dvander@0
   725
        return NULL;
dvander@0
   726
    }
dvander@0
   727
    NamedFunction *fun = scope_->declareFunction(name);
dvander@0
   728
    if (!fun)
dvander@0
   729
        return NULL;
dvander@0
   730
dvander@0
   731
    Scope *scope = enterScope(Scope::FUNCTION);
dvander@0
   732
    if (!scope)
dvander@0
   733
        return NULL;
dvander@0
   734
dvander@14
   735
    ParameterList *parameters = new ParameterList();
dvander@14
   736
dvander@0
   737
    if (!expect(TOK_LPAREN))
dvander@0
   738
        return NULL;
dvander@0
   739
    if (!match(TOK_RPAREN)) {
dvander@0
   740
        while (true) {
dvander@14
   741
            bool ref = match(TOK_AMPERSAND);
dvander@14
   742
dvander@4
   743
            Name *name = expectName();
dvander@0
   744
            if (!name)
dvander@0
   745
                return NULL;
dvander@0
   746
dvander@0
   747
            if (scope_->localLookup(name)) {
dvander@0
   748
                redeclarationError();
dvander@0
   749
                return NULL;
dvander@0
   750
            }
dvander@14
   751
            Variable *arg = scope_->declareArgument(name);
dvander@14
   752
            if (!arg)
dvander@0
   753
                return NULL;
dvander@0
   754
dvander@14
   755
            Parameter *parameter = new (pool_) Parameter(arg, NULL, ref);
dvander@14
   756
            parameters->push_back(parameter);
dvander@14
   757
dvander@0
   758
            if (!match(TOK_COMMA))
dvander@0
   759
                break;
dvander@0
   760
        }
dvander@0
   761
        if (!expect(TOK_RPAREN))
dvander@0
   762
            return NULL;
dvander@0
   763
    }
dvander@0
   764
dvander@0
   765
    Statement *body = block();
dvander@0
   766
    if (!body)
dvander@0
   767
        return NULL;
dvander@0
   768
dvander@0
   769
    scope_ = scope_->enclosing();
dvander@14
   770
    return new (pool_) FunctionStatement(scope, fun, body, parameters);
dvander@0
   771
}
dvander@0
   772
dvander@0
   773
ParseTree *
dvander@0
   774
Parser::parse()
dvander@0
   775
{
dvander@0
   776
    StatementList *statements = new (pool_) StatementList();
dvander@0
   777
dvander@0
   778
    if (!enterScope(Scope::GLOBAL))
dvander@0
   779
        return NULL;
dvander@0
   780
dvander@0
   781
    for (;;) {
dvander@0
   782
        Statement *statement = NULL;
dvander@0
   783
dvander@0
   784
        switch (scanner_.peek()) {
dvander@0
   785
          case TOK_ERROR:
dvander@0
   786
            return NULL;
dvander@0
   787
dvander@0
   788
          case TOK_EOF:
dvander@0
   789
            break;
dvander@0
   790
dvander@0
   791
          case TOK_NAME:
dvander@0
   792
            if ((statement = function()) == NULL)
dvander@0
   793
                return NULL;
dvander@0
   794
            break;
dvander@0
   795
dvander@2
   796
          case TOK_ENUM:
dvander@2
   797
            if ((statement = enum_()) == NULL)
dvander@2
   798
                return NULL;
dvander@2
   799
            // :TODO: require semicolon
dvander@2
   800
            break;
dvander@2
   801
dvander@0
   802
          default:
dvander@0
   803
            fprintf(stderr, "expected function or global variable\n");
dvander@0
   804
            return NULL;
dvander@0
   805
        }
dvander@0
   806
dvander@0
   807
        if (!statement)
dvander@0
   808
            break;
dvander@0
   809
dvander@0
   810
        statements->append(pool_, statement);
dvander@0
   811
    }
dvander@0
   812
dvander@0
   813
    return new (pool_) ParseTree(scope_, statements, unbound_);
dvander@0
   814
}
dvander@0
   815
dvander@0
   816
class AstPrinter : public AstVisitor
dvander@0
   817
{
dvander@0
   818
    FILE *fp_;
dvander@0
   819
    size_t level_;
dvander@0
   820
dvander@0
   821
  private:
dvander@0
   822
    void prefix() {
dvander@0
   823
        for (size_t i = 0; i < level_; i++)
dvander@0
   824
            fprintf(fp_, "  ");
dvander@0
   825
    }
dvander@0
   826
    void indent() {
dvander@0
   827
        level_++;
dvander@0
   828
    }
dvander@0
   829
    void unindent() {
dvander@0
   830
        level_--;
dvander@0
   831
    }
dvander@0
   832
dvander@0
   833
  public:
dvander@0
   834
    AstPrinter(FILE *fp)
dvander@0
   835
      : fp_(fp),
dvander@0
   836
        level_(0)
dvander@0
   837
    {
dvander@0
   838
    }
dvander@0
   839
dvander@0
   840
    void visit(NameProxy *name) {
dvander@0
   841
        prefix();
dvander@0
   842
        fprintf(fp_, "[ NameProxy (%s)%s\n", name->name(),
dvander@0
   843
                (name->binding() ? "" : " unbound"));
dvander@0
   844
    }
dvander@0
   845
    void visit(CallExpression *node) {
dvander@0
   846
        prefix();
dvander@0
   847
        fprintf(fp_, "[ CallExpression\n");
dvander@0
   848
        indent();
dvander@0
   849
        node->callee()->accept(this);
dvander@0
   850
        for (size_t i = 0; i < node->arguments()->size(); i++)
dvander@0
   851
            node->arguments()->at(i)->accept(this);
dvander@0
   852
        unindent();
dvander@0
   853
    }
dvander@0
   854
    void visit(FunctionStatement *node) {
dvander@0
   855
        prefix();
dvander@0
   856
        fprintf(fp_, "[ FunctionStatement (%s)\n", node->fun()->name());
dvander@0
   857
        indent();
dvander@0
   858
        node->body()->accept(this);
dvander@0
   859
        unindent();
dvander@0
   860
    }
dvander@0
   861
    void visit(ExpressionStatement *node) {
dvander@0
   862
        prefix();
dvander@0
   863
        fprintf(fp_, "[ ExpressionStatement\n");
dvander@0
   864
        indent();
dvander@0
   865
        node->expression()->accept(this);
dvander@0
   866
        unindent();
dvander@0
   867
    }
dvander@0
   868
    void visit(Assignment *node) {
dvander@0
   869
        prefix();
dvander@0
   870
        fprintf(fp_, "[ Assignment\n");
dvander@0
   871
        indent();
dvander@0
   872
        node->lvalue()->accept(this);
dvander@0
   873
        node->expression()->accept(this);
dvander@0
   874
        unindent();
dvander@0
   875
    }
dvander@0
   876
    void visit(BinaryExpression *node) {
dvander@0
   877
        prefix();
dvander@0
   878
        fprintf(fp_, "[ BinaryExpression (%s)\n", TokenNames[node->token()]);
dvander@0
   879
        indent();
dvander@0
   880
        node->left()->accept(this);
dvander@0
   881
        node->right()->accept(this);
dvander@0
   882
        unindent();
dvander@0
   883
    }
dvander@0
   884
    void visit(ReturnStatement *node) {
dvander@0
   885
        prefix();
dvander@0
   886
        fprintf(fp_, "[ ReturnStatement\n");
dvander@0
   887
        indent();
dvander@0
   888
        node->expression()->accept(this);
dvander@0
   889
        unindent();
dvander@0
   890
    }
dvander@0
   891
    void visit(ForStatement *node) {
dvander@0
   892
        prefix();
dvander@0
   893
        fprintf(fp_, "[ ForStatement\n");
dvander@0
   894
        indent();
dvander@0
   895
        if (node->declaration())
dvander@0
   896
            node->declaration()->accept(this);
dvander@0
   897
        if (node->condition())
dvander@0
   898
            node->condition()->accept(this);
dvander@0
   899
        if (node->update())
dvander@0
   900
            node->update()->accept(this);
dvander@0
   901
        node->body()->accept(this);
dvander@0
   902
        unindent();
dvander@0
   903
    }
dvander@0
   904
    void visit(BlockStatement *node) {
dvander@0
   905
        prefix();
dvander@0
   906
        fprintf(fp_, "[ BlockStatement\n");
dvander@0
   907
        indent();
dvander@0
   908
        for (size_t i = 0; i < node->statements()->length(); i++)
dvander@0
   909
            node->statements()->at(i)->accept(this);
dvander@0
   910
        unindent();
dvander@0
   911
    }
dvander@0
   912
    void visit(VariableDeclaration *node) {
dvander@0
   913
        prefix();
dvander@0
   914
        fprintf(fp_, "[ VariableDeclaration (%s)\n", node->variable()->name());
dvander@0
   915
        indent();
dvander@0
   916
        if (node->initialization())
dvander@0
   917
            node->initialization()->accept(this);
dvander@0
   918
        unindent();
dvander@0
   919
    }
dvander@4
   920
    void visit(IntegerLiteral *node) {
dvander@0
   921
        prefix();
dvander@4
   922
        fprintf(fp_, "[ IntegerLiteral (%d)\n", node->value());
dvander@4
   923
    }
dvander@4
   924
    void visit(FloatLiteral *node) {
dvander@4
   925
        prefix();
dvander@4
   926
        fprintf(fp_, "[ FloatLiteral (%f)\n", node->value());
dvander@0
   927
    }
dvander@0
   928
    void visit(IfStatement *node) {
dvander@0
   929
        prefix();
dvander@0
   930
        fprintf(fp_, "[ IfStatement\n");
dvander@0
   931
        indent();
dvander@0
   932
        node->ifTrue()->accept(this);
dvander@0
   933
        if (node->ifFalse())
dvander@0
   934
            node->ifFalse()->accept(this);
dvander@0
   935
        unindent();
dvander@0
   936
    }
dvander@0
   937
    void visit(IndexExpression *node) {
dvander@0
   938
        prefix();
dvander@0
   939
        fprintf(fp_, "[ IndexExpression\n");
dvander@0
   940
        indent();
dvander@0
   941
        node->left()->accept(this);
dvander@0
   942
        node->right()->accept(this);
dvander@0
   943
        unindent();
dvander@0
   944
    }
dvander@2
   945
    void visit(EnumStatement *node) {
dvander@2
   946
        prefix();
dvander@2
   947
        fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name() : "<anonymous>");
dvander@2
   948
        indent();
dvander@2
   949
        for (size_t i = 0; i < node->entries()->size(); i++) {
dvander@2
   950
            prefix();
dvander@2
   951
            fprintf(fp_, "%s =\n", node->entries()->at(i).name->name());
dvander@2
   952
            if (node->entries()->at(i).expr) {
dvander@2
   953
                indent();
dvander@2
   954
                node->entries()->at(i).expr->accept(this);
dvander@2
   955
                unindent();
dvander@2
   956
            }
dvander@2
   957
        }
dvander@2
   958
        unindent();
dvander@2
   959
    }
dvander@9
   960
    void visit(WhileStatement *node) {
dvander@9
   961
        prefix();
dvander@9
   962
        fprintf(fp_, "[ WhileStatement (%s)\n",
dvander@9
   963
                (node->token() == TOK_DO) ? "do" : "while");
dvander@9
   964
        indent();
dvander@9
   965
        if (node->token() == TOK_DO) {
dvander@9
   966
            node->condition()->accept(this);
dvander@9
   967
            node->body()->accept(this);
dvander@9
   968
        } else {
dvander@9
   969
            node->condition()->accept(this);
dvander@9
   970
            node->body()->accept(this);
dvander@9
   971
        }
dvander@9
   972
        unindent();
dvander@9
   973
    }
dvander@10
   974
    void visit(BreakStatement *node) {
dvander@10
   975
        prefix();
dvander@10
   976
        fprintf(fp_, "[ BreakStatement\n");
dvander@10
   977
    }
dvander@10
   978
    void visit(ContinueStatement *node) {
dvander@10
   979
        prefix();
dvander@10
   980
        fprintf(fp_, "[ ContinueStatement\n");
dvander@10
   981
    }
dvander@0
   982
};
dvander@0
   983
dvander@0
   984
void
dvander@0
   985
ParseTree::dump(FILE *fp)
dvander@0
   986
{
dvander@0
   987
    AstPrinter printer(fp);
dvander@0
   988
dvander@0
   989
    for (size_t i = 0; i < statements_->length(); i++)
dvander@0
   990
        statements_->at(i)->accept(&printer);
dvander@0
   991
}