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 ();
@@ -841,6 +845,7 @@ const Statement *Parser::parseFunctionDefinition(Scope *scope)
841845 parseFunctionHeader (scope, name, returntype, newscope, args);
842846 Function *function = new Function (name, returntype, newscope, args);
843847 scope->addName (name, function);
848+ loops.push (std::list<std::pair<TokenType, unsigned int >>());
844849 while (tokens[i].type != END) {
845850 const Statement *s = parseStatement (newscope);
846851 if (s != nullptr ) {
@@ -852,6 +857,7 @@ const Statement *Parser::parseFunctionDefinition(Scope *scope)
852857 error (2102 , tokens[i], " 'FUNCTION' expected" );
853858 }
854859 ++i;
860+ loops.pop ();
855861 return nullptr ;
856862}
857863
@@ -1002,6 +1008,8 @@ const Statement *Parser::parseWhileStatement(Scope *scope)
10021008 error (2082 , tokens[i], " DO expected" );
10031009 }
10041010 ++i;
1011+ auto loop_id = i;
1012+ loops.top ().push_back (std::make_pair (WHILE, loop_id));
10051013 std::vector<const Statement *> statements;
10061014 while (tokens[i].type != END && tokens[i].type != END_OF_FILE) {
10071015 const Statement *s = parseStatement (scope);
@@ -1017,7 +1025,8 @@ const Statement *Parser::parseWhileStatement(Scope *scope)
10171025 error (2104 , tokens[i], " WHILE expected" );
10181026 }
10191027 ++i;
1020- return new WhileStatement (cond, statements);
1028+ loops.top ().pop_back ();
1029+ return new WhileStatement (loop_id, cond, statements);
10211030}
10221031
10231032const Statement *Parser::parseCaseStatement (Scope *scope)
@@ -1277,6 +1286,8 @@ const Statement *Parser::parseForStatement(Scope *scope)
12771286 error (2118 , tokens[i], " 'DO' expected" );
12781287 }
12791288 ++i;
1289+ auto loop_id = i;
1290+ loops.top ().push_back (std::make_pair (FOR, loop_id));
12801291 std::vector<const Statement *> statements;
12811292 while (tokens[i].type != END && tokens[i].type != END_OF_FILE) {
12821293 const Statement *s = parseStatement (scope);
@@ -1292,7 +1303,27 @@ const Statement *Parser::parseForStatement(Scope *scope)
12921303 error (2120 , tokens[i], " 'END FOR' expected" );
12931304 }
12941305 ++i;
1295- return new ForStatement (var, start, end, statements);
1306+ loops.top ().pop_back ();
1307+ return new ForStatement (loop_id, var, start, end, statements);
1308+ }
1309+
1310+ const Statement *Parser::parseExitStatement (Scope *)
1311+ {
1312+ ++i;
1313+ if (tokens[i].type != WHILE
1314+ && tokens[i].type != FOR) {
1315+ error (2136 , tokens[i], " loop type expected" );
1316+ }
1317+ TokenType type = tokens[i].type ;
1318+ ++i;
1319+ if (not loops.empty ()) {
1320+ for (auto j = loops.top ().rbegin (); j != loops.top ().rend (); ++j) {
1321+ if (j->first == type) {
1322+ return new ExitStatement (j->second );
1323+ }
1324+ }
1325+ }
1326+ error (2137 , tokens[i-1 ], " no matching loop found in current scope" );
12961327}
12971328
12981329const Statement *Parser::parseImport (Scope *scope)
@@ -1330,6 +1361,8 @@ const Statement *Parser::parseStatement(Scope *scope)
13301361 return parseCaseStatement (scope);
13311362 } else if (tokens[i].type == FOR) {
13321363 return parseForStatement (scope);
1364+ } else if (tokens[i].type == EXIT) {
1365+ return parseExitStatement (scope);
13331366 } else if (tokens[i].type == IDENTIFIER) {
13341367 const VariableReference *ref = parseVariableReference (scope);
13351368 if (tokens[i].type == ASSIGN) {
@@ -1364,12 +1397,14 @@ const Program *Parser::parse()
13641397{
13651398 Program *program = new Program ();
13661399 global_scope = program->scope ;
1400+ loops.push (std::list<std::pair<TokenType, unsigned int >>());
13671401 while (tokens[i].type != END_OF_FILE) {
13681402 const Statement *s = parseStatement (program->scope );
13691403 if (s != nullptr ) {
13701404 program->statements .push_back (s);
13711405 }
13721406 }
1407+ loops.pop ();
13731408 return program;
13741409}
13751410
0 commit comments