61 int g_NumEvents = 0; |
61 int g_NumEvents = 0; |
62 int g_CurMode = MODE_TOPLEVEL; |
62 int g_CurMode = MODE_TOPLEVEL; |
63 str g_CurState = ""; |
63 str g_CurState = ""; |
64 bool g_stateSpawnDefined = false; |
64 bool g_stateSpawnDefined = false; |
65 bool g_GotMainLoop = false; |
65 bool g_GotMainLoop = false; |
66 int g_StructStack = 0; |
66 unsigned int g_BlockStackCursor = 0; |
67 |
67 |
68 // ============================================================================ |
68 // ============================================================================ |
69 // Main parser code. Begins read of the script file, checks the syntax of it |
69 // Main parser code. Begins read of the script file, checks the syntax of it |
70 // and writes the data to the object file via ObjWriter - which also takes care |
70 // and writes the data to the object file via ObjWriter - which also takes care |
71 // of necessary buffering so stuff is written in the correct order. |
71 // of necessary buffering so stuff is written in the correct order. |
72 void ScriptReader::BeginParse (ObjWriter* w) { |
72 void ScriptReader::BeginParse (ObjWriter* w) { |
73 g_StructStack = 0; |
73 g_BlockStackCursor = 0; |
74 while (Next()) { |
74 while (Next()) { |
75 printf ("BeginParse: token: `%s`\n", token.chars()); |
75 printf ("BeginParse: token: `%s`\n", token.chars()); |
76 if (!token.icompare ("state")) { |
76 if (!token.icompare ("state")) { |
77 MUST_TOPLEVEL |
77 MUST_TOPLEVEL |
78 |
78 |
200 w->AddReference (m); |
200 w->AddReference (m); |
201 MustNext (";"); |
201 MustNext (";"); |
202 continue; |
202 continue; |
203 } |
203 } |
204 |
204 |
|
205 // If |
|
206 if (!token.icompare ("if")) { |
|
207 // Condition |
|
208 MustNext ("("); |
|
209 |
|
210 // Read the expression and write it. |
|
211 MustNext (); |
|
212 DataBuffer* c = ParseExpression (TYPE_INT); |
|
213 w->WriteBuffer (c); |
|
214 delete c; |
|
215 |
|
216 MustNext (")"); |
|
217 MustNext ("{"); |
|
218 |
|
219 // Add a mark - to here temporarily - and add a reference to it. |
|
220 // Upon a closing brace, the mark will be adjusted. |
|
221 unsigned int marknum = w->AddMark (MARKTYPE_IF, ""); |
|
222 |
|
223 // Use DH_IFNOTGOTO - if the expression is not true, we goto the mark |
|
224 // we just defined - and this mark will be at the end of the block. |
|
225 w->Write<word> (DH_IFNOTGOTO); |
|
226 w->AddReference (marknum); |
|
227 |
|
228 // Store it in the block stack |
|
229 blockstack[g_BlockStackCursor] = marknum; |
|
230 g_BlockStackCursor++; |
|
231 continue; |
|
232 } |
|
233 |
205 if (!token.compare ("}")) { |
234 if (!token.compare ("}")) { |
206 // If this was done inside the struct stack (i.e. |
235 // Closing brace |
207 // inside "if" for instance), it does not end the mode. |
236 |
208 if (g_StructStack > 0) { |
237 // If we're in the block stack, we're descending down from it now |
209 g_StructStack--; |
238 if (g_BlockStackCursor > 0) { |
|
239 // Adjust its closing mark so that it's here. |
|
240 unsigned int marknum = blockstack[g_BlockStackCursor]; |
|
241 if (marknum != MAX_MARKS) { |
|
242 // printf ("\tblock %d stack mark moved from %d ", |
|
243 g_BlockStackCursor, w->GetCurrentBuffer()->marks[marknum]->pos); |
|
244 w->MoveMark (marknum); |
|
245 // printf ("to %d\n", w->GetCurrentBuffer()->marks[marknum]->pos); |
|
246 } |
|
247 |
|
248 g_BlockStackCursor--; |
210 continue; |
249 continue; |
211 } |
250 } |
212 |
251 |
213 // Closing brace |
|
214 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT : |
252 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT : |
215 (g_CurMode == MODE_MAINLOOP) ? DH_ENDMAINLOOP : |
253 (g_CurMode == MODE_MAINLOOP) ? DH_ENDMAINLOOP : |
216 (g_CurMode == MODE_ONENTER) ? DH_ENDONENTER : |
254 (g_CurMode == MODE_ONENTER) ? DH_ENDONENTER : |
217 (g_CurMode == MODE_ONEXIT) ? DH_ENDONEXIT : -1; |
255 (g_CurMode == MODE_ONEXIT) ? DH_ENDONEXIT : -1; |
218 |
256 |
365 case OPER_ADD: return DH_ADD; |
403 case OPER_ADD: return DH_ADD; |
366 case OPER_SUBTRACT: return DH_SUBTRACT; |
404 case OPER_SUBTRACT: return DH_SUBTRACT; |
367 case OPER_MULTIPLY: return DH_MULTIPLY; |
405 case OPER_MULTIPLY: return DH_MULTIPLY; |
368 case OPER_DIVIDE: return DH_DIVIDE; |
406 case OPER_DIVIDE: return DH_DIVIDE; |
369 case OPER_MODULUS: return DH_MODULUS; |
407 case OPER_MODULUS: return DH_MODULUS; |
|
408 case OPER_EQUALS: return DH_EQUALS; |
|
409 case OPER_NOTEQUALS: return DH_NOTEQUALS; |
|
410 case OPER_LESSTHAN: return DH_LESSTHAN; |
|
411 case OPER_GREATERTHAN: return DH_GREATERTHAN; |
|
412 case OPER_LESSTHANEQUALS: return DH_LESSTHANEQUALS; |
|
413 case OPER_GREATERTHANEQUALS: return DH_GREATERTHANEQUALS; |
370 } |
414 } |
371 |
415 |
372 error ("DataHeaderByOperator: couldn't find dataheader for operator %d!\n", oper); |
416 error ("DataHeaderByOperator: couldn't find dataheader for operator %d!\n", oper); |
373 return 0; |
417 return 0; |
374 } |
418 } |
429 oper += PeekNext (); |
473 oper += PeekNext (); |
430 else |
474 else |
431 oper += token; |
475 oper += token; |
432 |
476 |
433 // Check one-char operators |
477 // Check one-char operators |
434 int o = !oper.compare ("=") ? OPER_ASSIGN : |
478 bool equalsnext = !PeekNext (peek ? 1 : 0).compare ("="); |
|
479 printf ("operator one-char: %s\nequals is%s next (`%s`)\n", oper.chars(), |
|
480 (equalsnext) ? "" : " not", PeekNext (peek ? 1 : 0).chars()); |
|
481 int o = (!oper.compare ("=") && !equalsnext) ? OPER_ASSIGN : |
|
482 (!oper.compare (">") && !equalsnext) ? OPER_GREATERTHAN : |
|
483 (!oper.compare ("<") && !equalsnext) ? OPER_LESSTHAN : |
435 !oper.compare ("+") ? OPER_ADD : |
484 !oper.compare ("+") ? OPER_ADD : |
436 !oper.compare ("-") ? OPER_SUBTRACT : |
485 !oper.compare ("-") ? OPER_SUBTRACT : |
437 !oper.compare ("*") ? OPER_MULTIPLY : |
486 !oper.compare ("*") ? OPER_MULTIPLY : |
438 !oper.compare ("/") ? OPER_DIVIDE : |
487 !oper.compare ("/") ? OPER_DIVIDE : |
439 !oper.compare ("%") ? OPER_MODULUS : |
488 !oper.compare ("%") ? OPER_MODULUS : |
444 } |
493 } |
445 |
494 |
446 // Two-char operators |
495 // Two-char operators |
447 oper += PeekNext (peek ? 1 : 0); |
496 oper += PeekNext (peek ? 1 : 0); |
448 |
497 |
|
498 printf ("operator two-char: %s\n", oper.chars()); |
|
499 |
449 o = !oper.compare ("+=") ? OPER_ASSIGNADD : |
500 o = !oper.compare ("+=") ? OPER_ASSIGNADD : |
450 !oper.compare ("-=") ? OPER_ASSIGNSUB : |
501 !oper.compare ("-=") ? OPER_ASSIGNSUB : |
451 !oper.compare ("*=") ? OPER_ASSIGNMUL : |
502 !oper.compare ("*=") ? OPER_ASSIGNMUL : |
452 !oper.compare ("/=") ? OPER_ASSIGNDIV : |
503 !oper.compare ("/=") ? OPER_ASSIGNDIV : |
453 !oper.compare ("%=") ? OPER_ASSIGNMOD : |
504 !oper.compare ("%=") ? OPER_ASSIGNMOD : |
|
505 !oper.compare ("==") ? OPER_EQUALS : |
|
506 !oper.compare ("!=") ? OPER_NOTEQUALS : |
|
507 !oper.compare (">=") ? OPER_GREATERTHANEQUALS : |
|
508 !oper.compare ("<=") ? OPER_LESSTHANEQUALS : |
454 -1; |
509 -1; |
455 |
510 |
456 if (o != -1) |
511 if (o != -1) |
457 MustNext (); |
512 MustNext (); |
458 |
513 |
500 MustNumber (true); |
555 MustNumber (true); |
501 |
556 |
502 // All values are written unsigned - thus we need to write the value's |
557 // All values are written unsigned - thus we need to write the value's |
503 // absolute value, followed by an unary minus if it was negative. |
558 // absolute value, followed by an unary minus if it was negative. |
504 b->Write<word> (DH_PUSHNUMBER); |
559 b->Write<word> (DH_PUSHNUMBER); |
|
560 |
505 long v = atoi (token.chars ()); |
561 long v = atoi (token.chars ()); |
506 b->Write<word> (static_cast<word> (abs (v))); |
562 b->Write<word> (static_cast<word> (abs (v))); |
507 if (v < 0) |
563 if (v < 0) |
508 b->Write<word> (DH_UNARYMINUS); |
564 b->Write<word> (DH_UNARYMINUS); |
509 break; |
565 break; |