| 80 mOnEnterBuffer = new DataBuffer; |
80 mOnEnterBuffer = new DataBuffer; |
| 81 mMainLoopBuffer = new DataBuffer; |
81 mMainLoopBuffer = new DataBuffer; |
| 82 mCurrentMode = ETopLevelMode; |
82 mCurrentMode = ETopLevelMode; |
| 83 mNumStates = 0; |
83 mNumStates = 0; |
| 84 mNumEvents = 0; |
84 mNumEvents = 0; |
| 85 mScopeCursor = 0; |
85 mScopeCursor = -1; |
| 86 mStateSpawnDefined = false; |
86 mStateSpawnDefined = false; |
| 87 mGotMainLoop = false; |
87 mGotMainLoop = false; |
| 88 mIfExpression = null; |
88 mIfExpression = null; |
| 89 mCanElse = false; |
89 mCanElse = false; |
| 90 |
90 PushScope(); |
| 91 // Zero the entire block stack first |
|
| 92 // TODO: this shouldn't be necessary |
|
| 93 for (int i = 0; i < MAX_SCOPE; i++) |
|
| 94 ZERO (mScopeStack[i]); |
|
| 95 |
91 |
| 96 while (mLexer->GetNext()) |
92 while (mLexer->GetNext()) |
| 97 { |
93 { |
| 98 // Check if else is potentically valid |
94 // Check if else is potentically valid |
| 99 if (TokenIs (tkElse) && mCanElse == false) |
95 if (TokenIs (tkElse) && mCanElse == false) |
| 417 // |
413 // |
| 418 void BotscriptParser::ParseElse() |
414 void BotscriptParser::ParseElse() |
| 419 { |
415 { |
| 420 CheckNotToplevel(); |
416 CheckNotToplevel(); |
| 421 mLexer->MustGetNext (tkBraceStart); |
417 mLexer->MustGetNext (tkBraceStart); |
| 422 |
418 PushScope (eNoReset); |
| 423 // Don't use PushScope as it resets the scope |
|
| 424 mScopeCursor++; |
|
| 425 |
|
| 426 if (mScopeCursor >= MAX_SCOPE) |
|
| 427 Error ("too deep scope"); |
|
| 428 |
419 |
| 429 if (SCOPE (0).type != eIfScope) |
420 if (SCOPE (0).type != eIfScope) |
| 430 Error ("else without preceding if"); |
421 Error ("else without preceding if"); |
| 431 |
422 |
| 432 // write down to jump to the end of the else statement |
423 // write down to jump to the end of the else statement |
| 574 { |
565 { |
| 575 // case is only allowed inside switch |
566 // case is only allowed inside switch |
| 576 if (SCOPE (0).type != eSwitchScope) |
567 if (SCOPE (0).type != eSwitchScope) |
| 577 Error ("case label outside switch"); |
568 Error ("case label outside switch"); |
| 578 |
569 |
| 579 // Get the literal (Zandronum does not support expressions here) |
570 // Get a literal value for the case block. Zandronum does not support |
| |
571 // expressions here. |
| 580 mLexer->MustGetNext (tkNumber); |
572 mLexer->MustGetNext (tkNumber); |
| 581 int num = mLexer->GetToken()->text.ToLong(); |
573 int num = mLexer->GetToken()->text.ToLong(); |
| 582 mLexer->MustGetNext (tkColon); |
574 mLexer->MustGetNext (tkColon); |
| 583 |
575 |
| 584 for (int i = 0; i < MAX_CASE; i++) |
576 for (const CaseInfo& info : SCOPE(0).cases) |
| 585 if (SCOPE (0).casenumbers[i] == num) |
577 if (info.number == num) |
| 586 Error ("multiple case %d labels in one switch", num); |
578 Error ("multiple case %1 labels in one switch", num); |
| 587 |
579 |
| 588 // Write down the expression and case-go-to. This builds |
580 // Write down the expression and case-go-to. This builds |
| 589 // the case tree. The closing event will write the actual |
581 // the case tree. The closing event will write the actual |
| 590 // blocks and move the marks appropriately. |
582 // blocks and move the marks appropriately. |
| 591 // |
583 // |
| 597 // we want it all under the switch, not into the case-buffers. |
589 // we want it all under the switch, not into the case-buffers. |
| 598 mSwitchBuffer = null; |
590 mSwitchBuffer = null; |
| 599 buffer()->WriteDWord (dhCaseGoto); |
591 buffer()->WriteDWord (dhCaseGoto); |
| 600 buffer()->WriteDWord (num); |
592 buffer()->WriteDWord (num); |
| 601 AddSwitchCase (null); |
593 AddSwitchCase (null); |
| 602 SCOPE (0).casenumbers[SCOPE (0).casecursor] = num; |
594 SCOPE (0).casecursor->number = num; |
| 603 } |
595 } |
| 604 |
596 |
| 605 // ============================================================================ |
597 // ============================================================================ |
| 606 // |
598 // |
| 607 void BotscriptParser::ParseSwitchDefault() |
599 void BotscriptParser::ParseSwitchDefault() |
| 608 { |
600 { |
| 609 if (SCOPE (0).type != eSwitchScope) |
601 if (SCOPE (0).type != eSwitchScope) |
| 610 Error ("default label outside switch"); |
602 Error ("default label outside switch"); |
| 611 |
603 |
| 612 if (SCOPE (0).buffer1) |
604 if (SCOPE (0).buffer1 != null) |
| 613 Error ("multiple default labels in one switch"); |
605 Error ("multiple default labels in one switch"); |
| 614 |
606 |
| 615 mLexer->MustGetNext (tkColon); |
607 mLexer->MustGetNext (tkColon); |
| 616 |
608 |
| 617 // The default header is buffered into buffer1, since |
609 // The default header is buffered into buffer1, since |
| 619 // |
611 // |
| 620 // Since the expression is pushed into the switch |
612 // Since the expression is pushed into the switch |
| 621 // and is only popped when case succeeds, we have |
613 // and is only popped when case succeeds, we have |
| 622 // to pop it with dhDrop manually if we end up in |
614 // to pop it with dhDrop manually if we end up in |
| 623 // a default. |
615 // a default. |
| 624 DataBuffer* b = new DataBuffer; |
616 DataBuffer* buf = new DataBuffer; |
| 625 SCOPE (0).buffer1 = b; |
617 SCOPE (0).buffer1 = buf; |
| 626 b->WriteDWord (dhDrop); |
618 buf->WriteDWord (dhDrop); |
| 627 b->WriteDWord (dhGoto); |
619 buf->WriteDWord (dhGoto); |
| 628 AddSwitchCase (b); |
620 AddSwitchCase (buf); |
| 629 } |
621 } |
| 630 |
622 |
| 631 // ============================================================================ |
623 // ============================================================================ |
| 632 // |
624 // |
| 633 void BotscriptParser::ParseBreak() |
625 void BotscriptParser::ParseBreak() |
| 748 |
740 |
| 749 case eSwitchScope: |
741 case eSwitchScope: |
| 750 { |
742 { |
| 751 // Switch closes. Move down to the record buffer of |
743 // Switch closes. Move down to the record buffer of |
| 752 // the lower block. |
744 // the lower block. |
| 753 if (SCOPE (1).casecursor != -1) |
745 if (SCOPE (1).casecursor != SCOPE (1).cases.begin() - 1) |
| 754 mSwitchBuffer = SCOPE (1).casebuffers[SCOPE (1).casecursor]; |
746 mSwitchBuffer = SCOPE (1).casecursor->data; |
| 755 else |
747 else |
| 756 mSwitchBuffer = null; |
748 mSwitchBuffer = null; |
| 757 |
749 |
| 758 // If there was a default in the switch, write its header down now. |
750 // If there was a default in the switch, write its header down now. |
| 759 // If not, write instruction to jump to the end of switch after |
751 // If not, write instruction to jump to the end of switch after |
| 767 buffer()->AddReference (SCOPE (0).mark1); |
759 buffer()->AddReference (SCOPE (0).mark1); |
| 768 } |
760 } |
| 769 |
761 |
| 770 // Go through all of the buffers we |
762 // Go through all of the buffers we |
| 771 // recorded down and write them. |
763 // recorded down and write them. |
| 772 for (int u = 0; u < MAX_CASE; u++) |
764 for (CaseInfo& info : SCOPE (0).cases) |
| 773 { |
765 { |
| 774 if (SCOPE (0).casebuffers[u] == null) |
766 buffer()->AdjustMark (info.mark); |
| 775 continue; |
767 buffer()->MergeAndDestroy (info.data); |
| 776 |
|
| 777 buffer()->AdjustMark (SCOPE (0).casemarks[u]); |
|
| 778 buffer()->MergeAndDestroy (SCOPE (0).casebuffers[u]); |
|
| 779 } |
768 } |
| 780 |
769 |
| 781 // Move the closing mark here |
770 // Move the closing mark here |
| 782 buffer()->AdjustMark (SCOPE (0).mark1); |
771 buffer()->AdjustMark (SCOPE (0).mark1); |
| 783 break; |
772 break; |
| 1184 return retbuf; |
1173 return retbuf; |
| 1185 } |
1174 } |
| 1186 |
1175 |
| 1187 // ============================================================================ |
1176 // ============================================================================ |
| 1188 // |
1177 // |
| 1189 void BotscriptParser::PushScope() |
1178 void BotscriptParser::PushScope (EReset reset) |
| 1190 { |
1179 { |
| 1191 mScopeCursor++; |
1180 mScopeCursor++; |
| 1192 |
1181 |
| 1193 if (mScopeCursor >= MAX_SCOPE) |
1182 Print ("%1 <-> %2\n", mScopeStack.Size(), mScopeCursor + 1); |
| 1194 Error ("too deep scope"); |
1183 |
| 1195 |
1184 if (mScopeStack.Size() < mScopeCursor + 1) |
| 1196 ScopeInfo* info = &SCOPE (0); |
1185 { |
| 1197 info->type = eUnknownScope; |
1186 Print ("Adding a scope\n"); |
| 1198 info->mark1 = null; |
1187 ScopeInfo newscope; |
| 1199 info->mark2 = null; |
1188 mScopeStack << newscope; |
| 1200 info->buffer1 = null; |
1189 reset = eResetScope; |
| 1201 info->casecursor = -1; |
1190 } |
| 1202 |
1191 |
| 1203 for (int i = 0; i < MAX_CASE; i++) |
1192 if (reset == eResetScope) |
| 1204 { |
1193 { |
| 1205 info->casemarks[i] = null; |
1194 ScopeInfo* info = &SCOPE (0); |
| 1206 info->casebuffers[i] = null; |
1195 info->type = eUnknownScope; |
| 1207 info->casenumbers[i] = -1; |
1196 info->mark1 = null; |
| |
1197 info->mark2 = null; |
| |
1198 info->buffer1 = null; |
| |
1199 info->cases.Clear(); |
| |
1200 info->casecursor = info->cases.begin() - 1; |
| 1208 } |
1201 } |
| 1209 } |
1202 } |
| 1210 |
1203 |
| 1211 // ============================================================================ |
1204 // ============================================================================ |
| 1212 // |
1205 // |
| 1238 return null; |
1231 return null; |
| 1239 } |
1232 } |
| 1240 |
1233 |
| 1241 // ============================================================================ |
1234 // ============================================================================ |
| 1242 // |
1235 // |
| 1243 void BotscriptParser::AddSwitchCase (DataBuffer* b) |
1236 void BotscriptParser::AddSwitchCase (DataBuffer* casebuffer) |
| 1244 { |
1237 { |
| 1245 ScopeInfo* info = &SCOPE (0); |
1238 ScopeInfo* info = &SCOPE (0); |
| 1246 |
1239 CaseInfo casedata; |
| 1247 info->casecursor++; |
|
| 1248 |
|
| 1249 if (info->casecursor >= MAX_CASE) |
|
| 1250 Error ("too many cases in one switch"); |
|
| 1251 |
1240 |
| 1252 // Init a mark for the case buffer |
1241 // Init a mark for the case buffer |
| 1253 ByteMark* casemark = buffer()->AddMark (""); |
1242 ByteMark* casemark = buffer()->AddMark (""); |
| 1254 info->casemarks[info->casecursor] = casemark; |
1243 casedata.mark = casemark; |
| 1255 |
1244 |
| 1256 // Add a reference to the mark. "case" and "default" both |
1245 // Add a reference to the mark. "case" and "default" both |
| 1257 // add the necessary bytecode before the reference. |
1246 // add the necessary bytecode before the reference. |
| 1258 if (b) |
1247 if (casebuffer != null) |
| 1259 b->AddReference (casemark); |
1248 casebuffer->AddReference (casemark); |
| 1260 else |
1249 else |
| 1261 buffer()->AddReference (casemark); |
1250 buffer()->AddReference (casemark); |
| 1262 |
1251 |
| 1263 // Init a buffer for the case block and tell the object |
1252 // Init a buffer for the case block and tell the object |
| 1264 // writer to record all written data to it. |
1253 // writer to record all written data to it. |
| 1265 info->casebuffers[info->casecursor] = mSwitchBuffer = new DataBuffer; |
1254 casedata.data = mSwitchBuffer = new DataBuffer; |
| |
1255 SCOPE(0).cases << casedata; |
| |
1256 info->casecursor++; |
| 1266 } |
1257 } |
| 1267 |
1258 |
| 1268 // ============================================================================ |
1259 // ============================================================================ |
| 1269 // |
1260 // |
| 1270 ConstantInfo* BotscriptParser::FindConstant (const String& tok) |
1261 ConstantInfo* BotscriptParser::FindConstant (const String& tok) |
| 1371 |
1362 |
| 1372 // First, resolve references |
1363 // First, resolve references |
| 1373 for (MarkReference* ref : mMainBuffer->GetReferences()) |
1364 for (MarkReference* ref : mMainBuffer->GetReferences()) |
| 1374 { |
1365 { |
| 1375 // Substitute the placeholder with the mark position |
1366 // Substitute the placeholder with the mark position |
| 1376 for (int v = 0; v < 4; v++) |
1367 for (int i = 0; i < 4; ++i) |
| 1377 mMainBuffer->GetBuffer()[ref->pos + v] = ((ref->target->pos) << (8 * v)) & 0xFF; |
1368 mMainBuffer->GetBuffer()[ref->pos + i] = (ref->target->pos >> (8 * i)) & 0xFF; |
| 1378 |
1369 |
| 1379 Print ("reference at %1 resolved to mark at %2\n", ref->pos, ref->target->pos); |
1370 Print ("reference at %1 resolved to mark at %2\n", ref->pos, ref->target->pos); |
| 1380 } |
1371 } |
| 1381 |
1372 |
| 1382 // Then, dump the main buffer to the file |
1373 // Then, dump the main buffer to the file |