src/Parser.cc

changeset 108
6409ece8297c
parent 107
55c2bcd8ed5c
child 110
7a7a53f1d51b
equal deleted inserted replaced
107:55c2bcd8ed5c 108:6409ece8297c
45 mOnEnterBuffer (new DataBuffer), 45 mOnEnterBuffer (new DataBuffer),
46 mMainLoopBuffer (new DataBuffer), 46 mMainLoopBuffer (new DataBuffer),
47 mLexer (new Lexer), 47 mLexer (new Lexer),
48 mNumStates (0), 48 mNumStates (0),
49 mNumEvents (0), 49 mNumEvents (0),
50 mCurrentMode (ETopLevelMode), 50 mCurrentMode (PARSERMODE_TopLevel),
51 mStateSpawnDefined (false), 51 mStateSpawnDefined (false),
52 mGotMainLoop (false), 52 mGotMainLoop (false),
53 mScopeCursor (-1), 53 mScopeCursor (-1),
54 mCanElse (false), 54 mCanElse (false),
55 mHighestGlobalVarIndex (0), 55 mHighestGlobalVarIndex (0),
64 64
65 // ============================================================================ 65 // ============================================================================
66 // 66 //
67 void BotscriptParser::CheckToplevel() 67 void BotscriptParser::CheckToplevel()
68 { 68 {
69 if (mCurrentMode != ETopLevelMode) 69 if (mCurrentMode != PARSERMODE_TopLevel)
70 Error ("%1-statements may only be defined at top level!", GetTokenString()); 70 Error ("%1-statements may only be defined at top level!", GetTokenString());
71 } 71 }
72 72
73 // ============================================================================ 73 // ============================================================================
74 // 74 //
75 void BotscriptParser::CheckNotToplevel() 75 void BotscriptParser::CheckNotToplevel()
76 { 76 {
77 if (mCurrentMode == ETopLevelMode) 77 if (mCurrentMode == PARSERMODE_TopLevel)
78 Error ("%1-statements must not be defined at top level!", GetTokenString()); 78 Error ("%1-statements must not be defined at top level!", GetTokenString());
79 } 79 }
80 80
81 // ============================================================================ 81 // ============================================================================
82 // 82 //
221 } 221 }
222 } 222 }
223 223
224 // =============================================================================== 224 // ===============================================================================
225 // Script file ended. Do some last checks and write the last things to main buffer 225 // Script file ended. Do some last checks and write the last things to main buffer
226 if (mCurrentMode != ETopLevelMode) 226 if (mCurrentMode != PARSERMODE_TopLevel)
227 Error ("script did not end at top level; a `}` is missing somewhere"); 227 Error ("script did not end at top level; a `}` is missing somewhere");
228 228
229 if (IsReadOnly() == false) 229 if (IsReadOnly() == false)
230 { 230 {
231 // stateSpawn must be defined! 231 // stateSpawn must be defined!
274 // write the previous state's onenter and 274 // write the previous state's onenter and
275 // mainloop buffers to file now 275 // mainloop buffers to file now
276 if (mCurrentState.IsEmpty() == false) 276 if (mCurrentState.IsEmpty() == false)
277 writeMemberBuffers(); 277 writeMemberBuffers();
278 278
279 buffer()->WriteDWord (dhStateName); 279 buffer()->WriteDWord (DH_StateName);
280 buffer()->WriteString (statename); 280 buffer()->WriteString (statename);
281 buffer()->WriteDWord (dhStateIndex); 281 buffer()->WriteDWord (DH_StateIndex);
282 buffer()->WriteDWord (mNumStates); 282 buffer()->WriteDWord (mNumStates);
283 283
284 mNumStates++; 284 mNumStates++;
285 mCurrentState = statename; 285 mCurrentState = statename;
286 mGotMainLoop = false; 286 mGotMainLoop = false;
297 297
298 if (e == null) 298 if (e == null)
299 Error ("bad event, got `%1`\n", GetTokenString()); 299 Error ("bad event, got `%1`\n", GetTokenString());
300 300
301 mLexer->MustGetNext (tkBraceStart); 301 mLexer->MustGetNext (tkBraceStart);
302 mCurrentMode = EEventMode; 302 mCurrentMode = PARSERMODE_Event;
303 buffer()->WriteDWord (dhEvent); 303 buffer()->WriteDWord (DH_Event);
304 buffer()->WriteDWord (e->number); 304 buffer()->WriteDWord (e->number);
305 mNumEvents++; 305 mNumEvents++;
306 } 306 }
307 307
308 // ============================================================================ 308 // ============================================================================
310 void BotscriptParser::ParseMainloop() 310 void BotscriptParser::ParseMainloop()
311 { 311 {
312 CheckToplevel(); 312 CheckToplevel();
313 mLexer->MustGetNext (tkBraceStart); 313 mLexer->MustGetNext (tkBraceStart);
314 314
315 mCurrentMode = EMainLoopMode; 315 mCurrentMode = PARSERMODE_MainLoop;
316 mMainLoopBuffer->WriteDWord (dhMainLoop); 316 mMainLoopBuffer->WriteDWord (DH_MainLoop);
317 } 317 }
318 318
319 // ============================================================================ 319 // ============================================================================
320 // 320 //
321 void BotscriptParser::ParseOnEnterExit() 321 void BotscriptParser::ParseOnEnterExit()
322 { 322 {
323 CheckToplevel(); 323 CheckToplevel();
324 bool onenter = (TokenIs (tkOnenter)); 324 bool onenter = (TokenIs (tkOnenter));
325 mLexer->MustGetNext (tkBraceStart); 325 mLexer->MustGetNext (tkBraceStart);
326 326
327 mCurrentMode = onenter ? EOnenterMode : EOnexitMode; 327 mCurrentMode = onenter ? PARSERMODE_Onenter : PARSERMODE_Onexit;
328 buffer()->WriteDWord (onenter ? dhOnEnter : dhOnExit); 328 buffer()->WriteDWord (onenter ? DH_OnEnter : DH_OnExit);
329 } 329 }
330 330
331 // ============================================================================ 331 // ============================================================================
332 // 332 //
333 void BotscriptParser::ParseVar() 333 void BotscriptParser::ParseVar()
336 var->origin = mLexer->DescribeCurrentPosition(); 336 var->origin = mLexer->DescribeCurrentPosition();
337 var->isarray = false; 337 var->isarray = false;
338 const bool isconst = mLexer->GetNext (tkConst); 338 const bool isconst = mLexer->GetNext (tkConst);
339 mLexer->MustGetAnyOf ({tkInt, tkStr, tkVoid}); 339 mLexer->MustGetAnyOf ({tkInt, tkStr, tkVoid});
340 340
341 EType vartype = (TokenIs (tkInt)) ? EIntType : 341 DataType vartype = (TokenIs (tkInt)) ? TYPE_Int :
342 (TokenIs (tkStr)) ? EStringType : 342 (TokenIs (tkStr)) ? TYPE_String :
343 EBoolType; 343 TYPE_Bool;
344 344
345 mLexer->MustGetNext (tkSymbol); 345 mLexer->MustGetNext (tkSymbol);
346 String name = GetTokenString(); 346 String name = GetTokenString();
347 347
348 if (mLexer->GetNext (tkBracketStart)) 348 if (mLexer->GetNext (tkBracketStart))
365 var->statename = ""; 365 var->statename = "";
366 var->type = vartype; 366 var->type = vartype;
367 367
368 if (isconst == false) 368 if (isconst == false)
369 { 369 {
370 var->writelevel = Variable::WRITE_Mutable; 370 var->writelevel = WRITE_Mutable;
371 } 371 }
372 else 372 else
373 { 373 {
374 mLexer->MustGetNext (tkAssign); 374 mLexer->MustGetNext (tkAssign);
375 Expression expr (this, mLexer, vartype); 375 Expression expr (this, mLexer, vartype);
376 376
377 // If the expression was constexpr, we know its value and thus 377 // If the expression was constexpr, we know its value and thus
378 // can store it in the variable. 378 // can store it in the variable.
379 if (expr.GetResult()->IsConstexpr()) 379 if (expr.GetResult()->IsConstexpr())
380 { 380 {
381 var->writelevel = Variable::WRITE_Constexpr; 381 var->writelevel = WRITE_Constexpr;
382 var->value = expr.GetResult()->GetValue(); 382 var->value = expr.GetResult()->GetValue();
383 } 383 }
384 else 384 else
385 { 385 {
386 // TODO: might need a VM-wise oninit for this... 386 // TODO: might need a VM-wise oninit for this...
389 } 389 }
390 390
391 // Assign an index for the variable if it is not constexpr. Constexpr 391 // Assign an index for the variable if it is not constexpr. Constexpr
392 // variables can simply be substituted out for their value when used 392 // variables can simply be substituted out for their value when used
393 // so they need no index. 393 // so they need no index.
394 if (var->writelevel != Variable::WRITE_Constexpr) 394 if (var->writelevel != WRITE_Constexpr)
395 { 395 {
396 bool isglobal = IsInGlobalState(); 396 bool isglobal = IsInGlobalState();
397 var->index = isglobal ? SCOPE(0).globalVarIndexBase++ : SCOPE(0).localVarIndexBase++; 397 var->index = isglobal ? SCOPE(0).globalVarIndexBase++ : SCOPE(0).localVarIndexBase++;
398 398
399 if ((isglobal == true && var->index >= gMaxGlobalVars) || 399 if ((isglobal == true && var->index >= gMaxGlobalVars) ||
434 undf.target = buffer()->AddMark (target); 434 undf.target = buffer()->AddMark (target);
435 mUndefinedLabels << undf; 435 mUndefinedLabels << undf;
436 } 436 }
437 437
438 // Add a reference to the mark. 438 // Add a reference to the mark.
439 buffer()->WriteDWord (dhGoto); 439 buffer()->WriteDWord (DH_Goto);
440 buffer()->AddReference (mark); 440 buffer()->AddReference (mark);
441 mLexer->MustGetNext (tkSemicolon); 441 mLexer->MustGetNext (tkSemicolon);
442 } 442 }
443 443
444 // ============================================================================ 444 // ============================================================================
450 450
451 // Condition 451 // Condition
452 mLexer->MustGetNext (tkParenStart); 452 mLexer->MustGetNext (tkParenStart);
453 453
454 // Read the expression and write it. 454 // Read the expression and write it.
455 DataBuffer* c = ParseExpression (EIntType); 455 DataBuffer* c = ParseExpression (TYPE_Int);
456 buffer()->MergeAndDestroy (c); 456 buffer()->MergeAndDestroy (c);
457 457
458 mLexer->MustGetNext (tkParenEnd); 458 mLexer->MustGetNext (tkParenEnd);
459 mLexer->MustGetNext (tkBraceStart); 459 mLexer->MustGetNext (tkBraceStart);
460 460
461 // Add a mark - to here temporarily - and add a reference to it. 461 // Add a mark - to here temporarily - and add a reference to it.
462 // Upon a closing brace, the mark will be adjusted. 462 // Upon a closing brace, the mark will be adjusted.
463 ByteMark* mark = buffer()->AddMark (""); 463 ByteMark* mark = buffer()->AddMark ("");
464 464
465 // Use dhIfNotGoto - if the expression is not true, we goto the mark 465 // Use DH_IfNotGoto - if the expression is not true, we goto the mark
466 // we just defined - and this mark will be at the end of the scope block. 466 // we just defined - and this mark will be at the end of the scope block.
467 buffer()->WriteDWord (dhIfNotGoto); 467 buffer()->WriteDWord (DH_IfNotGoto);
468 buffer()->AddReference (mark); 468 buffer()->AddReference (mark);
469 469
470 // Store it 470 // Store it
471 SCOPE (0).mark1 = mark; 471 SCOPE (0).mark1 = mark;
472 SCOPE (0).type = eIfScope; 472 SCOPE (0).type = SCOPE_If;
473 } 473 }
474 474
475 // ============================================================================ 475 // ============================================================================
476 // 476 //
477 void BotscriptParser::ParseElse() 477 void BotscriptParser::ParseElse()
478 { 478 {
479 CheckNotToplevel(); 479 CheckNotToplevel();
480 mLexer->MustGetNext (tkBraceStart); 480 mLexer->MustGetNext (tkBraceStart);
481 PushScope (eNoReset); 481 PushScope (eNoReset);
482 482
483 if (SCOPE (0).type != eIfScope) 483 if (SCOPE (0).type != SCOPE_If)
484 Error ("else without preceding if"); 484 Error ("else without preceding if");
485 485
486 // write down to jump to the end of the else statement 486 // write down to jump to the end of the else statement
487 // Otherwise we have fall-throughs 487 // Otherwise we have fall-throughs
488 SCOPE (0).mark2 = buffer()->AddMark (""); 488 SCOPE (0).mark2 = buffer()->AddMark ("");
489 489
490 // Instruction to jump to the end after if block is complete 490 // Instruction to jump to the end after if block is complete
491 buffer()->WriteDWord (dhGoto); 491 buffer()->WriteDWord (DH_Goto);
492 buffer()->AddReference (SCOPE (0).mark2); 492 buffer()->AddReference (SCOPE (0).mark2);
493 493
494 // Move the ifnot mark here and set type to else 494 // Move the ifnot mark here and set type to else
495 buffer()->AdjustMark (SCOPE (0).mark1); 495 buffer()->AdjustMark (SCOPE (0).mark1);
496 SCOPE (0).type = eElseScope; 496 SCOPE (0).type = SCOPE_Else;
497 } 497 }
498 498
499 // ============================================================================ 499 // ============================================================================
500 // 500 //
501 void BotscriptParser::ParseWhileBlock() 501 void BotscriptParser::ParseWhileBlock()
510 ByteMark* mark1 = buffer()->AddMark (""); // start 510 ByteMark* mark1 = buffer()->AddMark (""); // start
511 ByteMark* mark2 = buffer()->AddMark (""); // end 511 ByteMark* mark2 = buffer()->AddMark (""); // end
512 512
513 // Condition 513 // Condition
514 mLexer->MustGetNext (tkParenStart); 514 mLexer->MustGetNext (tkParenStart);
515 DataBuffer* expr = ParseExpression (EIntType); 515 DataBuffer* expr = ParseExpression (TYPE_Int);
516 mLexer->MustGetNext (tkParenEnd); 516 mLexer->MustGetNext (tkParenEnd);
517 mLexer->MustGetNext (tkBraceStart); 517 mLexer->MustGetNext (tkBraceStart);
518 518
519 // write condition 519 // write condition
520 buffer()->MergeAndDestroy (expr); 520 buffer()->MergeAndDestroy (expr);
521 521
522 // Instruction to go to the end if it fails 522 // Instruction to go to the end if it fails
523 buffer()->WriteDWord (dhIfNotGoto); 523 buffer()->WriteDWord (DH_IfNotGoto);
524 buffer()->AddReference (mark2); 524 buffer()->AddReference (mark2);
525 525
526 // Store the needed stuff 526 // Store the needed stuff
527 SCOPE (0).mark1 = mark1; 527 SCOPE (0).mark1 = mark1;
528 SCOPE (0).mark2 = mark2; 528 SCOPE (0).mark2 = mark2;
529 SCOPE (0).type = eWhileScope; 529 SCOPE (0).type = SCOPE_While;
530 } 530 }
531 531
532 // ============================================================================ 532 // ============================================================================
533 // 533 //
534 void BotscriptParser::ParseForBlock() 534 void BotscriptParser::ParseForBlock()
544 Error ("bad statement for initializer of for"); 544 Error ("bad statement for initializer of for");
545 545
546 mLexer->MustGetNext (tkSemicolon); 546 mLexer->MustGetNext (tkSemicolon);
547 547
548 // Condition 548 // Condition
549 DataBuffer* cond = ParseExpression (EIntType); 549 DataBuffer* cond = ParseExpression (TYPE_Int);
550 550
551 if (cond == null) 551 if (cond == null)
552 Error ("bad statement for condition of for"); 552 Error ("bad statement for condition of for");
553 553
554 mLexer->MustGetNext (tkSemicolon); 554 mLexer->MustGetNext (tkSemicolon);
569 ByteMark* mark1 = buffer()->AddMark (""); 569 ByteMark* mark1 = buffer()->AddMark ("");
570 ByteMark* mark2 = buffer()->AddMark (""); 570 ByteMark* mark2 = buffer()->AddMark ("");
571 571
572 // Add the condition 572 // Add the condition
573 buffer()->MergeAndDestroy (cond); 573 buffer()->MergeAndDestroy (cond);
574 buffer()->WriteDWord (dhIfNotGoto); 574 buffer()->WriteDWord (DH_IfNotGoto);
575 buffer()->AddReference (mark2); 575 buffer()->AddReference (mark2);
576 576
577 // Store the marks and incrementor 577 // Store the marks and incrementor
578 SCOPE (0).mark1 = mark1; 578 SCOPE (0).mark1 = mark1;
579 SCOPE (0).mark2 = mark2; 579 SCOPE (0).mark2 = mark2;
580 SCOPE (0).buffer1 = incr; 580 SCOPE (0).buffer1 = incr;
581 SCOPE (0).type = eForScope; 581 SCOPE (0).type = SCOPE_For;
582 } 582 }
583 583
584 // ============================================================================ 584 // ============================================================================
585 // 585 //
586 void BotscriptParser::ParseDoBlock() 586 void BotscriptParser::ParseDoBlock()
587 { 587 {
588 CheckNotToplevel(); 588 CheckNotToplevel();
589 PushScope(); 589 PushScope();
590 mLexer->MustGetNext (tkBraceStart); 590 mLexer->MustGetNext (tkBraceStart);
591 SCOPE (0).mark1 = buffer()->AddMark (""); 591 SCOPE (0).mark1 = buffer()->AddMark ("");
592 SCOPE (0).type = eDoScope; 592 SCOPE (0).type = SCOPE_Do;
593 } 593 }
594 594
595 // ============================================================================ 595 // ============================================================================
596 // 596 //
597 void BotscriptParser::ParseSwitchBlock() 597 void BotscriptParser::ParseSwitchBlock()
610 // mark1: // end mark 610 // mark1: // end mark
611 611
612 CheckNotToplevel(); 612 CheckNotToplevel();
613 PushScope(); 613 PushScope();
614 mLexer->MustGetNext (tkParenStart); 614 mLexer->MustGetNext (tkParenStart);
615 buffer()->MergeAndDestroy (ParseExpression (EIntType)); 615 buffer()->MergeAndDestroy (ParseExpression (TYPE_Int));
616 mLexer->MustGetNext (tkParenEnd); 616 mLexer->MustGetNext (tkParenEnd);
617 mLexer->MustGetNext (tkBraceStart); 617 mLexer->MustGetNext (tkBraceStart);
618 SCOPE (0).type = eSwitchScope; 618 SCOPE (0).type = SCOPE_Switch;
619 SCOPE (0).mark1 = buffer()->AddMark (""); // end mark 619 SCOPE (0).mark1 = buffer()->AddMark (""); // end mark
620 SCOPE (0).buffer1 = null; // default header 620 SCOPE (0).buffer1 = null; // default header
621 } 621 }
622 622
623 // ============================================================================ 623 // ============================================================================
624 // 624 //
625 void BotscriptParser::ParseSwitchCase() 625 void BotscriptParser::ParseSwitchCase()
626 { 626 {
627 // case is only allowed inside switch 627 // case is only allowed inside switch
628 if (SCOPE (0).type != eSwitchScope) 628 if (SCOPE (0).type != SCOPE_Switch)
629 Error ("case label outside switch"); 629 Error ("case label outside switch");
630 630
631 // Get a literal value for the case block. Zandronum does not support 631 // Get a literal value for the case block. Zandronum does not support
632 // expressions here. 632 // expressions here.
633 mLexer->MustGetNext (tkNumber); 633 mLexer->MustGetNext (tkNumber);
647 // of buffering setup and stuff like that. 647 // of buffering setup and stuff like that.
648 // 648 //
649 // We null the switch buffer for the case-go-to statement as 649 // We null the switch buffer for the case-go-to statement as
650 // we want it all under the switch, not into the case-buffers. 650 // we want it all under the switch, not into the case-buffers.
651 mSwitchBuffer = null; 651 mSwitchBuffer = null;
652 buffer()->WriteDWord (dhCaseGoto); 652 buffer()->WriteDWord (DH_CaseGoto);
653 buffer()->WriteDWord (num); 653 buffer()->WriteDWord (num);
654 AddSwitchCase (null); 654 AddSwitchCase (null);
655 SCOPE (0).casecursor->number = num; 655 SCOPE (0).casecursor->number = num;
656 } 656 }
657 657
658 // ============================================================================ 658 // ============================================================================
659 // 659 //
660 void BotscriptParser::ParseSwitchDefault() 660 void BotscriptParser::ParseSwitchDefault()
661 { 661 {
662 if (SCOPE (0).type != eSwitchScope) 662 if (SCOPE (0).type != SCOPE_Switch)
663 Error ("default label outside switch"); 663 Error ("default label outside switch");
664 664
665 if (SCOPE (0).buffer1 != null) 665 if (SCOPE (0).buffer1 != null)
666 Error ("multiple default labels in one switch"); 666 Error ("multiple default labels in one switch");
667 667
670 // The default header is buffered into buffer1, since 670 // The default header is buffered into buffer1, since
671 // it has to be the last of the case headers 671 // it has to be the last of the case headers
672 // 672 //
673 // Since the expression is pushed into the switch 673 // Since the expression is pushed into the switch
674 // and is only popped when case succeeds, we have 674 // and is only popped when case succeeds, we have
675 // to pop it with dhDrop manually if we end up in 675 // to pop it with DH_Drop manually if we end up in
676 // a default. 676 // a default.
677 DataBuffer* buf = new DataBuffer; 677 DataBuffer* buf = new DataBuffer;
678 SCOPE (0).buffer1 = buf; 678 SCOPE (0).buffer1 = buf;
679 buf->WriteDWord (dhDrop); 679 buf->WriteDWord (DH_Drop);
680 buf->WriteDWord (dhGoto); 680 buf->WriteDWord (DH_Goto);
681 AddSwitchCase (buf); 681 AddSwitchCase (buf);
682 } 682 }
683 683
684 // ============================================================================ 684 // ============================================================================
685 // 685 //
686 void BotscriptParser::ParseBreak() 686 void BotscriptParser::ParseBreak()
687 { 687 {
688 if (mScopeCursor == 0) 688 if (mScopeCursor == 0)
689 Error ("unexpected `break`"); 689 Error ("unexpected `break`");
690 690
691 buffer()->WriteDWord (dhGoto); 691 buffer()->WriteDWord (DH_Goto);
692 692
693 // switch and if use mark1 for the closing point, 693 // switch and if use mark1 for the closing point,
694 // for and while use mark2. 694 // for and while use mark2.
695 switch (SCOPE (0).type) 695 switch (SCOPE (0).type)
696 { 696 {
697 case eIfScope: 697 case SCOPE_If:
698 case eSwitchScope: 698 case SCOPE_Switch:
699 { 699 {
700 buffer()->AddReference (SCOPE (0).mark1); 700 buffer()->AddReference (SCOPE (0).mark1);
701 } break; 701 } break;
702 702
703 case eForScope: 703 case SCOPE_For:
704 case eWhileScope: 704 case SCOPE_While:
705 { 705 {
706 buffer()->AddReference (SCOPE (0).mark2); 706 buffer()->AddReference (SCOPE (0).mark2);
707 } break; 707 } break;
708 708
709 default: 709 default:
727 // Fall through the scope until we find a loop block 727 // Fall through the scope until we find a loop block
728 for (curs = mScopeCursor; curs > 0 && !found; curs--) 728 for (curs = mScopeCursor; curs > 0 && !found; curs--)
729 { 729 {
730 switch (mScopeStack[curs].type) 730 switch (mScopeStack[curs].type)
731 { 731 {
732 case eForScope: 732 case SCOPE_For:
733 case eWhileScope: 733 case SCOPE_While:
734 case eDoScope: 734 case SCOPE_Do:
735 { 735 {
736 buffer()->WriteDWord (dhGoto); 736 buffer()->WriteDWord (DH_Goto);
737 buffer()->AddReference (mScopeStack[curs].mark1); 737 buffer()->AddReference (mScopeStack[curs].mark1);
738 found = true; 738 found = true;
739 } break; 739 } break;
740 740
741 default: 741 default:
756 // If we're in the block stack, we're descending down from it now 756 // If we're in the block stack, we're descending down from it now
757 if (mScopeCursor > 0) 757 if (mScopeCursor > 0)
758 { 758 {
759 switch (SCOPE (0).type) 759 switch (SCOPE (0).type)
760 { 760 {
761 case eIfScope: 761 case SCOPE_If:
762 { 762 {
763 // Adjust the closing mark. 763 // Adjust the closing mark.
764 buffer()->AdjustMark (SCOPE (0).mark1); 764 buffer()->AdjustMark (SCOPE (0).mark1);
765 765
766 // We're returning from `if`, thus `else` follow 766 // We're returning from `if`, thus `else` follow
767 mCanElse = true; 767 mCanElse = true;
768 break; 768 break;
769 } 769 }
770 770
771 case eElseScope: 771 case SCOPE_Else:
772 { 772 {
773 // else instead uses mark1 for itself (so if expression 773 // else instead uses mark1 for itself (so if expression
774 // fails, jump to else), mark2 means end of else 774 // fails, jump to else), mark2 means end of else
775 buffer()->AdjustMark (SCOPE (0).mark2); 775 buffer()->AdjustMark (SCOPE (0).mark2);
776 break; 776 break;
777 } 777 }
778 778
779 case eForScope: 779 case SCOPE_For:
780 { // write the incrementor at the end of the loop block 780 { // write the incrementor at the end of the loop block
781 buffer()->MergeAndDestroy (SCOPE (0).buffer1); 781 buffer()->MergeAndDestroy (SCOPE (0).buffer1);
782 } 782 }
783 case eWhileScope: 783 case SCOPE_While:
784 { // write down the instruction to go back to the start of the loop 784 { // write down the instruction to go back to the start of the loop
785 buffer()->WriteDWord (dhGoto); 785 buffer()->WriteDWord (DH_Goto);
786 buffer()->AddReference (SCOPE (0).mark1); 786 buffer()->AddReference (SCOPE (0).mark1);
787 787
788 // Move the closing mark here since we're at the end of the while loop 788 // Move the closing mark here since we're at the end of the while loop
789 buffer()->AdjustMark (SCOPE (0).mark2); 789 buffer()->AdjustMark (SCOPE (0).mark2);
790 break; 790 break;
791 } 791 }
792 792
793 case eDoScope: 793 case SCOPE_Do:
794 { 794 {
795 mLexer->MustGetNext (tkWhile); 795 mLexer->MustGetNext (tkWhile);
796 mLexer->MustGetNext (tkParenStart); 796 mLexer->MustGetNext (tkParenStart);
797 DataBuffer* expr = ParseExpression (EIntType); 797 DataBuffer* expr = ParseExpression (TYPE_Int);
798 mLexer->MustGetNext (tkParenEnd); 798 mLexer->MustGetNext (tkParenEnd);
799 mLexer->MustGetNext (tkSemicolon); 799 mLexer->MustGetNext (tkSemicolon);
800 800
801 // If the condition runs true, go back to the start. 801 // If the condition runs true, go back to the start.
802 buffer()->MergeAndDestroy (expr); 802 buffer()->MergeAndDestroy (expr);
803 buffer()->WriteDWord (dhIfGoto); 803 buffer()->WriteDWord (DH_IfGoto);
804 buffer()->AddReference (SCOPE (0).mark1); 804 buffer()->AddReference (SCOPE (0).mark1);
805 break; 805 break;
806 } 806 }
807 807
808 case eSwitchScope: 808 case SCOPE_Switch:
809 { 809 {
810 // Switch closes. Move down to the record buffer of 810 // Switch closes. Move down to the record buffer of
811 // the lower block. 811 // the lower block.
812 if (SCOPE (1).casecursor != SCOPE (1).cases.begin() - 1) 812 if (SCOPE (1).casecursor != SCOPE (1).cases.begin() - 1)
813 mSwitchBuffer = SCOPE (1).casecursor->data; 813 mSwitchBuffer = SCOPE (1).casecursor->data;
819 // the headers (thus won't fall-through if no case matched) 819 // the headers (thus won't fall-through if no case matched)
820 if (SCOPE (0).buffer1) 820 if (SCOPE (0).buffer1)
821 buffer()->MergeAndDestroy (SCOPE (0).buffer1); 821 buffer()->MergeAndDestroy (SCOPE (0).buffer1);
822 else 822 else
823 { 823 {
824 buffer()->WriteDWord (dhDrop); 824 buffer()->WriteDWord (DH_Drop);
825 buffer()->WriteDWord (dhGoto); 825 buffer()->WriteDWord (DH_Goto);
826 buffer()->AddReference (SCOPE (0).mark1); 826 buffer()->AddReference (SCOPE (0).mark1);
827 } 827 }
828 828
829 // Go through all of the buffers we 829 // Go through all of the buffers we
830 // recorded down and write them. 830 // recorded down and write them.
837 // Move the closing mark here 837 // Move the closing mark here
838 buffer()->AdjustMark (SCOPE (0).mark1); 838 buffer()->AdjustMark (SCOPE (0).mark1);
839 break; 839 break;
840 } 840 }
841 841
842 case eUnknownScope: 842 case SCOPE_Unknown:
843 break; 843 break;
844 } 844 }
845 845
846 // Descend down the stack 846 // Descend down the stack
847 mScopeCursor--; 847 mScopeCursor--;
848 return; 848 return;
849 } 849 }
850 850
851 int dataheader = (mCurrentMode == EEventMode) ? dhEndEvent : 851 int dataheader = (mCurrentMode == PARSERMODE_Event) ? DH_EndEvent :
852 (mCurrentMode == EMainLoopMode) ? dhEndMainLoop : 852 (mCurrentMode == PARSERMODE_MainLoop) ? DH_EndMainLoop :
853 (mCurrentMode == EOnenterMode) ? dhEndOnEnter : 853 (mCurrentMode == PARSERMODE_Onenter) ? DH_EndOnEnter :
854 (mCurrentMode == EOnexitMode) ? dhEndOnExit : -1; 854 (mCurrentMode == PARSERMODE_Onexit) ? DH_EndOnExit : -1;
855 855
856 if (dataheader == -1) 856 if (dataheader == -1)
857 Error ("unexpected `}`"); 857 Error ("unexpected `}`");
858 858
859 // Data header must be written before mode is changed because 859 // Data header must be written before mode is changed because
860 // onenter and mainloop go into special buffers, and we want 860 // onenter and mainloop go into special buffers, and we want
861 // the closing data headers into said buffers too. 861 // the closing data headers into said buffers too.
862 buffer()->WriteDWord (dataheader); 862 buffer()->WriteDWord (dataheader);
863 mCurrentMode = ETopLevelMode; 863 mCurrentMode = PARSERMODE_TopLevel;
864 mLexer->GetNext (tkSemicolon); 864 mLexer->GetNext (tkSemicolon);
865 } 865 }
866 866
867 // ============================================================================ 867 // ============================================================================
868 // 868 //
940 if (comm->args.IsEmpty() == false) 940 if (comm->args.IsEmpty() == false)
941 mLexer->MustGetNext (tkComma); 941 mLexer->MustGetNext (tkComma);
942 942
943 CommandArgument arg; 943 CommandArgument arg;
944 mLexer->MustGetAnyOf ({tkInt, tkBool, tkStr}); 944 mLexer->MustGetAnyOf ({tkInt, tkBool, tkStr});
945 EType type = GetTypeByName (mLexer->GetToken()->text); // TODO 945 DataType type = GetTypeByName (mLexer->GetToken()->text); // TODO
946 assert (type != -1 && type != EVoidType); 946 assert (type != -1 && type != TYPE_Void);
947 arg.type = type; 947 arg.type = type;
948 948
949 mLexer->MustGetNext (tkSymbol); 949 mLexer->MustGetNext (tkSymbol);
950 arg.name = mLexer->GetToken()->text; 950 arg.name = mLexer->GetToken()->text;
951 951
954 { 954 {
955 mLexer->MustGetNext (tkAssign); 955 mLexer->MustGetNext (tkAssign);
956 956
957 switch (type) 957 switch (type)
958 { 958 {
959 case EIntType: 959 case TYPE_Int:
960 case EBoolType: 960 case TYPE_Bool:
961 mLexer->MustGetNext (tkNumber); 961 mLexer->MustGetNext (tkNumber);
962 break; 962 break;
963 963
964 case EStringType: 964 case TYPE_String:
965 Error ("string arguments cannot have default values"); 965 Error ("string arguments cannot have default values");
966 966
967 case EUnknownType: 967 case TYPE_Unknown:
968 case EVoidType: 968 case TYPE_Void:
969 break; 969 break;
970 } 970 }
971 971
972 arg.defvalue = mLexer->GetToken()->text.ToLong(); 972 arg.defvalue = mLexer->GetToken()->text.ToLong();
973 } 973 }
986 // Parses a command call 986 // Parses a command call
987 DataBuffer* BotscriptParser::ParseCommand (CommandInfo* comm) 987 DataBuffer* BotscriptParser::ParseCommand (CommandInfo* comm)
988 { 988 {
989 DataBuffer* r = new DataBuffer (64); 989 DataBuffer* r = new DataBuffer (64);
990 990
991 if (mCurrentMode == ETopLevelMode && comm->returnvalue == EVoidType) 991 if (mCurrentMode == PARSERMODE_TopLevel && comm->returnvalue == TYPE_Void)
992 Error ("command call at top level"); 992 Error ("command call at top level");
993 993
994 mLexer->MustGetNext (tkParenStart); 994 mLexer->MustGetNext (tkParenStart);
995 mLexer->MustGetNext (tkAny); 995 mLexer->MustGetNext (tkAny);
996 996
1038 } 1038 }
1039 1039
1040 // If the script skipped any optional arguments, fill in defaults. 1040 // If the script skipped any optional arguments, fill in defaults.
1041 while (curarg < comm->args.Size()) 1041 while (curarg < comm->args.Size())
1042 { 1042 {
1043 r->WriteDWord (dhPushNumber); 1043 r->WriteDWord (DH_PushNumber);
1044 r->WriteDWord (comm->args[curarg].defvalue); 1044 r->WriteDWord (comm->args[curarg].defvalue);
1045 curarg++; 1045 curarg++;
1046 } 1046 }
1047 1047
1048 r->WriteDWord (dhCommand); 1048 r->WriteDWord (DH_Command);
1049 r->WriteDWord (comm->number); 1049 r->WriteDWord (comm->number);
1050 r->WriteDWord (comm->args.Size()); 1050 r->WriteDWord (comm->args.Size());
1051 1051
1052 return r; 1052 return r;
1053 } 1053 }
1074 1074
1075 // ============================================================================ 1075 // ============================================================================
1076 // 1076 //
1077 // Parses an assignment operator. 1077 // Parses an assignment operator.
1078 // 1078 //
1079 EAssignmentOperator BotscriptParser::ParseAssignmentOperator() 1079 AssignmentOperator BotscriptParser::ParseAssignmentOperator()
1080 { 1080 {
1081 const List<EToken> tokens = 1081 const List<EToken> tokens =
1082 { 1082 {
1083 tkAssign, 1083 tkAssign,
1084 tkAddAssign, 1084 tkAddAssign,
1092 1092
1093 mLexer->MustGetAnyOf (tokens); 1093 mLexer->MustGetAnyOf (tokens);
1094 1094
1095 switch (mLexer->GetTokenType()) 1095 switch (mLexer->GetTokenType())
1096 { 1096 {
1097 case tkAssign: return EAssign; 1097 case tkAssign: return ASSIGNOP_Assign;
1098 case tkAddAssign: return EAssignAdd; 1098 case tkAddAssign: return ASSIGNOP_Add;
1099 case tkSubAssign: return EAssignSub; 1099 case tkSubAssign: return ASSIGNOP_Subtract;
1100 case tkMultiplyAssign: return EAssignMul; 1100 case tkMultiplyAssign: return ASSIGNOP_Multiply;
1101 case tkDivideAssign: return EAssignDiv; 1101 case tkDivideAssign: return ASSIGNOP_Divide;
1102 case tkModulusAssign: return EAssignMod; 1102 case tkModulusAssign: return ASSIGNOP_Modulus;
1103 case tkDoublePlus: return EAssignIncrement; 1103 case tkDoublePlus: return ASSIGNOP_Increase;
1104 case tkDoubleMinus: return EAssignDecrement; 1104 case tkDoubleMinus: return ASSIGNOP_Decrease;
1105 default: break; 1105 default: break;
1106 } 1106 }
1107 1107
1108 assert (false); 1108 assert (false);
1109 return (EAssignmentOperator) 0; 1109 return (AssignmentOperator) 0;
1110 } 1110 }
1111 1111
1112 // ============================================================================ 1112 // ============================================================================
1113 // 1113 //
1114 struct AssignmentDataHeaderInfo 1114 struct AssignmentDataHeaderInfo
1115 { 1115 {
1116 EAssignmentOperator op; 1116 AssignmentOperator op;
1117 EDataHeader local; 1117 DataHeader local;
1118 EDataHeader global; 1118 DataHeader global;
1119 EDataHeader array; 1119 DataHeader array;
1120 }; 1120 };
1121 1121
1122 const AssignmentDataHeaderInfo gAssignmentDataHeaders[] = 1122 const AssignmentDataHeaderInfo gAssignmentDataHeaders[] =
1123 { 1123 {
1124 { EAssign, dhAssignLocalVar, dhAssignGlobalVar, dhAssignGlobalArray }, 1124 { ASSIGNOP_Assign, DH_AssignLocalVar, DH_AssignGlobalVar, DH_AssignGlobalArray },
1125 { EAssignAdd, dhAddLocalVar, dhAddGlobalVar, dhAddGlobalArray }, 1125 { ASSIGNOP_Add, DH_AddLocalVar, DH_AddGlobalVar, DH_AddGlobalArray },
1126 { EAssignSub, dhSubtractLocalVar, dhSubtractGlobalVar, dhSubtractGlobalArray }, 1126 { ASSIGNOP_Subtract, DH_SubtractLocalVar, DH_SubtractGlobalVar, DH_SubtractGlobalArray },
1127 { EAssignMul, dhMultiplyLocalVar, dhMultiplyGlobalVar, dhMultiplyGlobalArray }, 1127 { ASSIGNOP_Multiply, DH_MultiplyLocalVar, DH_MultiplyGlobalVar, DH_MultiplyGlobalArray },
1128 { EAssignDiv, dhDivideLocalVar, dhDivideGlobalVar, dhDivideGlobalArray }, 1128 { ASSIGNOP_Divide, DH_DivideLocalVar, DH_DivideGlobalVar, DH_DivideGlobalArray },
1129 { EAssignMod, dhModLocalVar, dhModGlobalVar, dhModGlobalArray }, 1129 { ASSIGNOP_Modulus, DH_ModLocalVar, DH_ModGlobalVar, DH_ModGlobalArray },
1130 { EAssignIncrement, dhIncreaseLocalVar, dhIncreaseGlobalVar, dhIncreaseGlobalArray }, 1130 { ASSIGNOP_Increase, DH_IncreaseLocalVar, DH_IncreaseGlobalVar, DH_IncreaseGlobalArray },
1131 { EAssignDecrement, dhDecreaseLocalVar, dhDecreaseGlobalVar, dhDecreaseGlobalArray }, 1131 { ASSIGNOP_Decrease, DH_DecreaseLocalVar, DH_DecreaseGlobalVar, DH_DecreaseGlobalArray },
1132 }; 1132 };
1133 1133
1134 EDataHeader BotscriptParser::GetAssigmentDataHeader (EAssignmentOperator op, Variable* var) 1134 DataHeader BotscriptParser::GetAssigmentDataHeader (AssignmentOperator op, Variable* var)
1135 { 1135 {
1136 for (const auto& a : gAssignmentDataHeaders) 1136 for (const auto& a : gAssignmentDataHeaders)
1137 { 1137 {
1138 if (a.op != op) 1138 if (a.op != op)
1139 continue; 1139 continue;
1146 1146
1147 return a.local; 1147 return a.local;
1148 } 1148 }
1149 1149
1150 Error ("WTF: couldn't find data header for operator #%1", op); 1150 Error ("WTF: couldn't find data header for operator #%1", op);
1151 return (EDataHeader) 0; 1151 return (DataHeader) 0;
1152 } 1152 }
1153 1153
1154 // ============================================================================ 1154 // ============================================================================
1155 // 1155 //
1156 // Parses an assignment. An assignment starts with a variable name, followed 1156 // Parses an assignment. An assignment starts with a variable name, followed
1160 DataBuffer* BotscriptParser::ParseAssignment (Variable* var) 1160 DataBuffer* BotscriptParser::ParseAssignment (Variable* var)
1161 { 1161 {
1162 DataBuffer* retbuf = new DataBuffer; 1162 DataBuffer* retbuf = new DataBuffer;
1163 DataBuffer* arrayindex = null; 1163 DataBuffer* arrayindex = null;
1164 1164
1165 if (var->writelevel != Variable::WRITE_Mutable) 1165 if (var->writelevel != WRITE_Mutable)
1166 Error ("cannot alter read-only variable $%1", var->name); 1166 Error ("cannot alter read-only variable $%1", var->name);
1167 1167
1168 if (var->isarray) 1168 if (var->isarray)
1169 { 1169 {
1170 mLexer->MustGetNext (tkBracketStart); 1170 mLexer->MustGetNext (tkBracketStart);
1171 Expression expr (this, mLexer, EIntType); 1171 Expression expr (this, mLexer, TYPE_Int);
1172 expr.GetResult()->ConvertToBuffer(); 1172 expr.GetResult()->ConvertToBuffer();
1173 arrayindex = expr.GetResult()->GetBuffer()->Clone(); 1173 arrayindex = expr.GetResult()->GetBuffer()->Clone();
1174 mLexer->MustGetNext (tkBracketEnd); 1174 mLexer->MustGetNext (tkBracketEnd);
1175 } 1175 }
1176 1176
1177 // Get an operator 1177 // Get an operator
1178 EAssignmentOperator oper = ParseAssignmentOperator(); 1178 AssignmentOperator oper = ParseAssignmentOperator();
1179 1179
1180 if (mCurrentMode == ETopLevelMode) 1180 if (mCurrentMode == PARSERMODE_TopLevel)
1181 Error ("can't alter variables at top level"); 1181 Error ("can't alter variables at top level");
1182 1182
1183 // Parse the right operand 1183 // Parse the right operand
1184 if (oper != EAssignIncrement && oper != EAssignDecrement) 1184 if (oper != ASSIGNOP_Increase && oper != ASSIGNOP_Decrease)
1185 { 1185 {
1186 DataBuffer* expr = ParseExpression (var->type); 1186 DataBuffer* expr = ParseExpression (var->type);
1187 retbuf->MergeAndDestroy (expr); 1187 retbuf->MergeAndDestroy (expr);
1188 } 1188 }
1189 1189
1192 1192
1193 #if 0 1193 #if 0
1194 // <<= and >>= do not have data headers. Solution: expand them. 1194 // <<= and >>= do not have data headers. Solution: expand them.
1195 // a <<= b -> a = a << b 1195 // a <<= b -> a = a << b
1196 // a >>= b -> a = a >> b 1196 // a >>= b -> a = a >> b
1197 retbuf->WriteDWord (var->IsGlobal() ? dhPushGlobalVar : dhPushLocalVar); 1197 retbuf->WriteDWord (var->IsGlobal() ? DH_PushGlobalVar : DH_PushLocalVar);
1198 retbuf->WriteDWord (var->index); 1198 retbuf->WriteDWord (var->index);
1199 retbuf->MergeAndDestroy (expr); 1199 retbuf->MergeAndDestroy (expr);
1200 retbuf->WriteDWord ((oper == OPER_ASSIGNLEFTSHIFT) ? dhLeftShift : dhRightShift); 1200 retbuf->WriteDWord ((oper == OPER_ASSIGNLEFTSHIFT) ? DH_LeftShift : DH_RightShift);
1201 retbuf->WriteDWord (var->IsGlobal() ? dhAssignGlobalVar : dhAssignLocalVar); 1201 retbuf->WriteDWord (var->IsGlobal() ? DH_AssignGlobalVar : DH_AssignLocalVar);
1202 retbuf->WriteDWord (var->index); 1202 retbuf->WriteDWord (var->index);
1203 #endif 1203 #endif
1204 1204
1205 EDataHeader dh = GetAssigmentDataHeader (oper, var); 1205 DataHeader dh = GetAssigmentDataHeader (oper, var);
1206 retbuf->WriteDWord (dh); 1206 retbuf->WriteDWord (dh);
1207 retbuf->WriteDWord (var->index); 1207 retbuf->WriteDWord (var->index);
1208 return retbuf; 1208 return retbuf;
1209 } 1209 }
1210 1210
1216 1216
1217 if (mScopeStack.Size() < mScopeCursor + 1) 1217 if (mScopeStack.Size() < mScopeCursor + 1)
1218 { 1218 {
1219 ScopeInfo newscope; 1219 ScopeInfo newscope;
1220 mScopeStack << newscope; 1220 mScopeStack << newscope;
1221 reset = eResetScope; 1221 reset = SCOPE_Reset;
1222 } 1222 }
1223 1223
1224 if (reset == eResetScope) 1224 if (reset == SCOPE_Reset)
1225 { 1225 {
1226 ScopeInfo* info = &SCOPE (0); 1226 ScopeInfo* info = &SCOPE (0);
1227 info->type = eUnknownScope; 1227 info->type = SCOPE_Unknown;
1228 info->mark1 = null; 1228 info->mark1 = null;
1229 info->mark2 = null; 1229 info->mark2 = null;
1230 info->buffer1 = null; 1230 info->buffer1 = null;
1231 info->cases.Clear(); 1231 info->cases.Clear();
1232 info->casecursor = info->cases.begin() - 1; 1232 info->casecursor = info->cases.begin() - 1;
1243 SCOPE(0).globalVariables.Clear(); 1243 SCOPE(0).globalVariables.Clear();
1244 } 1244 }
1245 1245
1246 // ============================================================================ 1246 // ============================================================================
1247 // 1247 //
1248 DataBuffer* BotscriptParser::ParseExpression (EType reqtype, bool fromhere) 1248 DataBuffer* BotscriptParser::ParseExpression (DataType reqtype, bool fromhere)
1249 { 1249 {
1250 // hehe 1250 // hehe
1251 if (fromhere == true) 1251 if (fromhere == true)
1252 mLexer->Skip (-1); 1252 mLexer->Skip (-1);
1253 1253
1330 DataBuffer* BotscriptParser::buffer() 1330 DataBuffer* BotscriptParser::buffer()
1331 { 1331 {
1332 if (mSwitchBuffer != null) 1332 if (mSwitchBuffer != null)
1333 return mSwitchBuffer; 1333 return mSwitchBuffer;
1334 1334
1335 if (mCurrentMode == EMainLoopMode) 1335 if (mCurrentMode == PARSERMODE_MainLoop)
1336 return mMainLoopBuffer; 1336 return mMainLoopBuffer;
1337 1337
1338 if (mCurrentMode == EOnenterMode) 1338 if (mCurrentMode == PARSERMODE_Onenter)
1339 return mOnEnterBuffer; 1339 return mOnEnterBuffer;
1340 1340
1341 return mMainBuffer; 1341 return mMainBuffer;
1342 } 1342 }
1343 1343
1346 void BotscriptParser::writeMemberBuffers() 1346 void BotscriptParser::writeMemberBuffers()
1347 { 1347 {
1348 // If there was no mainloop defined, write a dummy one now. 1348 // If there was no mainloop defined, write a dummy one now.
1349 if (mGotMainLoop == false) 1349 if (mGotMainLoop == false)
1350 { 1350 {
1351 mMainLoopBuffer->WriteDWord (dhMainLoop); 1351 mMainLoopBuffer->WriteDWord (DH_MainLoop);
1352 mMainLoopBuffer->WriteDWord (dhEndMainLoop); 1352 mMainLoopBuffer->WriteDWord (DH_EndMainLoop);
1353 } 1353 }
1354 1354
1355 // Write the onenter and mainloop buffers, in that order in particular. 1355 // Write the onenter and mainloop buffers, in that order in particular.
1356 for (DataBuffer** bufp : List<DataBuffer**> ({&mOnEnterBuffer, &mMainLoopBuffer})) 1356 for (DataBuffer** bufp : List<DataBuffer**> ({&mOnEnterBuffer, &mMainLoopBuffer}))
1357 { 1357 {
1375 1375
1376 if (stringcount == 0) 1376 if (stringcount == 0)
1377 return; 1377 return;
1378 1378
1379 // Write header 1379 // Write header
1380 mMainBuffer->WriteDWord (dhStringList); 1380 mMainBuffer->WriteDWord (DH_StringList);
1381 mMainBuffer->WriteDWord (stringcount); 1381 mMainBuffer->WriteDWord (stringcount);
1382 1382
1383 // Write all strings 1383 // Write all strings
1384 for (int i = 0; i < stringcount; i++) 1384 for (int i = 0; i < stringcount; i++)
1385 mMainBuffer->WriteString (GetStringTable()[i]); 1385 mMainBuffer->WriteString (GetStringTable()[i]);

mercurial