Sat, 25 Aug 2012 05:20:16 +0300
goto is now allowed to reference labels that will get defined afterwards.
parser.cxx | file | annotate | diff | comparison | revisions |
--- a/parser.cxx Sat Aug 25 05:05:58 2012 +0300 +++ b/parser.cxx Sat Aug 25 05:20:16 2012 +0300 @@ -68,6 +68,7 @@ unsigned int g_ScopeCursor = 0; DataBuffer* g_IfExpression = NULL; bool g_CanElse = false; +str* g_UnmarkedLabels[MAX_MARKS]; // ============================================================================ // Main parser code. Begins read of the script file, checks the syntax of it @@ -78,6 +79,9 @@ for (int i = 0; i < MAX_SCOPE; i++) ZERO(scopestack[i]); + for (int i = 0; i < MAX_MARKS; i++) + g_UnmarkedLabels[i] = NULL; + while (Next()) { // Check if else is potentically valid if (!token.compare ("else") && !g_CanElse) @@ -197,11 +201,13 @@ MustNext (); // Find the mark this goto statement points to - // TODO: This should define the mark instead of bombing - // out if the mark isn't found! unsigned int m = w->FindMark (token); - if (m == MAX_MARKS) - ParserError ("unknown label `%s`!", token.chars()); + + // If not set, define it + if (m == MAX_MARKS) { + m = w->AddMark (token); + g_UnmarkedLabels[m] = new str (token); + } // Add a reference to the mark. w->Write<word> (DH_GOTO); @@ -501,6 +507,7 @@ if (!PeekNext().compare (":")) { MUST_NOT_TOPLEVEL + // want no conflicts.. if (IsKeyword (token)) ParserError ("label name `%s` conflicts with keyword\n", token.chars()); if (FindCommand (token)) @@ -508,7 +515,23 @@ if (FindGlobalVariable (token)) ParserError ("label name `%s` conflicts with variable\n", token.chars()); - w->AddMark (token); + // See if the label is already defined but unmarked + int mark = -1; + for (int i = 0; i < MAX_MARKS; i++) { + if (g_UnmarkedLabels[i] && !g_UnmarkedLabels[i]->compare (token)) { + mark = i; + w->MoveMark (i); + + // No longer unmarked + delete g_UnmarkedLabels[i]; + g_UnmarkedLabels[i] = NULL; + } + } + + // Not found in unmarked lists, define it now + if (mark == -1) + w->AddMark (token); + MustNext (":"); continue; } @@ -631,6 +654,10 @@ if (!g_stateSpawnDefined) ParserError ("script must have a state named `stateSpawn`!"); + for (int i = 0; i < MAX_MARKS; i++) + if (g_UnmarkedLabels[i]) + ParserError ("label `%s` is referenced via `goto` but isn't defined\n", g_UnmarkedLabels[i]->chars()); + // Dump the last state's onenter and mainloop w->WriteBuffers ();