dvander@48: /* vim: set ts=4 sw=4 tw=99 et: dvander@48: * dvander@0: * Copyright (C) 2012 David Anderson dvander@0: * dvander@117: * This file is part of SourcePawn. dvander@0: * dvander@117: * SourcePawn is free software: you can redistribute it and/or modify it under dvander@0: * the terms of the GNU General Public License as published by the Free dvander@0: * Software Foundation, either version 3 of the License, or (at your option) dvander@0: * any later version. dvander@0: * dvander@117: * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY dvander@0: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@0: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@0: * dvander@0: * You should have received a copy of the GNU General Public License along with dvander@117: * SourcePawn. If not, see http://www.gnu.org/licenses/. dvander@0: */ danderson@92: #include dvander@195: #include "../Zone.h" dvander@195: #include "../FixedArray.h" dvander@195: #include "../Heap.h" dvander@195: #include "../Strings.h" dvander@195: #include "../TypeManager.h" dvander@0: #include "Parser.h" dvander@195: #include "../Heap-inl.h" dvander@0: dvander@59: using namespace ke; dvander@0: dvander@54: Parser::Parser(Zone *zone, CompileContext &cc, const char *stream, size_t length) dvander@54: : zone_(zone), dvander@54: cc_(cc), dvander@54: pool_(zone_->pool()), dvander@25: scanner_(cc, stream, length), dvander@0: unbound_(NULL) dvander@0: { dvander@57: unbound_ = new (pool_) PoolList(); dvander@195: imports_ = new (pool_) PoolList(); dvander@0: } dvander@0: dvander@0: bool dvander@145: Parser::peek(TokenKind kind) dvander@145: { dvander@145: return scanner_.peek() == kind; dvander@145: } dvander@145: dvander@145: bool dvander@0: Parser::match(TokenKind kind) dvander@0: { dvander@145: if (!peek(kind)) dvander@0: return false; dvander@0: scanner_.scan(); dvander@0: return true; dvander@0: } dvander@0: dvander@0: bool dvander@63: Parser::matchSemicolon() dvander@63: { dvander@63: return expect(TOK_SEMICOLON); dvander@63: } dvander@63: dvander@63: bool dvander@0: Parser::expect(TokenKind kind) dvander@0: { dvander@0: TokenKind got = scanner_.scan(); dvander@0: if (got == kind) dvander@0: return true; dvander@25: cc_.reportError(scanner_.begin(), Message_WrongToken, TokenNames[kind], TokenNames[got]); dvander@0: return false; dvander@0: } dvander@0: dvander@4: bool dvander@54: Parser::matchName(String **name, TokenKind kind) dvander@4: { dvander@4: assert(kind == TOK_NAME || kind == TOK_LABEL); dvander@4: *name = NULL; dvander@4: if (!match(kind)) dvander@4: return false; dvander@54: *name = zone_->makeSymbol(scanner_.literal(), scanner_.literal_length()); dvander@4: return true; dvander@4: } dvander@4: dvander@54: String * dvander@4: Parser::expectName() dvander@4: { dvander@4: if (!expect(TOK_NAME)) dvander@4: return NULL; dvander@54: return zone_->makeSymbol(scanner_.literal(), scanner_.literal_length()); dvander@4: } dvander@4: dvander@0: Expression * dvander@0: Parser::primitive() dvander@0: { dvander@25: TokenKind kind = scanner_.peek(); dvander@25: switch (kind) { dvander@4: case TOK_FLOAT_LITERAL: dvander@4: { dvander@4: scanner_.scan(); dvander@4: double value = Scanner::ParseDouble(scanner_.literal()); dvander@25: return new (pool_) FloatLiteral(scanner_.begin(), value); dvander@4: } dvander@4: dvander@176: case TOK_HEX_LITERAL: dvander@176: { dvander@176: scanner_.scan(); dvander@176: int value = strtol(scanner_.literal(), NULL, 16); dvander@176: return new (pool_) IntegerLiteral(scanner_.begin(), value); dvander@176: } dvander@176: dvander@0: case TOK_INTEGER_LITERAL: dvander@0: { dvander@0: scanner_.scan(); dvander@0: int value = atoi(scanner_.literal()); dvander@25: return new (pool_) IntegerLiteral(scanner_.begin(), value); dvander@0: } dvander@0: dvander@143: case TOK_TRUE: dvander@143: case TOK_FALSE: dvander@143: scanner_.scan(); dvander@143: return new (pool_) BooleanLiteral(scanner_.begin(), kind); dvander@143: dvander@21: case TOK_STRING_LITERAL: dvander@21: { dvander@21: scanner_.scan(); dvander@54: Local array(zone_, ByteArray::New(zone_, scanner_.literal_length() + 1)); dvander@21: if (!array) dvander@21: return NULL; dvander@54: memcpy(array->raw(), scanner_.literal(), scanner_.literal_length() + 1); dvander@25: return new (pool_) StringLiteral(scanner_.begin(), array); dvander@21: } dvander@21: dvander@0: default: dvander@0: { dvander@25: if (kind != TOK_ERROR) dvander@25: cc_.reportError(scanner_.begin(), Message_ExpectedExpression, TokenNames[kind]); dvander@0: return NULL; dvander@0: } dvander@0: } dvander@0: } dvander@0: dvander@0: Expression * dvander@212: Parser::fixedArrayLiteral() dvander@187: { dvander@187: SourcePosition pos = scanner_.begin(); dvander@187: dvander@187: ExpressionList *list = new (pool_) ExpressionList(); dvander@187: do { dvander@212: // { } is an illegal array literal. dvander@212: if (list->length() > 0 && match(TOK_LBRACE)) dvander@187: break; dvander@187: dvander@187: Expression *expr = NULL; dvander@212: if (peek(TOK_LBRACE)) dvander@212: expr = fixedArrayLiteral(); dvander@212: else dvander@212: expr = primitive(); dvander@187: if (!expr) dvander@187: return NULL; dvander@187: dvander@187: if (!list->append(expr)) dvander@187: return NULL; dvander@187: dvander@187: if (!match(TOK_COMMA)) { dvander@212: if (!expect(TOK_RBRACE)) dvander@187: return NULL; dvander@187: break; dvander@187: } dvander@187: } while (true); dvander@187: dvander@212: return new (pool_) ArrayLiteral(pos, TOK_LBRACE, list); dvander@187: } dvander@187: dvander@187: Expression * dvander@0: Parser::prefix() dvander@0: { dvander@0: switch (scanner_.peek()) { dvander@0: case TOK_LPAREN: dvander@0: { dvander@0: scanner_.scan(); dvander@0: Expression *expr = expression(); dvander@0: if (!expr) dvander@0: return NULL; dvander@0: if (!expect(TOK_RPAREN)) dvander@0: return NULL; dvander@0: return expr; dvander@0: } dvander@0: dvander@187: case TOK_NAME: dvander@187: { dvander@187: Local name(zone_, expectName()); dvander@187: if (!name) dvander@187: return NULL; dvander@195: return new (pool_) NameProxy(scanner_.begin(), name); dvander@187: } dvander@187: dvander@0: default: dvander@0: return primitive(); dvander@0: } dvander@0: } dvander@0: dvander@195: // Parses only old-style declarations. dvander@195: bool dvander@195: Parser::typeAndName(Expression **type, String **namep) dvander@195: { dvander@195: if (match(TOK_LABEL)) { dvander@195: // Old-style declaration: dvander@195: // new X:type dvander@195: Local name(zone_, zone_->makeSymbol(scanner_.literal(), scanner_.literal_length())); dvander@195: if (!name) dvander@195: return false; dvander@195: dvander@195: *type = new (pool_) NameProxy(scanner_.begin(), name); dvander@195: *namep = expectName(); dvander@195: return !!*namep; dvander@195: } dvander@195: dvander@195: *type = NULL; dvander@195: *namep = expectName(); dvander@195: dvander@195: return !!*namep; dvander@195: } dvander@195: dvander@195: // Parses both old and new style declarations. dvander@195: bool dvander@195: Parser::fullTypeAndName(Expression **type, String **namep, DeclKind kind) dvander@195: { dvander@195: // Declaration: dvander@195: // NewDecl ::= Type Ident dvander@195: // OldDecl ::= Label? (Ident | "...") dvander@195: // Type ::= Ident dvander@195: // Label ::= Ident ":" dvander@195: // dvander@195: if (match(TOK_LABEL)) { dvander@195: // We something of the form: dvander@195: // Label Ident dvander@195: // or: Label "..." dvander@195: Local name(zone_, zone_->makeSymbol(scanner_.literal(), scanner_.literal_length())); dvander@195: if (!name) dvander@195: return false; dvander@195: dvander@195: *type = new (pool_) NameProxy(scanner_.begin(), name); dvander@195: if (kind == DeclArg && match(TOK_ELLIPSES)) { dvander@195: *namep = NULL; dvander@195: } else { dvander@195: if ((*namep = expectName()) == NULL) dvander@195: return false; dvander@195: } dvander@195: return true; dvander@195: } dvander@195: dvander@195: Local name(zone_, expectName()); dvander@195: if (!name) dvander@195: return false; dvander@195: dvander@195: if (peek(TOK_NAME) || (kind == DeclArg && peek(TOK_ELLIPSES))) { dvander@195: // We got something of the form: dvander@195: // Ident Ident dvander@195: *type = new (pool_) NameProxy(scanner_.begin(), name); dvander@195: if (peek(TOK_NAME)) { dvander@195: if ((*namep = expectName()) == NULL) dvander@195: return false; dvander@195: } else { dvander@195: *namep = NULL; dvander@195: } dvander@195: return true; dvander@195: } dvander@195: dvander@195: // We got something of the form: dvander@195: // Ident dvander@195: *type = NULL; dvander@195: *namep = name; dvander@195: return true; dvander@195: } dvander@195: dvander@0: Expression * dvander@0: Parser::call(Expression *callee) dvander@0: { dvander@56: ExpressionList *arguments = new (pool_) ExpressionList(); dvander@0: dvander@25: SourcePosition pos = scanner_.begin(); dvander@0: expect(TOK_LPAREN); dvander@0: dvander@0: if (!match(TOK_RPAREN)) { dvander@0: while (true) { dvander@0: Expression *expr = expression(); dvander@0: if (!expr) dvander@0: return NULL; dvander@0: dvander@55: if (!arguments->append(expr)) dvander@55: return NULL; dvander@0: dvander@0: if (!match(TOK_COMMA)) dvander@0: break; dvander@0: } dvander@0: dvander@0: if (!expect(TOK_RPAREN)) dvander@0: return NULL; dvander@0: } dvander@0: dvander@25: return new (pool_) CallExpression(pos, callee, arguments); dvander@0: } dvander@0: dvander@0: Expression * dvander@0: Parser::index(Expression *left) dvander@0: { dvander@0: expect(TOK_LBRACKET); dvander@0: dvander@25: SourcePosition pos = scanner_.begin(); dvander@0: Expression *expr = expression(); dvander@0: if (!expr) dvander@0: return NULL; dvander@0: dvander@0: if (!expect(TOK_RBRACKET)) dvander@0: return NULL; dvander@0: dvander@25: return new (pool_) IndexExpression(pos, left, expr); dvander@0: } dvander@0: dvander@0: Expression * dvander@148: Parser::field(Expression *left) dvander@148: { dvander@148: expect(TOK_DOT); dvander@148: dvander@148: SourcePosition pos = scanner_.begin(); dvander@148: Local name(zone_, expectName()); dvander@148: if (!name) dvander@148: return NULL; dvander@148: dvander@148: return new (pool_) FieldExpression(pos, left, name); dvander@148: } dvander@148: dvander@148: Expression * dvander@0: Parser::primary() dvander@0: { dvander@0: Expression *expr = prefix(); dvander@0: if (!expr) dvander@0: return NULL; dvander@0: dvander@0: for (;;) { dvander@0: switch (scanner_.peek()) { dvander@0: case TOK_LPAREN: dvander@148: if ((expr = call(expr)) == NULL) dvander@0: return NULL; dvander@0: break; dvander@0: dvander@0: case TOK_LBRACKET: dvander@148: if ((expr = index(expr)) == NULL) dvander@148: return NULL; dvander@148: break; dvander@148: dvander@148: case TOK_DOT: dvander@148: if ((expr = field(expr)) == NULL) dvander@0: return NULL; dvander@0: break; dvander@0: dvander@0: default: dvander@0: return expr; dvander@0: } dvander@0: } dvander@0: } dvander@0: dvander@0: Expression * dvander@0: Parser::unary() dvander@0: { dvander@23: TokenKind token = scanner_.peek(); dvander@23: dvander@25: SourcePosition pos = scanner_.begin(); dvander@23: switch (token) { dvander@23: case TOK_INCREMENT: dvander@23: case TOK_DECREMENT: dvander@23: { dvander@23: scanner_.scan(); dvander@141: Expression *expr = unary(); dvander@23: if (!expr) dvander@23: return NULL; dvander@25: return new (pool_) IncDecExpression(pos, token, expr, false); dvander@23: } dvander@78: dvander@80: case TOK_MINUS: dvander@79: case TOK_NOT: dvander@78: case TOK_TILDE: dvander@78: { dvander@78: scanner_.scan(); dvander@141: Expression *expr = unary(); dvander@78: if (!expr) dvander@78: return NULL; dvander@78: return new (pool_) UnaryExpression(pos, token, expr); dvander@78: } dvander@78: dvander@194: case TOK_SIZEOF: dvander@194: { dvander@194: scanner_.scan(); dvander@194: if (!expect(TOK_LPAREN)) dvander@194: return NULL; dvander@194: Expression *expr = unary(); dvander@194: if (!expr) dvander@194: return NULL; dvander@194: if (!expect(TOK_RPAREN)) dvander@194: return NULL; dvander@194: return new (pool_) UnaryExpression(pos, token, expr); dvander@194: } dvander@194: dvander@141: case TOK_LABEL: dvander@141: { dvander@141: scanner_.scan(); dvander@141: Local tag(zone_, zone_->makeSymbol(scanner_.literal(), scanner_.literal_length())); dvander@141: if (!tag) dvander@141: return NULL; dvander@141: dvander@195: NameProxy *proxy = new (pool_) NameProxy(scanner_.begin(), tag); dvander@145: dvander@141: Expression *expr = unary(); dvander@141: if (!expr) dvander@141: return NULL; dvander@141: dvander@195: return new (pool_) UnaryExpression(pos, TOK_LABEL, expr, proxy); dvander@141: } dvander@141: dvander@28: default: dvander@28: break; dvander@23: } dvander@23: dvander@23: Expression *expr = primary(); dvander@23: dvander@23: token = scanner_.peek(); dvander@23: if (token == TOK_INCREMENT || token == TOK_DECREMENT) { dvander@23: scanner_.scan(); dvander@25: return new (pool_) IncDecExpression(pos, token, expr, true); dvander@23: } dvander@23: dvander@23: return expr; dvander@0: } dvander@0: dvander@0: Expression * dvander@0: Parser::multiplication() dvander@0: { dvander@0: Expression *left = unary(); dvander@0: do { dvander@82: if (!match(TOK_SLASH) && !match(TOK_STAR) && !match(TOK_PERCENT)) dvander@0: break; dvander@25: SourcePosition pos = scanner_.begin(); dvander@0: TokenKind kind = scanner_.last(); dvander@0: Expression *right = unary(); dvander@0: if (!right) dvander@0: return NULL; dvander@25: left = new (pool_) BinaryExpression(pos, kind, left, right); dvander@0: } while (left); dvander@0: return left; dvander@0: } dvander@0: dvander@0: Expression * dvander@0: Parser::addition() dvander@0: { dvander@0: Expression *left = multiplication(); dvander@0: while (left) { dvander@0: if (!match(TOK_PLUS) && !match(TOK_MINUS)) dvander@0: break; dvander@25: SourcePosition pos = scanner_.begin(); dvander@0: TokenKind kind = scanner_.last(); dvander@0: Expression *right = multiplication(); dvander@0: if (!right) dvander@0: return NULL; dvander@25: left = new (pool_) BinaryExpression(pos, kind, left, right); dvander@0: } dvander@0: return left; dvander@0: } dvander@0: dvander@0: Expression * dvander@2: Parser::shift() dvander@2: { dvander@2: Expression *left = addition(); dvander@2: while (left) { dvander@8: if (!match(TOK_SHL) && !match(TOK_SHR) && !match(TOK_USHR)) dvander@2: break; dvander@25: SourcePosition pos = scanner_.begin(); dvander@2: TokenKind kind = scanner_.last(); dvander@2: Expression *right = addition(); dvander@2: if (!right) dvander@2: return NULL; dvander@25: left = new (pool_) BinaryExpression(pos, kind, left, right); dvander@2: } dvander@2: return left; dvander@2: } dvander@2: dvander@2: Expression * dvander@28: Parser::bitand_() dvander@8: { dvander@8: Expression *left = shift(); dvander@8: while (left) { dvander@8: if (!match(TOK_BITAND)) dvander@8: break; dvander@25: SourcePosition pos = scanner_.begin(); dvander@8: Expression *right = shift(); dvander@8: if (!right) dvander@8: return NULL; dvander@25: left = new (pool_) BinaryExpression(pos, TOK_BITAND, left, right); dvander@8: } dvander@8: return left; dvander@8: } dvander@8: dvander@8: Expression * dvander@8: Parser::bitxor() dvander@8: { dvander@28: Expression *left = bitand_(); dvander@8: while (left) { dvander@8: if (!match(TOK_BITXOR)) dvander@8: break; dvander@25: SourcePosition pos = scanner_.begin(); dvander@8: Expression *right = shift(); dvander@8: if (!right) dvander@8: return NULL; dvander@25: left = new (pool_) BinaryExpression(pos, TOK_BITXOR, left, right); dvander@8: } dvander@8: return left; dvander@8: } dvander@8: dvander@8: Expression * dvander@28: Parser::bitor_() dvander@8: { dvander@8: Expression *left = bitxor(); dvander@8: while (left) { dvander@8: if (!match(TOK_BITOR)) dvander@8: break; dvander@25: SourcePosition pos = scanner_.begin(); dvander@75: Expression *right = bitxor(); dvander@8: if (!right) dvander@8: return NULL; dvander@25: left = new (pool_) BinaryExpression(pos, TOK_BITOR, left, right); dvander@8: } dvander@8: return left; dvander@8: } dvander@8: dvander@8: Expression * dvander@0: Parser::relational() dvander@0: { dvander@28: Expression *left = bitor_(); dvander@0: while (left) { dvander@0: TokenKind kind = scanner_.peek(); dvander@0: if (kind < TOK_LT || kind > TOK_GE) dvander@0: break; dvander@0: scanner_.scan(); dvander@25: SourcePosition pos = scanner_.begin(); dvander@2: Expression *right = shift(); dvander@0: if (!right) dvander@0: return NULL; dvander@25: left = new (pool_) BinaryExpression(pos, kind, left, right); dvander@0: } dvander@0: return left; dvander@0: } dvander@0: dvander@0: Expression * dvander@0: Parser::equals() dvander@0: { dvander@0: Expression *left = relational(); dvander@0: while (left) { dvander@0: if (!match(TOK_EQUALS) && !match(TOK_NOTEQUALS)) dvander@0: break; dvander@0: TokenKind kind = scanner_.last(); dvander@25: SourcePosition pos = scanner_.begin(); dvander@0: Expression *right = relational(); dvander@0: if (!right) dvander@0: return NULL; dvander@25: left = new (pool_) BinaryExpression(pos, kind, left, right); dvander@0: } dvander@0: return left; dvander@0: } dvander@0: dvander@0: Expression * dvander@75: Parser::and_() dvander@75: { dvander@75: Expression *left = equals(); dvander@75: while (left) { dvander@75: if (!match(TOK_AND)) dvander@75: break; dvander@75: SourcePosition pos = scanner_.begin(); dvander@75: Expression *right = equals(); dvander@75: if (!right) dvander@75: return NULL; dvander@75: left = new (pool_) BinaryExpression(pos, TOK_AND, left, right); dvander@75: } dvander@75: return left; dvander@75: } dvander@75: dvander@75: Expression * dvander@75: Parser::or_() dvander@75: { dvander@75: Expression *left = and_(); dvander@75: while (left) { dvander@75: if (!match(TOK_OR)) dvander@75: break; dvander@75: SourcePosition pos = scanner_.begin(); dvander@75: Expression *right = and_(); dvander@75: if (!right) dvander@75: return NULL; dvander@75: left = new (pool_) BinaryExpression(pos, TOK_OR, left, right); dvander@75: } dvander@75: return left; dvander@75: } dvander@75: dvander@75: Expression * dvander@83: Parser::ternary() dvander@83: { dvander@83: Expression *cond = or_(); dvander@83: if (!cond) dvander@83: return NULL; dvander@83: dvander@83: if (!match(TOK_QMARK)) dvander@83: return cond; dvander@83: dvander@172: Expression *left; dvander@83: SourcePosition pos = scanner_.begin(); dvander@172: AutoAllowTags disableTags(scanner_); dvander@172: { dvander@172: if ((left = expression()) == NULL) dvander@172: return NULL; dvander@172: } dvander@83: dvander@83: if (!expect(TOK_COLON)) dvander@83: return NULL; dvander@83: dvander@83: Expression *right = expression(); dvander@83: if (!right) dvander@83: return NULL; dvander@83: dvander@83: return new (pool_) TernaryExpression(pos, cond, left, right); dvander@83: } dvander@83: dvander@83: Expression * dvander@22: Parser::assignment() dvander@22: { dvander@83: Expression *left = ternary(); dvander@22: while (left) { dvander@22: TokenKind token = scanner_.peek(); dvander@22: if (token != TOK_ASSIGN && (token < TOK_ASSIGN_ADD || token > TOK_ASSIGN_SHL)) dvander@22: break; dvander@22: scanner_.scan(); dvander@25: SourcePosition pos = scanner_.begin(); dvander@83: Expression *expr = ternary(); dvander@22: if (!expr) dvander@22: return NULL; dvander@22: dvander@25: left = new (pool_) Assignment(pos, token, left, expr); dvander@22: } dvander@22: return left; dvander@22: } dvander@22: dvander@22: Expression * dvander@0: Parser::expression() dvander@0: { dvander@22: return assignment(); dvander@0: } dvander@0: dvander@0: Statement * dvander@9: Parser::while_() dvander@9: { dvander@25: SourcePosition pos = scanner_.begin(); dvander@9: scanner_.scan(); dvander@9: dvander@9: if (!expect(TOK_LPAREN)) dvander@9: return NULL; dvander@25: dvander@9: Expression *condition = expression(); dvander@9: if (!condition) dvander@9: return NULL; dvander@25: dvander@9: if (!expect(TOK_RPAREN)) dvander@9: return NULL; dvander@9: dvander@48: Statement *body; dvander@48: if (scanner_.peek() == TOK_LBRACE) dvander@195: body = block(); dvander@48: else dvander@48: body = localStatement(); dvander@9: if (!body) dvander@9: return NULL; dvander@9: dvander@25: return new (pool_) WhileStatement(pos, TOK_WHILE, condition, body); dvander@9: } dvander@9: dvander@9: Statement * dvander@9: Parser::do_() dvander@9: { dvander@25: SourcePosition pos = scanner_.begin(); dvander@9: scanner_.scan(); dvander@9: dvander@48: Statement *body; dvander@48: if (scanner_.peek() == TOK_LBRACE) dvander@195: body = block(); dvander@48: else dvander@48: body = localStatement(); dvander@9: if (!body) dvander@9: return NULL; dvander@9: dvander@9: if (!expect(TOK_WHILE)) dvander@9: return NULL; dvander@9: dvander@9: if (!expect(TOK_LPAREN)) dvander@9: return NULL; dvander@9: Expression *condition = expression(); dvander@9: if (!condition) dvander@9: return NULL; dvander@9: if (!expect(TOK_RPAREN)) dvander@9: return NULL; dvander@9: dvander@25: return new (pool_) WhileStatement(pos, TOK_DO, condition, body); dvander@9: } dvander@9: dvander@9: Statement * dvander@172: Parser::switch_() dvander@172: { dvander@172: expect(TOK_SWITCH); dvander@172: dvander@172: SourcePosition pos = scanner_.begin(); dvander@172: dvander@172: if (!expect(TOK_LPAREN)) dvander@172: return NULL; dvander@172: Expression *expr = expression(); dvander@172: if (!expr) dvander@172: return NULL; dvander@172: if (!expect(TOK_RPAREN)) dvander@172: return NULL; dvander@172: dvander@172: if (!expect(TOK_LBRACE)) dvander@172: return NULL; dvander@172: dvander@172: SourcePosition defaultPos; dvander@172: PoolList *cases = new (pool_) PoolList(); dvander@172: dvander@172: Statement *defaultCase = NULL; dvander@172: dvander@172: while (!peek(TOK_RBRACE)) { dvander@172: Expression *expr = NULL; dvander@172: ExpressionList *others = NULL; dvander@172: if (match(TOK_DEFAULT)) { dvander@172: if (defaultCase) { dvander@172: cc_.reportError(scanner_.begin(), Message_OneDefaultPerSwitch); dvander@172: return NULL; dvander@172: } dvander@172: dvander@172: defaultPos = scanner_.begin(); dvander@172: } else { dvander@172: if (defaultCase) { dvander@172: cc_.reportError(defaultPos, Message_DefaultMustBeLastCase); dvander@172: return NULL; dvander@172: } dvander@172: dvander@172: if (!expect(TOK_CASE)) dvander@172: return NULL; dvander@172: dvander@172: // A limitation in the grammar is that |case :| will be dvander@172: // detected as a label. dvander@172: AutoAllowTags disableTags(scanner_); dvander@172: dvander@172: if ((expr = expression()) == NULL) dvander@172: return NULL; dvander@172: dvander@172: if (peek(TOK_COMMA)) { dvander@172: others = new (pool_) ExpressionList(); dvander@172: while (match(TOK_COMMA)) { dvander@172: Expression *other = expression(); dvander@172: if (!other) dvander@172: return NULL; dvander@172: if (!others->append(other)) dvander@172: return NULL; dvander@172: } dvander@172: } dvander@172: } dvander@172: dvander@172: if (!expect(TOK_COLON)) dvander@172: return NULL; dvander@172: dvander@172: Statement *statement = localStatement(); dvander@172: if (!statement) dvander@172: return NULL; dvander@172: dvander@172: if (!peek(TOK_CASE) && dvander@172: !peek(TOK_DEFAULT) && dvander@172: !peek(TOK_RBRACE)) dvander@172: { dvander@172: cc_.reportError(scanner_.begin(), Message_SingleStatementPerCase); dvander@172: return NULL; dvander@172: } dvander@172: dvander@172: if (expr) { dvander@172: Case *caze = new (pool_) Case(expr, others, statement); dvander@172: if (!cases->append(caze)) dvander@172: return NULL; dvander@172: } else { dvander@172: defaultCase = statement; dvander@172: } dvander@172: } dvander@172: dvander@172: if (!expect(TOK_RBRACE)) dvander@172: return NULL; dvander@172: dvander@172: return new (pool_) SwitchStatement(pos, expr, cases, defaultCase); dvander@172: } dvander@172: dvander@172: Statement * dvander@0: Parser::forStatement() dvander@0: { dvander@25: SourcePosition pos = scanner_.begin(); dvander@0: scanner_.scan(); dvander@0: if (!expect(TOK_LPAREN)) dvander@0: return NULL; dvander@0: dvander@22: Statement *decl = NULL; dvander@0: if (!match(TOK_SEMICOLON)) { dvander@135: if (match(TOK_NEW)) { dvander@195: if ((decl = vars(Qual_None)) == NULL) dvander@22: return NULL; dvander@22: } else { dvander@22: if ((decl = expressionStatement()) == NULL) dvander@22: return NULL; dvander@22: } dvander@0: if (!expect(TOK_SEMICOLON)) dvander@0: return NULL; dvander@0: } dvander@0: dvander@0: Expression *condition = NULL; dvander@0: if (!match(TOK_SEMICOLON)) { dvander@0: if ((condition = expression()) == NULL) dvander@0: return NULL; dvander@0: if (!expect(TOK_SEMICOLON)) dvander@0: return NULL; dvander@0: } dvander@0: dvander@0: Statement *update = NULL; dvander@0: if (!match(TOK_RPAREN)) { dvander@0: if ((update = expressionStatement()) == NULL) dvander@0: return NULL; dvander@0: if (!expect(TOK_RPAREN)) dvander@0: return NULL; dvander@0: } dvander@0: dvander@48: Statement *body; dvander@48: if (scanner_.peek() == TOK_LBRACE) dvander@195: body = block(); dvander@48: else dvander@48: body = localStatement(); dvander@0: if (!body) dvander@0: return NULL; dvander@0: dvander@195: return new (pool_) ForStatement(pos, decl, condition, update, body); dvander@0: } dvander@0: dvander@145: ExpressionList * dvander@145: Parser::dimensions() dvander@145: { dvander@145: ExpressionList *postDimensions = new (pool_) ExpressionList(); dvander@145: while (match(TOK_LBRACKET)) { dvander@145: Expression *dim = NULL; dvander@145: if (!match(TOK_RBRACKET)) { dvander@145: if ((dim = expression()) == NULL) dvander@145: return NULL; dvander@145: if (!expect(TOK_RBRACKET)) dvander@145: return NULL; dvander@145: } dvander@145: dvander@145: if (!postDimensions->append(dim)) dvander@145: return NULL; dvander@145: } dvander@145: return postDimensions; dvander@145: } dvander@145: dvander@0: VariableDeclaration * dvander@195: Parser::var(TypeQualifiers qual) dvander@0: { dvander@195: Expression *type; dvander@195: Local name(zone_); dvander@195: dvander@195: if (!typeAndName(&type, name.ref())) dvander@4: return NULL; dvander@0: dvander@209: ExpressionList *dims = NULL; dvander@212: if (peek(TOK_LBRACKET)) { dvander@209: if ((dims = dimensions()) == NULL) dvander@209: return NULL;; dvander@209: } dvander@209: dvander@189: SourcePosition pos = scanner_.begin(); dvander@0: dvander@0: Expression *expr = NULL; dvander@0: if (match(TOK_ASSIGN)) { dvander@187: switch (scanner_.peek()) { dvander@187: // Note: we don't support [] literals yet. dvander@187: case TOK_LBRACE: dvander@212: scanner_.scan(); dvander@212: if ((expr = fixedArrayLiteral()) == NULL) dvander@187: return NULL; dvander@187: break; dvander@187: dvander@187: default: dvander@187: if ((expr = expression()) == NULL) dvander@187: return NULL; dvander@187: break; dvander@187: } dvander@0: } dvander@0: dvander@209: return new (pool_) VariableDeclaration(pos, qual, name, type, dims, expr); dvander@0: } dvander@0: dvander@0: Statement * dvander@195: Parser::vars(TypeQualifiers qual) dvander@165: { dvander@195: VariableDeclaration *decl = var(qual); dvander@165: if (!decl) dvander@165: return NULL; dvander@165: dvander@165: if (!peek(TOK_COMMA)) dvander@165: return decl; dvander@165: dvander@165: StatementList *statements = new (pool_) StatementList(); dvander@165: if (!statements->append(decl)) dvander@165: return NULL; dvander@165: dvander@165: while (match(TOK_COMMA)) { dvander@195: Statement *decl = var(qual); dvander@165: if (!decl) dvander@165: return NULL; dvander@165: if (!statements->append(decl)) dvander@165: return NULL; dvander@165: } dvander@165: dvander@165: // Create a fake-o block with no scope to create a statement list. dvander@195: return new (pool_) BlockStatement(decl->pos(), statements); dvander@165: } dvander@165: dvander@165: Statement * dvander@0: Parser::returnStatement() dvander@0: { dvander@25: SourcePosition pos = scanner_.begin(); dvander@0: if (!expect(TOK_RETURN)) dvander@0: return NULL; dvander@0: dvander@72: Expression *expr = NULL; dvander@72: if (scanner_.peek() != TOK_SEMICOLON) { dvander@72: if ((expr = expression()) == NULL) dvander@72: return NULL; dvander@0: dvander@72: // We only care about non-void returns when determining whether a dvander@72: // tagless function is non-void. dvander@72: encounteredReturn_ = true; dvander@72: } dvander@71: dvander@25: return new (pool_) ReturnStatement(pos, expr); dvander@0: } dvander@0: dvander@0: Statement * dvander@0: Parser::expressionStatement() dvander@0: { dvander@22: Expression *left = assignment(); dvander@21: if (!left) dvander@0: return NULL; dvander@0: dvander@0: return new (pool_) ExpressionStatement(left); dvander@0: } dvander@0: dvander@0: Statement * dvander@195: Parser::block() dvander@0: { dvander@0: if (!expect(TOK_LBRACE)) dvander@0: return NULL; dvander@0: dvander@25: SourcePosition pos = scanner_.begin(); dvander@0: dvander@0: StatementList *statements = new (pool_) StatementList(); dvander@0: while (!match(TOK_RBRACE)) { dvander@0: Statement *statement = localStatement(); dvander@0: if (statement == NULL) dvander@0: return NULL; dvander@56: if (!statements->append(statement)) dvander@56: return NULL; dvander@0: } dvander@0: dvander@195: BlockStatement *block = new (pool_) BlockStatement(pos, statements); dvander@0: return block; dvander@0: } dvander@0: dvander@0: Statement * dvander@0: Parser::if_() dvander@0: { dvander@0: expect(TOK_IF); dvander@25: dvander@25: SourcePosition pos = scanner_.begin(); dvander@0: if (!expect(TOK_LPAREN)) dvander@0: return NULL; dvander@0: dvander@0: Expression *cond = expression(); dvander@0: if (!cond) dvander@0: return NULL; dvander@0: dvander@0: if (!expect(TOK_RPAREN)) dvander@0: return NULL; dvander@0: dvander@0: Statement *ifTrue = localStatement(); dvander@0: if (!ifTrue) dvander@0: return NULL; dvander@0: dvander@25: IfStatement *outer = new (pool_) IfStatement(pos, cond, ifTrue); dvander@0: dvander@0: IfStatement *last = outer; dvander@0: while (match(TOK_ELSE)) { dvander@0: if (!match(TOK_IF)) { dvander@0: Statement *ifFalse = localStatement(); dvander@0: if (!ifFalse) dvander@0: return NULL; dvander@0: dvander@0: last->setIfFalse(ifFalse); dvander@0: break; dvander@0: } dvander@0: dvander@25: SourcePosition pos = scanner_.begin(); dvander@0: if (!expect(TOK_LPAREN)) dvander@0: return NULL; dvander@0: dvander@0: Expression *otherCond = expression(); dvander@0: if (!otherCond) dvander@0: return NULL; dvander@0: dvander@0: if (!expect(TOK_RPAREN)) dvander@0: return NULL; dvander@0: dvander@0: Statement *otherIfTrue = localStatement(); dvander@0: if (!otherIfTrue) dvander@0: return NULL; dvander@0: dvander@25: IfStatement *inner = new (pool_) IfStatement(pos, otherCond, otherIfTrue); dvander@0: last->setIfFalse(inner); dvander@0: last = inner; dvander@0: } dvander@0: dvander@0: return outer; dvander@0: } dvander@0: dvander@0: Statement * dvander@0: Parser::localStatement() dvander@0: { dvander@0: Statement *statement = NULL; dvander@0: dvander@0: // Statements which must be followed by a semicolon will break out of the dvander@0: // switch. If they may end in BlockStatements, they'll immediately return. dvander@0: dvander@135: TokenKind kind = scanner_.peek(); dvander@135: switch (kind) { dvander@135: case TOK_CONST: dvander@131: case TOK_NEW: dvander@195: { dvander@195: TypeQualifiers quals = (kind == TOK_CONST) dvander@195: ? Qual_Const dvander@195: : Qual_None; dvander@135: scanner_.scan(); dvander@195: if ((statement = vars(quals)) == NULL) dvander@172: return NULL; dvander@131: break; dvander@195: } dvander@0: dvander@131: case TOK_FOR: dvander@131: return forStatement(); dvander@0: dvander@131: case TOK_WHILE: dvander@131: return while_(); dvander@9: dvander@131: case TOK_BREAK: dvander@131: scanner_.scan(); dvander@131: statement = new (pool_) BreakStatement(scanner_.begin()); dvander@131: break; dvander@10: dvander@131: case TOK_CONTINUE: dvander@131: scanner_.scan(); dvander@131: statement = new (pool_) ContinueStatement(scanner_.begin()); dvander@131: break; dvander@10: dvander@131: case TOK_DO: dvander@131: if ((statement = do_()) == NULL) dvander@131: return NULL; dvander@131: break; dvander@9: dvander@131: case TOK_RETURN: dvander@131: if ((statement = returnStatement()) == NULL) dvander@172: return NULL; dvander@131: break; dvander@0: dvander@131: case TOK_ENUM: dvander@131: if ((statement = enum_()) == NULL) dvander@172: return NULL; dvander@131: break; dvander@2: dvander@146: case TOK_STRUCT: dvander@146: if ((statement = struct_()) == NULL) dvander@172: return NULL; dvander@146: break; dvander@146: dvander@172: case TOK_SWITCH: dvander@172: return switch_(); dvander@172: dvander@131: case TOK_IF: dvander@131: return if_(); dvander@0: dvander@131: case TOK_LBRACE: dvander@131: return block(); dvander@28: dvander@131: default: dvander@131: break; dvander@0: } dvander@0: dvander@0: if (!statement) { dvander@0: if ((statement = expressionStatement()) == NULL) dvander@0: return NULL; dvander@0: } dvander@0: dvander@0: if (!expect(TOK_SEMICOLON)) dvander@0: return NULL; dvander@0: dvander@0: return statement; dvander@0: } dvander@0: dvander@0: Statement * dvander@146: Parser::struct_() dvander@146: { dvander@146: expect(TOK_STRUCT); dvander@146: dvander@146: Local name(zone_, expectName()); dvander@146: if (!name) dvander@146: return NULL; dvander@146: dvander@146: SourcePosition pos = scanner_.begin(); dvander@146: dvander@146: if (!expect(TOK_LBRACE)) dvander@146: return NULL; dvander@146: dvander@146: FieldList *fields = new (pool_) FieldList(); dvander@146: dvander@146: while (!peek(TOK_RBRACE)) { dvander@195: Expression *type; dvander@195: Local fieldName(zone_); dvander@146: dvander@195: if (!fullTypeAndName(&type, fieldName.ref(), DeclField)) dvander@146: return NULL; dvander@146: dvander@146: SourcePosition pos = scanner_.begin(); dvander@146: dvander@146: if (!matchSemicolon()) dvander@146: return NULL; dvander@146: dvander@146: StructureStatement::Field *field = dvander@195: new (pool_) StructureStatement::Field(pos, type, fieldName); dvander@146: if (!field || !fields->append(field)) dvander@146: return NULL; dvander@146: } dvander@146: dvander@146: if (!expect(TOK_RBRACE)) dvander@146: return NULL; dvander@146: mibusby@180: if (fields->empty()) { mibusby@180: cc_.reportError(pos, Message_StructCantBeEmpty); mibusby@180: return NULL; mibusby@180: } mibusby@180: dvander@195: return new (pool_) StructureStatement(pos, name, fields); dvander@146: } dvander@146: dvander@146: Statement * dvander@2: Parser::enum_() dvander@2: { dvander@2: expect(TOK_ENUM); dvander@2: dvander@25: SourcePosition pos = scanner_.begin(); dvander@25: dvander@54: Local name(zone_); dvander@195: if (matchName(name.ref()) && !name) dvander@195: return NULL; dvander@2: dvander@57: EnumStatement::EntryList *entries = new (pool_) EnumStatement::EntryList(); dvander@2: dvander@2: if (!expect(TOK_LBRACE)) dvander@2: return NULL; dvander@2: dvander@2: do { dvander@2: if (scanner_.peek() == TOK_RBRACE) dvander@2: break; dvander@2: dvander@54: Local name(zone_, expectName()); dvander@2: if (!name) dvander@2: return NULL; dvander@2: dvander@2: Expression *expr = NULL; dvander@2: if (match(TOK_ASSIGN)) { dvander@2: if ((expr = expression()) == NULL) dvander@2: return NULL; dvander@2: } dvander@2: dvander@195: if (!entries->append(EnumStatement::Entry(name, expr))) dvander@57: return NULL; dvander@2: } while (match(TOK_COMMA)); dvander@2: if (!expect(TOK_RBRACE)) dvander@2: return NULL; dvander@2: dvander@195: return new (pool_) EnumStatement(pos, name, entries); dvander@195: } dvander@195: dvander@195: template dvander@195: static inline ScopedRoot * dvander@195: NewScopedRoot(PoolAllocator &pool, Handle obj) dvander@195: { dvander@195: ScopedRoot *root = pool.alloc >(); dvander@195: new (root) ScopedRoot(obj); dvander@195: return root; dvander@195: } dvander@195: dvander@195: ImportStatement * dvander@195: Parser::import() dvander@195: { dvander@195: NameList *names = new (pool_) NameList(); dvander@195: dvander@195: SourcePosition pos = scanner_.begin(); dvander@195: dvander@195: Local name(zone_, expectName()); dvander@195: if (!name || !names->append(NewScopedRoot(pool_, name))) dvander@195: return NULL; dvander@195: dvander@195: TokenKind suffix = TOK_NONE; dvander@195: while (match(TOK_DOT)) { dvander@195: if (match(TOK_STAR)) { dvander@195: suffix = TOK_STAR; dvander@195: break; dvander@195: } dvander@195: dvander@195: if ((name = expectName()) == NULL) dvander@195: return NULL; dvander@195: dvander@195: if (!names->append(NewScopedRoot(pool_, name))) dvander@195: return NULL; dvander@195: } dvander@195: dvander@195: return new (pool_) ImportStatement(pos, names, suffix); dvander@2: } dvander@2: dvander@2: Statement * dvander@63: Parser::function(TokenKind token) dvander@0: { dvander@195: Expression *returnType; dvander@191: Local name(zone_); dvander@191: dvander@195: if (!fullTypeAndName(&returnType, name.ref(), DeclFun)) dvander@195: return NULL; dvander@132: dvander@25: SourcePosition pos = scanner_.begin(); dvander@57: ParameterList *parameters = new (pool_) ParameterList(); dvander@14: dvander@0: if (!expect(TOK_LPAREN)) dvander@0: return NULL; dvander@133: dvander@195: bool variadic = false; dvander@195: dvander@0: if (!match(TOK_RPAREN)) { dvander@0: while (true) { dvander@67: bool isConst = match(TOK_CONST); dvander@14: bool ref = match(TOK_AMPERSAND); dvander@14: dvander@66: SourcePosition begin = scanner_.begin(); dvander@195: Expression *type; dvander@195: Local name(zone_); dvander@195: if (!fullTypeAndName(&type, name.ref(), DeclArg)) dvander@66: return NULL; dvander@66: dvander@195: if (!name) { dvander@68: if (isConst || ref) { dvander@68: cc_.reportError(begin, Message_InvalidVarArgs); dvander@68: return NULL; dvander@68: } dvander@68: dvander@68: if (token != TOK_NATIVE) { dvander@68: cc_.reportError(begin, Message_VarArgsOutsideNative); dvander@68: return NULL; dvander@68: } dvander@68: dvander@195: variadic = true; dvander@68: break; dvander@68: } dvander@68: dvander@133: Expression *expr = NULL; dvander@133: if (match(TOK_ASSIGN)) { dvander@133: if ((expr = expression()) == NULL) dvander@133: return NULL; dvander@133: } dvander@133: dvander@195: Parameter *parameter = new (pool_) Parameter(name, type, ref, isConst, expr, begin); dvander@57: if (!parameters->append(parameter)) dvander@57: return NULL; dvander@14: dvander@0: if (!match(TOK_COMMA)) dvander@0: break; dvander@0: } dvander@0: if (!expect(TOK_RPAREN)) dvander@0: return NULL; dvander@0: } dvander@0: dvander@71: encounteredReturn_ = false; dvander@71: dvander@63: Statement *body = NULL; dvander@174: if (token != TOK_FORWARD && token != TOK_NATIVE && token != TOK_TYPEDEF) { dvander@63: body = block(); dvander@63: if (!body) dvander@63: return NULL; dvander@63: } dvander@0: dvander@195: FunctionSignature signature(returnType, parameters, variadic); dvander@174: if (token == TOK_TYPEDEF) dvander@195: return new (pool_) FunctionTypeStatement(pos, name, signature); dvander@174: dvander@195: return new (pool_) FunctionStatement(pos, name, token, body, signature, encounteredReturn_); dvander@0: } dvander@0: dvander@145: static inline bool dvander@167: DeclareIntrinsicType(Zone *zone, Scope *scope, const char *name, Handle type) dvander@145: { dvander@145: Local tag(zone, zone->makeSymbol(name)); dvander@145: if (!tag) dvander@145: return false; dvander@145: dvander@195: assert(false); dvander@195: return false; //return !!scope->declareType(tag, type); dvander@167: } dvander@167: dvander@167: static inline bool dvander@167: DeclareIntrinsicType(Zone *zone, Scope *scope, const char *name, PrimitiveType type) dvander@167: { dvander@145: Local primitive(zone, zone->types()->getPrimitive(type)); dvander@145: assert(primitive); dvander@167: return DeclareIntrinsicType(zone, scope, name, primitive); dvander@145: } dvander@145: dvander@145: bool dvander@145: Parser::setupIntrinsics() dvander@145: { dvander@195: #if 0 dvander@145: if (!DeclareIntrinsicType(zone_, scope_, "Float", PrimitiveType_Float)) dvander@145: return false; dvander@145: if (!DeclareIntrinsicType(zone_, scope_, "_", PrimitiveType_Int32)) dvander@145: return false; dvander@145: if (!DeclareIntrinsicType(zone_, scope_, "bool", PrimitiveType_Bool)) dvander@145: return false; dvander@145: if (!DeclareIntrinsicType(zone_, scope_, "String", PrimitiveType_Char)) dvander@145: return false; dvander@167: dvander@167: Local unchecked(zone_, zone_->types()->getUnchecked()); dvander@167: if (!DeclareIntrinsicType(zone_, scope_, "unchecked", unchecked)) dvander@167: return false; dvander@167: dvander@174: Local voidType(zone_, zone_->types()->getVoid()); dvander@174: if (!DeclareIntrinsicType(zone_, scope_, "void", voidType)) dvander@174: return false; dvander@174: dvander@174: Local intType(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32)); dvander@174: if (!DeclareIntrinsicType(zone_, scope_, "int", intType)) dvander@174: return false; dvander@195: #endif dvander@145: return true; dvander@145: } dvander@145: dvander@0: ParseTree * dvander@0: Parser::parse() dvander@0: { dvander@0: StatementList *statements = new (pool_) StatementList(); dvander@0: dvander@145: if (!setupIntrinsics()) dvander@145: return NULL; dvander@145: dvander@0: for (;;) { dvander@0: Statement *statement = NULL; dvander@0: dvander@135: TokenKind kind = scanner_.peek(); dvander@135: switch (kind) { dvander@0: case TOK_ERROR: dvander@0: return NULL; dvander@0: dvander@0: case TOK_EOF: dvander@0: break; dvander@0: dvander@0: case TOK_NAME: dvander@63: if ((statement = function(TOK_NAME)) == NULL) dvander@0: return NULL; dvander@0: break; dvander@0: dvander@195: case TOK_IMPORT: dvander@195: { dvander@195: scanner_.scan(); dvander@195: if (statements->length()) dvander@195: cc_.reportError(scanner_.begin(), Message_ImportsMustBeFirst); dvander@195: ImportStatement *stmt = import(); dvander@195: if (!stmt) dvander@195: return NULL; dvander@195: if (!imports_->append(stmt)) dvander@195: return NULL; dvander@195: if (!matchSemicolon()) dvander@195: return NULL; dvander@195: continue; dvander@195: } dvander@195: dvander@63: case TOK_FORWARD: dvander@63: case TOK_PUBLIC: dvander@68: case TOK_NATIVE: dvander@134: case TOK_STOCK: dvander@145: case TOK_LABEL: dvander@174: case TOK_TYPEDEF: dvander@63: { dvander@195: if (kind != TOK_LABEL) dvander@195: scanner_.scan(); dvander@170: if (kind == TOK_PUBLIC && peek(TOK_CONST)) { dvander@195: TypeQualifiers quals = TypeQualifiers(Qual_Public | Qual_Const); dvander@195: if ((statement = var(quals)) == NULL) dvander@170: return NULL; dvander@170: if (!matchSemicolon()) dvander@170: return NULL; dvander@170: } else { dvander@170: if ((statement = function(kind)) == NULL) dvander@170: return NULL; dvander@174: if ((kind == TOK_FORWARD || kind == TOK_NATIVE || kind == TOK_TYPEDEF) && !matchSemicolon()) dvander@170: return NULL; dvander@170: } dvander@63: break; dvander@63: } dvander@63: dvander@135: case TOK_CONST: dvander@85: case TOK_NEW: dvander@85: { dvander@195: TypeQualifiers quals = (kind == TOK_NEW) ? Qual_Const : Qual_None; dvander@165: // Note: at global scope, we don't accept comma-delimited dvander@165: // declarations yet, to see if we can get away with forcing dvander@165: // a nicer top-level style. dvander@135: scanner_.scan(); dvander@195: if ((statement = var(quals)) == NULL) dvander@170: return NULL; dvander@85: if (!matchSemicolon()) dvander@85: return NULL; dvander@85: break; dvander@85: } dvander@74: dvander@2: case TOK_ENUM: dvander@2: if ((statement = enum_()) == NULL) dvander@2: return NULL; dvander@63: if (!matchSemicolon()) dvander@63: return NULL; dvander@2: break; dvander@2: dvander@146: case TOK_STRUCT: dvander@146: if ((statement = struct_()) == NULL) dvander@146: return NULL; dvander@146: if (!matchSemicolon()) dvander@146: return NULL; dvander@146: break; dvander@146: dvander@0: default: dvander@63: cc_.reportError(scanner_.begin(), Message_ExpectedGlobal); dvander@0: return NULL; dvander@0: } dvander@0: dvander@0: if (!statement) dvander@0: break; dvander@0: dvander@56: if (!statements->append(statement)) dvander@56: return NULL; dvander@0: } dvander@0: dvander@195: return new (pool_) ParseTree(statements, unbound_, imports_); dvander@0: } dvander@0: dvander@0: class AstPrinter : public AstVisitor dvander@0: { dvander@0: FILE *fp_; dvander@0: size_t level_; dvander@0: dvander@0: private: dvander@0: void prefix() { dvander@0: for (size_t i = 0; i < level_; i++) dvander@0: fprintf(fp_, " "); dvander@0: } dvander@0: void indent() { dvander@0: level_++; dvander@0: } dvander@0: void unindent() { dvander@0: level_--; dvander@0: } dvander@0: dvander@0: public: dvander@0: AstPrinter(FILE *fp) dvander@0: : fp_(fp), dvander@0: level_(0) dvander@0: { dvander@0: } dvander@0: dvander@191: void dump(const FunctionSignature &sig) { dvander@191: prefix(); dvander@191: fprintf(fp_, "()\n"); dvander@191: } dvander@195: void visitNameProxy(NameProxy *name) { dvander@0: prefix(); dvander@195: fprintf(fp_, "[ NameProxy (%s)\n", name->name()->chars()); dvander@0: } dvander@195: void visitCallExpression(CallExpression *node) { dvander@0: prefix(); dvander@0: fprintf(fp_, "[ CallExpression\n"); dvander@0: indent(); dvander@0: node->callee()->accept(this); dvander@55: for (size_t i = 0; i < node->arguments()->length(); i++) dvander@0: node->arguments()->at(i)->accept(this); dvander@0: unindent(); dvander@0: } dvander@195: void visitFunctionTypeStatement(FunctionTypeStatement *node) { dvander@174: prefix(); dvander@195: fprintf(fp_, "[ FunctionTypeStatement (%s)\n", node->name()->chars()); dvander@191: indent(); dvander@191: dump(node->signature()); dvander@191: unindent(); dvander@174: } dvander@195: void visitFunctionStatement(FunctionStatement *node) { dvander@0: prefix(); dvander@195: fprintf(fp_, "[ FunctionStatement (%s)\n", node->name()->chars()); dvander@0: indent(); dvander@191: dump(node->signature()); dvander@63: if (node->body()) dvander@63: node->body()->accept(this); dvander@0: unindent(); dvander@0: } dvander@195: void visitExpressionStatement(ExpressionStatement *node) { dvander@0: prefix(); dvander@0: fprintf(fp_, "[ ExpressionStatement\n"); dvander@0: indent(); dvander@0: node->expression()->accept(this); dvander@0: unindent(); dvander@0: } dvander@195: void visitAssignment(Assignment *node) { dvander@0: prefix(); dvander@0: fprintf(fp_, "[ Assignment\n"); dvander@0: indent(); dvander@0: node->lvalue()->accept(this); dvander@0: node->expression()->accept(this); dvander@0: unindent(); dvander@0: } dvander@195: void visitTernaryExpression(TernaryExpression *node) { dvander@83: prefix(); dvander@83: fprintf(fp_, "[ TernaryExpression\n"); dvander@83: indent(); dvander@83: node->condition()->accept(this); dvander@83: node->left()->accept(this); dvander@83: node->right()->accept(this); dvander@83: unindent(); dvander@83: } dvander@195: void visitBinaryExpression(BinaryExpression *node) { dvander@0: prefix(); dvander@0: fprintf(fp_, "[ BinaryExpression (%s)\n", TokenNames[node->token()]); dvander@0: indent(); dvander@0: node->left()->accept(this); dvander@0: node->right()->accept(this); dvander@0: unindent(); dvander@0: } dvander@195: void visitUnaryExpression(UnaryExpression *node) { dvander@78: prefix(); dvander@78: fprintf(fp_, "[ UnaryExpression (%s)\n", TokenNames[node->token()]); dvander@78: indent(); dvander@78: node->expression()->accept(this); dvander@78: unindent(); dvander@78: } dvander@195: void visitReturnStatement(ReturnStatement *node) { dvander@0: prefix(); dvander@0: fprintf(fp_, "[ ReturnStatement\n"); dvander@0: indent(); dvander@72: if (node->expression()) dvander@72: node->expression()->accept(this); dvander@0: unindent(); dvander@0: } dvander@195: void visitForStatement(ForStatement *node) { dvander@0: prefix(); dvander@0: fprintf(fp_, "[ ForStatement\n"); dvander@0: indent(); dvander@22: if (node->initialization()) dvander@22: node->initialization()->accept(this); dvander@0: if (node->condition()) dvander@0: node->condition()->accept(this); dvander@0: if (node->update()) dvander@0: node->update()->accept(this); dvander@0: node->body()->accept(this); dvander@0: unindent(); dvander@0: } dvander@195: void visitBlockStatement(BlockStatement *node) { dvander@0: prefix(); dvander@0: fprintf(fp_, "[ BlockStatement\n"); dvander@0: indent(); dvander@0: for (size_t i = 0; i < node->statements()->length(); i++) dvander@0: node->statements()->at(i)->accept(this); dvander@0: unindent(); dvander@0: } dvander@195: void visitVariableDeclaration(VariableDeclaration *node) { dvander@0: prefix(); dvander@195: fprintf(fp_, "[ VariableDeclaration (%s)\n", node->name()->chars()); dvander@0: indent(); dvander@0: if (node->initialization()) dvander@0: node->initialization()->accept(this); dvander@0: unindent(); dvander@0: } dvander@195: void visitIntegerLiteral(IntegerLiteral *node) { dvander@0: prefix(); dvander@4: fprintf(fp_, "[ IntegerLiteral (%d)\n", node->value()); dvander@4: } dvander@195: void visitBooleanLiteral(BooleanLiteral *node) { dvander@143: prefix(); dvander@143: fprintf(fp_, "[ BooleanLiteral (%s)\n", dvander@143: (node->token() == TOK_TRUE) ? "true" : "false"); dvander@143: } dvander@195: void visitFloatLiteral(FloatLiteral *node) { dvander@4: prefix(); dvander@4: fprintf(fp_, "[ FloatLiteral (%f)\n", node->value()); dvander@0: } dvander@195: void visitIfStatement(IfStatement *node) { dvander@0: prefix(); dvander@0: fprintf(fp_, "[ IfStatement\n"); dvander@0: indent(); dvander@0: node->ifTrue()->accept(this); dvander@0: if (node->ifFalse()) dvander@0: node->ifFalse()->accept(this); dvander@0: unindent(); dvander@0: } dvander@195: void visitIndexExpression(IndexExpression *node) { dvander@0: prefix(); dvander@0: fprintf(fp_, "[ IndexExpression\n"); dvander@0: indent(); dvander@0: node->left()->accept(this); dvander@0: node->right()->accept(this); dvander@0: unindent(); dvander@0: } dvander@195: void visitEnumStatement(EnumStatement *node) { dvander@2: prefix(); dvander@54: fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name()->chars() : ""); dvander@2: indent(); dvander@57: for (size_t i = 0; i < node->entries()->length(); i++) { dvander@2: prefix(); dvander@195: fprintf(fp_, "%s =\n", node->entries()->at(i).name->chars()); dvander@2: if (node->entries()->at(i).expr) { dvander@2: indent(); dvander@2: node->entries()->at(i).expr->accept(this); dvander@2: unindent(); dvander@2: } dvander@2: } dvander@2: unindent(); dvander@2: } dvander@195: void visitWhileStatement(WhileStatement *node) { dvander@9: prefix(); dvander@9: fprintf(fp_, "[ WhileStatement (%s)\n", dvander@9: (node->token() == TOK_DO) ? "do" : "while"); dvander@9: indent(); dvander@9: if (node->token() == TOK_DO) { dvander@9: node->condition()->accept(this); dvander@9: node->body()->accept(this); dvander@9: } else { dvander@9: node->condition()->accept(this); dvander@9: node->body()->accept(this); dvander@9: } dvander@9: unindent(); dvander@9: } dvander@195: void visitBreakStatement(BreakStatement *node) { dvander@10: prefix(); dvander@10: fprintf(fp_, "[ BreakStatement\n"); dvander@10: } dvander@195: void visitContinueStatement(ContinueStatement *node) { dvander@10: prefix(); dvander@10: fprintf(fp_, "[ ContinueStatement\n"); dvander@10: } dvander@195: void visitStringLiteral(StringLiteral *node) { dvander@21: prefix(); dvander@21: fprintf(fp_, "[ StringLiteral\n"); dvander@21: } dvander@195: void visitIncDecExpression(IncDecExpression *node) { dvander@23: prefix(); dvander@23: fprintf(fp_, "[ IncDecExpression (postfix=%d)\n", node->postfix()); dvander@23: indent(); dvander@23: node->expression()->accept(this); dvander@23: unindent(); dvander@23: } dvander@195: void visitStructureStatement(StructureStatement *node) { dvander@146: prefix(); dvander@195: fprintf(fp_, "[ StructureStatement %s\n", node->name()->chars()); dvander@148: } dvander@195: void visitFieldExpression(FieldExpression *node) { dvander@148: prefix(); dvander@148: fprintf(fp_, "[ FieldExpression %s\n", node->field()->chars()); dvander@148: indent(); dvander@148: node->left()->accept(this); dvander@148: unindent(); dvander@146: } dvander@195: void visitSwitchStatement(SwitchStatement *node) { dvander@172: prefix(); dvander@172: fprintf(fp_, "[ SwitchStatement\n"); dvander@172: indent(); dvander@172: node->expression()->accept(this); dvander@172: for (size_t i = 0; i < node->cases()->length(); i++) { dvander@172: Case *c = node->cases()->at(i); dvander@172: c->expression()->accept(this); dvander@172: if (c->others()) { dvander@172: for (size_t j = 0; j < c->others()->length(); j++) dvander@172: c->others()->at(j)->accept(this); dvander@172: } dvander@172: indent(); dvander@172: c->statement()->accept(this); dvander@172: unindent(); dvander@172: } dvander@172: if (node->defaultCase()) dvander@172: node->defaultCase()->accept(this); dvander@172: unindent(); dvander@172: } dvander@195: void visitArrayLiteral(ArrayLiteral *node) { dvander@187: prefix(); dvander@187: fprintf(fp_, "[ ArrayLiteral\n"); dvander@187: indent(); dvander@187: for (size_t i = 0; i < node->expressions()->length(); i++) { dvander@187: Expression *expr = node->expressions()->at(i); dvander@187: indent(); dvander@187: expr->accept(this); dvander@187: unindent(); dvander@187: } dvander@187: } dvander@195: void visitImportStatement(ImportStatement *node) { dvander@195: prefix(); dvander@195: fprintf(fp_, "[ ImportStatement\n"); dvander@195: } dvander@0: }; dvander@0: dvander@0: void dvander@0: ParseTree::dump(FILE *fp) dvander@0: { dvander@0: AstPrinter printer(fp); dvander@0: dvander@0: for (size_t i = 0; i < statements_->length(); i++) dvander@0: statements_->at(i)->accept(&printer); dvander@0: }