Added bogo "unchecked" type that will evolve later.
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, Handle<Type> type)
1231 Local<String> tag(zone, zone->makeSymbol(name));
1235 return !!scope->declareType(tag, type);
1239 DeclareIntrinsicType(Zone *zone, Scope *scope, const char *name, PrimitiveType type)
1241 Local<Type> primitive(zone, zone->types()->getPrimitive(type));
1243 return DeclareIntrinsicType(zone, scope, name, primitive);
1247 Parser::setupIntrinsics()
1249 if (!DeclareIntrinsicType(zone_, scope_, "Float", PrimitiveType_Float))
1251 if (!DeclareIntrinsicType(zone_, scope_, "_", PrimitiveType_Int32))
1253 if (!DeclareIntrinsicType(zone_, scope_, "bool", PrimitiveType_Bool))
1255 if (!DeclareIntrinsicType(zone_, scope_, "String", PrimitiveType_Char))
1258 Local<Type> unchecked(zone_, zone_->types()->getUnchecked());
1259 if (!DeclareIntrinsicType(zone_, scope_, "unchecked", unchecked))
1268 StatementList *statements = new (pool_) StatementList();
1270 if (!enterScope(Scope::GLOBAL))
1273 if (!setupIntrinsics())
1277 Statement *statement = NULL;
1279 TokenKind kind = scanner_.peek();
1288 if ((statement = function(TOK_NAME)) == NULL)
1299 if ((statement = function(kind)) == NULL)
1301 if ((kind == TOK_FORWARD || kind == TOK_NATIVE) && !matchSemicolon())
1309 // Note: at global scope, we don't accept comma-delimited
1310 // declarations yet, to see if we can get away with forcing
1311 // a nicer top-level style.
1313 if ((statement = var(kind)) == NULL)
1315 if (!matchSemicolon())
1321 if ((statement = enum_()) == NULL)
1323 if (!matchSemicolon())
1328 if ((statement = struct_()) == NULL)
1330 if (!matchSemicolon())
1335 cc_.reportError(scanner_.begin(), Message_ExpectedGlobal);
1342 if (!statements->append(statement))
1346 return new (pool_) ParseTree(scope_, statements, unbound_);
1349 class AstPrinter : public AstVisitor
1356 for (size_t i = 0; i < level_; i++)
1367 AstPrinter(FILE *fp)
1373 void visit(NameProxy *name) {
1375 fprintf(fp_, "[ NameProxy (%s)%s\n", name->name()->chars(),
1376 (name->binding() ? "" : " unbound"));
1378 void visit(CallExpression *node) {
1380 fprintf(fp_, "[ CallExpression\n");
1382 node->callee()->accept(this);
1383 for (size_t i = 0; i < node->arguments()->length(); i++)
1384 node->arguments()->at(i)->accept(this);
1387 void visit(FunctionStatement *node) {
1389 fprintf(fp_, "[ FunctionStatement (%s)\n", node->fun()->name()->chars());
1392 node->body()->accept(this);
1395 void visit(ExpressionStatement *node) {
1397 fprintf(fp_, "[ ExpressionStatement\n");
1399 node->expression()->accept(this);
1402 void visit(Assignment *node) {
1404 fprintf(fp_, "[ Assignment\n");
1406 node->lvalue()->accept(this);
1407 node->expression()->accept(this);
1410 void visit(TernaryExpression *node) {
1412 fprintf(fp_, "[ TernaryExpression\n");
1414 node->condition()->accept(this);
1415 node->left()->accept(this);
1416 node->right()->accept(this);
1419 void visit(BinaryExpression *node) {
1421 fprintf(fp_, "[ BinaryExpression (%s)\n", TokenNames[node->token()]);
1423 node->left()->accept(this);
1424 node->right()->accept(this);
1427 void visit(UnaryExpression *node) {
1429 fprintf(fp_, "[ UnaryExpression (%s)\n", TokenNames[node->token()]);
1431 node->expression()->accept(this);
1434 void visit(ReturnStatement *node) {
1436 fprintf(fp_, "[ ReturnStatement\n");
1438 if (node->expression())
1439 node->expression()->accept(this);
1442 void visit(ForStatement *node) {
1444 fprintf(fp_, "[ ForStatement\n");
1446 if (node->initialization())
1447 node->initialization()->accept(this);
1448 if (node->condition())
1449 node->condition()->accept(this);
1451 node->update()->accept(this);
1452 node->body()->accept(this);
1455 void visit(BlockStatement *node) {
1457 fprintf(fp_, "[ BlockStatement\n");
1459 for (size_t i = 0; i < node->statements()->length(); i++)
1460 node->statements()->at(i)->accept(this);
1463 void visit(VariableDeclaration *node) {
1465 fprintf(fp_, "[ VariableDeclaration (%s)\n", node->variable()->name()->chars());
1467 if (node->initialization())
1468 node->initialization()->accept(this);
1471 void visit(IntegerLiteral *node) {
1473 fprintf(fp_, "[ IntegerLiteral (%d)\n", node->value());
1475 void visit(BooleanLiteral *node) {
1477 fprintf(fp_, "[ BooleanLiteral (%s)\n",
1478 (node->token() == TOK_TRUE) ? "true" : "false");
1480 void visit(FloatLiteral *node) {
1482 fprintf(fp_, "[ FloatLiteral (%f)\n", node->value());
1484 void visit(IfStatement *node) {
1486 fprintf(fp_, "[ IfStatement\n");
1488 node->ifTrue()->accept(this);
1489 if (node->ifFalse())
1490 node->ifFalse()->accept(this);
1493 void visit(IndexExpression *node) {
1495 fprintf(fp_, "[ IndexExpression\n");
1497 node->left()->accept(this);
1498 node->right()->accept(this);
1501 void visit(EnumStatement *node) {
1503 fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name()->chars() : "<anonymous>");
1505 for (size_t i = 0; i < node->entries()->length(); i++) {
1507 fprintf(fp_, "%s =\n", node->entries()->at(i).name->name()->chars());
1508 if (node->entries()->at(i).expr) {
1510 node->entries()->at(i).expr->accept(this);
1516 void visit(WhileStatement *node) {
1518 fprintf(fp_, "[ WhileStatement (%s)\n",
1519 (node->token() == TOK_DO) ? "do" : "while");
1521 if (node->token() == TOK_DO) {
1522 node->condition()->accept(this);
1523 node->body()->accept(this);
1525 node->condition()->accept(this);
1526 node->body()->accept(this);
1530 void visit(BreakStatement *node) {
1532 fprintf(fp_, "[ BreakStatement\n");
1534 void visit(ContinueStatement *node) {
1536 fprintf(fp_, "[ ContinueStatement\n");
1538 void visit(StringLiteral *node) {
1540 fprintf(fp_, "[ StringLiteral\n");
1542 void visit(IncDecExpression *node) {
1544 fprintf(fp_, "[ IncDecExpression (postfix=%d)\n", node->postfix());
1546 node->expression()->accept(this);
1549 void visit(StructureStatement *node) {
1551 fprintf(fp_, "[ StructureStatement %s\n", node->decl()->name()->chars());
1553 void visit(FieldExpression *node) {
1555 fprintf(fp_, "[ FieldExpression %s\n", node->field()->chars());
1557 node->left()->accept(this);
1563 ParseTree::dump(FILE *fp)
1565 AstPrinter printer(fp);
1567 for (size_t i = 0; i < statements_->length(); i++)
1568 statements_->at(i)->accept(&printer);