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 #define SCOPE(n) blockstack[g_BlockStackCursor - n] |
|
61 |
60 int g_NumStates = 0; |
62 int g_NumStates = 0; |
61 int g_NumEvents = 0; |
63 int g_NumEvents = 0; |
62 int g_CurMode = MODE_TOPLEVEL; |
64 int g_CurMode = MODE_TOPLEVEL; |
63 str g_CurState = ""; |
65 str g_CurState = ""; |
64 bool g_stateSpawnDefined = false; |
66 bool g_stateSpawnDefined = false; |
69 // ============================================================================ |
71 // ============================================================================ |
70 // Main parser code. Begins read of the script file, checks the syntax of it |
72 // Main parser code. Begins read of the script file, checks the syntax of it |
71 // and writes the data to the object file via ObjWriter - which also takes care |
73 // and writes the data to the object file via ObjWriter - which also takes care |
72 // of necessary buffering so stuff is written in the correct order. |
74 // of necessary buffering so stuff is written in the correct order. |
73 void ScriptReader::ParseBotScript (ObjWriter* w) { |
75 void ScriptReader::ParseBotScript (ObjWriter* w) { |
|
76 // Zero the entire block stack first |
|
77 for (int i = 0; i < MAX_STRUCTSTACK; i++) |
|
78 memset (&blockstack[i], 0, sizeof (BlockInformation)); |
|
79 |
74 while (Next()) { |
80 while (Next()) { |
75 // ============================================================ |
81 // ============================================================ |
76 if (!token.compare ("state")) { |
82 if (!token.compare ("state")) { |
77 MUST_TOPLEVEL |
83 MUST_TOPLEVEL |
78 |
84 |
224 // we just defined - and this mark will be at the end of the block. |
228 // we just defined - and this mark will be at the end of the block. |
225 w->Write<word> (DH_IFNOTGOTO); |
229 w->Write<word> (DH_IFNOTGOTO); |
226 w->AddReference (marknum); |
230 w->AddReference (marknum); |
227 |
231 |
228 // Store it in the block stack |
232 // Store it in the block stack |
229 blockstack[g_BlockStackCursor].mark1 = marknum; |
233 SCOPE(0).mark1 = marknum; |
230 blockstack[g_BlockStackCursor].type = BLOCKTYPE_IF; |
234 SCOPE(0).type = BLOCKTYPE_IF; |
|
235 continue; |
|
236 } |
|
237 |
|
238 if (!token.compare ("else")) { |
|
239 MUST_NOT_TOPLEVEL |
|
240 MustNext ("{"); |
|
241 |
|
242 // Don't use PushBlockStack as that will reset the scope. |
|
243 g_BlockStackCursor++; |
|
244 if (g_BlockStackCursor >= MAX_STRUCTSTACK) |
|
245 ParserError ("too deep scope"); |
|
246 |
|
247 if (SCOPE(0).type != BLOCKTYPE_IF) |
|
248 ParserError ("else without preceding if"); |
|
249 |
|
250 // Write down to jump to the end of the else statement |
|
251 // Otherwise we have fall-throughs |
|
252 SCOPE(0).mark2 = w->AddMark (""); |
|
253 |
|
254 // Instruction to jump to the end after if block is complete |
|
255 w->Write (DH_GOTO); |
|
256 w->AddReference (SCOPE(0).mark2); |
|
257 |
|
258 // Move the ifnot mark here and set type to else |
|
259 w->MoveMark (SCOPE(0).mark1); |
|
260 SCOPE(0).type = BLOCKTYPE_ELSE; |
231 continue; |
261 continue; |
232 } |
262 } |
233 |
263 |
234 // ============================================================ |
264 // ============================================================ |
235 // While |
265 // While |
257 // Instruction to go to the end if it fails |
287 // Instruction to go to the end if it fails |
258 w->Write<word> (DH_IFNOTGOTO); |
288 w->Write<word> (DH_IFNOTGOTO); |
259 w->AddReference (mark2); |
289 w->AddReference (mark2); |
260 |
290 |
261 // Store the needed stuff |
291 // Store the needed stuff |
262 blockstack[g_BlockStackCursor].mark1 = mark1; |
292 SCOPE(0).mark1 = mark1; |
263 blockstack[g_BlockStackCursor].mark2 = mark2; |
293 SCOPE(0).mark2 = mark2; |
264 blockstack[g_BlockStackCursor].type = BLOCKTYPE_WHILE; |
294 SCOPE(0).type = BLOCKTYPE_WHILE; |
265 continue; |
295 continue; |
266 } |
296 } |
267 |
297 |
268 // ============================================================ |
298 // ============================================================ |
269 // For loop |
299 // For loop |
299 w->WriteBuffer (cond); |
329 w->WriteBuffer (cond); |
300 w->Write<word> (DH_IFNOTGOTO); |
330 w->Write<word> (DH_IFNOTGOTO); |
301 w->AddReference (mark2); |
331 w->AddReference (mark2); |
302 |
332 |
303 // Store the marks and incrementor |
333 // Store the marks and incrementor |
304 blockstack[g_BlockStackCursor].mark1 = mark1; |
334 SCOPE(0).mark1 = mark1; |
305 blockstack[g_BlockStackCursor].mark2 = mark2; |
335 SCOPE(0).mark2 = mark2; |
306 blockstack[g_BlockStackCursor].buffer1 = incr; |
336 SCOPE(0).buffer1 = incr; |
307 blockstack[g_BlockStackCursor].type = BLOCKTYPE_FOR; |
337 SCOPE(0).type = BLOCKTYPE_FOR; |
308 continue; |
338 continue; |
309 } |
339 } |
310 |
340 |
311 // ============================================================ |
341 // ============================================================ |
312 // Do/while loop |
342 // Do/while loop |
313 if (!token.compare ("do")) { |
343 if (!token.compare ("do")) { |
314 MUST_NOT_TOPLEVEL |
344 MUST_NOT_TOPLEVEL |
315 PushBlockStack (); |
345 PushBlockStack (); |
316 MustNext ("{"); |
346 MustNext ("{"); |
317 blockstack[g_BlockStackCursor].mark1 = w->AddMark (""); |
347 SCOPE(0).mark1 = w->AddMark (""); |
318 blockstack[g_BlockStackCursor].type = BLOCKTYPE_DO; |
348 SCOPE(0).type = BLOCKTYPE_DO; |
319 continue; |
349 continue; |
320 } |
350 } |
321 |
351 |
322 // ============================================================ |
352 // ============================================================ |
323 // Switch |
353 // Switch |
340 MustNext ("("); |
370 MustNext ("("); |
341 MustNext (); |
371 MustNext (); |
342 w->WriteBuffer (ParseExpression (TYPE_INT)); |
372 w->WriteBuffer (ParseExpression (TYPE_INT)); |
343 MustNext (")"); |
373 MustNext (")"); |
344 MustNext ("{"); |
374 MustNext ("{"); |
345 blockstack[g_BlockStackCursor].type = BLOCKTYPE_SWITCH; |
375 SCOPE(0).type = BLOCKTYPE_SWITCH; |
346 blockstack[g_BlockStackCursor].mark1 = w->AddMark (""); // end mark |
376 SCOPE(0).mark1 = w->AddMark (""); // end mark |
347 blockstack[g_BlockStackCursor].buffer1 = NULL; // default header |
377 SCOPE(0).buffer1 = NULL; // default header |
348 continue; |
378 continue; |
349 } |
379 } |
350 |
380 |
351 // ============================================================ |
381 // ============================================================ |
352 if (!token.compare ("case")) { |
382 if (!token.compare ("case")) { |
353 // case is only allowed inside switch |
383 // case is only allowed inside switch |
354 BlockInformation* info = &blockstack[g_BlockStackCursor]; |
384 if (SCOPE(0).type != BLOCKTYPE_SWITCH) |
355 if (info->type != BLOCKTYPE_SWITCH) |
|
356 ParserError ("case label outside switch"); |
385 ParserError ("case label outside switch"); |
357 |
386 |
358 // Get the literal (Zandronum does not support expressions here) |
387 // Get the literal (Zandronum does not support expressions here) |
359 MustNumber (); |
388 MustNumber (); |
360 int num = atoi (token.chars ()); |
389 int num = atoi (token.chars ()); |
361 MustNext (":"); |
390 MustNext (":"); |
362 |
391 |
363 for (int i = 0; i < MAX_CASE; i++) |
392 for (int i = 0; i < MAX_CASE; i++) |
364 if (info->casenumbers[i] == num) |
393 if (SCOPE(0).casenumbers[i] == num) |
365 ParserError ("multiple case %d labels in one switch", num); |
394 ParserError ("multiple case %d labels in one switch", num); |
366 |
395 |
367 // Write down the expression and case-go-to. This builds |
396 // Write down the expression and case-go-to. This builds |
368 // the case tree. The closing event will write the actual |
397 // the case tree. The closing event will write the actual |
369 // blocks and move the marks appropriately. |
398 // blocks and move the marks appropriately. |
374 // we want it all under the switch, not into the case-buffers. |
403 // we want it all under the switch, not into the case-buffers. |
375 w->SwitchBuffer = NULL; |
404 w->SwitchBuffer = NULL; |
376 w->Write<word> (DH_CASEGOTO); |
405 w->Write<word> (DH_CASEGOTO); |
377 w->Write<word> (num); |
406 w->Write<word> (num); |
378 AddSwitchCase (w, NULL); |
407 AddSwitchCase (w, NULL); |
379 info->casenumbers[info->casecursor] = num; |
408 SCOPE(0).casenumbers[SCOPE(0).casecursor] = num; |
380 continue; |
409 continue; |
381 } |
410 } |
382 |
411 |
383 if (!token.compare ("default")) { |
412 if (!token.compare ("default")) { |
384 BlockInformation* info = &blockstack[g_BlockStackCursor]; |
413 if (SCOPE(0).type != BLOCKTYPE_SWITCH) |
385 if (info->type != BLOCKTYPE_SWITCH) |
|
386 ParserError ("default label outside switch"); |
414 ParserError ("default label outside switch"); |
387 |
415 |
388 if (info->buffer1) |
416 if (SCOPE(0).buffer1) |
389 ParserError ("multiple default labels in one switch"); |
417 ParserError ("multiple default labels in one switch"); |
390 |
418 |
391 MustNext (":"); |
419 MustNext (":"); |
392 |
420 |
393 // The default header is buffered into buffer1, since |
421 // The default header is buffered into buffer1, since |
396 // Since the expression is pushed into the switch |
424 // Since the expression is pushed into the switch |
397 // and is only popped when case succeeds, we have |
425 // and is only popped when case succeeds, we have |
398 // to pop it with DH_DROP manually if we end up in |
426 // to pop it with DH_DROP manually if we end up in |
399 // a default. |
427 // a default. |
400 DataBuffer* b = new DataBuffer; |
428 DataBuffer* b = new DataBuffer; |
401 info->buffer1 = b; |
429 SCOPE(0).buffer1 = b; |
402 b->Write<word> (DH_DROP); |
430 b->Write<word> (DH_DROP); |
403 b->Write<word> (DH_GOTO); |
431 b->Write<word> (DH_GOTO); |
404 AddSwitchCase (w, b); |
432 AddSwitchCase (w, b); |
405 continue; |
433 continue; |
406 } |
434 } |
409 // Break statement. |
437 // Break statement. |
410 if (!token.compare ("break")) { |
438 if (!token.compare ("break")) { |
411 if (!g_BlockStackCursor) |
439 if (!g_BlockStackCursor) |
412 ParserError ("unexpected `break`"); |
440 ParserError ("unexpected `break`"); |
413 |
441 |
414 BlockInformation* info = &blockstack[g_BlockStackCursor]; |
|
415 |
|
416 w->Write<word> (DH_GOTO); |
442 w->Write<word> (DH_GOTO); |
417 |
443 |
418 // switch and if use mark1 for the closing point, |
444 // switch and if use mark1 for the closing point, |
419 // for and while use mark2. |
445 // for and while use mark2. |
420 switch (info->type) { |
446 switch (SCOPE(0).type) { |
421 case BLOCKTYPE_IF: |
447 case BLOCKTYPE_IF: |
422 case BLOCKTYPE_SWITCH: |
448 case BLOCKTYPE_SWITCH: |
423 w->AddReference (info->mark1); |
449 w->AddReference (SCOPE(0).mark1); |
424 break; |
450 break; |
425 case BLOCKTYPE_FOR: |
451 case BLOCKTYPE_FOR: |
426 case BLOCKTYPE_WHILE: |
452 case BLOCKTYPE_WHILE: |
427 w->AddReference (info->mark2); |
453 w->AddReference (SCOPE(0).mark2); |
428 break; |
454 break; |
429 default: |
455 default: |
430 ParserError ("unexpected `break`"); |
456 ParserError ("unexpected `break`"); |
431 break; |
457 break; |
432 } |
458 } |
456 if (!token.compare ("}")) { |
482 if (!token.compare ("}")) { |
457 // Closing brace |
483 // Closing brace |
458 |
484 |
459 // If we're in the block stack, we're descending down from it now |
485 // If we're in the block stack, we're descending down from it now |
460 if (g_BlockStackCursor > 0) { |
486 if (g_BlockStackCursor > 0) { |
461 BlockInformation* info = &blockstack[g_BlockStackCursor]; |
487 switch (SCOPE(0).type) { |
462 switch (info->type) { |
|
463 case BLOCKTYPE_IF: |
488 case BLOCKTYPE_IF: |
464 // Adjust the closing mark. |
489 // Adjust the closing mark. |
465 w->MoveMark (info->mark1); |
490 w->MoveMark (SCOPE(0).mark1); |
|
491 break; |
|
492 case BLOCKTYPE_ELSE: |
|
493 // else instead uses mark1 for itself (so if expression |
|
494 // fails, jump to else), mark2 means end of else |
|
495 w->MoveMark (SCOPE(0).mark2); |
466 break; |
496 break; |
467 case BLOCKTYPE_FOR: |
497 case BLOCKTYPE_FOR: |
468 // Write the incrementor at the end of the loop block |
498 // Write the incrementor at the end of the loop block |
469 w->WriteBuffer (info->buffer1); |
499 w->WriteBuffer (SCOPE(0).buffer1); |
470 // fall-thru |
500 // fall-thru |
471 case BLOCKTYPE_WHILE: |
501 case BLOCKTYPE_WHILE: |
472 // Write down the instruction to go back to the start of the loop |
502 // Write down the instruction to go back to the start of the loop |
473 w->Write (DH_GOTO); |
503 w->Write (DH_GOTO); |
474 w->AddReference (info->mark1); |
504 w->AddReference (SCOPE(0).mark1); |
475 |
505 |
476 // Move the closing mark here since we're at the end of the while loop |
506 // Move the closing mark here since we're at the end of the while loop |
477 w->MoveMark (info->mark2); |
507 w->MoveMark (SCOPE(0).mark2); |
478 break; |
508 break; |
479 case BLOCKTYPE_DO: { |
509 case BLOCKTYPE_DO: { |
480 MustNext ("while"); |
510 MustNext ("while"); |
481 MustNext ("("); |
511 MustNext ("("); |
482 MustNext (); |
512 MustNext (); |
485 MustNext (";"); |
515 MustNext (";"); |
486 |
516 |
487 // If the condition runs true, go back to the start. |
517 // If the condition runs true, go back to the start. |
488 w->WriteBuffer (expr); |
518 w->WriteBuffer (expr); |
489 w->Write<long> (DH_IFGOTO); |
519 w->Write<long> (DH_IFGOTO); |
490 w->AddReference (info->mark1); |
520 w->AddReference (SCOPE(0).mark1); |
491 break; |
521 break; |
492 } |
522 } |
493 case BLOCKTYPE_SWITCH: { |
523 case BLOCKTYPE_SWITCH: { |
494 // Switch closes. Move down to the record buffer of |
524 // Switch closes. Move down to the record buffer of |
495 // the lower block. |
525 // the lower block. |
496 BlockInformation* previnfo = &blockstack[g_BlockStackCursor - 1]; |
526 if (SCOPE(1).casecursor != -1) |
497 if (previnfo->casecursor != -1) |
527 w->SwitchBuffer = SCOPE(1).casebuffers[SCOPE(1).casecursor]; |
498 w->SwitchBuffer = previnfo->casebuffers[previnfo->casecursor]; |
|
499 else |
528 else |
500 w->SwitchBuffer = NULL; |
529 w->SwitchBuffer = NULL; |
501 |
530 |
502 // If there was a default in the switch, write its header down now. |
531 // If there was a default in the switch, write its header down now. |
503 // If not, write instruction to jump to the end of switch after |
532 // If not, write instruction to jump to the end of switch after |
504 // the headers (thus won't fall-through if no case matched) |
533 // the headers (thus won't fall-through if no case matched) |
505 if (info->buffer1) |
534 if (SCOPE(0).buffer1) |
506 w->WriteBuffer (info->buffer1); |
535 w->WriteBuffer (SCOPE(0).buffer1); |
507 else { |
536 else { |
508 w->Write<word> (DH_DROP); |
537 w->Write<word> (DH_DROP); |
509 w->Write<word> (DH_GOTO); |
538 w->Write<word> (DH_GOTO); |
510 w->AddReference (info->mark1); |
539 w->AddReference (SCOPE(0).mark1); |
511 } |
540 } |
512 |
541 |
513 // Go through all of the buffers we |
542 // Go through all of the buffers we |
514 // recorded down and write them. |
543 // recorded down and write them. |
515 for (unsigned int u = 0; u < MAX_CASE; u++) { |
544 for (unsigned int u = 0; u < MAX_CASE; u++) { |
516 if (!info->casebuffers[u]) |
545 if (!SCOPE(0).casebuffers[u]) |
517 continue; |
546 continue; |
518 |
547 |
519 w->MoveMark (info->casemarks[u]); |
548 w->MoveMark (SCOPE(0).casemarks[u]); |
520 w->WriteBuffer (info->casebuffers[u]); |
549 w->WriteBuffer (SCOPE(0).casebuffers[u]); |
521 } |
550 } |
522 |
551 |
523 // Move the closing mark here |
552 // Move the closing mark here |
524 w->MoveMark (info->mark1); |
553 w->MoveMark (SCOPE(0).mark1); |
525 } |
554 } |
526 } |
555 } |
527 |
556 |
528 // Descend down the stack |
557 // Descend down the stack |
529 g_BlockStackCursor--; |
558 g_BlockStackCursor--; |
711 |
740 |
712 // Parse the right operand, |
741 // Parse the right operand, |
713 MustNext (); |
742 MustNext (); |
714 DataBuffer* rb = ParseExprValue (reqtype); |
743 DataBuffer* rb = ParseExprValue (reqtype); |
715 |
744 |
716 // Ternary operator requires - naturally - a third operator |
|
717 if (oper == OPER_TERNARY) { |
745 if (oper == OPER_TERNARY) { |
|
746 // Ternary operator requires - naturally - a third operand. |
718 MustNext (":"); |
747 MustNext (":"); |
719 MustNext (); |
748 MustNext (); |
720 DataBuffer* tb = ParseExprValue (reqtype); |
749 DataBuffer* tb = ParseExprValue (reqtype); |
721 |
750 |
722 // It also is handled differently: there isn't a dataheader for ternary |
751 // It also is handled differently: there isn't a dataheader for ternary |
950 return retbuf; |
979 return retbuf; |
951 } |
980 } |
952 |
981 |
953 void ScriptReader::PushBlockStack () { |
982 void ScriptReader::PushBlockStack () { |
954 g_BlockStackCursor++; |
983 g_BlockStackCursor++; |
955 BlockInformation* info = &blockstack[g_BlockStackCursor]; |
984 if (g_BlockStackCursor >= MAX_STRUCTSTACK) |
|
985 ParserError ("too deep scope"); |
|
986 |
|
987 BlockInformation* info = &SCOPE(0); |
956 info->type = 0; |
988 info->type = 0; |
957 info->mark1 = 0; |
989 info->mark1 = 0; |
958 info->mark2 = 0; |
990 info->mark2 = 0; |
959 info->buffer1 = NULL; |
991 info->buffer1 = NULL; |
960 info->casecursor = -1; |
992 info->casecursor = -1; |