goto is now allowed to reference labels that will get defined afterwards.

Sat, 25 Aug 2012 05:20:16 +0300

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Sat, 25 Aug 2012 05:20:16 +0300
changeset 61
11451e7a2fe6
parent 60
8834e4b6aebd
child 62
824ab7b28e3c

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 ();
 	

mercurial