Allow unused functions to be semantically checked, but do not bytecode compile them.
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"
29 Parser::Parser(Zone *zone, CompileContext &cc, const char *stream, size_t length)
33 scanner_(cc, stream, length),
37 unbound_ = new (pool_) PoolList<NameProxy *>();
41 Parser::match(TokenKind kind)
43 if (scanner_.peek() != kind)
50 Parser::matchSemicolon()
52 return expect(TOK_SEMICOLON);
56 Parser::expect(TokenKind kind)
58 TokenKind got = scanner_.scan();
61 cc_.reportError(scanner_.begin(), Message_WrongToken, TokenNames[kind], TokenNames[got]);
66 Parser::enterScope(Scope::Kind kind)
68 scope_ = new (pool_) Scope(pool_, kind, scope_);
69 if (!scope_->initialize())
75 Parser::bind(Handle<String> name)
77 BoundName *bound = scope_->lookup(name);
78 NameProxy *proxy = new (pool_) NameProxy(scanner_.begin(), name, bound);
79 if (!bound && !unbound_->append(proxy))
85 Parser::matchName(String **name, TokenKind kind)
87 assert(kind == TOK_NAME || kind == TOK_LABEL);
91 *name = zone_->makeSymbol(scanner_.literal(), scanner_.literal_length());
98 if (!expect(TOK_NAME))
100 return zone_->makeSymbol(scanner_.literal(), scanner_.literal_length());
104 Parser::redeclarationError(BoundName *other)
106 cc_.reportError(scanner_.begin(), Message_RedeclaredName, other->name()->chars(),
107 other->pos().line, other->pos().col);
113 TokenKind kind = scanner_.peek();
117 Local<String> name(zone_, expectName());
123 case TOK_FLOAT_LITERAL:
126 double value = Scanner::ParseDouble(scanner_.literal());
127 return new (pool_) FloatLiteral(scanner_.begin(), value);
130 case TOK_INTEGER_LITERAL:
133 int value = atoi(scanner_.literal());
134 return new (pool_) IntegerLiteral(scanner_.begin(), value);
137 case TOK_STRING_LITERAL:
140 Local<ByteArray> array(zone_, ByteArray::New(zone_, scanner_.literal_length() + 1));
143 memcpy(array->raw(), scanner_.literal(), scanner_.literal_length() + 1);
144 return new (pool_) StringLiteral(scanner_.begin(), array);
149 if (kind != TOK_ERROR)
150 cc_.reportError(scanner_.begin(), Message_ExpectedExpression, TokenNames[kind]);
159 switch (scanner_.peek()) {
163 Expression *expr = expression();
166 if (!expect(TOK_RPAREN))
177 Parser::call(Expression *callee)
179 ExpressionList *arguments = new (pool_) ExpressionList();
181 SourcePosition pos = scanner_.begin();
184 if (!match(TOK_RPAREN)) {
186 Expression *expr = expression();
190 if (!arguments->append(expr))
193 if (!match(TOK_COMMA))
197 if (!expect(TOK_RPAREN))
201 return new (pool_) CallExpression(pos, callee, arguments);
205 Parser::index(Expression *left)
207 expect(TOK_LBRACKET);
209 SourcePosition pos = scanner_.begin();
210 Expression *expr = expression();
214 if (!expect(TOK_RBRACKET))
217 return new (pool_) IndexExpression(pos, left, expr);
223 Expression *expr = prefix();
228 switch (scanner_.peek()) {
250 TokenKind token = scanner_.peek();
252 SourcePosition pos = scanner_.begin();
258 Expression *expr = expression();
261 return new (pool_) IncDecExpression(pos, token, expr, false);
269 Expression *expr = expression();
272 return new (pool_) UnaryExpression(pos, token, expr);
279 Expression *expr = primary();
281 token = scanner_.peek();
282 if (token == TOK_INCREMENT || token == TOK_DECREMENT) {
284 return new (pool_) IncDecExpression(pos, token, expr, true);
291 Parser::multiplication()
293 Expression *left = unary();
295 if (!match(TOK_SLASH) && !match(TOK_STAR) && !match(TOK_PERCENT))
297 SourcePosition pos = scanner_.begin();
298 TokenKind kind = scanner_.last();
299 Expression *right = unary();
302 left = new (pool_) BinaryExpression(pos, kind, left, right);
310 Expression *left = multiplication();
312 if (!match(TOK_PLUS) && !match(TOK_MINUS))
314 SourcePosition pos = scanner_.begin();
315 TokenKind kind = scanner_.last();
316 Expression *right = multiplication();
319 left = new (pool_) BinaryExpression(pos, kind, left, right);
327 Expression *left = addition();
329 if (!match(TOK_SHL) && !match(TOK_SHR) && !match(TOK_USHR))
331 SourcePosition pos = scanner_.begin();
332 TokenKind kind = scanner_.last();
333 Expression *right = addition();
336 left = new (pool_) BinaryExpression(pos, kind, left, right);
344 Expression *left = shift();
346 if (!match(TOK_BITAND))
348 SourcePosition pos = scanner_.begin();
349 Expression *right = shift();
352 left = new (pool_) BinaryExpression(pos, TOK_BITAND, left, right);
360 Expression *left = bitand_();
362 if (!match(TOK_BITXOR))
364 SourcePosition pos = scanner_.begin();
365 Expression *right = shift();
368 left = new (pool_) BinaryExpression(pos, TOK_BITXOR, left, right);
376 Expression *left = bitxor();
378 if (!match(TOK_BITOR))
380 SourcePosition pos = scanner_.begin();
381 Expression *right = bitxor();
384 left = new (pool_) BinaryExpression(pos, TOK_BITOR, left, right);
392 Expression *left = bitor_();
394 TokenKind kind = scanner_.peek();
395 if (kind < TOK_LT || kind > TOK_GE)
398 SourcePosition pos = scanner_.begin();
399 Expression *right = shift();
402 left = new (pool_) BinaryExpression(pos, kind, left, right);
410 Expression *left = relational();
412 if (!match(TOK_EQUALS) && !match(TOK_NOTEQUALS))
414 TokenKind kind = scanner_.last();
415 SourcePosition pos = scanner_.begin();
416 Expression *right = relational();
419 left = new (pool_) BinaryExpression(pos, kind, left, right);
427 Expression *left = equals();
431 SourcePosition pos = scanner_.begin();
432 Expression *right = equals();
435 left = new (pool_) BinaryExpression(pos, TOK_AND, left, right);
443 Expression *left = and_();
447 SourcePosition pos = scanner_.begin();
448 Expression *right = and_();
451 left = new (pool_) BinaryExpression(pos, TOK_OR, left, right);
459 Expression *cond = or_();
463 if (!match(TOK_QMARK))
466 SourcePosition pos = scanner_.begin();
467 Expression *left = expression();
471 if (!expect(TOK_COLON))
474 Expression *right = expression();
478 return new (pool_) TernaryExpression(pos, cond, left, right);
484 Expression *left = ternary();
486 TokenKind token = scanner_.peek();
487 if (token != TOK_ASSIGN && (token < TOK_ASSIGN_ADD || token > TOK_ASSIGN_SHL))
490 SourcePosition pos = scanner_.begin();
491 Expression *expr = ternary();
495 left = new (pool_) Assignment(pos, token, left, expr);
509 SourcePosition pos = scanner_.begin();
512 if (!expect(TOK_LPAREN))
515 Expression *condition = expression();
519 if (!expect(TOK_RPAREN))
522 // Inside a loop, we force the creation of a scope object. Normally, we
523 // will cull scopes if they have no variables. However inside a loop,
524 // function calls that take references may compute a LIFO object, and to
525 // avoid temporarily leaking many such objects, we ensure that a scope
526 // is present so a LIFO slot can be allocated.
527 if (!enterScope(Scope::BLOCK))
531 if (scanner_.peek() == TOK_LBRACE)
532 body = block(scope_);
534 body = localStatement();
538 scope_ = scope_->enclosing();
539 return new (pool_) WhileStatement(pos, TOK_WHILE, condition, body);
545 SourcePosition pos = scanner_.begin();
548 // See the comment in ::while_() as to why we force a scope.
549 if (!enterScope(Scope::BLOCK))
553 if (scanner_.peek() == TOK_LBRACE)
554 body = block(scope_);
556 body = localStatement();
560 scope_ = scope_->enclosing();
562 if (!expect(TOK_WHILE))
565 if (!expect(TOK_LPAREN))
567 Expression *condition = expression();
570 if (!expect(TOK_RPAREN))
573 return new (pool_) WhileStatement(pos, TOK_DO, condition, body);
577 Parser::forStatement()
579 SourcePosition pos = scanner_.begin();
581 if (!expect(TOK_LPAREN))
584 Statement *decl = NULL;
585 if (!match(TOK_SEMICOLON)) {
586 if (match(TOK_NEW)) {
587 if (!enterScope(Scope::BLOCK))
589 if ((decl = variableDeclaration(TOK_NEW)) == NULL)
592 if ((decl = expressionStatement()) == NULL)
595 if (!expect(TOK_SEMICOLON))
599 Expression *condition = NULL;
600 if (!match(TOK_SEMICOLON)) {
601 if ((condition = expression()) == NULL)
603 if (!expect(TOK_SEMICOLON))
607 Statement *update = NULL;
608 if (!match(TOK_RPAREN)) {
609 if ((update = expressionStatement()) == NULL)
611 if (!expect(TOK_RPAREN))
615 // See the comment in ::while_() as to why we force a scope.
616 if (!enterScope(Scope::BLOCK))
620 if (scanner_.peek() == TOK_LBRACE)
621 body = block(scope_);
623 body = localStatement();
627 scope_ = scope_->enclosing();
629 Scope *declScope = NULL;
630 if (decl && decl->isVariableDeclaration()) {
631 declScope = scope_->unlinkIfEmpty();
632 scope_ = scope_->enclosing();
634 return new (pool_) ForStatement(pos, declScope, decl, condition, update, body);
637 VariableDeclaration *
638 Parser::variableDeclaration(TokenKind kind)
640 Local<String> tag(zone_);
641 if (matchName(tag.ref(), TOK_LABEL) && !tag)
644 Local<String> name(zone_, expectName());
648 if (BoundName *other = scope_->localLookup(name)) {
649 redeclarationError(other);
653 Variable *var = scope_->declareVariable(name, scanner_.begin());
657 ExpressionList *postDimensions = NULL;
658 if (scanner_.peek() == TOK_LBRACKET) {
659 postDimensions = new (pool_) ExpressionList();
660 while (match(TOK_LBRACKET)) {
661 Expression *dim = expression();
665 if (!expect(TOK_RBRACKET))
668 if (!postDimensions->append(dim))
673 Expression *expr = NULL;
674 if (match(TOK_ASSIGN)) {
675 if ((expr = expression()) == NULL)
679 return new (pool_) VariableDeclaration(var->pos(), kind, var, tag, postDimensions, expr);
683 Parser::returnStatement()
685 SourcePosition pos = scanner_.begin();
686 if (!expect(TOK_RETURN))
689 Expression *expr = NULL;
690 if (scanner_.peek() != TOK_SEMICOLON) {
691 if ((expr = expression()) == NULL)
694 // We only care about non-void returns when determining whether a
695 // tagless function is non-void.
696 encounteredReturn_ = true;
699 return new (pool_) ReturnStatement(pos, expr);
703 Parser::expressionStatement()
705 Expression *left = assignment();
709 return new (pool_) ExpressionStatement(left);
713 Parser::block(Scope *scope)
715 if (!expect(TOK_LBRACE))
718 SourcePosition pos = scanner_.begin();
719 if (!scope && !enterScope(Scope::BLOCK))
722 StatementList *statements = new (pool_) StatementList();
723 while (!match(TOK_RBRACE)) {
724 Statement *statement = localStatement();
725 if (statement == NULL)
727 if (!statements->append(statement))
732 scope = scope_->unlinkIfEmpty();
733 scope_ = scope_->enclosing();
735 BlockStatement *block = new (pool_) BlockStatement(pos, scope, statements);
744 SourcePosition pos = scanner_.begin();
745 if (!expect(TOK_LPAREN))
748 Expression *cond = expression();
752 if (!expect(TOK_RPAREN))
755 Statement *ifTrue = localStatement();
759 IfStatement *outer = new (pool_) IfStatement(pos, cond, ifTrue);
761 IfStatement *last = outer;
762 while (match(TOK_ELSE)) {
763 if (!match(TOK_IF)) {
764 Statement *ifFalse = localStatement();
768 last->setIfFalse(ifFalse);
772 SourcePosition pos = scanner_.begin();
773 if (!expect(TOK_LPAREN))
776 Expression *otherCond = expression();
780 if (!expect(TOK_RPAREN))
783 Statement *otherIfTrue = localStatement();
787 IfStatement *inner = new (pool_) IfStatement(pos, otherCond, otherIfTrue);
788 last->setIfFalse(inner);
796 Parser::localStatement()
798 Statement *statement = NULL;
800 // Statements which must be followed by a semicolon will break out of the
801 // switch. If they may end in BlockStatements, they'll immediately return.
803 TokenKind kind = scanner_.peek();
808 if ((statement = variableDeclaration(kind)) == NULL)
813 return forStatement();
820 statement = new (pool_) BreakStatement(scanner_.begin());
825 statement = new (pool_) ContinueStatement(scanner_.begin());
829 if ((statement = do_()) == NULL)
834 if ((statement = returnStatement()) == NULL)
839 if ((statement = enum_()) == NULL)
854 if ((statement = expressionStatement()) == NULL)
858 if (!expect(TOK_SEMICOLON))
869 SourcePosition pos = scanner_.begin();
871 Local<String> name(zone_);
872 if (matchName(name.ref())) {
876 if (BoundName *other = scope_->localLookup(name)) {
877 redeclarationError(other);
881 if (!scope_->declareEnum(name, scanner_.begin()))
885 EnumStatement::EntryList *entries = new (pool_) EnumStatement::EntryList();
887 if (!expect(TOK_LBRACE))
891 if (scanner_.peek() == TOK_RBRACE)
894 Local<String> name(zone_, expectName());
898 if (BoundName *other = scope_->localLookup(name)) {
899 redeclarationError(other);
903 NamedConstant *constant = scope_->declareConstant(name, scanner_.begin());
907 Expression *expr = NULL;
908 if (match(TOK_ASSIGN)) {
909 if ((expr = expression()) == NULL)
913 if (!entries->append(EnumStatement::Entry(constant, expr)))
915 } while (match(TOK_COMMA));
916 if (!expect(TOK_RBRACE))
919 return new (pool_) EnumStatement(pos, name, entries);
923 Parser::function(TokenKind token)
925 Local<String> returnTag(zone_);
926 if (matchName(returnTag.ref(), TOK_LABEL) && !returnTag)
929 Local<String> name(zone_, expectName());
933 SourcePosition pos = scanner_.begin();
935 // The function name goes into the outer (global) scope.
936 assert(!scope_->enclosing());
939 if (BoundName *other = scope_->localLookup(name)) {
940 // We allow a redeclaration if the new type is a public, and the old
941 // type was a forward. However, the forward must come first.
942 if (other->kind() != BoundName::FUNCTION) {
943 redeclarationError(other);
947 fun = other->toNamedFunction();
948 if (!fun->isForward() || token != TOK_PUBLIC) {
949 redeclarationError(other);
953 // We've got the same name, but the original is a forward, so let it
954 // slide and re-use the original declaration.
955 fun->setImplemented(scanner_.begin());
957 fun = scope_->declareFunction(name, scanner_.begin(), token);
965 Scope *scope = enterScope(Scope::FUNCTION);
969 ParameterList *parameters = new (pool_) ParameterList();
971 if (!expect(TOK_LPAREN))
974 if (!match(TOK_RPAREN)) {
976 bool isConst = match(TOK_CONST);
977 bool ref = match(TOK_AMPERSAND);
979 SourcePosition begin = scanner_.begin();
980 Local<String> tag(zone_);
981 if (matchName(tag.ref(), TOK_LABEL) && !tag)
984 if (match(TOK_ELLIPSES)) {
985 if (isConst || ref) {
986 cc_.reportError(begin, Message_InvalidVarArgs);
990 if (token != TOK_NATIVE) {
991 cc_.reportError(begin, Message_VarArgsOutsideNative);
995 fun->markNativeVariadic();
999 Local<String> name(zone_, expectName());
1003 if (BoundName *other = scope_->localLookup(name)) {
1004 redeclarationError(other);
1007 Variable *arg = scope_->declareArgument(name, scanner_.begin());
1011 // Look for dimensions.
1012 ExpressionList *postDimensions = NULL;
1013 while (match(TOK_LBRACKET)) {
1014 if (!postDimensions)
1015 postDimensions = new (pool_) ExpressionList();
1017 Expression *dim = NULL;
1018 if (!match(TOK_RBRACKET)) {
1019 if ((dim = expression()) == NULL)
1021 if (!expect(TOK_RBRACKET))
1025 if (!postDimensions->append(dim))
1029 Expression *expr = NULL;
1030 if (match(TOK_ASSIGN)) {
1031 if ((expr = expression()) == NULL)
1035 Parameter *parameter = new (pool_) Parameter(arg, tag, ref, isConst, postDimensions,
1037 if (!parameters->append(parameter))
1040 if (!match(TOK_COMMA))
1043 if (!expect(TOK_RPAREN))
1047 encounteredReturn_ = false;
1049 Statement *body = NULL;
1050 if (token != TOK_FORWARD && token != TOK_NATIVE) {
1056 scope_ = scope_->enclosing();
1057 return new (pool_) FunctionStatement(pos, scope, fun, body, parameters, returnTag,
1058 encounteredReturn_);
1064 StatementList *statements = new (pool_) StatementList();
1066 if (!enterScope(Scope::GLOBAL))
1070 Statement *statement = NULL;
1072 TokenKind kind = scanner_.peek();
1081 if ((statement = function(TOK_NAME)) == NULL)
1091 if ((statement = function(kind)) == NULL)
1093 if ((kind == TOK_FORWARD || kind == TOK_NATIVE) && !matchSemicolon())
1102 if ((statement = variableDeclaration(kind)) == NULL)
1104 if (!matchSemicolon())
1110 if ((statement = enum_()) == NULL)
1112 if (!matchSemicolon())
1117 cc_.reportError(scanner_.begin(), Message_ExpectedGlobal);
1124 if (!statements->append(statement))
1128 return new (pool_) ParseTree(scope_, statements, unbound_);
1131 class AstPrinter : public AstVisitor
1138 for (size_t i = 0; i < level_; i++)
1149 AstPrinter(FILE *fp)
1155 void visit(NameProxy *name) {
1157 fprintf(fp_, "[ NameProxy (%s)%s\n", name->name()->chars(),
1158 (name->binding() ? "" : " unbound"));
1160 void visit(CallExpression *node) {
1162 fprintf(fp_, "[ CallExpression\n");
1164 node->callee()->accept(this);
1165 for (size_t i = 0; i < node->arguments()->length(); i++)
1166 node->arguments()->at(i)->accept(this);
1169 void visit(FunctionStatement *node) {
1171 fprintf(fp_, "[ FunctionStatement (%s)\n", node->fun()->name()->chars());
1174 node->body()->accept(this);
1177 void visit(ExpressionStatement *node) {
1179 fprintf(fp_, "[ ExpressionStatement\n");
1181 node->expression()->accept(this);
1184 void visit(Assignment *node) {
1186 fprintf(fp_, "[ Assignment\n");
1188 node->lvalue()->accept(this);
1189 node->expression()->accept(this);
1192 void visit(TernaryExpression *node) {
1194 fprintf(fp_, "[ TernaryExpression\n");
1196 node->condition()->accept(this);
1197 node->left()->accept(this);
1198 node->right()->accept(this);
1201 void visit(BinaryExpression *node) {
1203 fprintf(fp_, "[ BinaryExpression (%s)\n", TokenNames[node->token()]);
1205 node->left()->accept(this);
1206 node->right()->accept(this);
1209 void visit(UnaryExpression *node) {
1211 fprintf(fp_, "[ UnaryExpression (%s)\n", TokenNames[node->token()]);
1213 node->expression()->accept(this);
1216 void visit(ReturnStatement *node) {
1218 fprintf(fp_, "[ ReturnStatement\n");
1220 if (node->expression())
1221 node->expression()->accept(this);
1224 void visit(ForStatement *node) {
1226 fprintf(fp_, "[ ForStatement\n");
1228 if (node->initialization())
1229 node->initialization()->accept(this);
1230 if (node->condition())
1231 node->condition()->accept(this);
1233 node->update()->accept(this);
1234 node->body()->accept(this);
1237 void visit(BlockStatement *node) {
1239 fprintf(fp_, "[ BlockStatement\n");
1241 for (size_t i = 0; i < node->statements()->length(); i++)
1242 node->statements()->at(i)->accept(this);
1245 void visit(VariableDeclaration *node) {
1247 fprintf(fp_, "[ VariableDeclaration (%s)\n", node->variable()->name()->chars());
1249 if (node->initialization())
1250 node->initialization()->accept(this);
1253 void visit(IntegerLiteral *node) {
1255 fprintf(fp_, "[ IntegerLiteral (%d)\n", node->value());
1257 void visit(FloatLiteral *node) {
1259 fprintf(fp_, "[ FloatLiteral (%f)\n", node->value());
1261 void visit(IfStatement *node) {
1263 fprintf(fp_, "[ IfStatement\n");
1265 node->ifTrue()->accept(this);
1266 if (node->ifFalse())
1267 node->ifFalse()->accept(this);
1270 void visit(IndexExpression *node) {
1272 fprintf(fp_, "[ IndexExpression\n");
1274 node->left()->accept(this);
1275 node->right()->accept(this);
1278 void visit(EnumStatement *node) {
1280 fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name()->chars() : "<anonymous>");
1282 for (size_t i = 0; i < node->entries()->length(); i++) {
1284 fprintf(fp_, "%s =\n", node->entries()->at(i).name->name()->chars());
1285 if (node->entries()->at(i).expr) {
1287 node->entries()->at(i).expr->accept(this);
1293 void visit(WhileStatement *node) {
1295 fprintf(fp_, "[ WhileStatement (%s)\n",
1296 (node->token() == TOK_DO) ? "do" : "while");
1298 if (node->token() == TOK_DO) {
1299 node->condition()->accept(this);
1300 node->body()->accept(this);
1302 node->condition()->accept(this);
1303 node->body()->accept(this);
1307 void visit(BreakStatement *node) {
1309 fprintf(fp_, "[ BreakStatement\n");
1311 void visit(ContinueStatement *node) {
1313 fprintf(fp_, "[ ContinueStatement\n");
1315 void visit(StringLiteral *node) {
1317 fprintf(fp_, "[ StringLiteral\n");
1319 void visit(IncDecExpression *node) {
1321 fprintf(fp_, "[ IncDecExpression (postfix=%d)\n", node->postfix());
1323 node->expression()->accept(this);
1329 ParseTree::dump(FILE *fp)
1331 AstPrinter printer(fp);
1333 for (size_t i = 0; i < statements_->length(); i++)
1334 statements_->at(i)->accept(&printer);