Added support for comma-delimited variable declarations.
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of SourcePawn.
7 * SourcePawn is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation, either version 3 of the License, or (at your option)
12 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with
17 * SourcePawn. If not, see http://www.gnu.org/licenses/.
22 #include "FixedArray.h"
25 #include "TypeManager.h"
30 Parser::Parser(Zone *zone, CompileContext &cc, const char *stream, size_t length)
34 scanner_(cc, stream, length),
38 unbound_ = new (pool_) PoolList<NameProxy *>();
42 Parser::peek(TokenKind kind)
44 return scanner_.peek() == kind;
48 Parser::match(TokenKind kind)
57 Parser::matchSemicolon()
59 return expect(TOK_SEMICOLON);
63 Parser::expect(TokenKind kind)
65 TokenKind got = scanner_.scan();
68 cc_.reportError(scanner_.begin(), Message_WrongToken, TokenNames[kind], TokenNames[got]);
73 Parser::enterScope(Scope::Kind kind)
75 scope_ = new (pool_) Scope(pool_, kind, scope_);
76 if (!scope_->initialize())
82 Parser::bind(Handle<String> name)
84 BoundName *bound = scope_->lookup(name);
85 NameProxy *proxy = new (pool_) NameProxy(scanner_.begin(), name, bound);
86 if (!bound && !unbound_->append(proxy))
92 Parser::bindType(Handle<String> name)
94 if (BoundName *binding = scope_->lookup(name))
97 return new (pool_) UnboundName(scope_, name);
101 Parser::matchName(String **name, TokenKind kind)
103 assert(kind == TOK_NAME || kind == TOK_LABEL);
107 *name = zone_->makeSymbol(scanner_.literal(), scanner_.literal_length());
114 if (!expect(TOK_NAME))
116 return zone_->makeSymbol(scanner_.literal(), scanner_.literal_length());
120 Parser::redeclarationError(BoundName *other)
122 cc_.reportError(scanner_.begin(), Message_RedeclaredName, other->name()->chars(),
123 other->pos().line, other->pos().col);
129 TokenKind kind = scanner_.peek();
133 Local<String> name(zone_, expectName());
139 case TOK_FLOAT_LITERAL:
142 double value = Scanner::ParseDouble(scanner_.literal());
143 return new (pool_) FloatLiteral(scanner_.begin(), value);
146 case TOK_INTEGER_LITERAL:
149 int value = atoi(scanner_.literal());
150 return new (pool_) IntegerLiteral(scanner_.begin(), value);
156 return new (pool_) BooleanLiteral(scanner_.begin(), kind);
158 case TOK_STRING_LITERAL:
161 Local<ByteArray> array(zone_, ByteArray::New(zone_, scanner_.literal_length() + 1));
164 memcpy(array->raw(), scanner_.literal(), scanner_.literal_length() + 1);
165 return new (pool_) StringLiteral(scanner_.begin(), array);
170 if (kind != TOK_ERROR)
171 cc_.reportError(scanner_.begin(), Message_ExpectedExpression, TokenNames[kind]);
180 switch (scanner_.peek()) {
184 Expression *expr = expression();
187 if (!expect(TOK_RPAREN))
198 Parser::call(Expression *callee)
200 ExpressionList *arguments = new (pool_) ExpressionList();
202 SourcePosition pos = scanner_.begin();
205 if (!match(TOK_RPAREN)) {
207 Expression *expr = expression();
211 if (!arguments->append(expr))
214 if (!match(TOK_COMMA))
218 if (!expect(TOK_RPAREN))
222 return new (pool_) CallExpression(pos, callee, arguments);
226 Parser::index(Expression *left)
228 expect(TOK_LBRACKET);
230 SourcePosition pos = scanner_.begin();
231 Expression *expr = expression();
235 if (!expect(TOK_RBRACKET))
238 return new (pool_) IndexExpression(pos, left, expr);
242 Parser::field(Expression *left)
246 SourcePosition pos = scanner_.begin();
247 Local<String> name(zone_, expectName());
251 return new (pool_) FieldExpression(pos, left, name);
257 Expression *expr = prefix();
262 switch (scanner_.peek()) {
264 if ((expr = call(expr)) == NULL)
269 if ((expr = index(expr)) == NULL)
274 if ((expr = field(expr)) == NULL)
287 TokenKind token = scanner_.peek();
289 SourcePosition pos = scanner_.begin();
295 Expression *expr = unary();
298 return new (pool_) IncDecExpression(pos, token, expr, false);
306 Expression *expr = unary();
309 return new (pool_) UnaryExpression(pos, token, expr);
315 Local<String> tag(zone_, zone_->makeSymbol(scanner_.literal(), scanner_.literal_length()));
319 BoundName *type = NULL;
321 type = bindType(tag);
323 Expression *expr = unary();
327 return new (pool_) UnaryExpression(pos, TOK_LABEL, expr, type);
334 Expression *expr = primary();
336 token = scanner_.peek();
337 if (token == TOK_INCREMENT || token == TOK_DECREMENT) {
339 return new (pool_) IncDecExpression(pos, token, expr, true);
346 Parser::multiplication()
348 Expression *left = unary();
350 if (!match(TOK_SLASH) && !match(TOK_STAR) && !match(TOK_PERCENT))
352 SourcePosition pos = scanner_.begin();
353 TokenKind kind = scanner_.last();
354 Expression *right = unary();
357 left = new (pool_) BinaryExpression(pos, kind, left, right);
365 Expression *left = multiplication();
367 if (!match(TOK_PLUS) && !match(TOK_MINUS))
369 SourcePosition pos = scanner_.begin();
370 TokenKind kind = scanner_.last();
371 Expression *right = multiplication();
374 left = new (pool_) BinaryExpression(pos, kind, left, right);
382 Expression *left = addition();
384 if (!match(TOK_SHL) && !match(TOK_SHR) && !match(TOK_USHR))
386 SourcePosition pos = scanner_.begin();
387 TokenKind kind = scanner_.last();
388 Expression *right = addition();
391 left = new (pool_) BinaryExpression(pos, kind, left, right);
399 Expression *left = shift();
401 if (!match(TOK_BITAND))
403 SourcePosition pos = scanner_.begin();
404 Expression *right = shift();
407 left = new (pool_) BinaryExpression(pos, TOK_BITAND, left, right);
415 Expression *left = bitand_();
417 if (!match(TOK_BITXOR))
419 SourcePosition pos = scanner_.begin();
420 Expression *right = shift();
423 left = new (pool_) BinaryExpression(pos, TOK_BITXOR, left, right);
431 Expression *left = bitxor();
433 if (!match(TOK_BITOR))
435 SourcePosition pos = scanner_.begin();
436 Expression *right = bitxor();
439 left = new (pool_) BinaryExpression(pos, TOK_BITOR, left, right);
447 Expression *left = bitor_();
449 TokenKind kind = scanner_.peek();
450 if (kind < TOK_LT || kind > TOK_GE)
453 SourcePosition pos = scanner_.begin();
454 Expression *right = shift();
457 left = new (pool_) BinaryExpression(pos, kind, left, right);
465 Expression *left = relational();
467 if (!match(TOK_EQUALS) && !match(TOK_NOTEQUALS))
469 TokenKind kind = scanner_.last();
470 SourcePosition pos = scanner_.begin();
471 Expression *right = relational();
474 left = new (pool_) BinaryExpression(pos, kind, left, right);
482 Expression *left = equals();
486 SourcePosition pos = scanner_.begin();
487 Expression *right = equals();
490 left = new (pool_) BinaryExpression(pos, TOK_AND, left, right);
498 Expression *left = and_();
502 SourcePosition pos = scanner_.begin();
503 Expression *right = and_();
506 left = new (pool_) BinaryExpression(pos, TOK_OR, left, right);
514 Expression *cond = or_();
518 if (!match(TOK_QMARK))
521 SourcePosition pos = scanner_.begin();
522 Expression *left = expression();
526 if (!expect(TOK_COLON))
529 Expression *right = expression();
533 return new (pool_) TernaryExpression(pos, cond, left, right);
539 Expression *left = ternary();
541 TokenKind token = scanner_.peek();
542 if (token != TOK_ASSIGN && (token < TOK_ASSIGN_ADD || token > TOK_ASSIGN_SHL))
545 SourcePosition pos = scanner_.begin();
546 Expression *expr = ternary();
550 left = new (pool_) Assignment(pos, token, left, expr);
564 SourcePosition pos = scanner_.begin();
567 if (!expect(TOK_LPAREN))
570 Expression *condition = expression();
574 if (!expect(TOK_RPAREN))
577 // Inside a loop, we force the creation of a scope object. Normally, we
578 // will cull scopes if they have no variables. However inside a loop,
579 // function calls that take references may compute a LIFO object, and to
580 // avoid temporarily leaking many such objects, we ensure that a scope
581 // is present so a LIFO slot can be allocated.
582 if (!enterScope(Scope::BLOCK))
586 if (scanner_.peek() == TOK_LBRACE)
587 body = block(scope_);
589 body = localStatement();
593 scope_ = scope_->enclosing();
594 return new (pool_) WhileStatement(pos, TOK_WHILE, condition, body);
600 SourcePosition pos = scanner_.begin();
603 // See the comment in ::while_() as to why we force a scope.
604 if (!enterScope(Scope::BLOCK))
608 if (scanner_.peek() == TOK_LBRACE)
609 body = block(scope_);
611 body = localStatement();
615 scope_ = scope_->enclosing();
617 if (!expect(TOK_WHILE))
620 if (!expect(TOK_LPAREN))
622 Expression *condition = expression();
625 if (!expect(TOK_RPAREN))
628 return new (pool_) WhileStatement(pos, TOK_DO, condition, body);
632 Parser::forStatement()
634 SourcePosition pos = scanner_.begin();
636 if (!expect(TOK_LPAREN))
639 Statement *decl = NULL;
640 if (!match(TOK_SEMICOLON)) {
641 if (match(TOK_NEW)) {
642 if (!enterScope(Scope::BLOCK))
644 if ((decl = vars(TOK_NEW)) == NULL)
647 if ((decl = expressionStatement()) == NULL)
650 if (!expect(TOK_SEMICOLON))
654 Expression *condition = NULL;
655 if (!match(TOK_SEMICOLON)) {
656 if ((condition = expression()) == NULL)
658 if (!expect(TOK_SEMICOLON))
662 Statement *update = NULL;
663 if (!match(TOK_RPAREN)) {
664 if ((update = expressionStatement()) == NULL)
666 if (!expect(TOK_RPAREN))
670 // See the comment in ::while_() as to why we force a scope.
671 if (!enterScope(Scope::BLOCK))
675 if (scanner_.peek() == TOK_LBRACE)
676 body = block(scope_);
678 body = localStatement();
682 scope_ = scope_->enclosing();
684 Scope *declScope = NULL;
685 if (decl && (decl->isVariableDeclaration() || decl->isBlockStatement())) {
686 declScope = scope_->unlinkIfEmpty();
687 scope_ = scope_->enclosing();
689 return new (pool_) ForStatement(pos, declScope, decl, condition, update, body);
695 ExpressionList *postDimensions = new (pool_) ExpressionList();
696 while (match(TOK_LBRACKET)) {
697 Expression *dim = NULL;
698 if (!match(TOK_RBRACKET)) {
699 if ((dim = expression()) == NULL)
701 if (!expect(TOK_RBRACKET))
705 if (!postDimensions->append(dim))
708 return postDimensions;
711 VariableDeclaration *
712 Parser::var(TokenKind kind)
714 Local<String> tag(zone_);
715 if (matchName(tag.ref(), TOK_LABEL) && !tag)
718 BoundName *type = NULL;
720 type = bindType(tag);
722 Local<String> name(zone_, expectName());
726 if (BoundName *other = scope_->localLookup(name)) {
727 redeclarationError(other);
731 Variable *var = scope_->declareVariable(name, scanner_.begin());
735 ExpressionList *postDimensions = NULL;
736 if (peek(TOK_LBRACKET)) {
737 if ((postDimensions = dimensions()) == NULL)
741 Expression *expr = NULL;
742 if (match(TOK_ASSIGN)) {
743 if ((expr = expression()) == NULL)
747 return new (pool_) VariableDeclaration(var->pos(), kind, var, type, postDimensions, expr);
751 Parser::vars(TokenKind kind)
753 VariableDeclaration *decl = var(kind);
757 if (!peek(TOK_COMMA))
760 StatementList *statements = new (pool_) StatementList();
761 if (!statements->append(decl))
764 while (match(TOK_COMMA)) {
765 Statement *decl = var(kind);
768 if (!statements->append(decl))
772 // Create a fake-o block with no scope to create a statement list.
773 return new (pool_) BlockStatement(decl->pos(), NULL, statements);
777 Parser::returnStatement()
779 SourcePosition pos = scanner_.begin();
780 if (!expect(TOK_RETURN))
783 Expression *expr = NULL;
784 if (scanner_.peek() != TOK_SEMICOLON) {
785 if ((expr = expression()) == NULL)
788 // We only care about non-void returns when determining whether a
789 // tagless function is non-void.
790 encounteredReturn_ = true;
793 return new (pool_) ReturnStatement(pos, expr);
797 Parser::expressionStatement()
799 Expression *left = assignment();
803 return new (pool_) ExpressionStatement(left);
807 Parser::block(Scope *scope)
809 if (!expect(TOK_LBRACE))
812 SourcePosition pos = scanner_.begin();
813 if (!scope && !enterScope(Scope::BLOCK))
816 StatementList *statements = new (pool_) StatementList();
817 while (!match(TOK_RBRACE)) {
818 Statement *statement = localStatement();
819 if (statement == NULL)
821 if (!statements->append(statement))
826 scope = scope_->unlinkIfEmpty();
827 scope_ = scope_->enclosing();
829 BlockStatement *block = new (pool_) BlockStatement(pos, scope, statements);
838 SourcePosition pos = scanner_.begin();
839 if (!expect(TOK_LPAREN))
842 Expression *cond = expression();
846 if (!expect(TOK_RPAREN))
849 Statement *ifTrue = localStatement();
853 IfStatement *outer = new (pool_) IfStatement(pos, cond, ifTrue);
855 IfStatement *last = outer;
856 while (match(TOK_ELSE)) {
857 if (!match(TOK_IF)) {
858 Statement *ifFalse = localStatement();
862 last->setIfFalse(ifFalse);
866 SourcePosition pos = scanner_.begin();
867 if (!expect(TOK_LPAREN))
870 Expression *otherCond = expression();
874 if (!expect(TOK_RPAREN))
877 Statement *otherIfTrue = localStatement();
881 IfStatement *inner = new (pool_) IfStatement(pos, otherCond, otherIfTrue);
882 last->setIfFalse(inner);
890 Parser::localStatement()
892 Statement *statement = NULL;
894 // Statements which must be followed by a semicolon will break out of the
895 // switch. If they may end in BlockStatements, they'll immediately return.
897 TokenKind kind = scanner_.peek();
902 if ((statement = vars(kind)) == NULL)
907 return forStatement();
914 statement = new (pool_) BreakStatement(scanner_.begin());
919 statement = new (pool_) ContinueStatement(scanner_.begin());
923 if ((statement = do_()) == NULL)
928 if ((statement = returnStatement()) == NULL)
933 if ((statement = enum_()) == NULL)
938 if ((statement = struct_()) == NULL)
953 if ((statement = expressionStatement()) == NULL)
957 if (!expect(TOK_SEMICOLON))
968 Local<String> name(zone_, expectName());
972 SourcePosition pos = scanner_.begin();
974 if (BoundName *other = scope_->localLookup(name)) {
975 redeclarationError(other);
980 if ((type = scope_->declareType(name, scanner_.begin())) == NULL)
983 if (!expect(TOK_LBRACE))
986 FieldList *fields = new (pool_) FieldList();
988 while (!peek(TOK_RBRACE)) {
989 if (matchName(name.ref(), TOK_LABEL) && !name)
992 BoundName *type = NULL;
994 if ((type = bindType(name)) == NULL)
1002 SourcePosition pos = scanner_.begin();
1004 ExpressionList *postDimensions = NULL;
1005 //if (peek(TOK_LBRACKET)) {
1006 // if ((postDimensions = dimensions()) == NULL)
1010 if (!matchSemicolon())
1013 StructureStatement::Field *field =
1014 new (pool_) StructureStatement::Field(pos, type, name, postDimensions);
1015 if (!field || !fields->append(field))
1019 if (!expect(TOK_RBRACE))
1022 return new (pool_) StructureStatement(pos, type, fields);
1030 NamedType *type = NULL;
1031 SourcePosition pos = scanner_.begin();
1033 Local<String> name(zone_);
1034 if (matchName(name.ref())) {
1038 if (BoundName *other = scope_->localLookup(name)) {
1039 redeclarationError(other);
1043 if ((type = scope_->declareType(name, scanner_.begin())) == NULL)
1047 EnumStatement::EntryList *entries = new (pool_) EnumStatement::EntryList();
1049 if (!expect(TOK_LBRACE))
1053 if (scanner_.peek() == TOK_RBRACE)
1056 Local<String> name(zone_, expectName());
1060 if (BoundName *other = scope_->localLookup(name)) {
1061 redeclarationError(other);
1065 NamedConstant *constant = scope_->declareConstant(name, scanner_.begin());
1069 Expression *expr = NULL;
1070 if (match(TOK_ASSIGN)) {
1071 if ((expr = expression()) == NULL)
1075 if (!entries->append(EnumStatement::Entry(constant, expr)))
1077 } while (match(TOK_COMMA));
1078 if (!expect(TOK_RBRACE))
1081 return new (pool_) EnumStatement(pos, type, name, entries);
1085 Parser::function(TokenKind token)
1087 Local<String> returnTag(zone_);
1088 if (token == TOK_LABEL) {
1089 returnTag = zone_->makeSymbol(scanner_.literal(), scanner_.literal_length());
1095 if (matchName(returnTag.ref(), TOK_LABEL) && !returnTag)
1099 BoundName *returnType = NULL;
1101 returnType = bindType(returnTag);
1103 Local<String> name(zone_, expectName());
1107 SourcePosition pos = scanner_.begin();
1109 // The function name goes into the outer (global) scope.
1110 assert(!scope_->enclosing());
1113 if (BoundName *other = scope_->localLookup(name)) {
1114 // We allow a redeclaration if the new type is a public, and the old
1115 // type was a forward. However, the forward must come first.
1116 if (other->kind() != BoundName::FUNCTION) {
1117 redeclarationError(other);
1121 fun = other->toNamedFunction();
1122 if (!fun->isForward() || token != TOK_PUBLIC) {
1123 redeclarationError(other);
1127 // We've got the same name, but the original is a forward, so let it
1128 // slide and re-use the original declaration.
1129 fun->setImplemented(scanner_.begin());
1131 fun = scope_->declareFunction(name, scanner_.begin(), token);
1136 if (fun->isPublic())
1139 Scope *scope = enterScope(Scope::FUNCTION);
1143 ParameterList *parameters = new (pool_) ParameterList();
1145 if (!expect(TOK_LPAREN))
1148 if (!match(TOK_RPAREN)) {
1150 bool isConst = match(TOK_CONST);
1151 bool ref = match(TOK_AMPERSAND);
1153 SourcePosition begin = scanner_.begin();
1154 Local<String> tag(zone_);
1155 if (matchName(tag.ref(), TOK_LABEL) && !tag)
1158 BoundName *type = NULL;
1160 type = bindType(tag);
1162 if (match(TOK_ELLIPSES)) {
1163 if (isConst || ref) {
1164 cc_.reportError(begin, Message_InvalidVarArgs);
1168 if (token != TOK_NATIVE) {
1169 cc_.reportError(begin, Message_VarArgsOutsideNative);
1173 fun->markNativeVariadic();
1177 Local<String> name(zone_, expectName());
1181 if (BoundName *other = scope_->localLookup(name)) {
1182 redeclarationError(other);
1185 Variable *arg = scope_->declareArgument(name, scanner_.begin());
1189 // Look for dimensions.
1190 ExpressionList *postDimensions = NULL;
1191 if (peek(TOK_LBRACKET)) {
1192 if ((postDimensions = dimensions()) == NULL)
1196 Expression *expr = NULL;
1197 if (match(TOK_ASSIGN)) {
1198 if ((expr = expression()) == NULL)
1202 Parameter *parameter = new (pool_) Parameter(arg, type, ref, isConst, postDimensions,
1204 if (!parameters->append(parameter))
1207 if (!match(TOK_COMMA))
1210 if (!expect(TOK_RPAREN))
1214 encounteredReturn_ = false;
1216 Statement *body = NULL;
1217 if (token != TOK_FORWARD && token != TOK_NATIVE) {
1223 scope_ = scope_->enclosing();
1224 return new (pool_) FunctionStatement(pos, scope, fun, body, parameters, returnType,
1225 encounteredReturn_);
1229 DeclareIntrinsicType(Zone *zone, Scope *scope, const char *name, PrimitiveType type)
1231 Local<String> tag(zone, zone->makeSymbol(name));
1235 Local<Type> primitive(zone, zone->types()->getPrimitive(type));
1238 return !!scope->declareType(tag, primitive);
1242 Parser::setupIntrinsics()
1244 if (!DeclareIntrinsicType(zone_, scope_, "Float", PrimitiveType_Float))
1246 if (!DeclareIntrinsicType(zone_, scope_, "_", PrimitiveType_Int32))
1248 if (!DeclareIntrinsicType(zone_, scope_, "bool", PrimitiveType_Bool))
1250 if (!DeclareIntrinsicType(zone_, scope_, "String", PrimitiveType_Char))
1258 StatementList *statements = new (pool_) StatementList();
1260 if (!enterScope(Scope::GLOBAL))
1263 if (!setupIntrinsics())
1267 Statement *statement = NULL;
1269 TokenKind kind = scanner_.peek();
1278 if ((statement = function(TOK_NAME)) == NULL)
1289 if ((statement = function(kind)) == NULL)
1291 if ((kind == TOK_FORWARD || kind == TOK_NATIVE) && !matchSemicolon())
1299 // Note: at global scope, we don't accept comma-delimited
1300 // declarations yet, to see if we can get away with forcing
1301 // a nicer top-level style.
1303 if ((statement = var(kind)) == NULL)
1305 if (!matchSemicolon())
1311 if ((statement = enum_()) == NULL)
1313 if (!matchSemicolon())
1318 if ((statement = struct_()) == NULL)
1320 if (!matchSemicolon())
1325 cc_.reportError(scanner_.begin(), Message_ExpectedGlobal);
1332 if (!statements->append(statement))
1336 return new (pool_) ParseTree(scope_, statements, unbound_);
1339 class AstPrinter : public AstVisitor
1346 for (size_t i = 0; i < level_; i++)
1357 AstPrinter(FILE *fp)
1363 void visit(NameProxy *name) {
1365 fprintf(fp_, "[ NameProxy (%s)%s\n", name->name()->chars(),
1366 (name->binding() ? "" : " unbound"));
1368 void visit(CallExpression *node) {
1370 fprintf(fp_, "[ CallExpression\n");
1372 node->callee()->accept(this);
1373 for (size_t i = 0; i < node->arguments()->length(); i++)
1374 node->arguments()->at(i)->accept(this);
1377 void visit(FunctionStatement *node) {
1379 fprintf(fp_, "[ FunctionStatement (%s)\n", node->fun()->name()->chars());
1382 node->body()->accept(this);
1385 void visit(ExpressionStatement *node) {
1387 fprintf(fp_, "[ ExpressionStatement\n");
1389 node->expression()->accept(this);
1392 void visit(Assignment *node) {
1394 fprintf(fp_, "[ Assignment\n");
1396 node->lvalue()->accept(this);
1397 node->expression()->accept(this);
1400 void visit(TernaryExpression *node) {
1402 fprintf(fp_, "[ TernaryExpression\n");
1404 node->condition()->accept(this);
1405 node->left()->accept(this);
1406 node->right()->accept(this);
1409 void visit(BinaryExpression *node) {
1411 fprintf(fp_, "[ BinaryExpression (%s)\n", TokenNames[node->token()]);
1413 node->left()->accept(this);
1414 node->right()->accept(this);
1417 void visit(UnaryExpression *node) {
1419 fprintf(fp_, "[ UnaryExpression (%s)\n", TokenNames[node->token()]);
1421 node->expression()->accept(this);
1424 void visit(ReturnStatement *node) {
1426 fprintf(fp_, "[ ReturnStatement\n");
1428 if (node->expression())
1429 node->expression()->accept(this);
1432 void visit(ForStatement *node) {
1434 fprintf(fp_, "[ ForStatement\n");
1436 if (node->initialization())
1437 node->initialization()->accept(this);
1438 if (node->condition())
1439 node->condition()->accept(this);
1441 node->update()->accept(this);
1442 node->body()->accept(this);
1445 void visit(BlockStatement *node) {
1447 fprintf(fp_, "[ BlockStatement\n");
1449 for (size_t i = 0; i < node->statements()->length(); i++)
1450 node->statements()->at(i)->accept(this);
1453 void visit(VariableDeclaration *node) {
1455 fprintf(fp_, "[ VariableDeclaration (%s)\n", node->variable()->name()->chars());
1457 if (node->initialization())
1458 node->initialization()->accept(this);
1461 void visit(IntegerLiteral *node) {
1463 fprintf(fp_, "[ IntegerLiteral (%d)\n", node->value());
1465 void visit(BooleanLiteral *node) {
1467 fprintf(fp_, "[ BooleanLiteral (%s)\n",
1468 (node->token() == TOK_TRUE) ? "true" : "false");
1470 void visit(FloatLiteral *node) {
1472 fprintf(fp_, "[ FloatLiteral (%f)\n", node->value());
1474 void visit(IfStatement *node) {
1476 fprintf(fp_, "[ IfStatement\n");
1478 node->ifTrue()->accept(this);
1479 if (node->ifFalse())
1480 node->ifFalse()->accept(this);
1483 void visit(IndexExpression *node) {
1485 fprintf(fp_, "[ IndexExpression\n");
1487 node->left()->accept(this);
1488 node->right()->accept(this);
1491 void visit(EnumStatement *node) {
1493 fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name()->chars() : "<anonymous>");
1495 for (size_t i = 0; i < node->entries()->length(); i++) {
1497 fprintf(fp_, "%s =\n", node->entries()->at(i).name->name()->chars());
1498 if (node->entries()->at(i).expr) {
1500 node->entries()->at(i).expr->accept(this);
1506 void visit(WhileStatement *node) {
1508 fprintf(fp_, "[ WhileStatement (%s)\n",
1509 (node->token() == TOK_DO) ? "do" : "while");
1511 if (node->token() == TOK_DO) {
1512 node->condition()->accept(this);
1513 node->body()->accept(this);
1515 node->condition()->accept(this);
1516 node->body()->accept(this);
1520 void visit(BreakStatement *node) {
1522 fprintf(fp_, "[ BreakStatement\n");
1524 void visit(ContinueStatement *node) {
1526 fprintf(fp_, "[ ContinueStatement\n");
1528 void visit(StringLiteral *node) {
1530 fprintf(fp_, "[ StringLiteral\n");
1532 void visit(IncDecExpression *node) {
1534 fprintf(fp_, "[ IncDecExpression (postfix=%d)\n", node->postfix());
1536 node->expression()->accept(this);
1539 void visit(StructureStatement *node) {
1541 fprintf(fp_, "[ StructureStatement %s\n", node->decl()->name()->chars());
1543 void visit(FieldExpression *node) {
1545 fprintf(fp_, "[ FieldExpression %s\n", node->field()->chars());
1547 node->left()->accept(this);
1553 ParseTree::dump(FILE *fp)
1555 AstPrinter printer(fp);
1557 for (size_t i = 0; i < statements_->length(); i++)
1558 statements_->at(i)->accept(&printer);