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