230 { |
215 { |
231 // stateSpawn must be defined! |
216 // stateSpawn must be defined! |
232 if (mStateSpawnDefined == false) |
217 if (mStateSpawnDefined == false) |
233 Error ("script must have a state named `stateSpawn`!"); |
218 Error ("script must have a state named `stateSpawn`!"); |
234 |
219 |
235 // Ensure no goto target is left undefined |
|
236 if (mUndefinedLabels.IsEmpty() == false) |
|
237 { |
|
238 StringList names; |
|
239 |
|
240 for (UndefinedLabel& undf : mUndefinedLabels) |
|
241 names << undf.name; |
|
242 |
|
243 Error ("labels `%1` are referenced via `goto` but are not defined\n", names); |
|
244 } |
|
245 |
|
246 // Dump the last state's onenter and mainloop |
220 // Dump the last state's onenter and mainloop |
247 writeMemberBuffers(); |
221 writeMemberBuffers(); |
248 |
222 |
249 // String table |
223 // String table |
250 WriteStringTable(); |
224 WriteStringTable(); |
263 if (statename.FirstIndexOf (" ") != -1) |
237 if (statename.FirstIndexOf (" ") != -1) |
264 Error ("state name must be a single word, got `%1`", statename); |
238 Error ("state name must be a single word, got `%1`", statename); |
265 |
239 |
266 // stateSpawn is special - it *must* be defined. If we |
240 // stateSpawn is special - it *must* be defined. If we |
267 // encountered it, then mark down that we have it. |
241 // encountered it, then mark down that we have it. |
268 if (-statename == "statespawn") |
242 if (statename.ToLowercase() == "statespawn") |
269 mStateSpawnDefined = true; |
243 mStateSpawnDefined = true; |
270 |
244 |
271 // Must end in a colon |
245 // Must end in a colon |
272 mLexer->MustGetNext (TK_Colon); |
246 mLexer->MustGetNext (TK_Colon); |
273 |
247 |
409 SCOPE(0).localVariables << var; |
383 SCOPE(0).localVariables << var; |
410 |
384 |
411 SuggestHighestVarIndex (IsInGlobalState(), var->index); |
385 SuggestHighestVarIndex (IsInGlobalState(), var->index); |
412 mLexer->MustGetNext (TK_Semicolon); |
386 mLexer->MustGetNext (TK_Semicolon); |
413 Print ("Declared %3 variable #%1 $%2\n", var->index, var->name, IsInGlobalState() ? "global" : "state-local"); |
387 Print ("Declared %3 variable #%1 $%2\n", var->index, var->name, IsInGlobalState() ? "global" : "state-local"); |
414 } |
|
415 |
|
416 // ============================================================================ |
|
417 // |
|
418 void BotscriptParser::ParseGoto() |
|
419 { |
|
420 CheckNotToplevel(); |
|
421 |
|
422 // Get the name of the label |
|
423 mLexer->MustGetNext (TK_Symbol); |
|
424 |
|
425 // Find the mark this goto statement points to |
|
426 String target = GetTokenString(); |
|
427 ByteMark* mark = buffer()->FindMarkByName (target); |
|
428 |
|
429 // If not set, define it |
|
430 if (mark == null) |
|
431 { |
|
432 UndefinedLabel undf; |
|
433 undf.name = target; |
|
434 undf.target = buffer()->AddMark (target); |
|
435 mUndefinedLabels << undf; |
|
436 } |
|
437 |
|
438 // Add a reference to the mark. |
|
439 buffer()->WriteDWord (DH_Goto); |
|
440 buffer()->AddReference (mark); |
|
441 mLexer->MustGetNext (TK_Semicolon); |
|
442 } |
388 } |
443 |
389 |
444 // ============================================================================ |
390 // ============================================================================ |
445 // |
391 // |
446 void BotscriptParser::ParseIf() |
392 void BotscriptParser::ParseIf() |
862 buffer()->WriteDWord (dataheader); |
808 buffer()->WriteDWord (dataheader); |
863 mCurrentMode = PARSERMODE_TopLevel; |
809 mCurrentMode = PARSERMODE_TopLevel; |
864 mLexer->GetNext (TK_Semicolon); |
810 mLexer->GetNext (TK_Semicolon); |
865 } |
811 } |
866 |
812 |
867 // ============================================================================ |
|
868 // |
|
869 void BotscriptParser::ParseLabel() |
|
870 { |
|
871 CheckNotToplevel(); |
|
872 String labelName = GetTokenString(); |
|
873 ByteMark* mark = null; |
|
874 |
|
875 // See if a mark already exists for this label |
|
876 for (UndefinedLabel& label : mUndefinedLabels) |
|
877 { |
|
878 if (label.name != labelName) |
|
879 continue; |
|
880 |
|
881 mark = label.target; |
|
882 buffer()->AdjustMark (mark); |
|
883 |
|
884 // No longer undefined |
|
885 mUndefinedLabels.Remove (label); |
|
886 break; |
|
887 } |
|
888 |
|
889 // Not found in unmarked lists, define it now |
|
890 if (mark == null) |
|
891 buffer()->AddMark (labelName); |
|
892 |
|
893 mLexer->MustGetNext (TK_Colon); |
|
894 } |
|
895 |
|
896 // ============================================================================= |
813 // ============================================================================= |
897 // |
814 // |
898 void BotscriptParser::ParseEventdef() |
815 void BotscriptParser::ParseEventdef() |
899 { |
816 { |
900 EventDefinition* e = new EventDefinition; |
817 EventDefinition* e = new EventDefinition; |