Basic support for parsing and creating types from structure syntax.
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);
244 Expression *expr = prefix();
249 switch (scanner_.peek()) {
271 TokenKind token = scanner_.peek();
273 SourcePosition pos = scanner_.begin();
279 Expression *expr = unary();
282 return new (pool_) IncDecExpression(pos, token, expr, false);
290 Expression *expr = unary();
293 return new (pool_) UnaryExpression(pos, token, expr);
299 Local<String> tag(zone_, zone_->makeSymbol(scanner_.literal(), scanner_.literal_length()));
303 BoundName *type = NULL;
305 type = bindType(tag);
307 Expression *expr = unary();
311 return new (pool_) UnaryExpression(pos, TOK_LABEL, expr, type);
318 Expression *expr = primary();
320 token = scanner_.peek();
321 if (token == TOK_INCREMENT || token == TOK_DECREMENT) {
323 return new (pool_) IncDecExpression(pos, token, expr, true);
330 Parser::multiplication()
332 Expression *left = unary();
334 if (!match(TOK_SLASH) && !match(TOK_STAR) && !match(TOK_PERCENT))
336 SourcePosition pos = scanner_.begin();
337 TokenKind kind = scanner_.last();
338 Expression *right = unary();
341 left = new (pool_) BinaryExpression(pos, kind, left, right);
349 Expression *left = multiplication();
351 if (!match(TOK_PLUS) && !match(TOK_MINUS))
353 SourcePosition pos = scanner_.begin();
354 TokenKind kind = scanner_.last();
355 Expression *right = multiplication();
358 left = new (pool_) BinaryExpression(pos, kind, left, right);
366 Expression *left = addition();
368 if (!match(TOK_SHL) && !match(TOK_SHR) && !match(TOK_USHR))
370 SourcePosition pos = scanner_.begin();
371 TokenKind kind = scanner_.last();
372 Expression *right = addition();
375 left = new (pool_) BinaryExpression(pos, kind, left, right);
383 Expression *left = shift();
385 if (!match(TOK_BITAND))
387 SourcePosition pos = scanner_.begin();
388 Expression *right = shift();
391 left = new (pool_) BinaryExpression(pos, TOK_BITAND, left, right);
399 Expression *left = bitand_();
401 if (!match(TOK_BITXOR))
403 SourcePosition pos = scanner_.begin();
404 Expression *right = shift();
407 left = new (pool_) BinaryExpression(pos, TOK_BITXOR, left, right);
415 Expression *left = bitxor();
417 if (!match(TOK_BITOR))
419 SourcePosition pos = scanner_.begin();
420 Expression *right = bitxor();
423 left = new (pool_) BinaryExpression(pos, TOK_BITOR, left, right);
431 Expression *left = bitor_();
433 TokenKind kind = scanner_.peek();
434 if (kind < TOK_LT || kind > TOK_GE)
437 SourcePosition pos = scanner_.begin();
438 Expression *right = shift();
441 left = new (pool_) BinaryExpression(pos, kind, left, right);
449 Expression *left = relational();
451 if (!match(TOK_EQUALS) && !match(TOK_NOTEQUALS))
453 TokenKind kind = scanner_.last();
454 SourcePosition pos = scanner_.begin();
455 Expression *right = relational();
458 left = new (pool_) BinaryExpression(pos, kind, left, right);
466 Expression *left = equals();
470 SourcePosition pos = scanner_.begin();
471 Expression *right = equals();
474 left = new (pool_) BinaryExpression(pos, TOK_AND, left, right);
482 Expression *left = and_();
486 SourcePosition pos = scanner_.begin();
487 Expression *right = and_();
490 left = new (pool_) BinaryExpression(pos, TOK_OR, left, right);
498 Expression *cond = or_();
502 if (!match(TOK_QMARK))
505 SourcePosition pos = scanner_.begin();
506 Expression *left = expression();
510 if (!expect(TOK_COLON))
513 Expression *right = expression();
517 return new (pool_) TernaryExpression(pos, cond, left, right);
523 Expression *left = ternary();
525 TokenKind token = scanner_.peek();
526 if (token != TOK_ASSIGN && (token < TOK_ASSIGN_ADD || token > TOK_ASSIGN_SHL))
529 SourcePosition pos = scanner_.begin();
530 Expression *expr = ternary();
534 left = new (pool_) Assignment(pos, token, left, expr);
548 SourcePosition pos = scanner_.begin();
551 if (!expect(TOK_LPAREN))
554 Expression *condition = expression();
558 if (!expect(TOK_RPAREN))
561 // Inside a loop, we force the creation of a scope object. Normally, we
562 // will cull scopes if they have no variables. However inside a loop,
563 // function calls that take references may compute a LIFO object, and to
564 // avoid temporarily leaking many such objects, we ensure that a scope
565 // is present so a LIFO slot can be allocated.
566 if (!enterScope(Scope::BLOCK))
570 if (scanner_.peek() == TOK_LBRACE)
571 body = block(scope_);
573 body = localStatement();
577 scope_ = scope_->enclosing();
578 return new (pool_) WhileStatement(pos, TOK_WHILE, condition, body);
584 SourcePosition pos = scanner_.begin();
587 // See the comment in ::while_() as to why we force a scope.
588 if (!enterScope(Scope::BLOCK))
592 if (scanner_.peek() == TOK_LBRACE)
593 body = block(scope_);
595 body = localStatement();
599 scope_ = scope_->enclosing();
601 if (!expect(TOK_WHILE))
604 if (!expect(TOK_LPAREN))
606 Expression *condition = expression();
609 if (!expect(TOK_RPAREN))
612 return new (pool_) WhileStatement(pos, TOK_DO, condition, body);
616 Parser::forStatement()
618 SourcePosition pos = scanner_.begin();
620 if (!expect(TOK_LPAREN))
623 Statement *decl = NULL;
624 if (!match(TOK_SEMICOLON)) {
625 if (match(TOK_NEW)) {
626 if (!enterScope(Scope::BLOCK))
628 if ((decl = variableDeclaration(TOK_NEW)) == NULL)
631 if ((decl = expressionStatement()) == NULL)
634 if (!expect(TOK_SEMICOLON))
638 Expression *condition = NULL;
639 if (!match(TOK_SEMICOLON)) {
640 if ((condition = expression()) == NULL)
642 if (!expect(TOK_SEMICOLON))
646 Statement *update = NULL;
647 if (!match(TOK_RPAREN)) {
648 if ((update = expressionStatement()) == NULL)
650 if (!expect(TOK_RPAREN))
654 // See the comment in ::while_() as to why we force a scope.
655 if (!enterScope(Scope::BLOCK))
659 if (scanner_.peek() == TOK_LBRACE)
660 body = block(scope_);
662 body = localStatement();
666 scope_ = scope_->enclosing();
668 Scope *declScope = NULL;
669 if (decl && decl->isVariableDeclaration()) {
670 declScope = scope_->unlinkIfEmpty();
671 scope_ = scope_->enclosing();
673 return new (pool_) ForStatement(pos, declScope, decl, condition, update, body);
679 ExpressionList *postDimensions = new (pool_) ExpressionList();
680 while (match(TOK_LBRACKET)) {
681 Expression *dim = NULL;
682 if (!match(TOK_RBRACKET)) {
683 if ((dim = expression()) == NULL)
685 if (!expect(TOK_RBRACKET))
689 if (!postDimensions->append(dim))
692 return postDimensions;
695 VariableDeclaration *
696 Parser::variableDeclaration(TokenKind kind)
698 Local<String> tag(zone_);
699 if (matchName(tag.ref(), TOK_LABEL) && !tag)
702 BoundName *type = NULL;
704 type = bindType(tag);
706 Local<String> name(zone_, expectName());
710 if (BoundName *other = scope_->localLookup(name)) {
711 redeclarationError(other);
715 Variable *var = scope_->declareVariable(name, scanner_.begin());
719 ExpressionList *postDimensions = NULL;
720 if (peek(TOK_LBRACKET)) {
721 if ((postDimensions = dimensions()) == NULL)
725 Expression *expr = NULL;
726 if (match(TOK_ASSIGN)) {
727 if ((expr = expression()) == NULL)
731 return new (pool_) VariableDeclaration(var->pos(), kind, var, type, postDimensions, expr);
735 Parser::returnStatement()
737 SourcePosition pos = scanner_.begin();
738 if (!expect(TOK_RETURN))
741 Expression *expr = NULL;
742 if (scanner_.peek() != TOK_SEMICOLON) {
743 if ((expr = expression()) == NULL)
746 // We only care about non-void returns when determining whether a
747 // tagless function is non-void.
748 encounteredReturn_ = true;
751 return new (pool_) ReturnStatement(pos, expr);
755 Parser::expressionStatement()
757 Expression *left = assignment();
761 return new (pool_) ExpressionStatement(left);
765 Parser::block(Scope *scope)
767 if (!expect(TOK_LBRACE))
770 SourcePosition pos = scanner_.begin();
771 if (!scope && !enterScope(Scope::BLOCK))
774 StatementList *statements = new (pool_) StatementList();
775 while (!match(TOK_RBRACE)) {
776 Statement *statement = localStatement();
777 if (statement == NULL)
779 if (!statements->append(statement))
784 scope = scope_->unlinkIfEmpty();
785 scope_ = scope_->enclosing();
787 BlockStatement *block = new (pool_) BlockStatement(pos, scope, statements);
796 SourcePosition pos = scanner_.begin();
797 if (!expect(TOK_LPAREN))
800 Expression *cond = expression();
804 if (!expect(TOK_RPAREN))
807 Statement *ifTrue = localStatement();
811 IfStatement *outer = new (pool_) IfStatement(pos, cond, ifTrue);
813 IfStatement *last = outer;
814 while (match(TOK_ELSE)) {
815 if (!match(TOK_IF)) {
816 Statement *ifFalse = localStatement();
820 last->setIfFalse(ifFalse);
824 SourcePosition pos = scanner_.begin();
825 if (!expect(TOK_LPAREN))
828 Expression *otherCond = expression();
832 if (!expect(TOK_RPAREN))
835 Statement *otherIfTrue = localStatement();
839 IfStatement *inner = new (pool_) IfStatement(pos, otherCond, otherIfTrue);
840 last->setIfFalse(inner);
848 Parser::localStatement()
850 Statement *statement = NULL;
852 // Statements which must be followed by a semicolon will break out of the
853 // switch. If they may end in BlockStatements, they'll immediately return.
855 TokenKind kind = scanner_.peek();
860 if ((statement = variableDeclaration(kind)) == NULL)
865 return forStatement();
872 statement = new (pool_) BreakStatement(scanner_.begin());
877 statement = new (pool_) ContinueStatement(scanner_.begin());
881 if ((statement = do_()) == NULL)
886 if ((statement = returnStatement()) == NULL)
891 if ((statement = enum_()) == NULL)
896 if ((statement = struct_()) == NULL)
911 if ((statement = expressionStatement()) == NULL)
915 if (!expect(TOK_SEMICOLON))
926 Local<String> name(zone_, expectName());
930 SourcePosition pos = scanner_.begin();
932 if (BoundName *other = scope_->localLookup(name)) {
933 redeclarationError(other);
938 if ((type = scope_->declareType(name, scanner_.begin())) == NULL)
941 if (!expect(TOK_LBRACE))
944 FieldList *fields = new (pool_) FieldList();
946 while (!peek(TOK_RBRACE)) {
947 if (matchName(name.ref(), TOK_LABEL) && !name)
950 BoundName *type = NULL;
952 if ((type = bindType(name)) == NULL)
960 SourcePosition pos = scanner_.begin();
962 ExpressionList *postDimensions = NULL;
963 if (peek(TOK_LBRACKET)) {
964 if ((postDimensions = dimensions()) == NULL)
968 if (!matchSemicolon())
971 StructureStatement::Field *field =
972 new (pool_) StructureStatement::Field(pos, type, name, postDimensions);
973 if (!field || !fields->append(field))
977 if (!expect(TOK_RBRACE))
980 return new (pool_) StructureStatement(pos, type, fields);
988 NamedType *type = NULL;
989 SourcePosition pos = scanner_.begin();
991 Local<String> name(zone_);
992 if (matchName(name.ref())) {
996 if (BoundName *other = scope_->localLookup(name)) {
997 redeclarationError(other);
1001 if ((type = scope_->declareType(name, scanner_.begin())) == NULL)
1005 EnumStatement::EntryList *entries = new (pool_) EnumStatement::EntryList();
1007 if (!expect(TOK_LBRACE))
1011 if (scanner_.peek() == TOK_RBRACE)
1014 Local<String> name(zone_, expectName());
1018 if (BoundName *other = scope_->localLookup(name)) {
1019 redeclarationError(other);
1023 NamedConstant *constant = scope_->declareConstant(name, scanner_.begin());
1027 Expression *expr = NULL;
1028 if (match(TOK_ASSIGN)) {
1029 if ((expr = expression()) == NULL)
1033 if (!entries->append(EnumStatement::Entry(constant, expr)))
1035 } while (match(TOK_COMMA));
1036 if (!expect(TOK_RBRACE))
1039 return new (pool_) EnumStatement(pos, type, name, entries);
1043 Parser::function(TokenKind token)
1045 Local<String> returnTag(zone_);
1046 if (token == TOK_LABEL) {
1047 returnTag = zone_->makeSymbol(scanner_.literal(), scanner_.literal_length());
1053 if (matchName(returnTag.ref(), TOK_LABEL) && !returnTag)
1057 BoundName *returnType = NULL;
1059 returnType = bindType(returnTag);
1061 Local<String> name(zone_, expectName());
1065 SourcePosition pos = scanner_.begin();
1067 // The function name goes into the outer (global) scope.
1068 assert(!scope_->enclosing());
1071 if (BoundName *other = scope_->localLookup(name)) {
1072 // We allow a redeclaration if the new type is a public, and the old
1073 // type was a forward. However, the forward must come first.
1074 if (other->kind() != BoundName::FUNCTION) {
1075 redeclarationError(other);
1079 fun = other->toNamedFunction();
1080 if (!fun->isForward() || token != TOK_PUBLIC) {
1081 redeclarationError(other);
1085 // We've got the same name, but the original is a forward, so let it
1086 // slide and re-use the original declaration.
1087 fun->setImplemented(scanner_.begin());
1089 fun = scope_->declareFunction(name, scanner_.begin(), token);
1094 if (fun->isPublic())
1097 Scope *scope = enterScope(Scope::FUNCTION);
1101 ParameterList *parameters = new (pool_) ParameterList();
1103 if (!expect(TOK_LPAREN))
1106 if (!match(TOK_RPAREN)) {
1108 bool isConst = match(TOK_CONST);
1109 bool ref = match(TOK_AMPERSAND);
1111 SourcePosition begin = scanner_.begin();
1112 Local<String> tag(zone_);
1113 if (matchName(tag.ref(), TOK_LABEL) && !tag)
1116 BoundName *type = NULL;
1118 type = bindType(tag);
1120 if (match(TOK_ELLIPSES)) {
1121 if (isConst || ref) {
1122 cc_.reportError(begin, Message_InvalidVarArgs);
1126 if (token != TOK_NATIVE) {
1127 cc_.reportError(begin, Message_VarArgsOutsideNative);
1131 fun->markNativeVariadic();
1135 Local<String> name(zone_, expectName());
1139 if (BoundName *other = scope_->localLookup(name)) {
1140 redeclarationError(other);
1143 Variable *arg = scope_->declareArgument(name, scanner_.begin());
1147 // Look for dimensions.
1148 ExpressionList *postDimensions = NULL;
1149 if (peek(TOK_LBRACKET)) {
1150 if ((postDimensions = dimensions()) == NULL)
1154 Expression *expr = NULL;
1155 if (match(TOK_ASSIGN)) {
1156 if ((expr = expression()) == NULL)
1160 Parameter *parameter = new (pool_) Parameter(arg, type, ref, isConst, postDimensions,
1162 if (!parameters->append(parameter))
1165 if (!match(TOK_COMMA))
1168 if (!expect(TOK_RPAREN))
1172 encounteredReturn_ = false;
1174 Statement *body = NULL;
1175 if (token != TOK_FORWARD && token != TOK_NATIVE) {
1181 scope_ = scope_->enclosing();
1182 return new (pool_) FunctionStatement(pos, scope, fun, body, parameters, returnType,
1183 encounteredReturn_);
1187 DeclareIntrinsicType(Zone *zone, Scope *scope, const char *name, PrimitiveType type)
1189 Local<String> tag(zone, zone->makeSymbol(name));
1193 Local<Type> primitive(zone, zone->types()->getPrimitive(type));
1196 return !!scope->declareType(tag, primitive);
1200 Parser::setupIntrinsics()
1202 if (!DeclareIntrinsicType(zone_, scope_, "Float", PrimitiveType_Float))
1204 if (!DeclareIntrinsicType(zone_, scope_, "_", PrimitiveType_Int32))
1206 if (!DeclareIntrinsicType(zone_, scope_, "bool", PrimitiveType_Bool))
1208 if (!DeclareIntrinsicType(zone_, scope_, "String", PrimitiveType_Char))
1216 StatementList *statements = new (pool_) StatementList();
1218 if (!enterScope(Scope::GLOBAL))
1221 if (!setupIntrinsics())
1225 Statement *statement = NULL;
1227 TokenKind kind = scanner_.peek();
1236 if ((statement = function(TOK_NAME)) == NULL)
1247 if ((statement = function(kind)) == NULL)
1249 if ((kind == TOK_FORWARD || kind == TOK_NATIVE) && !matchSemicolon())
1258 if ((statement = variableDeclaration(kind)) == NULL)
1260 if (!matchSemicolon())
1266 if ((statement = enum_()) == NULL)
1268 if (!matchSemicolon())
1273 if ((statement = struct_()) == NULL)
1275 if (!matchSemicolon())
1280 cc_.reportError(scanner_.begin(), Message_ExpectedGlobal);
1287 if (!statements->append(statement))
1291 return new (pool_) ParseTree(scope_, statements, unbound_);
1294 class AstPrinter : public AstVisitor
1301 for (size_t i = 0; i < level_; i++)
1312 AstPrinter(FILE *fp)
1318 void visit(NameProxy *name) {
1320 fprintf(fp_, "[ NameProxy (%s)%s\n", name->name()->chars(),
1321 (name->binding() ? "" : " unbound"));
1323 void visit(CallExpression *node) {
1325 fprintf(fp_, "[ CallExpression\n");
1327 node->callee()->accept(this);
1328 for (size_t i = 0; i < node->arguments()->length(); i++)
1329 node->arguments()->at(i)->accept(this);
1332 void visit(FunctionStatement *node) {
1334 fprintf(fp_, "[ FunctionStatement (%s)\n", node->fun()->name()->chars());
1337 node->body()->accept(this);
1340 void visit(ExpressionStatement *node) {
1342 fprintf(fp_, "[ ExpressionStatement\n");
1344 node->expression()->accept(this);
1347 void visit(Assignment *node) {
1349 fprintf(fp_, "[ Assignment\n");
1351 node->lvalue()->accept(this);
1352 node->expression()->accept(this);
1355 void visit(TernaryExpression *node) {
1357 fprintf(fp_, "[ TernaryExpression\n");
1359 node->condition()->accept(this);
1360 node->left()->accept(this);
1361 node->right()->accept(this);
1364 void visit(BinaryExpression *node) {
1366 fprintf(fp_, "[ BinaryExpression (%s)\n", TokenNames[node->token()]);
1368 node->left()->accept(this);
1369 node->right()->accept(this);
1372 void visit(UnaryExpression *node) {
1374 fprintf(fp_, "[ UnaryExpression (%s)\n", TokenNames[node->token()]);
1376 node->expression()->accept(this);
1379 void visit(ReturnStatement *node) {
1381 fprintf(fp_, "[ ReturnStatement\n");
1383 if (node->expression())
1384 node->expression()->accept(this);
1387 void visit(ForStatement *node) {
1389 fprintf(fp_, "[ ForStatement\n");
1391 if (node->initialization())
1392 node->initialization()->accept(this);
1393 if (node->condition())
1394 node->condition()->accept(this);
1396 node->update()->accept(this);
1397 node->body()->accept(this);
1400 void visit(BlockStatement *node) {
1402 fprintf(fp_, "[ BlockStatement\n");
1404 for (size_t i = 0; i < node->statements()->length(); i++)
1405 node->statements()->at(i)->accept(this);
1408 void visit(VariableDeclaration *node) {
1410 fprintf(fp_, "[ VariableDeclaration (%s)\n", node->variable()->name()->chars());
1412 if (node->initialization())
1413 node->initialization()->accept(this);
1416 void visit(IntegerLiteral *node) {
1418 fprintf(fp_, "[ IntegerLiteral (%d)\n", node->value());
1420 void visit(BooleanLiteral *node) {
1422 fprintf(fp_, "[ BooleanLiteral (%s)\n",
1423 (node->token() == TOK_TRUE) ? "true" : "false");
1425 void visit(FloatLiteral *node) {
1427 fprintf(fp_, "[ FloatLiteral (%f)\n", node->value());
1429 void visit(IfStatement *node) {
1431 fprintf(fp_, "[ IfStatement\n");
1433 node->ifTrue()->accept(this);
1434 if (node->ifFalse())
1435 node->ifFalse()->accept(this);
1438 void visit(IndexExpression *node) {
1440 fprintf(fp_, "[ IndexExpression\n");
1442 node->left()->accept(this);
1443 node->right()->accept(this);
1446 void visit(EnumStatement *node) {
1448 fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name()->chars() : "<anonymous>");
1450 for (size_t i = 0; i < node->entries()->length(); i++) {
1452 fprintf(fp_, "%s =\n", node->entries()->at(i).name->name()->chars());
1453 if (node->entries()->at(i).expr) {
1455 node->entries()->at(i).expr->accept(this);
1461 void visit(WhileStatement *node) {
1463 fprintf(fp_, "[ WhileStatement (%s)\n",
1464 (node->token() == TOK_DO) ? "do" : "while");
1466 if (node->token() == TOK_DO) {
1467 node->condition()->accept(this);
1468 node->body()->accept(this);
1470 node->condition()->accept(this);
1471 node->body()->accept(this);
1475 void visit(BreakStatement *node) {
1477 fprintf(fp_, "[ BreakStatement\n");
1479 void visit(ContinueStatement *node) {
1481 fprintf(fp_, "[ ContinueStatement\n");
1483 void visit(StringLiteral *node) {
1485 fprintf(fp_, "[ StringLiteral\n");
1487 void visit(IncDecExpression *node) {
1489 fprintf(fp_, "[ IncDecExpression (postfix=%d)\n", node->postfix());
1491 node->expression()->accept(this);
1494 void visit(StructureStatement *node) {
1496 fprintf(fp_, "[ StructureStatement\n");
1501 ParseTree::dump(FILE *fp)
1503 AstPrinter printer(fp);
1505 for (size_t i = 0; i < statements_->length(); i++)
1506 statements_->at(i)->accept(&printer);