src/Parser.cc

changeset 111
87d9ebd3ef34
parent 110
7a7a53f1d51b
child 112
def56932f938
equal deleted inserted replaced
110:7a7a53f1d51b 111:87d9ebd3ef34
120 120
121 case TK_Var: 121 case TK_Var:
122 ParseVar(); 122 ParseVar();
123 break; 123 break;
124 124
125 case TK_Goto:
126 ParseGoto();
127 break;
128
129 case TK_If: 125 case TK_If:
130 ParseIf(); 126 ParseIf();
131 break; 127 break;
132 128
133 case TK_Else: 129 case TK_Else:
181 case TK_Semicolon: 177 case TK_Semicolon:
182 break; 178 break;
183 179
184 default: 180 default:
185 { 181 {
186 // Check for labels
187 Lexer::Token next;
188
189 if (TokenIs (TK_Symbol) &&
190 mLexer->PeekNext (&next) &&
191 next.type ==TK_Colon)
192 {
193 ParseLabel();
194 break;
195 }
196
197 // Check if it's a command 182 // Check if it's a command
198 CommandInfo* comm = FindCommandByName (GetTokenString()); 183 CommandInfo* comm = FindCommandByName (GetTokenString());
199 184
200 if (comm) 185 if (comm)
201 { 186 {
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;

mercurial