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 |