parser.cxx

changeset 48
976c57f153b3
parent 47
d84d82213137
child 49
8e2f7a031410
equal deleted inserted replaced
47:d84d82213137 48:976c57f153b3
199 199
200 // Get the name of the label 200 // Get the name of the label
201 MustNext (); 201 MustNext ();
202 202
203 // Find the mark this goto statement points to 203 // Find the mark this goto statement points to
204 // TODO: This should define the mark instead of bombing
205 // out if the mark isn't found!
204 unsigned int m = w->FindMark (token); 206 unsigned int m = w->FindMark (token);
205 if (m == MAX_MARKS) 207 if (m == MAX_MARKS)
206 ParserError ("unknown label `%s`!", token.chars()); 208 ParserError ("unknown label `%s`!", token.chars());
207 209
208 // Add a reference to the mark. 210 // Add a reference to the mark.
219 PushBlockStack (); 221 PushBlockStack ();
220 222
221 // Condition 223 // Condition
222 MustNext ("("); 224 MustNext ("(");
223 225
224 // Read the expression and write it. Store it to memory too for else statements. 226 // Read the expression and write it.
227 // TODO: This should be storing it into a variable first, so
228 // that else statements would be possible!
225 MustNext (); 229 MustNext ();
226 DataBuffer* c = ParseExpression (TYPE_INT); 230 DataBuffer* c = ParseExpression (TYPE_INT);
227 w->WriteBuffer (c); 231 w->WriteBuffer (c);
228 232
229 MustNext (")"); 233 MustNext (")");
328 MUST_NOT_TOPLEVEL 332 MUST_NOT_TOPLEVEL
329 PushBlockStack (); 333 PushBlockStack ();
330 MustNext ("{"); 334 MustNext ("{");
331 blockstack[g_BlockStackCursor].mark1 = w->AddMark (""); 335 blockstack[g_BlockStackCursor].mark1 = w->AddMark ("");
332 blockstack[g_BlockStackCursor].type = BLOCKTYPE_DO; 336 blockstack[g_BlockStackCursor].type = BLOCKTYPE_DO;
337 continue;
338 }
339
340 // ============================================================
341 // Switch
342 if (!token.icompare ("switch")) {
343 /* This goes a bit tricky. switch is structured in the
344 * bytecode followingly:
345 * (expression)
346 * case a: goto casemark1
347 * case b: goto casemark2
348 * case c: goto casemark3
349 * goto mark1 // jump to end if no matches
350 * casemark1: ...
351 * casemark2: ...
352 * casemark3: ...
353 * mark1: // end mark
354 */
355
356 MUST_NOT_TOPLEVEL
357 PushBlockStack ();
358 MustNext ("(");
359 MustNext ();
360 w->WriteBuffer (ParseExpression (TYPE_INT));
361 MustNext (")");
362 MustNext ("{");
363 blockstack[g_BlockStackCursor].type = BLOCKTYPE_SWITCH;
364 blockstack[g_BlockStackCursor].mark1 = w->AddMark (""); // end mark
365 continue;
366 }
367
368 // ============================================================
369 if (!token.icompare ("case")) {
370 // case is only allowed inside switch
371 if (g_BlockStackCursor <= 0 || blockstack[g_BlockStackCursor].type != BLOCKTYPE_SWITCH)
372 ParserError ("`case` outside switch");
373
374 BlockInformation* info = &blockstack[g_BlockStackCursor];
375 info->casecursor++;
376 if (info->casecursor >= MAX_CASE)
377 ParserError ("too many `case` statements in one switch");
378
379 // Get the literal (Zandronum does not support expressions here)
380 MustNumber ();
381 int num = atoi (token.chars ());
382
383 MustNext (":");
384
385 // Init a mark for the case buffer
386 int m = w->AddMark ("");
387 info->casemarks[info->casecursor] = m;
388
389 // Write down the expression and case-go-to. This builds
390 // the case tree. The closing event will write the actual
391 // blocks and move the marks appropriately.
392 info->casebuffers[info->casecursor] = w->RecordBuffer = NULL;
393 w->Write<word> (DH_CASEGOTO);
394 w->Write<word> (num);
395 w->AddReference (m);
396
397 // Init a buffer for the case block, tell the object
398 // writer to record all written data to it.
399 info->casebuffers[info->casecursor] = w->RecordBuffer = new DataBuffer;
400 continue;
401 }
402
403 // ============================================================
404 // Break statement.
405 if (!token.icompare ("break")) {
406 if (!g_BlockStackCursor)
407 ParserError ("unexpected `break`");
408
409 BlockInformation* info = &blockstack[g_BlockStackCursor];
410
411 w->Write<word> (DH_GOTO);
412
413 // switch and if use mark1 for the closing point,
414 // for and while use mark2.
415 switch (info->type) {
416 case BLOCKTYPE_IF:
417 case BLOCKTYPE_SWITCH:
418 w->AddReference (info->mark1);
419 break;
420 case BLOCKTYPE_FOR:
421 case BLOCKTYPE_WHILE:
422 w->AddReference (info->mark2);
423 break;
424 default:
425 ParserError ("unexpected `break`");
426 break;
427 }
428
429 MustNext (";");
333 continue; 430 continue;
334 } 431 }
335 432
336 // ============================================================ 433 // ============================================================
337 if (!token.compare ("}")) { 434 if (!token.compare ("}")) {
355 w->AddReference (info->mark1); 452 w->AddReference (info->mark1);
356 453
357 // Move the closing mark here since we're at the end of the while loop 454 // Move the closing mark here since we're at the end of the while loop
358 w->MoveMark (info->mark2); 455 w->MoveMark (info->mark2);
359 break; 456 break;
360 case BLOCKTYPE_DO: 457 case BLOCKTYPE_DO: {
361 MustNext ("while"); 458 MustNext ("while");
362 MustNext ("("); 459 MustNext ("(");
363 MustNext (); 460 MustNext ();
364 DataBuffer* expr = ParseExpression (TYPE_INT); 461 DataBuffer* expr = ParseExpression (TYPE_INT);
365 MustNext (")"); 462 MustNext (")");
368 // If the condition runs true, go back to the start. 465 // If the condition runs true, go back to the start.
369 w->WriteBuffer (expr); 466 w->WriteBuffer (expr);
370 w->Write<long> (DH_IFGOTO); 467 w->Write<long> (DH_IFGOTO);
371 w->AddReference (info->mark1); 468 w->AddReference (info->mark1);
372 break; 469 break;
470 }
471
472 case BLOCKTYPE_SWITCH: {
473 // Switch closes. Move down to the record buffer of
474 // the lower block.
475 BlockInformation* previnfo = &blockstack[g_BlockStackCursor - 1];
476 if (previnfo->casecursor != -1)
477 w->RecordBuffer = previnfo->casebuffers[previnfo->casecursor];
478 else
479 w->RecordBuffer = NULL;
480
481 // Go through all of the buffers we
482 // recorded down and write them.
483 for (unsigned int u = 0; u < MAX_CASE; u++) {
484 if (!info->casebuffers[u])
485 continue;
486
487 w->MoveMark (info->casemarks[u]);
488 w->WriteBuffer (info->casebuffers[u]);
489 }
490
491 // Move the closing mark here
492 w->MoveMark (info->mark1);
493 }
373 } 494 }
374 495
375 // Descend down the stack 496 // Descend down the stack
376 g_BlockStackCursor--; 497 g_BlockStackCursor--;
377 continue; 498 continue;
691 BlockInformation* info = &blockstack[g_BlockStackCursor]; 812 BlockInformation* info = &blockstack[g_BlockStackCursor];
692 info->type = 0; 813 info->type = 0;
693 info->mark1 = 0; 814 info->mark1 = 0;
694 info->mark2 = 0; 815 info->mark2 = 0;
695 info->buffer1 = NULL; 816 info->buffer1 = NULL;
817 info->casecursor = -1;
818 for (int i = 0; i < MAX_CASE; i++) {
819 info->casemarks[i] = MAX_MARKS;
820 info->casebuffers[i] = NULL;
821 }
696 } 822 }
697 823
698 DataBuffer* ScriptReader::ParseStatement (ObjWriter* w) { 824 DataBuffer* ScriptReader::ParseStatement (ObjWriter* w) {
699 // If it's a variable, expect assignment. 825 // If it's a variable, expect assignment.
700 if (ScriptVar* var = FindGlobalVariable (token)) { 826 if (ScriptVar* var = FindGlobalVariable (token)) {

mercurial