parser.cxx

changeset 58
bc9317d1b9c9
parent 57
96f60ca748a0
child 59
891b9e6ee139
equal deleted inserted replaced
57:96f60ca748a0 58:bc9317d1b9c9
55 ParserError ("%s-statements may only be defined at top level!", token.chars()); 55 ParserError ("%s-statements may only be defined at top level!", token.chars());
56 56
57 #define MUST_NOT_TOPLEVEL if (g_CurMode == MODE_TOPLEVEL) \ 57 #define MUST_NOT_TOPLEVEL if (g_CurMode == MODE_TOPLEVEL) \
58 ParserError ("%s-statements may not be defined at top level!", token.chars()); 58 ParserError ("%s-statements may not be defined at top level!", token.chars());
59 59
60 #define SCOPE(n) blockstack[g_BlockStackCursor - n] 60 #define SCOPE(n) scopestack[g_ScopeCursor - n]
61 61
62 int g_NumStates = 0; 62 int g_NumStates = 0;
63 int g_NumEvents = 0; 63 int g_NumEvents = 0;
64 int g_CurMode = MODE_TOPLEVEL; 64 int g_CurMode = MODE_TOPLEVEL;
65 str g_CurState = ""; 65 str g_CurState = "";
66 bool g_stateSpawnDefined = false; 66 bool g_stateSpawnDefined = false;
67 bool g_GotMainLoop = false; 67 bool g_GotMainLoop = false;
68 unsigned int g_BlockStackCursor = 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 71
72 // ============================================================================ 72 // ============================================================================
73 // Main parser code. Begins read of the script file, checks the syntax of it 73 // 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 74 // 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. 75 // of necessary buffering so stuff is written in the correct order.
76 void ScriptReader::ParseBotScript (ObjWriter* w) { 76 void ScriptReader::ParseBotScript (ObjWriter* w) {
77 // Zero the entire block stack first 77 // Zero the entire block stack first
78 for (int i = 0; i < MAX_STRUCTSTACK; i++) 78 for (int i = 0; i < MAX_STRUCTSTACK; i++)
79 memset (&blockstack[i], 0, sizeof (BlockInformation)); 79 memset (&scopestack[i], 0, sizeof (BlockInformation));
80 80
81 while (Next()) { 81 while (Next()) {
82 // Check if else is potentically valid 82 // Check if else is potentically valid
83 if (!token.compare ("else") && !g_CanElse) 83 if (!token.compare ("else") && !g_CanElse)
84 ParserError ("else without preceding if"); 84 ParserError ("else without preceding if");
212 212
213 // ============================================================ 213 // ============================================================
214 // If 214 // If
215 if (!token.compare ("if")) { 215 if (!token.compare ("if")) {
216 MUST_NOT_TOPLEVEL 216 MUST_NOT_TOPLEVEL
217 PushBlockStack (); 217 PushScope ();
218 218
219 // Condition 219 // Condition
220 MustNext ("("); 220 MustNext ("(");
221 221
222 // Read the expression and write it. 222 // Read the expression and write it.
230 // Add a mark - to here temporarily - and add a reference to it. 230 // Add a mark - to here temporarily - and add a reference to it.
231 // Upon a closing brace, the mark will be adjusted. 231 // Upon a closing brace, the mark will be adjusted.
232 unsigned int marknum = w->AddMark (""); 232 unsigned int marknum = w->AddMark ("");
233 233
234 // Use DH_IFNOTGOTO - if the expression is not true, we goto the mark 234 // Use DH_IFNOTGOTO - if the expression is not true, we goto the mark
235 // we just defined - and this mark will be at the end of the block. 235 // we just defined - and this mark will be at the end of the scope block.
236 w->Write<word> (DH_IFNOTGOTO); 236 w->Write<word> (DH_IFNOTGOTO);
237 w->AddReference (marknum); 237 w->AddReference (marknum);
238 238
239 // Store it in the block stack 239 // Store it
240 SCOPE(0).mark1 = marknum; 240 SCOPE(0).mark1 = marknum;
241 SCOPE(0).type = BLOCKTYPE_IF; 241 SCOPE(0).type = SCOPETYPE_IF;
242 continue; 242 continue;
243 } 243 }
244 244
245 if (!token.compare ("else")) { 245 if (!token.compare ("else")) {
246 MUST_NOT_TOPLEVEL 246 MUST_NOT_TOPLEVEL
247 MustNext ("{"); 247 MustNext ("{");
248 248
249 // Don't use PushBlockStack as that will reset the scope. 249 // Don't use PushScope that will reset the scope.
250 g_BlockStackCursor++; 250 g_ScopeCursor++;
251 if (g_BlockStackCursor >= MAX_STRUCTSTACK) 251 if (g_ScopeCursor >= MAX_STRUCTSTACK)
252 ParserError ("too deep scope"); 252 ParserError ("too deep scope");
253 253
254 if (SCOPE(0).type != BLOCKTYPE_IF) 254 if (SCOPE(0).type != SCOPETYPE_IF)
255 ParserError ("else without preceding if"); 255 ParserError ("else without preceding if");
256 256
257 // Write down to jump to the end of the else statement 257 // Write down to jump to the end of the else statement
258 // Otherwise we have fall-throughs 258 // Otherwise we have fall-throughs
259 SCOPE(0).mark2 = w->AddMark (""); 259 SCOPE(0).mark2 = w->AddMark ("");
262 w->Write (DH_GOTO); 262 w->Write (DH_GOTO);
263 w->AddReference (SCOPE(0).mark2); 263 w->AddReference (SCOPE(0).mark2);
264 264
265 // Move the ifnot mark here and set type to else 265 // Move the ifnot mark here and set type to else
266 w->MoveMark (SCOPE(0).mark1); 266 w->MoveMark (SCOPE(0).mark1);
267 SCOPE(0).type = BLOCKTYPE_ELSE; 267 SCOPE(0).type = SCOPETYPE_ELSE;
268 continue; 268 continue;
269 } 269 }
270 270
271 // ============================================================ 271 // ============================================================
272 // While 272 // While
273 if (!token.compare ("while")) { 273 if (!token.compare ("while")) {
274 MUST_NOT_TOPLEVEL 274 MUST_NOT_TOPLEVEL
275 PushBlockStack (); 275 PushScope ();
276 276
277 // While loops need two marks - one at the start of the loop and one at the 277 // While loops need two marks - one at the start of the loop and one at the
278 // end. The condition is checked at the very start of the loop, if it fails, 278 // end. The condition is checked at the very start of the loop, if it fails,
279 // we use goto to skip to the end of the loop. At the end, we loop back to 279 // we use goto to skip to the end of the loop. At the end, we loop back to
280 // the beginning with a go-to statement. 280 // the beginning with a go-to statement.
296 w->AddReference (mark2); 296 w->AddReference (mark2);
297 297
298 // Store the needed stuff 298 // Store the needed stuff
299 SCOPE(0).mark1 = mark1; 299 SCOPE(0).mark1 = mark1;
300 SCOPE(0).mark2 = mark2; 300 SCOPE(0).mark2 = mark2;
301 SCOPE(0).type = BLOCKTYPE_WHILE; 301 SCOPE(0).type = SCOPETYPE_WHILE;
302 continue; 302 continue;
303 } 303 }
304 304
305 // ============================================================ 305 // ============================================================
306 // For loop 306 // For loop
307 if (!token.compare ("for")) { 307 if (!token.compare ("for")) {
308 MUST_NOT_TOPLEVEL 308 MUST_NOT_TOPLEVEL
309 PushBlockStack (); 309 PushScope ();
310 310
311 // Initializer 311 // Initializer
312 MustNext ("("); 312 MustNext ("(");
313 MustNext (); 313 MustNext ();
314 DataBuffer* init = ParseStatement (w); 314 DataBuffer* init = ParseStatement (w);
339 339
340 // Store the marks and incrementor 340 // Store the marks and incrementor
341 SCOPE(0).mark1 = mark1; 341 SCOPE(0).mark1 = mark1;
342 SCOPE(0).mark2 = mark2; 342 SCOPE(0).mark2 = mark2;
343 SCOPE(0).buffer1 = incr; 343 SCOPE(0).buffer1 = incr;
344 SCOPE(0).type = BLOCKTYPE_FOR; 344 SCOPE(0).type = SCOPETYPE_FOR;
345 continue; 345 continue;
346 } 346 }
347 347
348 // ============================================================ 348 // ============================================================
349 // Do/while loop 349 // Do/while loop
350 if (!token.compare ("do")) { 350 if (!token.compare ("do")) {
351 MUST_NOT_TOPLEVEL 351 MUST_NOT_TOPLEVEL
352 PushBlockStack (); 352 PushScope ();
353 MustNext ("{"); 353 MustNext ("{");
354 SCOPE(0).mark1 = w->AddMark (""); 354 SCOPE(0).mark1 = w->AddMark ("");
355 SCOPE(0).type = BLOCKTYPE_DO; 355 SCOPE(0).type = SCOPETYPE_DO;
356 continue; 356 continue;
357 } 357 }
358 358
359 // ============================================================ 359 // ============================================================
360 // Switch 360 // Switch
371 * casemark3: ... 371 * casemark3: ...
372 * mark1: // end mark 372 * mark1: // end mark
373 */ 373 */
374 374
375 MUST_NOT_TOPLEVEL 375 MUST_NOT_TOPLEVEL
376 PushBlockStack (); 376 PushScope ();
377 MustNext ("("); 377 MustNext ("(");
378 MustNext (); 378 MustNext ();
379 w->WriteBuffer (ParseExpression (TYPE_INT)); 379 w->WriteBuffer (ParseExpression (TYPE_INT));
380 MustNext (")"); 380 MustNext (")");
381 MustNext ("{"); 381 MustNext ("{");
382 SCOPE(0).type = BLOCKTYPE_SWITCH; 382 SCOPE(0).type = SCOPETYPE_SWITCH;
383 SCOPE(0).mark1 = w->AddMark (""); // end mark 383 SCOPE(0).mark1 = w->AddMark (""); // end mark
384 SCOPE(0).buffer1 = NULL; // default header 384 SCOPE(0).buffer1 = NULL; // default header
385 continue; 385 continue;
386 } 386 }
387 387
388 // ============================================================ 388 // ============================================================
389 if (!token.compare ("case")) { 389 if (!token.compare ("case")) {
390 // case is only allowed inside switch 390 // case is only allowed inside switch
391 if (SCOPE(0).type != BLOCKTYPE_SWITCH) 391 if (SCOPE(0).type != SCOPETYPE_SWITCH)
392 ParserError ("case label outside switch"); 392 ParserError ("case label outside switch");
393 393
394 // Get the literal (Zandronum does not support expressions here) 394 // Get the literal (Zandronum does not support expressions here)
395 MustNumber (); 395 MustNumber ();
396 int num = atoi (token.chars ()); 396 int num = atoi (token.chars ());
415 SCOPE(0).casenumbers[SCOPE(0).casecursor] = num; 415 SCOPE(0).casenumbers[SCOPE(0).casecursor] = num;
416 continue; 416 continue;
417 } 417 }
418 418
419 if (!token.compare ("default")) { 419 if (!token.compare ("default")) {
420 if (SCOPE(0).type != BLOCKTYPE_SWITCH) 420 if (SCOPE(0).type != SCOPETYPE_SWITCH)
421 ParserError ("default label outside switch"); 421 ParserError ("default label outside switch");
422 422
423 if (SCOPE(0).buffer1) 423 if (SCOPE(0).buffer1)
424 ParserError ("multiple default labels in one switch"); 424 ParserError ("multiple default labels in one switch");
425 425
441 } 441 }
442 442
443 // ============================================================ 443 // ============================================================
444 // Break statement. 444 // Break statement.
445 if (!token.compare ("break")) { 445 if (!token.compare ("break")) {
446 if (!g_BlockStackCursor) 446 if (!g_ScopeCursor)
447 ParserError ("unexpected `break`"); 447 ParserError ("unexpected `break`");
448 448
449 w->Write<word> (DH_GOTO); 449 w->Write<word> (DH_GOTO);
450 450
451 // switch and if use mark1 for the closing point, 451 // switch and if use mark1 for the closing point,
452 // for and while use mark2. 452 // for and while use mark2.
453 switch (SCOPE(0).type) { 453 switch (SCOPE(0).type) {
454 case BLOCKTYPE_IF: 454 case SCOPETYPE_IF:
455 case BLOCKTYPE_SWITCH: 455 case SCOPETYPE_SWITCH:
456 w->AddReference (SCOPE(0).mark1); 456 w->AddReference (SCOPE(0).mark1);
457 break; 457 break;
458 case BLOCKTYPE_FOR: 458 case SCOPETYPE_FOR:
459 case BLOCKTYPE_WHILE: 459 case SCOPETYPE_WHILE:
460 w->AddReference (SCOPE(0).mark2); 460 w->AddReference (SCOPE(0).mark2);
461 break; 461 break;
462 default: 462 default:
463 ParserError ("unexpected `break`"); 463 ParserError ("unexpected `break`");
464 break; 464 break;
488 // ============================================================ 488 // ============================================================
489 if (!token.compare ("}")) { 489 if (!token.compare ("}")) {
490 // Closing brace 490 // Closing brace
491 491
492 // If we're in the block stack, we're descending down from it now 492 // If we're in the block stack, we're descending down from it now
493 if (g_BlockStackCursor > 0) { 493 if (g_ScopeCursor > 0) {
494 switch (SCOPE(0).type) { 494 switch (SCOPE(0).type) {
495 case BLOCKTYPE_IF: 495 case SCOPETYPE_IF:
496 // Adjust the closing mark. 496 // Adjust the closing mark.
497 w->MoveMark (SCOPE(0).mark1); 497 w->MoveMark (SCOPE(0).mark1);
498 498
499 // We're returning from if, thus else can be next 499 // We're returning from if, thus else can be next
500 g_CanElse = true; 500 g_CanElse = true;
501 break; 501 break;
502 case BLOCKTYPE_ELSE: 502 case SCOPETYPE_ELSE:
503 // else instead uses mark1 for itself (so if expression 503 // else instead uses mark1 for itself (so if expression
504 // fails, jump to else), mark2 means end of else 504 // fails, jump to else), mark2 means end of else
505 w->MoveMark (SCOPE(0).mark2); 505 w->MoveMark (SCOPE(0).mark2);
506 break; 506 break;
507 case BLOCKTYPE_FOR: 507 case SCOPETYPE_FOR:
508 // Write the incrementor at the end of the loop block 508 // Write the incrementor at the end of the loop block
509 w->WriteBuffer (SCOPE(0).buffer1); 509 w->WriteBuffer (SCOPE(0).buffer1);
510 // fall-thru 510 // fall-thru
511 case BLOCKTYPE_WHILE: 511 case SCOPETYPE_WHILE:
512 // Write down the instruction to go back to the start of the loop 512 // Write down the instruction to go back to the start of the loop
513 w->Write (DH_GOTO); 513 w->Write (DH_GOTO);
514 w->AddReference (SCOPE(0).mark1); 514 w->AddReference (SCOPE(0).mark1);
515 515
516 // Move the closing mark here since we're at the end of the while loop 516 // Move the closing mark here since we're at the end of the while loop
517 w->MoveMark (SCOPE(0).mark2); 517 w->MoveMark (SCOPE(0).mark2);
518 break; 518 break;
519 case BLOCKTYPE_DO: { 519 case SCOPETYPE_DO: {
520 MustNext ("while"); 520 MustNext ("while");
521 MustNext ("("); 521 MustNext ("(");
522 MustNext (); 522 MustNext ();
523 DataBuffer* expr = ParseExpression (TYPE_INT); 523 DataBuffer* expr = ParseExpression (TYPE_INT);
524 MustNext (")"); 524 MustNext (")");
528 w->WriteBuffer (expr); 528 w->WriteBuffer (expr);
529 w->Write<long> (DH_IFGOTO); 529 w->Write<long> (DH_IFGOTO);
530 w->AddReference (SCOPE(0).mark1); 530 w->AddReference (SCOPE(0).mark1);
531 break; 531 break;
532 } 532 }
533 case BLOCKTYPE_SWITCH: { 533 case SCOPETYPE_SWITCH: {
534 // Switch closes. Move down to the record buffer of 534 // Switch closes. Move down to the record buffer of
535 // the lower block. 535 // the lower block.
536 if (SCOPE(1).casecursor != -1) 536 if (SCOPE(1).casecursor != -1)
537 w->SwitchBuffer = SCOPE(1).casebuffers[SCOPE(1).casecursor]; 537 w->SwitchBuffer = SCOPE(1).casebuffers[SCOPE(1).casecursor];
538 else 538 else
563 w->MoveMark (SCOPE(0).mark1); 563 w->MoveMark (SCOPE(0).mark1);
564 } 564 }
565 } 565 }
566 566
567 // Descend down the stack 567 // Descend down the stack
568 g_BlockStackCursor--; 568 g_ScopeCursor--;
569 continue; 569 continue;
570 } 570 }
571 571
572 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT : 572 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT :
573 (g_CurMode == MODE_MAINLOOP) ? DH_ENDMAINLOOP : 573 (g_CurMode == MODE_MAINLOOP) ? DH_ENDMAINLOOP :
987 } 987 }
988 988
989 return retbuf; 989 return retbuf;
990 } 990 }
991 991
992 void ScriptReader::PushBlockStack () { 992 void ScriptReader::PushScope () {
993 g_BlockStackCursor++; 993 g_ScopeCursor++;
994 if (g_BlockStackCursor >= MAX_STRUCTSTACK) 994 if (g_ScopeCursor >= MAX_STRUCTSTACK)
995 ParserError ("too deep scope"); 995 ParserError ("too deep scope");
996 996
997 BlockInformation* info = &SCOPE(0); 997 BlockInformation* info = &SCOPE(0);
998 info->type = 0; 998 info->type = 0;
999 info->mark1 = 0; 999 info->mark1 = 0;

mercurial