52 #include "variables.h" |
52 #include "variables.h" |
53 |
53 |
54 #define MUST_TOPLEVEL if (g_CurMode != MODE_TOPLEVEL) \ |
54 #define MUST_TOPLEVEL if (g_CurMode != MODE_TOPLEVEL) \ |
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 int g_NumStates = 0; |
60 int g_NumStates = 0; |
61 int g_NumEvents = 0; |
61 int g_NumEvents = 0; |
62 int g_CurMode = MODE_TOPLEVEL; |
62 int g_CurMode = MODE_TOPLEVEL; |
170 continue; |
170 continue; |
171 } |
171 } |
172 |
172 |
173 // Label |
173 // Label |
174 if (!PeekNext().compare (":")) { |
174 if (!PeekNext().compare (":")) { |
|
175 MUST_NOT_TOPLEVEL |
|
176 |
175 if (IsKeyword (token)) |
177 if (IsKeyword (token)) |
176 ParserError ("label name `%s` conflicts with keyword\n", token.chars()); |
178 ParserError ("label name `%s` conflicts with keyword\n", token.chars()); |
177 if (FindCommand (token)) |
179 if (FindCommand (token)) |
178 ParserError ("label name `%s` conflicts with command name\n", token.chars()); |
180 ParserError ("label name `%s` conflicts with command name\n", token.chars()); |
179 if (FindGlobalVariable (token)) |
181 if (FindGlobalVariable (token)) |
212 w->WriteBuffer (c); |
219 w->WriteBuffer (c); |
213 |
220 |
214 MustNext (")"); |
221 MustNext (")"); |
215 MustNext ("{"); |
222 MustNext ("{"); |
216 |
223 |
|
224 // Add a mark - to here temporarily - and add a reference to it. |
|
225 // Upon a closing brace, the mark will be adjusted. |
|
226 unsigned int marknum = w->AddMark (MARKTYPE_IF, ""); |
|
227 |
217 // Use DH_IFNOTGOTO - if the expression is not true, we goto the mark |
228 // Use DH_IFNOTGOTO - if the expression is not true, we goto the mark |
218 // we just defined - and this mark will be at the end of the block. |
229 // we just defined - and this mark will be at the end of the block. |
219 AddBlockMark (w, DH_IFNOTGOTO); |
230 w->Write<word> (DH_IFNOTGOTO); |
|
231 w->AddReference (marknum); |
|
232 |
|
233 // Store it in the block stack |
|
234 blockstack[g_BlockStackCursor].mark1 = marknum; |
|
235 blockstack[g_BlockStackCursor].type = BLOCKTYPE_IF; |
|
236 continue; |
|
237 } |
|
238 |
|
239 // While |
|
240 if (!token.compare ("while")) { |
|
241 printf ("begin while loop\n"); |
|
242 MUST_NOT_TOPLEVEL |
|
243 PushBlockStack (); |
|
244 |
|
245 // While loops need two marks - one at the start of the loop and one at the |
|
246 // end. The condition is checked at the very start of the loop, if it fails, |
|
247 // we use goto to skip to the end of the loop. At the end, we loop back to |
|
248 // the beginning with a go-to statement. |
|
249 unsigned int mark1 = w->AddMark (MARKTYPE_INTERNAL, ""); // start |
|
250 unsigned int mark2 = w->AddMark (MARKTYPE_INTERNAL, ""); // end |
|
251 |
|
252 // Condition |
|
253 MustNext ("("); |
|
254 MustNext (); |
|
255 DataBuffer* expr = ParseExpression (TYPE_INT); |
|
256 MustNext (")"); |
|
257 |
|
258 MustNext ("{"); |
|
259 |
|
260 // Write condition |
|
261 w->WriteBuffer (expr); |
|
262 |
|
263 // Instruction to go to the end if it fails |
|
264 w->Write<word> (DH_IFNOTGOTO); |
|
265 w->AddReference (mark2); |
|
266 |
|
267 // Store the needed stuff |
|
268 blockstack[g_BlockStackCursor].mark1 = mark1; |
|
269 blockstack[g_BlockStackCursor].mark2 = mark2; |
|
270 blockstack[g_BlockStackCursor].type = BLOCKTYPE_WHILE; |
220 continue; |
271 continue; |
221 } |
272 } |
222 |
273 |
223 if (!token.compare ("}")) { |
274 if (!token.compare ("}")) { |
224 // Closing brace |
275 // Closing brace |
225 |
276 |
226 // If we're in the block stack, we're descending down from it now |
277 // If we're in the block stack, we're descending down from it now |
227 if (g_BlockStackCursor > 0) { |
278 if (g_BlockStackCursor > 0) { |
228 // Adjust its closing mark so that it's here. |
279 BlockInformation* info = &blockstack[g_BlockStackCursor]; |
229 unsigned int marknum = blockstack[g_BlockStackCursor]; |
280 switch (info->type) { |
230 if (marknum != MAX_MARKS) |
281 case BLOCKTYPE_IF: |
231 w->MoveMark (marknum); |
282 printf ("end if\n"); |
232 w->AddMark (MARKTYPE_INTERNAL, ""); |
283 // Adjust the closing mark. |
|
284 w->MoveMark (info->mark1); |
|
285 break; |
|
286 case BLOCKTYPE_WHILE: |
|
287 printf ("end while loop\n"); |
|
288 |
|
289 // Write down the instruction to go back to the start of the loop |
|
290 w->Write (DH_GOTO); |
|
291 w->AddReference (info->mark1); |
|
292 |
|
293 // Move the closing mark here since we're at the end of the while loop |
|
294 w->MoveMark (info->mark2); |
|
295 |
|
296 // Offset it by 4 since the parser doesn't like having marks directly afte refs |
|
297 w->OffsetMark (info->mark2, sizeof (word)*2); |
|
298 } |
|
299 |
|
300 // Descend down the stack |
233 g_BlockStackCursor--; |
301 g_BlockStackCursor--; |
234 continue; |
302 continue; |
235 } |
303 } |
236 |
304 |
237 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT : |
305 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT : |
553 retbuf->Write<word> (var->index); |
621 retbuf->Write<word> (var->index); |
554 |
622 |
555 return retbuf; |
623 return retbuf; |
556 } |
624 } |
557 |
625 |
558 void ScriptReader::AddBlockMark (ObjWriter* w, word dataheader) { |
626 void ScriptReader::PushBlockStack () { |
559 // Add a mark - to here temporarily - and add a reference to it. |
627 BlockInformation* info = &blockstack[g_BlockStackCursor]; |
560 // Upon a closing brace, the mark will be adjusted. |
628 info->type = 0; |
561 unsigned int marknum = w->AddMark (MARKTYPE_IF, ""); |
629 info->mark1 = 0; |
562 |
630 info->mark2 = 0; |
563 // Write the header and store reference to the mark |
|
564 w->Write<word> (dataheader); |
|
565 w->AddReference (marknum); |
|
566 |
|
567 // Store it in the block stack |
|
568 g_BlockStackCursor++; |
631 g_BlockStackCursor++; |
569 blockstack[g_BlockStackCursor] = marknum; |
632 } |
570 } |
|