parser.cxx

changeset 61
11451e7a2fe6
parent 59
891b9e6ee139
child 62
824ab7b28e3c
equal deleted inserted replaced
60:8834e4b6aebd 61:11451e7a2fe6
66 bool g_stateSpawnDefined = false; 66 bool g_stateSpawnDefined = false;
67 bool g_GotMainLoop = false; 67 bool g_GotMainLoop = false;
68 unsigned int g_ScopeCursor = 0; 68 unsigned int g_ScopeCursor = 0;
69 DataBuffer* g_IfExpression = NULL; 69 DataBuffer* g_IfExpression = NULL;
70 bool g_CanElse = false; 70 bool g_CanElse = false;
71 str* g_UnmarkedLabels[MAX_MARKS];
71 72
72 // ============================================================================ 73 // ============================================================================
73 // Main parser code. Begins read of the script file, checks the syntax of it 74 // Main parser code. Begins read of the script file, checks the syntax of it
74 // and writes the data to the object file via ObjWriter - which also takes care 75 // and writes the data to the object file via ObjWriter - which also takes care
75 // of necessary buffering so stuff is written in the correct order. 76 // of necessary buffering so stuff is written in the correct order.
76 void ScriptReader::ParseBotScript (ObjWriter* w) { 77 void ScriptReader::ParseBotScript (ObjWriter* w) {
77 // Zero the entire block stack first 78 // Zero the entire block stack first
78 for (int i = 0; i < MAX_SCOPE; i++) 79 for (int i = 0; i < MAX_SCOPE; i++)
79 ZERO(scopestack[i]); 80 ZERO(scopestack[i]);
80 81
82 for (int i = 0; i < MAX_MARKS; i++)
83 g_UnmarkedLabels[i] = NULL;
84
81 while (Next()) { 85 while (Next()) {
82 // Check if else is potentically valid 86 // Check if else is potentically valid
83 if (!token.compare ("else") && !g_CanElse) 87 if (!token.compare ("else") && !g_CanElse)
84 ParserError ("else without preceding if"); 88 ParserError ("else without preceding if");
85 if (token.compare ("else") != 0) 89 if (token.compare ("else") != 0)
195 199
196 // Get the name of the label 200 // Get the name of the label
197 MustNext (); 201 MustNext ();
198 202
199 // Find the mark this goto statement points to 203 // Find the mark this goto statement points to
200 // TODO: This should define the mark instead of bombing
201 // out if the mark isn't found!
202 unsigned int m = w->FindMark (token); 204 unsigned int m = w->FindMark (token);
203 if (m == MAX_MARKS) 205
204 ParserError ("unknown label `%s`!", token.chars()); 206 // If not set, define it
207 if (m == MAX_MARKS) {
208 m = w->AddMark (token);
209 g_UnmarkedLabels[m] = new str (token);
210 }
205 211
206 // Add a reference to the mark. 212 // Add a reference to the mark.
207 w->Write<word> (DH_GOTO); 213 w->Write<word> (DH_GOTO);
208 w->AddReference (m); 214 w->AddReference (m);
209 MustNext (";"); 215 MustNext (";");
499 // ============================================================ 505 // ============================================================
500 // Label 506 // Label
501 if (!PeekNext().compare (":")) { 507 if (!PeekNext().compare (":")) {
502 MUST_NOT_TOPLEVEL 508 MUST_NOT_TOPLEVEL
503 509
510 // want no conflicts..
504 if (IsKeyword (token)) 511 if (IsKeyword (token))
505 ParserError ("label name `%s` conflicts with keyword\n", token.chars()); 512 ParserError ("label name `%s` conflicts with keyword\n", token.chars());
506 if (FindCommand (token)) 513 if (FindCommand (token))
507 ParserError ("label name `%s` conflicts with command name\n", token.chars()); 514 ParserError ("label name `%s` conflicts with command name\n", token.chars());
508 if (FindGlobalVariable (token)) 515 if (FindGlobalVariable (token))
509 ParserError ("label name `%s` conflicts with variable\n", token.chars()); 516 ParserError ("label name `%s` conflicts with variable\n", token.chars());
510 517
511 w->AddMark (token); 518 // See if the label is already defined but unmarked
519 int mark = -1;
520 for (int i = 0; i < MAX_MARKS; i++) {
521 if (g_UnmarkedLabels[i] && !g_UnmarkedLabels[i]->compare (token)) {
522 mark = i;
523 w->MoveMark (i);
524
525 // No longer unmarked
526 delete g_UnmarkedLabels[i];
527 g_UnmarkedLabels[i] = NULL;
528 }
529 }
530
531 // Not found in unmarked lists, define it now
532 if (mark == -1)
533 w->AddMark (token);
534
512 MustNext (":"); 535 MustNext (":");
513 continue; 536 continue;
514 } 537 }
515 538
516 // ============================================================ 539 // ============================================================
629 652
630 // stateSpawn must be defined! 653 // stateSpawn must be defined!
631 if (!g_stateSpawnDefined) 654 if (!g_stateSpawnDefined)
632 ParserError ("script must have a state named `stateSpawn`!"); 655 ParserError ("script must have a state named `stateSpawn`!");
633 656
657 for (int i = 0; i < MAX_MARKS; i++)
658 if (g_UnmarkedLabels[i])
659 ParserError ("label `%s` is referenced via `goto` but isn't defined\n", g_UnmarkedLabels[i]->chars());
660
634 // Dump the last state's onenter and mainloop 661 // Dump the last state's onenter and mainloop
635 w->WriteBuffers (); 662 w->WriteBuffers ();
636 663
637 // String table 664 // String table
638 w->WriteStringTable (); 665 w->WriteStringTable ();

mercurial