11#include " parser.h"
22
33#include < iso646.h>
4+ #include < list>
45
56#include " ast.h"
67#include " rtl.h"
@@ -14,6 +15,8 @@ class Parser {
1415 static Scope *global_scope; // TODO: static is a hack, used by StringReference constructor
1516 std::vector<Token>::size_type i;
1617
18+ std::stack<std::list<std::pair<TokenType, unsigned int >>> loops;
19+
1720 typedef std::pair<std::vector<std::string>, const Type *> VariableInfo;
1821
1922 const Type *parseArrayType (Scope *scope);
@@ -45,6 +48,7 @@ class Parser {
4548 const Statement *parseWhileStatement (Scope *scope);
4649 const Statement *parseCaseStatement (Scope *scope);
4750 const Statement *parseForStatement (Scope *scope);
51+ const Statement *parseExitStatement (Scope *scope);
4852 const Statement *parseImport (Scope *scope);
4953 const Statement *parseStatement (Scope *scope);
5054 const Program *parse ();
@@ -57,7 +61,8 @@ Scope *Parser::global_scope;
5761
5862Parser::Parser (const std::vector<Token> &tokens)
5963 : tokens(tokens),
60- i(0 )
64+ i(0 ),
65+ loops()
6166{
6267}
6368
@@ -841,6 +846,7 @@ const Statement *Parser::parseFunctionDefinition(Scope *scope)
841846 parseFunctionHeader (scope, name, returntype, newscope, args);
842847 Function *function = new Function (name, returntype, newscope, args);
843848 scope->addName (name, function);
849+ loops.push (std::list<std::pair<TokenType, unsigned int >>());
844850 while (tokens[i].type != END) {
845851 const Statement *s = parseStatement (newscope);
846852 if (s != nullptr ) {
@@ -852,6 +858,7 @@ const Statement *Parser::parseFunctionDefinition(Scope *scope)
852858 error (2102 , tokens[i], " 'FUNCTION' expected" );
853859 }
854860 ++i;
861+ loops.pop ();
855862 return nullptr ;
856863}
857864
@@ -1002,6 +1009,8 @@ const Statement *Parser::parseWhileStatement(Scope *scope)
10021009 error (2082 , tokens[i], " DO expected" );
10031010 }
10041011 ++i;
1012+ auto loop_id = i;
1013+ loops.top ().push_back (std::make_pair (WHILE, loop_id));
10051014 std::vector<const Statement *> statements;
10061015 while (tokens[i].type != END && tokens[i].type != END_OF_FILE) {
10071016 const Statement *s = parseStatement (scope);
@@ -1017,7 +1026,8 @@ const Statement *Parser::parseWhileStatement(Scope *scope)
10171026 error (2104 , tokens[i], " WHILE expected" );
10181027 }
10191028 ++i;
1020- return new WhileStatement (cond, statements);
1029+ loops.top ().pop_back ();
1030+ return new WhileStatement (loop_id, cond, statements);
10211031}
10221032
10231033const Statement *Parser::parseCaseStatement (Scope *scope)
@@ -1277,6 +1287,8 @@ const Statement *Parser::parseForStatement(Scope *scope)
12771287 error (2118 , tokens[i], " 'DO' expected" );
12781288 }
12791289 ++i;
1290+ auto loop_id = i;
1291+ loops.top ().push_back (std::make_pair (FOR, loop_id));
12801292 std::vector<const Statement *> statements;
12811293 while (tokens[i].type != END && tokens[i].type != END_OF_FILE) {
12821294 const Statement *s = parseStatement (scope);
@@ -1292,7 +1304,27 @@ const Statement *Parser::parseForStatement(Scope *scope)
12921304 error (2120 , tokens[i], " 'END FOR' expected" );
12931305 }
12941306 ++i;
1295- return new ForStatement (var, start, end, statements);
1307+ loops.top ().pop_back ();
1308+ return new ForStatement (loop_id, var, start, end, statements);
1309+ }
1310+
1311+ const Statement *Parser::parseExitStatement (Scope *)
1312+ {
1313+ ++i;
1314+ if (tokens[i].type != WHILE
1315+ && tokens[i].type != FOR) {
1316+ error (2136 , tokens[i], " loop type expected" );
1317+ }
1318+ TokenType type = tokens[i].type ;
1319+ ++i;
1320+ if (not loops.empty ()) {
1321+ for (auto j = loops.top ().rbegin (); j != loops.top ().rend (); ++j) {
1322+ if (j->first == type) {
1323+ return new ExitStatement (j->second );
1324+ }
1325+ }
1326+ }
1327+ error (2137 , tokens[i-1 ], " no matching loop found in current scope" );
12961328}
12971329
12981330const Statement *Parser::parseImport (Scope *scope)
@@ -1330,6 +1362,8 @@ const Statement *Parser::parseStatement(Scope *scope)
13301362 return parseCaseStatement (scope);
13311363 } else if (tokens[i].type == FOR) {
13321364 return parseForStatement (scope);
1365+ } else if (tokens[i].type == EXIT) {
1366+ return parseExitStatement (scope);
13331367 } else if (tokens[i].type == IDENTIFIER) {
13341368 const VariableReference *ref = parseVariableReference (scope);
13351369 if (tokens[i].type == ASSIGN) {
@@ -1364,12 +1398,14 @@ const Program *Parser::parse()
13641398{
13651399 Program *program = new Program ();
13661400 global_scope = program->scope ;
1401+ loops.push (std::list<std::pair<TokenType, unsigned int >>());
13671402 while (tokens[i].type != END_OF_FILE) {
13681403 const Statement *s = parseStatement (program->scope );
13691404 if (s != nullptr ) {
13701405 program->statements .push_back (s);
13711406 }
13721407 }
1408+ loops.pop ();
13731409 return program;
13741410}
13751411
0 commit comments