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_BlockStackCursor = 0; |
73 g_BlockStackCursor = 0; |
74 while (Next()) { |
74 while (Next()) { |
75 printf ("BeginParse: token: `%s`\n", token.chars()); |
|
76 if (!token.icompare ("state")) { |
75 if (!token.icompare ("state")) { |
77 MUST_TOPLEVEL |
76 MUST_TOPLEVEL |
78 |
77 |
79 MustString (); |
78 MustString (); |
80 |
79 |
224 // we just defined - and this mark will be at the end of the block. |
222 // we just defined - and this mark will be at the end of the block. |
225 w->Write<word> (DH_IFNOTGOTO); |
223 w->Write<word> (DH_IFNOTGOTO); |
226 w->AddReference (marknum); |
224 w->AddReference (marknum); |
227 |
225 |
228 // Store it in the block stack |
226 // Store it in the block stack |
|
227 g_BlockStackCursor++; |
229 blockstack[g_BlockStackCursor] = marknum; |
228 blockstack[g_BlockStackCursor] = marknum; |
230 g_BlockStackCursor++; |
|
231 continue; |
229 continue; |
232 } |
230 } |
233 |
231 |
234 if (!token.compare ("}")) { |
232 if (!token.compare ("}")) { |
235 // Closing brace |
233 // Closing brace |
236 |
234 |
237 // If we're in the block stack, we're descending down from it now |
235 // If we're in the block stack, we're descending down from it now |
238 if (g_BlockStackCursor > 0) { |
236 if (g_BlockStackCursor > 0) { |
239 // Adjust its closing mark so that it's here. |
237 // Adjust its closing mark so that it's here. |
240 unsigned int marknum = blockstack[g_BlockStackCursor]; |
238 unsigned int marknum = blockstack[g_BlockStackCursor]; |
241 if (marknum != MAX_MARKS) { |
239 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); |
240 w->MoveMark (marknum); |
245 // printf ("to %d\n", w->GetCurrentBuffer()->marks[marknum]->pos); |
241 w->AddMark (MARKTYPE_INTERNAL, ""); |
246 } |
|
247 |
|
248 g_BlockStackCursor--; |
242 g_BlockStackCursor--; |
249 continue; |
243 continue; |
250 } |
244 } |
251 |
245 |
252 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT : |
246 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT : |
269 } |
263 } |
270 |
264 |
271 // If it's a variable, expect assignment. |
265 // If it's a variable, expect assignment. |
272 if (ScriptVar* var = FindGlobalVariable (token)) { |
266 if (ScriptVar* var = FindGlobalVariable (token)) { |
273 DataBuffer* b = ParseAssignment (var); |
267 DataBuffer* b = ParseAssignment (var); |
274 printf ("current token after assignment: `%s`\n", token.chars()); |
|
275 MustNext (";"); |
268 MustNext (";"); |
276 w->WriteBuffer (b); |
269 w->WriteBuffer (b); |
277 delete b; |
|
278 continue; |
270 continue; |
279 } |
271 } |
280 |
272 |
281 // If it's not a keyword, parse it as an expression. |
273 // If it's not a keyword, parse it as an expression. |
282 printf ("token length: %d, first char: %c [%d]\n", token.len(), token.chars()[0], token.chars()[0]); |
|
283 DataBuffer* b = ParseExpression (TYPE_VOID); |
274 DataBuffer* b = ParseExpression (TYPE_VOID); |
284 w->WriteBuffer (b); |
275 w->WriteBuffer (b); |
285 delete b; |
|
286 printf ("expression done! current token is %s\n", token.chars()); |
|
287 MustNext (";"); |
276 MustNext (";"); |
288 } |
277 } |
289 |
278 |
290 if (g_CurMode != MODE_TOPLEVEL) |
279 if (g_CurMode != MODE_TOPLEVEL) |
291 ParserError ("script did not end at top level; did you forget a `}`?"); |
280 ParserError ("script did not end at top level; did you forget a `}`?"); |
306 DataBuffer* ScriptReader::ParseCommand (CommandDef* comm) { |
295 DataBuffer* ScriptReader::ParseCommand (CommandDef* comm) { |
307 DataBuffer* r = new DataBuffer(64); |
296 DataBuffer* r = new DataBuffer(64); |
308 if (g_CurMode == MODE_TOPLEVEL) |
297 if (g_CurMode == MODE_TOPLEVEL) |
309 ParserError ("command call at top level"); |
298 ParserError ("command call at top level"); |
310 |
299 |
311 printf ("\n\n\n=====================================\nBEGIN PARSING COMMAND\n"); |
|
312 printf ("token: %s\n", token.chars()); |
|
313 MustNext ("("); |
300 MustNext ("("); |
314 MustNext (); |
301 MustNext (); |
315 |
302 |
316 int curarg = 0; |
303 int curarg = 0; |
317 while (1) { |
304 while (1) { |
318 printf ("at argument %d\n", curarg); |
|
319 printf ("next token: %s\n", token.chars()); |
|
320 |
|
321 if (!token.compare (")")) { |
305 if (!token.compare (")")) { |
322 printf ("closing command with token `%s`\n", token.chars()); |
|
323 if (curarg < comm->numargs - 1) |
306 if (curarg < comm->numargs - 1) |
324 ParserError ("too few arguments passed to %s\n", comm->name.chars()); |
307 ParserError ("too few arguments passed to %s\n", comm->name.chars()); |
325 break; |
308 break; |
326 curarg++; |
309 curarg++; |
327 } |
310 } |
329 if (curarg >= comm->maxargs) |
312 if (curarg >= comm->maxargs) |
330 ParserError ("too many arguments passed to %s\n", comm->name.chars()); |
313 ParserError ("too many arguments passed to %s\n", comm->name.chars()); |
331 |
314 |
332 r->Merge (ParseExpression (comm->argtypes[curarg])); |
315 r->Merge (ParseExpression (comm->argtypes[curarg])); |
333 MustNext (); |
316 MustNext (); |
334 printf ("after expression, token is `%s`\n", token.chars()); |
|
335 |
317 |
336 if (curarg < comm->numargs - 1) { |
318 if (curarg < comm->numargs - 1) { |
337 MustThis (","); |
319 MustThis (","); |
338 MustNext (); |
320 MustNext (); |
339 } else if (curarg < comm->maxargs - 1) { |
321 } else if (curarg < comm->maxargs - 1) { |
359 |
341 |
360 r->Write<word> (DH_COMMAND); |
342 r->Write<word> (DH_COMMAND); |
361 r->Write<word> (comm->number); |
343 r->Write<word> (comm->number); |
362 r->Write<word> (comm->maxargs); |
344 r->Write<word> (comm->maxargs); |
363 |
345 |
364 printf ("command complete\n"); |
|
365 return r; |
346 return r; |
366 } |
347 } |
367 |
348 |
368 // ============================================================================ |
349 // ============================================================================ |
369 // Is the given operator an assignment operator? |
350 // Is the given operator an assignment operator? |
418 } |
399 } |
419 |
400 |
420 // ============================================================================ |
401 // ============================================================================ |
421 // Parses an expression, potentially recursively |
402 // Parses an expression, potentially recursively |
422 DataBuffer* ScriptReader::ParseExpression (int reqtype) { |
403 DataBuffer* ScriptReader::ParseExpression (int reqtype) { |
423 printf ("begin parsing expression. this token is `%s`, next token is `%s`\n", |
|
424 token.chars(), PeekNext().chars()); |
|
425 DataBuffer* retbuf = new DataBuffer (64); |
404 DataBuffer* retbuf = new DataBuffer (64); |
426 |
405 |
427 DataBuffer* lb = NULL; |
406 DataBuffer* lb = NULL; |
428 |
407 |
429 lb = ParseExprValue (reqtype); |
408 lb = ParseExprValue (reqtype); |
430 printf ("done\n"); |
|
431 |
409 |
432 // Get an operator |
410 // Get an operator |
433 printf ("parse operator at token %s\n", token.chars()); |
|
434 int oper = ParseOperator (true); |
411 int oper = ParseOperator (true); |
435 printf ("operator parsed: token is now %s\n", token.chars()); |
|
436 printf ("got %d\n", oper); |
|
437 |
412 |
438 // No operator found - stop here. |
413 // No operator found - stop here. |
439 if (oper == -1) { |
414 if (oper == -1) { |
440 retbuf->Merge (lb); |
415 retbuf->Merge (lb); |
441 printf ("expression complete without operator, stopping at `%s`\n", token.chars()); |
|
442 return retbuf; |
416 return retbuf; |
443 } |
417 } |
444 |
418 |
445 // We peeked the operator, move forward now |
419 // We peeked the operator, move forward now |
446 MustNext(); |
420 MustNext(); |
448 // Can't be an assignement operator, those belong in assignments. |
422 // Can't be an assignement operator, those belong in assignments. |
449 if (IsAssignmentOperator (oper)) |
423 if (IsAssignmentOperator (oper)) |
450 ParserError ("assignment operator inside expressions"); |
424 ParserError ("assignment operator inside expressions"); |
451 |
425 |
452 // Parse the right operand, |
426 // Parse the right operand, |
453 printf ("parse right operand\n"); |
|
454 MustNext (); |
427 MustNext (); |
455 DataBuffer* rb = ParseExprValue (reqtype); |
428 DataBuffer* rb = ParseExprValue (reqtype); |
456 printf ("done\n"); |
|
457 |
429 |
458 retbuf->Merge (rb); |
430 retbuf->Merge (rb); |
459 retbuf->Merge (lb); |
431 retbuf->Merge (lb); |
460 |
432 |
461 long dh = DataHeaderByOperator (NULL, oper); |
433 long dh = DataHeaderByOperator (NULL, oper); |
462 retbuf->Write<word> (dh); |
434 retbuf->Write<word> (dh); |
463 |
|
464 printf ("expression complete\n"); |
|
465 return retbuf; |
435 return retbuf; |
466 } |
436 } |
467 |
437 |
468 // ============================================================================ |
438 // ============================================================================ |
469 // Parses an operator string. Returns the operator number code. |
439 // `arses an operator string. Returns the operator number code. |
470 int ScriptReader::ParseOperator (bool peek) { |
440 int ScriptReader::ParseOperator (bool peek) { |
471 str oper; |
441 str oper; |
472 if (peek) |
442 if (peek) |
473 oper += PeekNext (); |
443 oper += PeekNext (); |
474 else |
444 else |
475 oper += token; |
445 oper += token; |
476 |
446 |
477 // Check one-char operators |
447 // Check one-char operators |
478 bool equalsnext = !PeekNext (peek ? 1 : 0).compare ("="); |
448 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 : |
449 int o = (!oper.compare ("=") && !equalsnext) ? OPER_ASSIGN : |
482 (!oper.compare (">") && !equalsnext) ? OPER_GREATERTHAN : |
450 (!oper.compare (">") && !equalsnext) ? OPER_GREATERTHAN : |
483 (!oper.compare ("<") && !equalsnext) ? OPER_LESSTHAN : |
451 (!oper.compare ("<") && !equalsnext) ? OPER_LESSTHAN : |
484 !oper.compare ("+") ? OPER_ADD : |
452 !oper.compare ("+") ? OPER_ADD : |
485 !oper.compare ("-") ? OPER_SUBTRACT : |
453 !oper.compare ("-") ? OPER_SUBTRACT : |
492 return o; |
460 return o; |
493 } |
461 } |
494 |
462 |
495 // Two-char operators |
463 // Two-char operators |
496 oper += PeekNext (peek ? 1 : 0); |
464 oper += PeekNext (peek ? 1 : 0); |
497 |
|
498 printf ("operator two-char: %s\n", oper.chars()); |
|
499 |
465 |
500 o = !oper.compare ("+=") ? OPER_ASSIGNADD : |
466 o = !oper.compare ("+=") ? OPER_ASSIGNADD : |
501 !oper.compare ("-=") ? OPER_ASSIGNSUB : |
467 !oper.compare ("-=") ? OPER_ASSIGNSUB : |
502 !oper.compare ("*=") ? OPER_ASSIGNMUL : |
468 !oper.compare ("*=") ? OPER_ASSIGNMUL : |
503 !oper.compare ("/=") ? OPER_ASSIGNDIV : |
469 !oper.compare ("/=") ? OPER_ASSIGNDIV : |
517 // ============================================================================ |
483 // ============================================================================ |
518 // Parses a value in the expression and returns the data needed to push |
484 // Parses a value in the expression and returns the data needed to push |
519 // it, contained in a data buffer. A value can be either a variable, a command, |
485 // it, contained in a data buffer. A value can be either a variable, a command, |
520 // a literal or an expression. |
486 // a literal or an expression. |
521 DataBuffer* ScriptReader::ParseExprValue (int reqtype) { |
487 DataBuffer* ScriptReader::ParseExprValue (int reqtype) { |
522 printf ("parse expr value `%s` with requirement type %d\n", token.chars(), reqtype); |
|
523 DataBuffer* b = new DataBuffer(16); |
488 DataBuffer* b = new DataBuffer(16); |
524 |
489 |
525 ScriptVar* g; |
490 ScriptVar* g; |
526 |
491 |
527 if (!token.compare ("(")) { |
492 if (!token.compare ("(")) { |
528 printf ("value is an expression\n"); |
|
529 // Expression |
493 // Expression |
530 MustNext (); |
494 MustNext (); |
531 DataBuffer* c = ParseExpression (reqtype); |
495 DataBuffer* c = ParseExpression (reqtype); |
532 b->Merge (c); |
496 b->Merge (c); |
533 MustNext (")"); |
497 MustNext (")"); |
534 } else if (CommandDef* comm = FindCommand (token)) { |
498 } else if (CommandDef* comm = FindCommand (token)) { |
535 printf ("value is a command\n"); |
|
536 delete b; |
499 delete b; |
537 |
500 |
538 // Command |
501 // Command |
539 if (reqtype && comm->returnvalue != reqtype) |
502 if (reqtype && comm->returnvalue != reqtype) |
540 ParserError ("%s returns an incompatible data type", comm->name.chars()); |
503 ParserError ("%s returns an incompatible data type", comm->name.chars()); |
541 b = ParseCommand (comm); |
504 b = ParseCommand (comm); |
542 } else if ((g = FindGlobalVariable (token)) && reqtype != TYPE_STRING) { |
505 } else if ((g = FindGlobalVariable (token)) && reqtype != TYPE_STRING) { |
543 printf ("value is a global var\n"); |
|
544 // Global variable |
506 // Global variable |
545 b->Write<word> (DH_PUSHGLOBALVAR); |
507 b->Write<word> (DH_PUSHGLOBALVAR); |
546 b->Write<word> (g->index); |
508 b->Write<word> (g->index); |
547 } else { |
509 } else { |
548 printf ("value is a literal\n"); |
|
549 // If nothing else, check for literal |
510 // If nothing else, check for literal |
550 switch (reqtype) { |
511 switch (reqtype) { |
551 case TYPE_VOID: |
512 case TYPE_VOID: |
552 ParserError ("bad syntax"); |
513 ParserError ("bad syntax"); |
553 break; |
514 break; |
566 } |
527 } |
567 case TYPE_STRING: |
528 case TYPE_STRING: |
568 // PushToStringTable either returns the string index of the |
529 // PushToStringTable either returns the string index of the |
569 // string if it finds it in the table, or writes it to the |
530 // string if it finds it in the table, or writes it to the |
570 // table and returns it index if it doesn't find it there. |
531 // table and returns it index if it doesn't find it there. |
571 printf ("value is a string literal\n"); |
|
572 MustString (true); |
532 MustString (true); |
573 b->Write<word> (DH_PUSHSTRINGINDEX); |
533 b->Write<word> (DH_PUSHSTRINGINDEX); |
574 b->Write<word> (PushToStringTable (token.chars())); |
534 b->Write<word> (PushToStringTable (token.chars())); |
575 break; |
535 break; |
576 } |
536 } |
577 } |
537 } |
578 printf ("value parsed: current token is `%s`\n", token.chars()); |
|
579 |
538 |
580 return b; |
539 return b; |
581 } |
540 } |
582 |
541 |
583 // ============================================================================ |
542 // ============================================================================ |