jitcraft/Parser.cpp
author David Anderson <dvander@alliedmods.net>
Tue Jun 26 00:35:15 2012 -0700 (2012-06-26)
changeset 2 46fc53b8fd2f
parent 0 c455ebb9a5dc
child 4 633176823669
permissions -rw-r--r--
Added support for enums.
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@0
    71
Expression *
dvander@0
    72
Parser::primitive()
dvander@0
    73
{
dvander@0
    74
    switch (scanner_.peek()) {
dvander@0
    75
      case TOK_NAME:
dvander@0
    76
      {
dvander@0
    77
        scanner_.scan();
dvander@0
    78
        Name *name = strings_.add(scanner_.literal());
dvander@0
    79
        return bind(name);
dvander@0
    80
      }
dvander@0
    81
dvander@0
    82
      case TOK_INTEGER_LITERAL:
dvander@0
    83
      {
dvander@0
    84
        scanner_.scan();
dvander@0
    85
        int value = atoi(scanner_.literal());
dvander@0
    86
        return new (pool_) IntegerLiteralExpression(value);
dvander@0
    87
      }
dvander@0
    88
dvander@0
    89
      default:
dvander@0
    90
      {
dvander@0
    91
        fprintf(stderr, "error: expected expression!\n");
dvander@0
    92
        return NULL;
dvander@0
    93
      }
dvander@0
    94
    }
dvander@0
    95
}
dvander@0
    96
dvander@0
    97
Expression *
dvander@0
    98
Parser::prefix()
dvander@0
    99
{
dvander@0
   100
    switch (scanner_.peek()) {
dvander@0
   101
      case TOK_LPAREN:
dvander@0
   102
      {
dvander@0
   103
        scanner_.scan();
dvander@0
   104
        Expression *expr = expression();
dvander@0
   105
        if (!expr)
dvander@0
   106
            return NULL;
dvander@0
   107
        if (!expect(TOK_RPAREN))
dvander@0
   108
            return NULL;
dvander@0
   109
        return expr;
dvander@0
   110
      }
dvander@0
   111
dvander@0
   112
      default:
dvander@0
   113
        return primitive();
dvander@0
   114
    }
dvander@0
   115
}
dvander@0
   116
dvander@0
   117
Expression *
dvander@0
   118
Parser::call(Expression *callee)
dvander@0
   119
{
dvander@0
   120
    ExpressionList *arguments = new ExpressionList();
dvander@0
   121
dvander@0
   122
    expect(TOK_LPAREN);
dvander@0
   123
    
dvander@0
   124
    if (!match(TOK_RPAREN)) {
dvander@0
   125
        while (true) {
dvander@0
   126
            Expression *expr = expression();
dvander@0
   127
            if (!expr)
dvander@0
   128
                return NULL;
dvander@0
   129
dvander@0
   130
            arguments->push_back(expr);
dvander@0
   131
dvander@0
   132
            if (!match(TOK_COMMA))
dvander@0
   133
                break;
dvander@0
   134
        }
dvander@0
   135
dvander@0
   136
        if (!expect(TOK_RPAREN))
dvander@0
   137
            return NULL;
dvander@0
   138
    }
dvander@0
   139
dvander@0
   140
    return new (pool_) CallExpression(callee, arguments);
dvander@0
   141
}
dvander@0
   142
dvander@0
   143
Expression *
dvander@0
   144
Parser::index(Expression *left)
dvander@0
   145
{
dvander@0
   146
    expect(TOK_LBRACKET);
dvander@0
   147
    
dvander@0
   148
    Expression *expr = expression();
dvander@0
   149
    if (!expr)
dvander@0
   150
        return NULL;
dvander@0
   151
dvander@0
   152
    if (!expect(TOK_RBRACKET))
dvander@0
   153
        return NULL;
dvander@0
   154
dvander@0
   155
    return new (pool_) IndexExpression(left, expr);
dvander@0
   156
}
dvander@0
   157
dvander@0
   158
Expression *
dvander@0
   159
Parser::primary()
dvander@0
   160
{
dvander@0
   161
    Expression *expr = prefix();
dvander@0
   162
    if (!expr)
dvander@0
   163
        return NULL;
dvander@0
   164
dvander@0
   165
    for (;;) {
dvander@0
   166
        switch (scanner_.peek()) {
dvander@0
   167
          case TOK_LPAREN:
dvander@0
   168
            expr = call(expr);
dvander@0
   169
            if (!expr)
dvander@0
   170
                return NULL;
dvander@0
   171
            break;
dvander@0
   172
dvander@0
   173
          case TOK_LBRACKET:
dvander@0
   174
            expr = index(expr);
dvander@0
   175
            if (!expr)
dvander@0
   176
                return NULL;
dvander@0
   177
            break;
dvander@0
   178
dvander@0
   179
          default:
dvander@0
   180
            return expr;
dvander@0
   181
        }
dvander@0
   182
    }
dvander@0
   183
}
dvander@0
   184
dvander@0
   185
Expression *
dvander@0
   186
Parser::unary()
dvander@0
   187
{
dvander@0
   188
    return primary();
dvander@0
   189
}
dvander@0
   190
dvander@0
   191
Expression *
dvander@0
   192
Parser::multiplication()
dvander@0
   193
{
dvander@0
   194
    Expression *left = unary();
dvander@0
   195
    do {
dvander@0
   196
        if (!match(TOK_SLASH) && !match(TOK_STAR))
dvander@0
   197
            break;
dvander@0
   198
        TokenKind kind = scanner_.last();
dvander@0
   199
        Expression *right = unary();
dvander@0
   200
        if (!right)
dvander@0
   201
            return NULL;
dvander@0
   202
        left = new (pool_) BinaryExpression(kind, left, right);
dvander@0
   203
    } while (left);
dvander@0
   204
    return left;
dvander@0
   205
}
dvander@0
   206
dvander@0
   207
Expression *
dvander@0
   208
Parser::addition()
dvander@0
   209
{
dvander@0
   210
    Expression *left = multiplication();
dvander@0
   211
    while (left) {
dvander@0
   212
        if (!match(TOK_PLUS) && !match(TOK_MINUS))
dvander@0
   213
            break;
dvander@0
   214
        TokenKind kind = scanner_.last();
dvander@0
   215
        Expression *right = multiplication();
dvander@0
   216
        if (!right)
dvander@0
   217
            return NULL;
dvander@0
   218
        left = new (pool_) BinaryExpression(kind, left, right);
dvander@0
   219
    }
dvander@0
   220
    return left;
dvander@0
   221
}
dvander@0
   222
dvander@0
   223
Expression *
dvander@2
   224
Parser::shift()
dvander@2
   225
{
dvander@2
   226
    Expression *left = addition();
dvander@2
   227
    while (left) {
dvander@2
   228
        if (!match(TOK_SHL))
dvander@2
   229
            break;
dvander@2
   230
        TokenKind kind = scanner_.last();
dvander@2
   231
        Expression *right = addition();
dvander@2
   232
        if (!right)
dvander@2
   233
            return NULL;
dvander@2
   234
        left = new (pool_) BinaryExpression(kind, left, right);
dvander@2
   235
    }
dvander@2
   236
    return left;
dvander@2
   237
}
dvander@2
   238
dvander@2
   239
Expression *
dvander@0
   240
Parser::relational()
dvander@0
   241
{
dvander@2
   242
    Expression *left = shift();
dvander@0
   243
    while (left) {
dvander@0
   244
        TokenKind kind = scanner_.peek();
dvander@0
   245
        if (kind < TOK_LT || kind > TOK_GE)
dvander@0
   246
            break;
dvander@0
   247
        scanner_.scan();
dvander@2
   248
        Expression *right = shift();
dvander@0
   249
        if (!right)
dvander@0
   250
            return NULL;
dvander@0
   251
        left = new (pool_) BinaryExpression(kind, left, right);
dvander@0
   252
    }
dvander@0
   253
    return left;
dvander@0
   254
}
dvander@0
   255
dvander@0
   256
Expression *
dvander@0
   257
Parser::equals()
dvander@0
   258
{
dvander@0
   259
    Expression *left = relational();
dvander@0
   260
    while (left) {
dvander@0
   261
        if (!match(TOK_EQUALS) && !match(TOK_NOTEQUALS))
dvander@0
   262
            break;
dvander@0
   263
        TokenKind kind = scanner_.last();
dvander@0
   264
        Expression *right = relational();
dvander@0
   265
        if (!right)
dvander@0
   266
            return NULL;
dvander@0
   267
        left = new (pool_) BinaryExpression(kind, left, right);
dvander@0
   268
    }
dvander@0
   269
    return left;
dvander@0
   270
}
dvander@0
   271
dvander@0
   272
Expression *
dvander@0
   273
Parser::expression()
dvander@0
   274
{
dvander@0
   275
    return equals();
dvander@0
   276
}
dvander@0
   277
dvander@0
   278
Statement *
dvander@0
   279
Parser::forStatement()
dvander@0
   280
{
dvander@0
   281
    scanner_.scan();
dvander@0
   282
    if (!expect(TOK_LPAREN))
dvander@0
   283
        return NULL;
dvander@0
   284
dvander@0
   285
    VariableDeclaration *decl = NULL;
dvander@0
   286
    if (!match(TOK_SEMICOLON)) {
dvander@0
   287
        if (!enterScope(Scope::BLOCK))
dvander@0
   288
            return NULL;
dvander@0
   289
        if ((decl = variableDeclaration()) == NULL)
dvander@0
   290
            return NULL;
dvander@0
   291
        if (!expect(TOK_SEMICOLON))
dvander@0
   292
            return NULL;
dvander@0
   293
    }
dvander@0
   294
dvander@0
   295
    Expression *condition = NULL;
dvander@0
   296
    if (!match(TOK_SEMICOLON)) {
dvander@0
   297
        if ((condition = expression()) == NULL)
dvander@0
   298
            return NULL;
dvander@0
   299
        if (!expect(TOK_SEMICOLON))
dvander@0
   300
            return NULL;
dvander@0
   301
    }
dvander@0
   302
dvander@0
   303
    Statement *update = NULL;
dvander@0
   304
    if (!match(TOK_RPAREN)) {
dvander@0
   305
        if ((update = expressionStatement()) == NULL)
dvander@0
   306
            return NULL;
dvander@0
   307
        if (!expect(TOK_RPAREN))
dvander@0
   308
            return NULL;
dvander@0
   309
    }
dvander@0
   310
dvander@0
   311
    Statement *body = localStatement();
dvander@0
   312
    if (!body)
dvander@0
   313
        return NULL;
dvander@0
   314
dvander@0
   315
    Scope *blockScope = NULL;
dvander@0
   316
    if (decl) {
dvander@0
   317
        blockScope = scope_->unlinkIfEmpty();
dvander@0
   318
        scope_ = scope_->enclosing();
dvander@0
   319
    }
dvander@0
   320
    return new (pool_) ForStatement(blockScope, decl, condition, update, body);
dvander@0
   321
}
dvander@0
   322
dvander@0
   323
VariableDeclaration *
dvander@0
   324
Parser::variableDeclaration()
dvander@0
   325
{
dvander@0
   326
    if (!expect(TOK_NEW))
dvander@0
   327
        return NULL;
dvander@0
   328
dvander@0
   329
    // Get the name.
dvander@0
   330
    if (!expect(TOK_NAME))
dvander@0
   331
        return NULL;
dvander@0
   332
    
dvander@0
   333
    Name *name = strings_.add(scanner_.literal());
dvander@0
   334
dvander@0
   335
    ExpressionList *postDimensions = NULL;
dvander@0
   336
    if (scanner_.peek() == TOK_LBRACKET) {
dvander@0
   337
        postDimensions = new ExpressionList();
dvander@0
   338
        while (match(TOK_LBRACKET)) {
dvander@0
   339
            Expression *dim = expression();
dvander@0
   340
            if (!dim)
dvander@0
   341
                return NULL;
dvander@0
   342
dvander@0
   343
            if (!expect(TOK_RBRACKET))
dvander@0
   344
                return NULL;
dvander@0
   345
dvander@0
   346
            postDimensions->push_back(dim);
dvander@0
   347
        }
dvander@0
   348
    }
dvander@0
   349
    
dvander@0
   350
    Expression *expr = NULL;
dvander@0
   351
    if (match(TOK_ASSIGN)) {
dvander@0
   352
        if ((expr = expression()) == NULL)
dvander@0
   353
            return NULL;
dvander@0
   354
    }
dvander@0
   355
    
dvander@0
   356
    if (scope_->localLookup(name)) {
dvander@0
   357
        redeclarationError();
dvander@0
   358
        return NULL;
dvander@0
   359
    }
dvander@0
   360
dvander@0
   361
    Variable *var = scope_->declareVariable(name);
dvander@0
   362
    VariableDeclaration *decl = new (pool_) VariableDeclaration(var, postDimensions, expr);
dvander@0
   363
dvander@0
   364
    return decl;
dvander@0
   365
}
dvander@0
   366
dvander@0
   367
Statement *
dvander@0
   368
Parser::returnStatement()
dvander@0
   369
{
dvander@0
   370
    if (!expect(TOK_RETURN))
dvander@0
   371
        return NULL;
dvander@0
   372
dvander@0
   373
    Expression *expr = expression();
dvander@0
   374
    if (!expr)
dvander@0
   375
        return NULL;
dvander@0
   376
dvander@0
   377
    return new (pool_) ReturnStatement(expr);
dvander@0
   378
}
dvander@0
   379
dvander@0
   380
Statement *
dvander@0
   381
Parser::expressionStatement()
dvander@0
   382
{
dvander@0
   383
    Expression *left = primary();
dvander@0
   384
    if (!left) {
dvander@0
   385
        fprintf(stderr, "expected expression or statement\n");
dvander@0
   386
        return NULL;
dvander@0
   387
    }
dvander@0
   388
dvander@0
   389
    if (match(TOK_ASSIGN)) {
dvander@0
   390
        Expression *expr = expression();
dvander@0
   391
        if (!expr)
dvander@0
   392
            return NULL;
dvander@0
   393
dvander@0
   394
        left = new (pool_) Assignment(left, expr);
dvander@0
   395
    }
dvander@0
   396
dvander@0
   397
    return new (pool_) ExpressionStatement(left);
dvander@0
   398
}
dvander@0
   399
dvander@0
   400
Statement *
dvander@0
   401
Parser::block()
dvander@0
   402
{
dvander@0
   403
    if (!expect(TOK_LBRACE))
dvander@0
   404
        return NULL;
dvander@0
   405
dvander@0
   406
    if (!enterScope(Scope::BLOCK))
dvander@0
   407
        return NULL;
dvander@0
   408
dvander@0
   409
    StatementList *statements = new (pool_) StatementList();
dvander@0
   410
    while (!match(TOK_RBRACE)) {
dvander@0
   411
        Statement *statement = localStatement();
dvander@0
   412
        if (statement == NULL)
dvander@0
   413
            return NULL;
dvander@0
   414
        statements->append(pool_, statement);
dvander@0
   415
    }
dvander@0
   416
dvander@0
   417
    Scope *blockScope = scope_->unlinkIfEmpty();
dvander@0
   418
    BlockStatement *block = new (pool_) BlockStatement(blockScope, statements);
dvander@0
   419
dvander@0
   420
    scope_ = scope_->enclosing();
dvander@0
   421
    return block;
dvander@0
   422
}
dvander@0
   423
dvander@0
   424
Statement *
dvander@0
   425
Parser::if_()
dvander@0
   426
{
dvander@0
   427
    expect(TOK_IF);
dvander@0
   428
dvander@0
   429
    if (!expect(TOK_LPAREN))
dvander@0
   430
        return NULL;
dvander@0
   431
dvander@0
   432
    Expression *cond = expression();
dvander@0
   433
    if (!cond)
dvander@0
   434
        return NULL;
dvander@0
   435
dvander@0
   436
    if (!expect(TOK_RPAREN))
dvander@0
   437
        return NULL;
dvander@0
   438
dvander@0
   439
    Statement *ifTrue = localStatement();
dvander@0
   440
    if (!ifTrue)
dvander@0
   441
        return NULL;
dvander@0
   442
dvander@0
   443
    IfStatement *outer = new (pool_) IfStatement(cond, ifTrue);
dvander@0
   444
dvander@0
   445
    IfStatement *last = outer;
dvander@0
   446
    while (match(TOK_ELSE)) {
dvander@0
   447
        if (!match(TOK_IF)) {
dvander@0
   448
            Statement *ifFalse = localStatement();
dvander@0
   449
            if (!ifFalse)
dvander@0
   450
                return NULL;
dvander@0
   451
dvander@0
   452
            last->setIfFalse(ifFalse);
dvander@0
   453
            break;
dvander@0
   454
        }
dvander@0
   455
dvander@0
   456
        if (!expect(TOK_IF))
dvander@0
   457
            return false;
dvander@0
   458
dvander@0
   459
        if (!expect(TOK_LPAREN))
dvander@0
   460
            return NULL;
dvander@0
   461
dvander@0
   462
        Expression *otherCond = expression();
dvander@0
   463
        if (!otherCond)
dvander@0
   464
            return NULL;
dvander@0
   465
dvander@0
   466
        if (!expect(TOK_RPAREN))
dvander@0
   467
            return NULL;
dvander@0
   468
dvander@0
   469
        Statement *otherIfTrue = localStatement();
dvander@0
   470
        if (!otherIfTrue)
dvander@0
   471
            return NULL;
dvander@0
   472
dvander@0
   473
        IfStatement *inner = new (pool_) IfStatement(otherCond, otherIfTrue);
dvander@0
   474
        last->setIfFalse(inner);
dvander@0
   475
        last = inner;
dvander@0
   476
    }
dvander@0
   477
dvander@0
   478
    return outer;
dvander@0
   479
}
dvander@0
   480
dvander@0
   481
Statement *
dvander@0
   482
Parser::localStatement()
dvander@0
   483
{
dvander@0
   484
    Statement *statement = NULL;
dvander@0
   485
dvander@0
   486
    // Statements which must be followed by a semicolon will break out of the
dvander@0
   487
    // switch. If they may end in BlockStatements, they'll immediately return.
dvander@0
   488
dvander@0
   489
    switch (scanner_.peek()) {
dvander@0
   490
        case TOK_NEW:
dvander@0
   491
          statement = variableDeclaration();
dvander@0
   492
          break;
dvander@0
   493
dvander@0
   494
        case TOK_FOR:
dvander@0
   495
          return forStatement();
dvander@0
   496
dvander@0
   497
        case TOK_RETURN:
dvander@0
   498
          statement = returnStatement();
dvander@0
   499
          break;
dvander@0
   500
dvander@2
   501
        case TOK_ENUM:
dvander@2
   502
          statement = enum_();
dvander@2
   503
          break;
dvander@2
   504
dvander@0
   505
        case TOK_IF:
dvander@0
   506
          return if_();
dvander@0
   507
dvander@0
   508
        case TOK_LBRACE:
dvander@0
   509
          return block();
dvander@0
   510
    }
dvander@0
   511
dvander@0
   512
    if (!statement) {
dvander@0
   513
        if ((statement = expressionStatement()) == NULL)
dvander@0
   514
            return NULL;
dvander@0
   515
    }
dvander@0
   516
dvander@0
   517
    if (!expect(TOK_SEMICOLON))
dvander@0
   518
        return NULL;
dvander@0
   519
dvander@0
   520
    return statement;
dvander@0
   521
}
dvander@0
   522
dvander@0
   523
Statement *
dvander@2
   524
Parser::enum_()
dvander@2
   525
{
dvander@2
   526
    expect(TOK_ENUM);
dvander@2
   527
dvander@2
   528
    Name *name = NULL;
dvander@2
   529
    if (match(TOK_NAME)) {
dvander@2
   530
        if ((name = strings_.add(scanner_.literal())) == NULL)
dvander@2
   531
            return NULL;
dvander@2
   532
dvander@2
   533
        if (scope_->localLookup(name)) {
dvander@2
   534
            redeclarationError();
dvander@2
   535
            return NULL;
dvander@2
   536
        }
dvander@2
   537
dvander@2
   538
        NamedEnum *e = scope_->declareEnum(name);
dvander@2
   539
        if (!e)
dvander@2
   540
            return NULL;
dvander@2
   541
    }
dvander@2
   542
dvander@2
   543
    EnumStatement::EntryList *entries = new EnumStatement::EntryList();
dvander@2
   544
dvander@2
   545
    if (!expect(TOK_LBRACE))
dvander@2
   546
        return NULL;
dvander@2
   547
dvander@2
   548
    do {
dvander@2
   549
        if (scanner_.peek() == TOK_RBRACE)
dvander@2
   550
            break;
dvander@2
   551
dvander@2
   552
        if (!expect(TOK_NAME))
dvander@2
   553
            return NULL;
dvander@2
   554
dvander@2
   555
        Name *name = strings_.add(scanner_.literal());
dvander@2
   556
        if (!name)
dvander@2
   557
            return NULL;
dvander@2
   558
dvander@2
   559
        if (scope_->localLookup(name)) {
dvander@2
   560
            redeclarationError();
dvander@2
   561
            return NULL;
dvander@2
   562
        }
dvander@2
   563
dvander@2
   564
        NamedConstant *constant = scope_->declareConstant(name);
dvander@2
   565
        if (!constant)
dvander@2
   566
            return NULL;
dvander@2
   567
dvander@2
   568
        Expression *expr = NULL;
dvander@2
   569
        if (match(TOK_ASSIGN)) {
dvander@2
   570
            if ((expr = expression()) == NULL)
dvander@2
   571
                return NULL;
dvander@2
   572
        }
dvander@2
   573
dvander@2
   574
        entries->push_back(EnumStatement::Entry(constant, expr));
dvander@2
   575
    } while (match(TOK_COMMA));
dvander@2
   576
    if (!expect(TOK_RBRACE))
dvander@2
   577
        return NULL;
dvander@2
   578
dvander@2
   579
    return new (pool_) EnumStatement(name, entries);
dvander@2
   580
}
dvander@2
   581
dvander@2
   582
Statement *
dvander@0
   583
Parser::function()
dvander@0
   584
{
dvander@0
   585
    expect(TOK_NAME);
dvander@0
   586
dvander@0
   587
    Name *name = strings_.add(scanner_.literal());
dvander@0
   588
    if (!name)
dvander@0
   589
        return NULL;
dvander@0
   590
dvander@0
   591
    // The function name goes into the outer (global) scope.
dvander@0
   592
    assert(!scope_->enclosing());
dvander@0
   593
dvander@0
   594
    if (scope_->localLookup(name)) {
dvander@0
   595
        redeclarationError();
dvander@0
   596
        return NULL;
dvander@0
   597
    }
dvander@0
   598
    NamedFunction *fun = scope_->declareFunction(name);
dvander@0
   599
    if (!fun)
dvander@0
   600
        return NULL;
dvander@0
   601
dvander@0
   602
    Scope *scope = enterScope(Scope::FUNCTION);
dvander@0
   603
    if (!scope)
dvander@0
   604
        return NULL;
dvander@0
   605
dvander@0
   606
    if (!expect(TOK_LPAREN))
dvander@0
   607
        return NULL;
dvander@0
   608
    if (!match(TOK_RPAREN)) {
dvander@0
   609
        while (true) {
dvander@0
   610
            if (!expect(TOK_NAME))
dvander@0
   611
                return NULL;
dvander@0
   612
dvander@0
   613
            Name *name = strings_.add(scanner_.literal());
dvander@0
   614
            if (!name)
dvander@0
   615
                return NULL;
dvander@0
   616
dvander@0
   617
            if (scope_->localLookup(name)) {
dvander@0
   618
                redeclarationError();
dvander@0
   619
                return NULL;
dvander@0
   620
            }
dvander@0
   621
            if (!scope_->declareArgument(name))
dvander@0
   622
                return NULL;
dvander@0
   623
dvander@0
   624
            if (!match(TOK_COMMA))
dvander@0
   625
                break;
dvander@0
   626
        }
dvander@0
   627
        if (!expect(TOK_RPAREN))
dvander@0
   628
            return NULL;
dvander@0
   629
    }
dvander@0
   630
dvander@0
   631
    Statement *body = block();
dvander@0
   632
    if (!body)
dvander@0
   633
        return NULL;
dvander@0
   634
dvander@0
   635
    scope_ = scope_->enclosing();
dvander@0
   636
    return new (pool_) FunctionStatement(scope, fun, body);
dvander@0
   637
}
dvander@0
   638
dvander@0
   639
ParseTree *
dvander@0
   640
Parser::parse()
dvander@0
   641
{
dvander@0
   642
    StatementList *statements = new (pool_) StatementList();
dvander@0
   643
dvander@0
   644
    if (!enterScope(Scope::GLOBAL))
dvander@0
   645
        return NULL;
dvander@0
   646
dvander@0
   647
    for (;;) {
dvander@0
   648
        Statement *statement = NULL;
dvander@0
   649
dvander@0
   650
        switch (scanner_.peek()) {
dvander@0
   651
          case TOK_ERROR:
dvander@0
   652
            return NULL;
dvander@0
   653
dvander@0
   654
          case TOK_EOF:
dvander@0
   655
            break;
dvander@0
   656
dvander@0
   657
          case TOK_NAME:
dvander@0
   658
            if ((statement = function()) == NULL)
dvander@0
   659
                return NULL;
dvander@0
   660
            break;
dvander@0
   661
dvander@2
   662
          case TOK_ENUM:
dvander@2
   663
            if ((statement = enum_()) == NULL)
dvander@2
   664
                return NULL;
dvander@2
   665
            // :TODO: require semicolon
dvander@2
   666
            break;
dvander@2
   667
dvander@0
   668
          default:
dvander@0
   669
            fprintf(stderr, "expected function or global variable\n");
dvander@0
   670
            return NULL;
dvander@0
   671
        }
dvander@0
   672
dvander@0
   673
        if (!statement)
dvander@0
   674
            break;
dvander@0
   675
dvander@0
   676
        statements->append(pool_, statement);
dvander@0
   677
    }
dvander@0
   678
dvander@0
   679
    return new (pool_) ParseTree(scope_, statements, unbound_);
dvander@0
   680
}
dvander@0
   681
dvander@0
   682
class AstPrinter : public AstVisitor
dvander@0
   683
{
dvander@0
   684
    FILE *fp_;
dvander@0
   685
    size_t level_;
dvander@0
   686
dvander@0
   687
  private:
dvander@0
   688
    void prefix() {
dvander@0
   689
        for (size_t i = 0; i < level_; i++)
dvander@0
   690
            fprintf(fp_, "  ");
dvander@0
   691
    }
dvander@0
   692
    void indent() {
dvander@0
   693
        level_++;
dvander@0
   694
    }
dvander@0
   695
    void unindent() {
dvander@0
   696
        level_--;
dvander@0
   697
    }
dvander@0
   698
dvander@0
   699
  public:
dvander@0
   700
    AstPrinter(FILE *fp)
dvander@0
   701
      : fp_(fp),
dvander@0
   702
        level_(0)
dvander@0
   703
    {
dvander@0
   704
    }
dvander@0
   705
dvander@0
   706
    void visit(NameProxy *name) {
dvander@0
   707
        prefix();
dvander@0
   708
        fprintf(fp_, "[ NameProxy (%s)%s\n", name->name(),
dvander@0
   709
                (name->binding() ? "" : " unbound"));
dvander@0
   710
    }
dvander@0
   711
    void visit(CallExpression *node) {
dvander@0
   712
        prefix();
dvander@0
   713
        fprintf(fp_, "[ CallExpression\n");
dvander@0
   714
        indent();
dvander@0
   715
        node->callee()->accept(this);
dvander@0
   716
        for (size_t i = 0; i < node->arguments()->size(); i++)
dvander@0
   717
            node->arguments()->at(i)->accept(this);
dvander@0
   718
        unindent();
dvander@0
   719
    }
dvander@0
   720
    void visit(FunctionStatement *node) {
dvander@0
   721
        prefix();
dvander@0
   722
        fprintf(fp_, "[ FunctionStatement (%s)\n", node->fun()->name());
dvander@0
   723
        indent();
dvander@0
   724
        node->body()->accept(this);
dvander@0
   725
        unindent();
dvander@0
   726
    }
dvander@0
   727
    void visit(ExpressionStatement *node) {
dvander@0
   728
        prefix();
dvander@0
   729
        fprintf(fp_, "[ ExpressionStatement\n");
dvander@0
   730
        indent();
dvander@0
   731
        node->expression()->accept(this);
dvander@0
   732
        unindent();
dvander@0
   733
    }
dvander@0
   734
    void visit(Assignment *node) {
dvander@0
   735
        prefix();
dvander@0
   736
        fprintf(fp_, "[ Assignment\n");
dvander@0
   737
        indent();
dvander@0
   738
        node->lvalue()->accept(this);
dvander@0
   739
        node->expression()->accept(this);
dvander@0
   740
        unindent();
dvander@0
   741
    }
dvander@0
   742
    void visit(BinaryExpression *node) {
dvander@0
   743
        prefix();
dvander@0
   744
        fprintf(fp_, "[ BinaryExpression (%s)\n", TokenNames[node->token()]);
dvander@0
   745
        indent();
dvander@0
   746
        node->left()->accept(this);
dvander@0
   747
        node->right()->accept(this);
dvander@0
   748
        unindent();
dvander@0
   749
    }
dvander@0
   750
    void visit(ReturnStatement *node) {
dvander@0
   751
        prefix();
dvander@0
   752
        fprintf(fp_, "[ ReturnStatement\n");
dvander@0
   753
        indent();
dvander@0
   754
        node->expression()->accept(this);
dvander@0
   755
        unindent();
dvander@0
   756
    }
dvander@0
   757
    void visit(ForStatement *node) {
dvander@0
   758
        prefix();
dvander@0
   759
        fprintf(fp_, "[ ForStatement\n");
dvander@0
   760
        indent();
dvander@0
   761
        if (node->declaration())
dvander@0
   762
            node->declaration()->accept(this);
dvander@0
   763
        if (node->condition())
dvander@0
   764
            node->condition()->accept(this);
dvander@0
   765
        if (node->update())
dvander@0
   766
            node->update()->accept(this);
dvander@0
   767
        node->body()->accept(this);
dvander@0
   768
        unindent();
dvander@0
   769
    }
dvander@0
   770
    void visit(BlockStatement *node) {
dvander@0
   771
        prefix();
dvander@0
   772
        fprintf(fp_, "[ BlockStatement\n");
dvander@0
   773
        indent();
dvander@0
   774
        for (size_t i = 0; i < node->statements()->length(); i++)
dvander@0
   775
            node->statements()->at(i)->accept(this);
dvander@0
   776
        unindent();
dvander@0
   777
    }
dvander@0
   778
    void visit(VariableDeclaration *node) {
dvander@0
   779
        prefix();
dvander@0
   780
        fprintf(fp_, "[ VariableDeclaration (%s)\n", node->variable()->name());
dvander@0
   781
        indent();
dvander@0
   782
        if (node->initialization())
dvander@0
   783
            node->initialization()->accept(this);
dvander@0
   784
        unindent();
dvander@0
   785
    }
dvander@0
   786
    void visit(IntegerLiteralExpression *node) {
dvander@0
   787
        prefix();
dvander@0
   788
        fprintf(fp_, "[ LiteralExpression (%d)\n", node->value());
dvander@0
   789
    }
dvander@0
   790
    void visit(IfStatement *node) {
dvander@0
   791
        prefix();
dvander@0
   792
        fprintf(fp_, "[ IfStatement\n");
dvander@0
   793
        indent();
dvander@0
   794
        node->ifTrue()->accept(this);
dvander@0
   795
        if (node->ifFalse())
dvander@0
   796
            node->ifFalse()->accept(this);
dvander@0
   797
        unindent();
dvander@0
   798
    }
dvander@0
   799
    void visit(IndexExpression *node) {
dvander@0
   800
        prefix();
dvander@0
   801
        fprintf(fp_, "[ IndexExpression\n");
dvander@0
   802
        indent();
dvander@0
   803
        node->left()->accept(this);
dvander@0
   804
        node->right()->accept(this);
dvander@0
   805
        unindent();
dvander@0
   806
    }
dvander@2
   807
    void visit(EnumStatement *node) {
dvander@2
   808
        prefix();
dvander@2
   809
        fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name() : "<anonymous>");
dvander@2
   810
        indent();
dvander@2
   811
        for (size_t i = 0; i < node->entries()->size(); i++) {
dvander@2
   812
            prefix();
dvander@2
   813
            fprintf(fp_, "%s =\n", node->entries()->at(i).name->name());
dvander@2
   814
            if (node->entries()->at(i).expr) {
dvander@2
   815
                indent();
dvander@2
   816
                node->entries()->at(i).expr->accept(this);
dvander@2
   817
                unindent();
dvander@2
   818
            }
dvander@2
   819
        }
dvander@2
   820
        unindent();
dvander@2
   821
    }
dvander@0
   822
};
dvander@0
   823
dvander@0
   824
void
dvander@0
   825
ParseTree::dump(FILE *fp)
dvander@0
   826
{
dvander@0
   827
    AstPrinter printer(fp);
dvander@0
   828
dvander@0
   829
    for (size_t i = 0; i < statements_->length(); i++)
dvander@0
   830
        statements_->at(i)->accept(&printer);
dvander@0
   831
}