parser.cxx

changeset 66
4fc1ec88aa41
parent 65
ec04357f5bb9
child 67
0a202714eea4
equal deleted inserted replaced
65:ec04357f5bb9 66:4fc1ec88aa41
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_UndefinedLabels[MAX_MARKS]; 71 str* g_UndefinedLabels[MAX_MARKS];
72 bool g_Neurosphere = false; // neurosphere-compat
72 73
73 // ============================================================================ 74 // ============================================================================
74 // Main parser code. Begins read of the script file, checks the syntax of it 75 // Main parser code. Begins read of the script file, checks the syntax of it
75 // and writes the data to the object file via ObjWriter - which also takes care 76 // and writes the data to the object file via ObjWriter - which also takes care
76 // of necessary buffering so stuff is written in the correct order. 77 // of necessary buffering so stuff is written in the correct order.
82 for (int i = 0; i < MAX_MARKS; i++) 83 for (int i = 0; i < MAX_MARKS; i++)
83 g_UndefinedLabels[i] = NULL; 84 g_UndefinedLabels[i] = NULL;
84 85
85 while (Next()) { 86 while (Next()) {
86 // Check if else is potentically valid 87 // Check if else is potentically valid
87 if (!token.compare ("else") && !g_CanElse) 88 if (token == "else" && !g_CanElse)
88 ParserError ("else without preceding if"); 89 ParserError ("else without preceding if");
89 if (token.compare ("else") != 0) 90 if (token != "else")
90 g_CanElse = false; 91 g_CanElse = false;
91 92
92 // ============================================================ 93 // ============================================================
93 if (!token.compare ("state")) { 94 if (token == "state") {
94 MUST_TOPLEVEL 95 MUST_TOPLEVEL
95 96
96 MustString (); 97 MustString ();
97 98
98 // State name must be a word. 99 // State name must be a word.
123 g_GotMainLoop = false; 124 g_GotMainLoop = false;
124 continue; 125 continue;
125 } 126 }
126 127
127 // ============================================================ 128 // ============================================================
128 if (!token.compare ("event")) { 129 if (token == "event") {
129 MUST_TOPLEVEL 130 MUST_TOPLEVEL
130 131
131 // Event definition 132 // Event definition
132 MustString (); 133 MustString ();
133 134
144 g_NumEvents++; 145 g_NumEvents++;
145 continue; 146 continue;
146 } 147 }
147 148
148 // ============================================================ 149 // ============================================================
149 if (!token.compare ("mainloop")) { 150 if (token == "mainloop") {
150 MUST_TOPLEVEL 151 MUST_TOPLEVEL
151 MustNext ("{"); 152 MustNext ("{");
152 153
153 // Mode must be set before dataheader is written here! 154 // Mode must be set before dataheader is written here!
154 g_CurMode = MODE_MAINLOOP; 155 g_CurMode = MODE_MAINLOOP;
155 w->Write (DH_MAINLOOP); 156 w->Write (DH_MAINLOOP);
156 continue; 157 continue;
157 } 158 }
158 159
159 // ============================================================ 160 // ============================================================
160 if (!token.compare ("onenter") || !token.compare ("onexit")) { 161 if (token == "onenter" || token == "onexit") {
161 MUST_TOPLEVEL 162 MUST_TOPLEVEL
162 bool onenter = !token.compare ("onenter"); 163 bool onenter = token == "onenter";
163 MustNext ("{"); 164 MustNext ("{");
164 165
165 // Mode must be set before dataheader is written here, 166 // Mode must be set before dataheader is written here,
166 // because onenter goes to a separate buffer. 167 // because onenter goes to a separate buffer.
167 g_CurMode = onenter ? MODE_ONENTER : MODE_ONEXIT; 168 g_CurMode = onenter ? MODE_ONENTER : MODE_ONEXIT;
168 w->Write (onenter ? DH_ONENTER : DH_ONEXIT); 169 w->Write (onenter ? DH_ONENTER : DH_ONEXIT);
169 continue; 170 continue;
170 } 171 }
171 172
172 // ============================================================ 173 // ============================================================
173 if (!token.compare ("var")) { 174 if (token == "var") {
174 // For now, only globals are supported 175 // For now, only globals are supported
175 if (g_CurMode != MODE_TOPLEVEL || g_CurState.len()) 176 if (g_CurMode != MODE_TOPLEVEL || g_CurState.len())
176 ParserError ("variables must only be global for now"); 177 ParserError ("variables must only be global for now");
177 178
178 MustNext (); 179 MustNext ();
192 continue; 193 continue;
193 } 194 }
194 195
195 // ============================================================ 196 // ============================================================
196 // Goto 197 // Goto
197 if (!token.compare ("goto")) { 198 if (token == "goto") {
198 MUST_NOT_TOPLEVEL 199 MUST_NOT_TOPLEVEL
199 200
200 // Get the name of the label 201 // Get the name of the label
201 MustNext (); 202 MustNext ();
202 203
216 continue; 217 continue;
217 } 218 }
218 219
219 // ============================================================ 220 // ============================================================
220 // If 221 // If
221 if (!token.compare ("if")) { 222 if (token == "if") {
222 MUST_NOT_TOPLEVEL 223 MUST_NOT_TOPLEVEL
223 PushScope (); 224 PushScope ();
224 225
225 // Condition 226 // Condition
226 MustNext ("("); 227 MustNext ("(");
246 SCOPE(0).mark1 = marknum; 247 SCOPE(0).mark1 = marknum;
247 SCOPE(0).type = SCOPETYPE_IF; 248 SCOPE(0).type = SCOPETYPE_IF;
248 continue; 249 continue;
249 } 250 }
250 251
251 if (!token.compare ("else")) { 252 if (token == "else") {
252 MUST_NOT_TOPLEVEL 253 MUST_NOT_TOPLEVEL
253 MustNext ("{"); 254 MustNext ("{");
254 255
255 // Don't use PushScope that will reset the scope. 256 // Don't use PushScope that will reset the scope.
256 g_ScopeCursor++; 257 g_ScopeCursor++;
274 continue; 275 continue;
275 } 276 }
276 277
277 // ============================================================ 278 // ============================================================
278 // While 279 // While
279 if (!token.compare ("while")) { 280 if (token == "while") {
280 MUST_NOT_TOPLEVEL 281 MUST_NOT_TOPLEVEL
281 PushScope (); 282 PushScope ();
282 283
283 // While loops need two marks - one at the start of the loop and one at the 284 // While loops need two marks - one at the start of the loop and one at the
284 // end. The condition is checked at the very start of the loop, if it fails, 285 // end. The condition is checked at the very start of the loop, if it fails,
308 continue; 309 continue;
309 } 310 }
310 311
311 // ============================================================ 312 // ============================================================
312 // For loop 313 // For loop
313 if (!token.compare ("for")) { 314 if (token == "for") {
314 MUST_NOT_TOPLEVEL 315 MUST_NOT_TOPLEVEL
315 PushScope (); 316 PushScope ();
316 317
317 // Initializer 318 // Initializer
318 MustNext ("("); 319 MustNext ("(");
351 continue; 352 continue;
352 } 353 }
353 354
354 // ============================================================ 355 // ============================================================
355 // Do/while loop 356 // Do/while loop
356 if (!token.compare ("do")) { 357 if (token == "do") {
357 MUST_NOT_TOPLEVEL 358 MUST_NOT_TOPLEVEL
358 PushScope (); 359 PushScope ();
359 MustNext ("{"); 360 MustNext ("{");
360 SCOPE(0).mark1 = w->AddMark (""); 361 SCOPE(0).mark1 = w->AddMark ("");
361 SCOPE(0).type = SCOPETYPE_DO; 362 SCOPE(0).type = SCOPETYPE_DO;
362 continue; 363 continue;
363 } 364 }
364 365
365 // ============================================================ 366 // ============================================================
366 // Switch 367 // Switch
367 if (!token.compare ("switch")) { 368 if (token == "switch") {
368 /* This goes a bit tricky. switch is structured in the 369 /* This goes a bit tricky. switch is structured in the
369 * bytecode followingly: 370 * bytecode followingly:
370 * (expression) 371 * (expression)
371 * case a: goto casemark1 372 * case a: goto casemark1
372 * case b: goto casemark2 373 * case b: goto casemark2
390 SCOPE(0).buffer1 = NULL; // default header 391 SCOPE(0).buffer1 = NULL; // default header
391 continue; 392 continue;
392 } 393 }
393 394
394 // ============================================================ 395 // ============================================================
395 if (!token.compare ("case")) { 396 if (token == "case") {
396 // case is only allowed inside switch 397 // case is only allowed inside switch
397 if (SCOPE(0).type != SCOPETYPE_SWITCH) 398 if (SCOPE(0).type != SCOPETYPE_SWITCH)
398 ParserError ("case label outside switch"); 399 ParserError ("case label outside switch");
399 400
400 // Get the literal (Zandronum does not support expressions here) 401 // Get the literal (Zandronum does not support expressions here)
420 AddSwitchCase (w, NULL); 421 AddSwitchCase (w, NULL);
421 SCOPE(0).casenumbers[SCOPE(0).casecursor] = num; 422 SCOPE(0).casenumbers[SCOPE(0).casecursor] = num;
422 continue; 423 continue;
423 } 424 }
424 425
425 if (!token.compare ("default")) { 426 if (token == "default") {
426 if (SCOPE(0).type != SCOPETYPE_SWITCH) 427 if (SCOPE(0).type != SCOPETYPE_SWITCH)
427 ParserError ("default label outside switch"); 428 ParserError ("default label outside switch");
428 429
429 if (SCOPE(0).buffer1) 430 if (SCOPE(0).buffer1)
430 ParserError ("multiple default labels in one switch"); 431 ParserError ("multiple default labels in one switch");
446 continue; 447 continue;
447 } 448 }
448 449
449 // ============================================================ 450 // ============================================================
450 // Break statement. 451 // Break statement.
451 if (!token.compare ("break")) { 452 if (token == "break") {
452 if (!g_ScopeCursor) 453 if (!g_ScopeCursor)
453 ParserError ("unexpected `break`"); 454 ParserError ("unexpected `break`");
454 455
455 w->Write<word> (DH_GOTO); 456 w->Write<word> (DH_GOTO);
456 457
474 continue; 475 continue;
475 } 476 }
476 477
477 // ============================================================ 478 // ============================================================
478 // Continue 479 // Continue
479 if (!token.compare ("continue")) { 480 if (token == "continue") {
480 MustNext (";"); 481 MustNext (";");
481 482
482 int curs; 483 int curs;
483 bool found = false; 484 bool found = false;
484 485
489 case SCOPETYPE_WHILE: 490 case SCOPETYPE_WHILE:
490 case SCOPETYPE_DO: 491 case SCOPETYPE_DO:
491 w->Write<word> (DH_GOTO); 492 w->Write<word> (DH_GOTO);
492 w->AddReference (scopestack[curs].mark1); 493 w->AddReference (scopestack[curs].mark1);
493 found = true; 494 found = true;
495 break;
496 default:
494 break; 497 break;
495 } 498 }
496 } 499 }
497 500
498 // No loop blocks 501 // No loop blocks
610 w->WriteBuffer (SCOPE(0).casebuffers[u]); 613 w->WriteBuffer (SCOPE(0).casebuffers[u]);
611 } 614 }
612 615
613 // Move the closing mark here 616 // Move the closing mark here
614 w->MoveMark (SCOPE(0).mark1); 617 w->MoveMark (SCOPE(0).mark1);
618 break;
615 } 619 }
620 case SCOPETYPE_UNKNOWN:
621 break;
616 } 622 }
617 623
618 // Descend down the stack 624 // Descend down the stack
619 g_ScopeCursor--; 625 g_ScopeCursor--;
620 continue; 626 continue;
637 if (!PeekNext().compare (";")) 643 if (!PeekNext().compare (";"))
638 MustNext (";"); 644 MustNext (";");
639 continue; 645 continue;
640 } 646 }
641 647
642 // ============================================================ 648 // Check if it's a command
643 // If nothing else, parse it as a statement (which is either 649 CommandDef* comm = FindCommand (token);
644 // assignment or expression) 650 if (comm) {
651 w->GetCurrentBuffer()->Merge (ParseCommand (comm));
652 MustNext (";");
653 continue;
654 }
655
656 // ============================================================
657 // If nothing else, parse it as a statement
645 DataBuffer* b = ParseStatement (w); 658 DataBuffer* b = ParseStatement (w);
646 w->WriteBuffer (b); 659 w->WriteBuffer (b);
647 MustNext (";"); 660 MustNext (";");
648 } 661 }
649 662
663 // ===============================================================================
664 // Script file ended. Do some last checks and write the last things to main buffer
650 if (g_CurMode != MODE_TOPLEVEL) 665 if (g_CurMode != MODE_TOPLEVEL)
651 ParserError ("script did not end at top level; did you forget a `}`?"); 666 ParserError ("script did not end at top level; did you forget a `}`?");
652 667
653 // stateSpawn must be defined! 668 // stateSpawn must be defined!
654 if (!g_stateSpawnDefined) 669 if (!g_stateSpawnDefined)
815 MustNext (); 830 MustNext ();
816 DataBuffer* tb = ParseExprValue (reqtype); 831 DataBuffer* tb = ParseExprValue (reqtype);
817 832
818 // It also is handled differently: there isn't a dataheader for ternary 833 // It also is handled differently: there isn't a dataheader for ternary
819 // operator. Instead, we abuse PUSHNUMBER and IFNOTGOTO for this. 834 // operator. Instead, we abuse PUSHNUMBER and IFNOTGOTO for this.
835 // Behold, big block of writing madness! :P
820 int mark1 = retbuf->AddMark (""); // start of "else" case 836 int mark1 = retbuf->AddMark (""); // start of "else" case
821 int mark2 = retbuf->AddMark (""); // end of expression 837 int mark2 = retbuf->AddMark (""); // end of expression
822 retbuf->Write<word> (DH_IFNOTGOTO); 838 retbuf->Write<word> (DH_IFNOTGOTO); // if the first operand (condition)
823 retbuf->AddMarkReference (mark1); 839 retbuf->AddMarkReference (mark1); // didn't eval true, jump into mark1
824 retbuf->Merge (rb); 840 retbuf->Merge (rb); // otherwise, perform second operand (true case)
825 retbuf->Write<word> (DH_GOTO); 841 retbuf->Write<word> (DH_GOTO); // afterwards, jump to the end, which is
826 retbuf->AddMarkReference (mark2); 842 retbuf->AddMarkReference (mark2); // marked by mark2.
827 retbuf->MoveMark (mark1); // start of "else" case 843 retbuf->MoveMark (mark1); // move mark1 at the end of the true case
828 retbuf->Merge (tb); 844 retbuf->Merge (tb); // perform third operand (false case)
829 retbuf->Write<word> (DH_GOTO); 845 retbuf->MoveMark (mark2); // move the ending mark2 here
830 retbuf->AddMarkReference (mark2);
831 retbuf->MoveMark (mark2); // move endmark to end
832 } else { 846 } else {
833 // Write to buffer 847 // Write to buffer
834 retbuf->Merge (rb); 848 retbuf->Merge (rb);
835 retbuf->Write<word> (DataHeaderByOperator (NULL, oper)); 849 retbuf->Write<word> (DataHeaderByOperator (NULL, oper));
836 } 850 }
1051 g_ScopeCursor++; 1065 g_ScopeCursor++;
1052 if (g_ScopeCursor >= MAX_SCOPE) 1066 if (g_ScopeCursor >= MAX_SCOPE)
1053 ParserError ("too deep scope"); 1067 ParserError ("too deep scope");
1054 1068
1055 ScopeInfo* info = &SCOPE(0); 1069 ScopeInfo* info = &SCOPE(0);
1056 info->type = 0; 1070 info->type = SCOPETYPE_UNKNOWN;
1057 info->mark1 = 0; 1071 info->mark1 = 0;
1058 info->mark2 = 0; 1072 info->mark2 = 0;
1059 info->buffer1 = NULL; 1073 info->buffer1 = NULL;
1060 info->casecursor = -1; 1074 info->casecursor = -1;
1061 for (int i = 0; i < MAX_CASE; i++) { 1075 for (int i = 0; i < MAX_CASE; i++) {

mercurial