src/parser.cxx

changeset 73
1ee9b312dc18
parent 72
03e4d9db3fd9
child 74
007fbadfa7f9
equal deleted inserted replaced
72:03e4d9db3fd9 73:1ee9b312dc18
1 #include "objwriter.h" 1 /*
2 #include "scriptreader.h" 2 Copyright (c) 2013-2014, Santeri Piippo
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 * Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
15 * Neither the name of the <organization> nor the
16 names of its contributors may be used to endorse or promote products
17 derived from this software without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
23 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "object_writer.h"
32 #include "parser.h"
3 #include "events.h" 33 #include "events.h"
4 #include "commands.h" 34 #include "commands.h"
5 #include "stringtable.h" 35 #include "stringtable.h"
6 #include "variables.h" 36 #include "variables.h"
7 #include "containers.h" 37 #include "containers.h"
8 38 #include "lexer.h"
9 #define MUST_TOPLEVEL if (g_CurMode != MODE_TOPLEVEL) \ 39
10 ParserError ("%s-statements may only be defined at top level!", token.chars()); 40 #define TOKEN (string (m_lx->get_token()->string))
11
12 #define MUST_NOT_TOPLEVEL if (g_CurMode == MODE_TOPLEVEL) \
13 ParserError ("%s-statements may not be defined at top level!", token.chars());
14
15 #define SCOPE(n) scopestack[g_ScopeCursor - n] 41 #define SCOPE(n) scopestack[g_ScopeCursor - n]
16 42
43 // TODO: make these static
17 int g_NumStates = 0; 44 int g_NumStates = 0;
18 int g_NumEvents = 0; 45 int g_NumEvents = 0;
19 parsermode_e g_CurMode = MODE_TOPLEVEL; 46 parsermode_e g_CurMode = MODE_TOPLEVEL;
20 string g_CurState = ""; 47 string g_CurState = "";
21 bool g_stateSpawnDefined = false; 48 bool g_stateSpawnDefined = false;
22 bool g_GotMainLoop = false; 49 bool g_GotMainLoop = false;
23 unsigned int g_ScopeCursor = 0; 50 int g_ScopeCursor = 0;
24 DataBuffer* g_IfExpression = null; 51 data_buffer* g_IfExpression = null;
25 bool g_CanElse = false; 52 bool g_CanElse = false;
26 string* g_UndefinedLabels[MAX_MARKS]; 53 string* g_UndefinedLabels[MAX_MARKS];
27 bool g_Neurosphere = false; // neurosphere-compat 54 list<constant_info> g_ConstInfo;
28 list<constinfo_t> g_ConstInfo; 55
56 static botscript_parser* g_current_parser = null;
57
58 // ============================================================================
59 //
60 botscript_parser::botscript_parser() :
61 m_lx (new lexer) {}
62
63 // ============================================================================
64 //
65 botscript_parser::~botscript_parser()
66 {
67 delete m_lx;
68 }
69
70 // ============================================================================
71 //
72 void botscript_parser::check_toplevel()
73 {
74 if (g_CurMode != MODE_TOPLEVEL)
75 error ("%1-statements may only be defined at top level!", TOKEN.chars());
76 }
77
78 // ============================================================================
79 //
80 void botscript_parser::check_not_toplevel()
81 {
82 if (g_CurMode == MODE_TOPLEVEL)
83 error ("%1-statements must not be defined at top level!", TOKEN.chars());
84 }
29 85
30 // ============================================================================ 86 // ============================================================================
31 // Main parser code. Begins read of the script file, checks the syntax of it 87 // Main parser code. Begins read of the script file, checks the syntax of it
32 // and writes the data to the object file via ObjWriter - which also takes care 88 // and writes the data to the object file via Objwriter - which also takes care
33 // of necessary buffering so stuff is written in the correct order. 89 // of necessary buffering so stuff is written in the correct order.
34 void ScriptReader::ParseBotScript (ObjWriter* w) { 90 void botscript_parser::parse_botscript (string file_name, object_writer* w)
91 {
92 // Lex and preprocess the file
93 m_lx->process_file (file_name);
94
35 // Zero the entire block stack first 95 // Zero the entire block stack first
36 for (int i = 0; i < MAX_SCOPE; i++) 96 for (int i = 0; i < MAX_SCOPE; i++)
37 ZERO(scopestack[i]); 97 ZERO (scopestack[i]);
38 98
39 for (int i = 0; i < MAX_MARKS; i++) 99 for (int i = 0; i < MAX_MARKS; i++)
40 g_UndefinedLabels[i] = null; 100 g_UndefinedLabels[i] = null;
41 101
42 while (Next()) { 102 while (m_lx->get_next())
103 {
43 // Check if else is potentically valid 104 // Check if else is potentically valid
44 if (token == "else" && !g_CanElse) 105 if (TOKEN == "else" && !g_CanElse)
45 ParserError ("else without preceding if"); 106 error ("else without preceding if");
46 if (token != "else") 107
108 if (TOKEN != "else")
47 g_CanElse = false; 109 g_CanElse = false;
48 110
49 // ============================================================ 111 switch (m_lx->get_token())
50 if (token == "state") { 112 {
51 MUST_TOPLEVEL 113 case tk_state:
52 114 {
53 MustString (); 115 check_toplevel();
54 116 m_lx->must_get_next (tk_string);
55 // State name must be a word. 117
56 if (token.first (" ") != token.len()) 118 // State name must be a word.
57 ParserError ("state name must be a single word, got `%s`", token.chars()); 119 if (TOKEN.first (" ") != -1)
58 string statename = token; 120 error ("state name must be a single word, got `%1`", TOKEN);
59 121
60 // stateSpawn is special - it *must* be defined. If we 122 string statename = TOKEN;
61 // encountered it, then mark down that we have it. 123
62 if (-token == "statespawn") 124 // stateSpawn is special - it *must* be defined. If we
63 g_stateSpawnDefined = true; 125 // encountered it, then mark down that we have it.
64 126 if (-TOKEN == "statespawn")
65 // Must end in a colon 127 g_stateSpawnDefined = true;
66 MustNext (":"); 128
67 129 // Must end in a colon
68 // Write the previous state's onenter and 130 m_lx->must_get_next (tk_colon);
69 // mainloop buffers to file now 131
70 if (g_CurState.len()) 132 // write the previous state's onenter and
71 w->WriteBuffers(); 133 // mainloop buffers to file now
72 134 if (g_CurState.len())
73 w->Write (DH_STATENAME); 135 w->write (Buffers();
74 w->WriteString (statename); 136
75 w->Write (DH_STATEIDX); 137 w->write (DH_STATENAME);
76 w->Write (g_NumStates); 138 w->write_string (statename);
77 139 w->write (DH_STATEIDX);
78 g_NumStates++; 140 w->write (g_NumStates);
79 g_CurState = token; 141
80 g_GotMainLoop = false; 142 g_NumStates++;
81 continue; 143 g_CurState = TOKEN;
144 g_GotMainLoop = false;
145 }
146 break;
147
148 // ============================================================
149 //
150 case tk_event:
151 {
152 check_toplevel();
153
154 // Event definition
155 m_lx->must_get_next (tk_string);
156
157 event_info* e = find_event_by_name (token_string());
158
159 if (!e)
160 error ("bad event, got `%1`\n", token_string());
161
162 m_lx->must_get_next (tk_brace_start);
163 g_CurMode = MODE_EVENT;
164 w->write (DH_EVENT);
165 w->write (e->number);
166 g_NumEvents++;
167 continue;
168 } break;
169
170 // ============================================================
171 //
172 case tk_mainloop:
173 {
174 check_toplevel();
175 m_lx->must_get_next (tk_brace_start);
176
177 // Mode must be set before dataheader is written here!
178 g_CurMode = MODE_MAINLOOP;
179 w->write (DH_MAINLOOP);
180 }
181 break;
182
183 // ============================================================
184 //
185 case tk_onenter:
186 case tk_onexit:
187 {
188 check_toplevel();
189 bool onenter = (m_lx->get_token() == "onenter");
190 m_lx->must_get_next (tk_brace_start);
191
192 // Mode must be set before dataheader is written here,
193 // because onenter goes to a separate buffer.
194 g_CurMode = onenter ? MODE_ONENTER : MODE_ONEXIT;
195 w->write (onenter ? DH_ONENTER : DH_ONEXIT);
196 }
197 break;
198
199 // ============================================================
200 //
201 case tk_int:
202 case tk_str:
203 case tk_void:
204 {
205 // For now, only globals are supported
206 if (g_CurMode != MODE_TOPLEVEL || g_CurState.len())
207 error ("variables must only be global for now");
208
209 type_e type = (TOKEN == "int") ? TYPE_INT :
210 (TOKEN == "str") ? TYPE_STRING :
211 TYPE_BOOL;
212
213 m_lx->must_get_next();
214
215 // Var name must not be a number
216 if (TOKEN.is_numeric())
217 error ("variable name must not be a number");
218
219 string varname = TOKEN;
220 script_variable* var = DeclareGlobalVariable (this, type, varname);
221 m_lx->must_get_next (tk_semicolon);
222 }
223 break;
224
225 // ============================================================
226 //
227 case tk_goto:
228 {
229 check_not_toplevel();
230
231 // Get the name of the label
232 m_lx->must_get_next();
233
234 // Find the mark this goto statement points to
235 int m = w->find_byte_mark (TOKEN);
236
237 // If not set, define it
238 if (m == MAX_MARKS)
239 {
240 m = w->add_mark (TOKEN);
241 g_UndefinedLabels[m] = new string (TOKEN);
242 }
243
244 // Add a reference to the mark.
245 w->write (DH_GOTO);
246 w->add_reference (m);
247 m_lx->must_get_next (tk_semicolon);
248 continue;
249 }
250
251 // ============================================================
252 //
253 case tk_if:
254 {
255 check_not_toplevel();
256 push_scope();
257
258 // Condition
259 m_lx->must_get_next (tk_paren_start);
260
261 // Read the expression and write it.
262 m_lx->must_get_next();
263 data_buffer* c = parse_expression (TYPE_INT);
264 w->write_buffer (c);
265
266 m_lx->must_get_next (tk_paren_end);
267 m_lx->must_get_next (tk_brace_start);
268
269 // Add a mark - to here temporarily - and add a reference to it.
270 // Upon a closing brace, the mark will be adjusted.
271 int marknum = w->add_mark ("");
272
273 // Use DH_IFNOTGOTO - if the expression is not true, we goto the mark
274 // we just defined - and this mark will be at the end of the scope block.
275 w->write (DH_IFNOTGOTO);
276 w->add_reference (marknum);
277
278 // Store it
279 SCOPE (0).mark1 = marknum;
280 SCOPE (0).type = SCOPETYPE_IF;
281 } break;
282
283 // ============================================================
284 //
285 case tk_else:
286 {
287 check_not_toplevel();
288 m_lx->must_get_next (tk_brace_start);
289
290 // Don't use PushScope as it resets the scope
291 g_ScopeCursor++;
292
293 if (g_ScopeCursor >= MAX_SCOPE)
294 error ("too deep scope");
295
296 if (SCOPE (0).type != SCOPETYPE_IF)
297 error ("else without preceding if");
298
299 // write down to jump to the end of the else statement
300 // Otherwise we have fall-throughs
301 SCOPE (0).mark2 = w->add_mark ("");
302
303 // Instruction to jump to the end after if block is complete
304 w->write (DH_GOTO);
305 w->add_reference (SCOPE (0).mark2);
306
307 // Move the ifnot mark here and set type to else
308 w->move_mark (SCOPE (0).mark1);
309 SCOPE (0).type = SCOPETYPE_ELSE;
310 }
311 break;
312
313 // ============================================================
314 //
315 case tk_while:
316 {
317 check_not_toplevel();
318 push_scope();
319
320 // While loops need two marks - one at the start of the loop and one at the
321 // end. The condition is checked at the very start of the loop, if it fails,
322 // we use goto to skip to the end of the loop. At the end, we loop back to
323 // the beginning with a go-to statement.
324 int mark1 = w->add_mark (""); // start
325 int mark2 = w->add_mark (""); // end
326
327 // Condition
328 m_lx->must_get_next (tk_paren_start);
329 m_lx->must_get_next();
330 data_buffer* expr = parse_expression (TYPE_INT);
331 m_lx->must_get_next (tk_paren_end);
332 m_lx->must_get_next (tk_brace_start);
333
334 // write condition
335 w->write_buffer (expr);
336
337 // Instruction to go to the end if it fails
338 w->write (DH_IFNOTGOTO);
339 w->add_reference (mark2);
340
341 // Store the needed stuff
342 SCOPE (0).mark1 = mark1;
343 SCOPE (0).mark2 = mark2;
344 SCOPE (0).type = SCOPETYPE_WHILE;
345 }
346 break;
347
348 // ============================================================
349 //
350 case tk_for:
351 {
352 check_not_toplevel();
353 push_scope();
354
355 // Initializer
356 m_lx->must_get_next (tk_paren_start);
357 m_lx->must_get_next();
358 data_buffer* init = parse_statement (w);
359
360 if (!init)
361 error ("bad statement for initializer of for");
362
363 m_lx->must_get_next (tk_semicolon);
364
365 // Condition
366 m_lx->must_get_next();
367 data_buffer* cond = parse_expression (TYPE_INT);
368
369 if (!cond)
370 error ("bad statement for condition of for");
371
372 m_lx->must_get_next (tk_semicolon);
373
374 // Incrementor
375 m_lx->must_get_next();
376 data_buffer* incr = parse_statement (w);
377
378 if (!incr)
379 error ("bad statement for incrementor of for");
380
381 m_lx->must_get_next (tk_paren_end);
382 m_lx->must_get_next (tk_brace_start);
383
384 // First, write out the initializer
385 w->write_buffer (init);
386
387 // Init two marks
388 int mark1 = w->add_mark ("");
389 int mark2 = w->add_mark ("");
390
391 // Add the condition
392 w->write_buffer (cond);
393 w->write (DH_IFNOTGOTO);
394 w->add_reference (mark2);
395
396 // Store the marks and incrementor
397 SCOPE (0).mark1 = mark1;
398 SCOPE (0).mark2 = mark2;
399 SCOPE (0).buffer1 = incr;
400 SCOPE (0).type = SCOPETYPE_FOR;
401 }
402 break;
403
404 // ============================================================
405 //
406 case tk_do:
407 {
408 check_not_toplevel();
409 push_scope();
410 m_lx->must_get_next (tk_brace_start);
411 SCOPE (0).mark1 = w->add_mark ("");
412 SCOPE (0).type = SCOPETYPE_DO;
413 }
414 break;
415
416 // ============================================================
417 //
418 case tk_switch:
419 {
420 // This gets a bit tricky. switch is structured in the
421 // bytecode followingly:
422 //
423 // (expression)
424 // case a: goto casemark1
425 // case b: goto casemark2
426 // case c: goto casemark3
427 // goto mark1 // jump to end if no matches
428 // casemark1: ...
429 // casemark2: ...
430 // casemark3: ...
431 // mark1: // end mark
432
433 check_not_toplevel();
434 push_scope();
435 m_lx->must_get_next (tk_paren_start);
436 m_lx->must_get_next();
437 w->write_buffer (parse_expression (TYPE_INT));
438 m_lx->must_get_next (tk_paren_end);
439 m_lx->must_get_next (tk_brace_start);
440 SCOPE (0).type = SCOPETYPE_SWITCH;
441 SCOPE (0).mark1 = w->add_mark (""); // end mark
442 SCOPE (0).buffer1 = null; // default header
443 }
444 break;
445
446 // ============================================================
447 //
448 case tk_case:
449 {
450 // case is only allowed inside switch
451 if (SCOPE (0).type != SCOPETYPE_SWITCH)
452 error ("case label outside switch");
453
454 // Get the literal (Zandronum does not support expressions here)
455 m_lx->must_get_next (tk_number);
456 int num = m_lx->get_token()->text.to_long();
457 m_lx->must_get_next (tk_colon);
458
459 for (int i = 0; i < MAX_CASE; i++)
460 if (SCOPE (0).casenumbers[i] == num)
461 error ("multiple case %d labels in one switch", num);
462
463 // write down the expression and case-go-to. This builds
464 // the case tree. The closing event will write the actual
465 // blocks and move the marks appropriately.
466 // AddSwitchCase will add the reference to the mark
467 // for the case block that this heralds, and takes care
468 // of buffering setup and stuff like that.
469 // null the switch buffer for the case-go-to statement,
470 // we want it all under the switch, not into the case-buffers.
471 w->SwitchBuffer = null;
472 w->write (DH_CASEGOTO);
473 w->write (num);
474 add_switch_case (w, null);
475 SCOPE (0).casenumbers[SCOPE (0).casecursor] = num;
476 }
477 break;
478
479 // ============================================================
480 //
481 case tk_default:
482 {
483 if (SCOPE (0).type != SCOPETYPE_SWITCH)
484 error ("default label outside switch");
485
486 if (SCOPE (0).buffer1)
487 error ("multiple default labels in one switch");
488
489 m_lx->must_get_next (tk_colon);
490
491 // The default header is buffered into buffer1, since
492 // it has to be the last of the case headers
493 //
494 // Since the expression is pushed into the switch
495 // and is only popped when case succeeds, we have
496 // to pop it with DH_DROP manually if we end up in
497 // a default.
498 data_buffer* b = new data_buffer;
499 SCOPE (0).buffer1 = b;
500 b->write (DH_DROP);
501 b->write (DH_GOTO);
502 add_switch_case (w, b);
503 }
504 break;
505
506 // ============================================================
507 //
508 case tk_break:
509 {
510 if (!g_ScopeCursor)
511 error ("unexpected `break`");
512
513 w->write (DH_GOTO);
514
515 // switch and if use mark1 for the closing point,
516 // for and while use mark2.
517 switch (SCOPE (0).type)
518 {
519 case SCOPETYPE_IF:
520 case SCOPETYPE_SWITCH:
521 {
522 w->add_reference (SCOPE (0).mark1);
523 } break;
524
525 case SCOPETYPE_FOR:
526 case SCOPETYPE_WHILE:
527 {
528 w->add_reference (SCOPE (0).mark2);
529 } break;
530
531 default:
532 {
533 error ("unexpected `break`");
534 } break;
535 }
536
537 m_lx->must_get_next (tk_semicolon);
538 }
539 break;
540
541 // ============================================================
542 //
543 case tk_continue:
544 {
545 m_lx->must_get_next (tk_semicolon);
546
547 int curs;
548 bool found = false;
549
550 // Fall through the scope until we find a loop block
551 for (curs = g_ScopeCursor; curs > 0 && !found; curs--)
552 {
553 switch (scopestack[curs].type)
554 {
555 case SCOPETYPE_FOR:
556 case SCOPETYPE_WHILE:
557 case SCOPETYPE_DO:
558 {
559 w->write (DH_GOTO);
560 w->add_reference (scopestack[curs].mark1);
561 found = true;
562 } break;
563
564 default:
565 break;
566 }
567 }
568
569 // No loop blocks
570 if (!found)
571 error ("`continue`-statement not inside a loop");
572 }
573 break;
574
575 case tk_brace_end:
576 {
577 // Closing brace
578 // If we're in the block stack, we're descending down from it now
579 if (g_ScopeCursor > 0)
580 {
581 switch (SCOPE (0).type)
582 {
583 case SCOPETYPE_IF:
584 // Adjust the closing mark.
585 w->move_mark (SCOPE (0).mark1);
586
587 // We're returning from if, thus else can be next
588 g_CanElse = true;
589 break;
590
591 case SCOPETYPE_ELSE:
592 // else instead uses mark1 for itself (so if expression
593 // fails, jump to else), mark2 means end of else
594 w->move_mark (SCOPE (0).mark2);
595 break;
596
597 case SCOPETYPE_FOR:
598 // write the incrementor at the end of the loop block
599 w->write_buffer (SCOPE (0).buffer1);
600
601 // fall-thru
602 case SCOPETYPE_WHILE:
603 // write down the instruction to go back to the start of the loop
604 w->write (DH_GOTO);
605 w->add_reference (SCOPE (0).mark1);
606
607 // Move the closing mark here since we're at the end of the while loop
608 w->move_mark (SCOPE (0).mark2);
609 break;
610
611 case SCOPETYPE_DO:
612 {
613 must_get_next (tk_while);
614 m_lx->must_get_next (tk_paren_start);
615 m_lx->must_get_next();
616 data_buffer* expr = parse_expression (TYPE_INT);
617 m_lx->must_get_next (tk_paren_end);
618 m_lx->must_get_next (tk_semicolon);
619
620 // If the condition runs true, go back to the start.
621 w->write_buffer (expr);
622 w->write (DH_IFGOTO);
623 w->add_reference (SCOPE (0).mark1);
624 break;
625 }
626
627 case SCOPETYPE_SWITCH:
628 {
629 // Switch closes. Move down to the record buffer of
630 // the lower block.
631 if (SCOPE (1).casecursor != -1)
632 w->SwitchBuffer = SCOPE (1).casebuffers[SCOPE (1).casecursor];
633 else
634 w->SwitchBuffer = null;
635
636 // If there was a default in the switch, write its header down now.
637 // If not, write instruction to jump to the end of switch after
638 // the headers (thus won't fall-through if no case matched)
639 if (SCOPE (0).buffer1)
640 w->write_buffer (SCOPE (0).buffer1);
641 else
642 {
643 w->write (DH_DROP);
644 w->write (DH_GOTO);
645 w->add_reference (SCOPE (0).mark1);
646 }
647
648 // Go through all of the buffers we
649 // recorded down and write them.
650 for (int u = 0; u < MAX_CASE; u++)
651 {
652 if (!SCOPE (0).casebuffers[u])
653 continue;
654
655 w->move_mark (SCOPE (0).casemarks[u]);
656 w->write_buffer (SCOPE (0).casebuffers[u]);
657 }
658
659 // Move the closing mark here
660 w->move_mark (SCOPE (0).mark1);
661 break;
662 }
663
664 case SCOPETYPE_UNKNOWN:
665 break;
666 }
667
668 // Descend down the stack
669 g_ScopeCursor--;
670 continue;
671 }
672
673 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT :
674 (g_CurMode == MODE_MAINLOOP) ? DH_ENDMAINLOOP :
675 (g_CurMode == MODE_ONENTER) ? DH_ENDONENTER :
676 (g_CurMode == MODE_ONEXIT) ? DH_ENDONEXIT : -1;
677
678 if (dataheader == -1)
679 error ("unexpected `}`");
680
681 // Data header must be written before mode is changed because
682 // onenter and mainloop go into special buffers, and we want
683 // the closing data headers into said buffers too.
684 w->write (dataheader);
685 g_CurMode = MODE_TOPLEVEL;
686
687 if (PeekNext() == ";")
688 m_lx->must_get_next (tk_semicolon);
689 }
690 break;
691
692 // ============================================================
693 case tk_const:
694 {
695 constant_info info;
696
697 // Get the type
698 m_lx->must_get_next();
699 info.type = GetTypeByName (TOKEN);
700
701 if (info.type == TYPE_UNKNOWN || info.type == TYPE_VOID)
702 error ("unknown type `%s` for constant", TOKEN.c_str());
703
704 m_lx->must_get_next();
705 info.name = TOKEN;
706
707 m_lx->must_get_next (tk_assign);
708
709 switch (info.type)
710 {
711 case TYPE_BOOL:
712 case TYPE_INT:
713 {
714 m_lx->must_get_next (tk_number);
715 info.val = m_lx->get_token()->text.to_long();
716 } break;
717
718 case TYPE_STRING:
719 {
720 m_lx->must_get_next (tk_string);
721 info.val = m_lx->get_token()->text;
722 } break;
723
724 case TYPE_UNKNOWN:
725 case TYPE_VOID:
726 break;
727 }
728
729 g_ConstInfo << info;
730
731 m_lx->must_get_next (tk_semicolon);
732 continue;
733 }
734
735 default:
736 {
737 // ============================================================
738 // Label
739 lexer::token* next;
740 if (m_lx->get_token() == tk_symbol &&
741 m_lx->peek_next (next) &&
742 next->type == tk_colon)
743 {
744 check_not_toplevel();
745 string label_name = token_string();
746
747 // want no conflicts..
748 if (FindCommand (label_name))
749 error ("label name `%s` conflicts with command name\n", label_name);
750
751 if (FindGlobalVariable (label_name))
752 error ("label name `%s` conflicts with variable\n", label_name);
753
754 // See if a mark already exists for this label
755 int mark = -1;
756
757 for (int i = 0; i < MAX_MARKS; i++)
758 {
759 if (g_UndefinedLabels[i] && *g_UndefinedLabels[i] == label_name)
760 {
761 mark = i;
762 w->move_mark (i);
763
764 // No longer undefinde
765 delete g_UndefinedLabels[i];
766 g_UndefinedLabels[i] = null;
767 }
768 }
769
770 // Not found in unmarked lists, define it now
771 if (mark == -1)
772 w->add_mark (label_name);
773
774 m_lx->must_get_next (tk_colon);
775 continue;
776 }
777
778 // Check if it's a command
779 CommandDef* comm = FindCommand (TOKEN);
780
781 if (comm)
782 {
783 w->get_current_buffer()->merge (ParseCommand (comm));
784 m_lx->must_get_next (tk_semicolon);
785 continue;
786 }
787
788 // ============================================================
789 // If nothing else, parse it as a statement
790 data_buffer* b = parse_statement (w);
791
792 if (!b)
793 error ("unknown TOKEN `%s`", TOKEN.chars());
794
795 w->write_buffer (b);
796 m_lx->must_get_next (tk_semicolon);
797 }
798 break;
82 } 799 }
83 800 }
84 // ============================================================ 801
85 if (token == "event") {
86 MUST_TOPLEVEL
87
88 // Event definition
89 MustString ();
90
91 EventDef* e = FindEventByName (token);
92 if (!e)
93 ParserError ("bad event, got `%s`\n", token.chars());
94
95 MustNext ("{");
96
97 g_CurMode = MODE_EVENT;
98
99 w->Write (DH_EVENT);
100 w->Write (e->number);
101 g_NumEvents++;
102 continue;
103 }
104
105 // ============================================================
106 if (token == "mainloop") {
107 MUST_TOPLEVEL
108 MustNext ("{");
109
110 // Mode must be set before dataheader is written here!
111 g_CurMode = MODE_MAINLOOP;
112 w->Write (DH_MAINLOOP);
113 continue;
114 }
115
116 // ============================================================
117 if (token == "onenter" || token == "onexit") {
118 MUST_TOPLEVEL
119 bool onenter = token == "onenter";
120 MustNext ("{");
121
122 // Mode must be set before dataheader is written here,
123 // because onenter goes to a separate buffer.
124 g_CurMode = onenter ? MODE_ONENTER : MODE_ONEXIT;
125 w->Write (onenter ? DH_ONENTER : DH_ONEXIT);
126 continue;
127 }
128
129 // ============================================================
130 if (token == "int" || token == "str" || token == "bool") {
131 // For now, only globals are supported
132 if (g_CurMode != MODE_TOPLEVEL || g_CurState.len())
133 ParserError ("variables must only be global for now");
134
135 type_e type = (token == "int") ? TYPE_INT :
136 (token == "str") ? TYPE_STRING :
137 TYPE_BOOL;
138
139 MustNext ();
140
141 // Var name must not be a number
142 if (token.is_numeric())
143 ParserError ("variable name must not be a number");
144
145 string varname = token;
146 ScriptVar* var = DeclareGlobalVariable (this, type, varname);
147
148 if (!var)
149 ParserError ("declaring %s variable %s failed",
150 g_CurState.len() ? "state" : "global", varname.chars());
151
152 MustNext (";");
153 continue;
154 }
155
156 // ============================================================
157 // Goto
158 if (token == "goto") {
159 MUST_NOT_TOPLEVEL
160
161 // Get the name of the label
162 MustNext ();
163
164 // Find the mark this goto statement points to
165 unsigned int m = w->FindMark (token);
166
167 // If not set, define it
168 if (m == MAX_MARKS) {
169 m = w->AddMark (token);
170 g_UndefinedLabels[m] = new string (token);
171 }
172
173 // Add a reference to the mark.
174 w->Write (DH_GOTO);
175 w->AddReference (m);
176 MustNext (";");
177 continue;
178 }
179
180 // ============================================================
181 // If
182 if (token == "if") {
183 MUST_NOT_TOPLEVEL
184 PushScope ();
185
186 // Condition
187 MustNext ("(");
188
189 // Read the expression and write it.
190 MustNext ();
191 DataBuffer* c = ParseExpression (TYPE_INT);
192 w->WriteBuffer (c);
193
194 MustNext (")");
195 MustNext ("{");
196
197 // Add a mark - to here temporarily - and add a reference to it.
198 // Upon a closing brace, the mark will be adjusted.
199 unsigned int marknum = w->AddMark ("");
200
201 // Use DH_IFNOTGOTO - if the expression is not true, we goto the mark
202 // we just defined - and this mark will be at the end of the scope block.
203 w->Write (DH_IFNOTGOTO);
204 w->AddReference (marknum);
205
206 // Store it
207 SCOPE(0).mark1 = marknum;
208 SCOPE(0).type = SCOPETYPE_IF;
209 continue;
210 }
211
212 if (token == "else") {
213 MUST_NOT_TOPLEVEL
214 MustNext ("{");
215
216 // Don't use PushScope as it resets the scope
217 g_ScopeCursor++;
218 if (g_ScopeCursor >= MAX_SCOPE)
219 ParserError ("too deep scope");
220
221 if (SCOPE(0).type != SCOPETYPE_IF)
222 ParserError ("else without preceding if");
223
224 // Write down to jump to the end of the else statement
225 // Otherwise we have fall-throughs
226 SCOPE(0).mark2 = w->AddMark ("");
227
228 // Instruction to jump to the end after if block is complete
229 w->Write (DH_GOTO);
230 w->AddReference (SCOPE(0).mark2);
231
232 // Move the ifnot mark here and set type to else
233 w->MoveMark (SCOPE(0).mark1);
234 SCOPE(0).type = SCOPETYPE_ELSE;
235 continue;
236 }
237
238 // ============================================================
239 // While
240 if (token == "while") {
241 MUST_NOT_TOPLEVEL
242 PushScope ();
243
244 // While loops need two marks - one at the start of the loop and one at the
245 // end. The condition is checked at the very start of the loop, if it fails,
246 // we use goto to skip to the end of the loop. At the end, we loop back to
247 // the beginning with a go-to statement.
248 unsigned int mark1 = w->AddMark (""); // start
249 unsigned int mark2 = w->AddMark (""); // end
250
251 // Condition
252 MustNext ("(");
253 MustNext ();
254 DataBuffer* expr = ParseExpression (TYPE_INT);
255 MustNext (")");
256 MustNext ("{");
257
258 // Write condition
259 w->WriteBuffer (expr);
260
261 // Instruction to go to the end if it fails
262 w->Write (DH_IFNOTGOTO);
263 w->AddReference (mark2);
264
265 // Store the needed stuff
266 SCOPE(0).mark1 = mark1;
267 SCOPE(0).mark2 = mark2;
268 SCOPE(0).type = SCOPETYPE_WHILE;
269 continue;
270 }
271
272 // ============================================================
273 // For loop
274 if (token == "for") {
275 MUST_NOT_TOPLEVEL
276 PushScope ();
277
278 // Initializer
279 MustNext ("(");
280 MustNext ();
281 DataBuffer* init = ParseStatement (w);
282 if (!init)
283 ParserError ("bad statement for initializer of for");
284
285 MustNext (";");
286
287 // Condition
288 MustNext ();
289 DataBuffer* cond = ParseExpression (TYPE_INT);
290 if (!cond)
291 ParserError ("bad statement for condition of for");
292
293 MustNext (";");
294
295 // Incrementor
296 MustNext ();
297 DataBuffer* incr = ParseStatement (w);
298 if (!incr)
299 ParserError ("bad statement for incrementor of for");
300
301 MustNext (")");
302 MustNext ("{");
303
304 // First, write out the initializer
305 w->WriteBuffer (init);
306
307 // Init two marks
308 int mark1 = w->AddMark ("");
309 int mark2 = w->AddMark ("");
310
311 // Add the condition
312 w->WriteBuffer (cond);
313 w->Write (DH_IFNOTGOTO);
314 w->AddReference (mark2);
315
316 // Store the marks and incrementor
317 SCOPE(0).mark1 = mark1;
318 SCOPE(0).mark2 = mark2;
319 SCOPE(0).buffer1 = incr;
320 SCOPE(0).type = SCOPETYPE_FOR;
321 continue;
322 }
323
324 // ============================================================
325 // Do/while loop
326 if (token == "do") {
327 MUST_NOT_TOPLEVEL
328 PushScope ();
329 MustNext ("{");
330 SCOPE(0).mark1 = w->AddMark ("");
331 SCOPE(0).type = SCOPETYPE_DO;
332 continue;
333 }
334
335 // ============================================================
336 // Switch
337 if (token == "switch") {
338 /* This goes a bit tricky. switch is structured in the
339 * bytecode followingly:
340 * (expression)
341 * case a: goto casemark1
342 * case b: goto casemark2
343 * case c: goto casemark3
344 * goto mark1 // jump to end if no matches
345 * casemark1: ...
346 * casemark2: ...
347 * casemark3: ...
348 * mark1: // end mark
349 */
350
351 MUST_NOT_TOPLEVEL
352 PushScope ();
353 MustNext ("(");
354 MustNext ();
355 w->WriteBuffer (ParseExpression (TYPE_INT));
356 MustNext (")");
357 MustNext ("{");
358 SCOPE(0).type = SCOPETYPE_SWITCH;
359 SCOPE(0).mark1 = w->AddMark (""); // end mark
360 SCOPE(0).buffer1 = null; // default header
361 continue;
362 }
363
364 // ============================================================
365 if (token == "case") {
366 // case is only allowed inside switch
367 if (SCOPE(0).type != SCOPETYPE_SWITCH)
368 ParserError ("case label outside switch");
369
370 // Get the literal (Zandronum does not support expressions here)
371 MustNumber ();
372 int num = atoi (token.chars ());
373 MustNext (":");
374
375 for (int i = 0; i < MAX_CASE; i++)
376 if (SCOPE(0).casenumbers[i] == num)
377 ParserError ("multiple case %d labels in one switch", num);
378
379 // Write down the expression and case-go-to. This builds
380 // the case tree. The closing event will write the actual
381 // blocks and move the marks appropriately.
382 // AddSwitchCase will add the reference to the mark
383 // for the case block that this heralds, and takes care
384 // of buffering setup and stuff like that.
385 // null the switch buffer for the case-go-to statement,
386 // we want it all under the switch, not into the case-buffers.
387 w->SwitchBuffer = null;
388 w->Write (DH_CASEGOTO);
389 w->Write (num);
390 AddSwitchCase (w, null);
391 SCOPE(0).casenumbers[SCOPE(0).casecursor] = num;
392 continue;
393 }
394
395 if (token == "default") {
396 if (SCOPE(0).type != SCOPETYPE_SWITCH)
397 ParserError ("default label outside switch");
398
399 if (SCOPE(0).buffer1)
400 ParserError ("multiple default labels in one switch");
401
402 MustNext (":");
403
404 // The default header is buffered into buffer1, since
405 // it has to be the last of the case headers
406 //
407 // Since the expression is pushed into the switch
408 // and is only popped when case succeeds, we have
409 // to pop it with DH_DROP manually if we end up in
410 // a default.
411 DataBuffer* b = new DataBuffer;
412 SCOPE(0).buffer1 = b;
413 b->Write (DH_DROP);
414 b->Write (DH_GOTO);
415 AddSwitchCase (w, b);
416 continue;
417 }
418
419 // ============================================================
420 // Break statement.
421 if (token == "break") {
422 if (!g_ScopeCursor)
423 ParserError ("unexpected `break`");
424
425 w->Write (DH_GOTO);
426
427 // switch and if use mark1 for the closing point,
428 // for and while use mark2.
429 switch (SCOPE(0).type) {
430 case SCOPETYPE_IF:
431 case SCOPETYPE_SWITCH:
432 w->AddReference (SCOPE(0).mark1);
433 break;
434 case SCOPETYPE_FOR:
435 case SCOPETYPE_WHILE:
436 w->AddReference (SCOPE(0).mark2);
437 break;
438 default:
439 ParserError ("unexpected `break`");
440 break;
441 }
442
443 MustNext (";");
444 continue;
445 }
446
447 // ============================================================
448 // Continue
449 if (token == "continue") {
450 MustNext (";");
451
452 int curs;
453 bool found = false;
454
455 // Drop through the scope until we find a loop block
456 for (curs = g_ScopeCursor; curs > 0 && !found; curs--) {
457 switch (scopestack[curs].type) {
458 case SCOPETYPE_FOR:
459 case SCOPETYPE_WHILE:
460 case SCOPETYPE_DO:
461 w->Write (DH_GOTO);
462 w->AddReference (scopestack[curs].mark1);
463 found = true;
464 break;
465 default:
466 break;
467 }
468 }
469
470 // No loop blocks
471 if (!found)
472 ParserError ("`continue`-statement not inside a loop");
473
474 continue;
475 }
476
477 // ============================================================
478 // Label
479 if (PeekNext() == ":") {
480 MUST_NOT_TOPLEVEL
481
482 // want no conflicts..
483 if (IsKeyword (token))
484 ParserError ("label name `%s` conflicts with keyword\n", token.chars());
485 if (FindCommand (token))
486 ParserError ("label name `%s` conflicts with command name\n", token.chars());
487 if (FindGlobalVariable (token))
488 ParserError ("label name `%s` conflicts with variable\n", token.chars());
489
490 // See if a mark already exists for this label
491 int mark = -1;
492 for (int i = 0; i < MAX_MARKS; i++) {
493 if (g_UndefinedLabels[i] && *g_UndefinedLabels[i] == token) {
494 mark = i;
495 w->MoveMark (i);
496
497 // No longer undefinde
498 delete g_UndefinedLabels[i];
499 g_UndefinedLabels[i] = null;
500 }
501 }
502
503 // Not found in unmarked lists, define it now
504 if (mark == -1)
505 w->AddMark (token);
506
507 MustNext (":");
508 continue;
509 }
510
511 // ============================================================
512 if (token == "const") {
513 constinfo_t info;
514
515 // Get the type
516 MustNext ();
517 info.type = GetTypeByName (token);
518
519 if (info.type == TYPE_UNKNOWN || info.type == TYPE_VOID)
520 ParserError ("unknown type `%s` for constant", token.c_str());
521
522 MustNext ();
523 info.name = token;
524
525 MustNext ("=");
526
527 switch (info.type) {
528 case TYPE_BOOL:
529 case TYPE_INT:
530 MustNumber (false);
531 info.val = token;
532 break;
533 case TYPE_STRING:
534 MustString ();
535 info.val = token;
536 break;
537 case TYPE_UNKNOWN:
538 case TYPE_VOID:
539 break;
540 }
541
542 g_ConstInfo << info;
543
544 MustNext (";");
545 continue;
546 }
547
548 // ============================================================
549 if (token == "}") {
550 // Closing brace
551
552 // If we're in the block stack, we're descending down from it now
553 if (g_ScopeCursor > 0) {
554 switch (SCOPE(0).type) {
555 case SCOPETYPE_IF:
556 // Adjust the closing mark.
557 w->MoveMark (SCOPE(0).mark1);
558
559 // We're returning from if, thus else can be next
560 g_CanElse = true;
561 break;
562 case SCOPETYPE_ELSE:
563 // else instead uses mark1 for itself (so if expression
564 // fails, jump to else), mark2 means end of else
565 w->MoveMark (SCOPE(0).mark2);
566 break;
567 case SCOPETYPE_FOR:
568 // Write the incrementor at the end of the loop block
569 w->WriteBuffer (SCOPE(0).buffer1);
570 // fall-thru
571 case SCOPETYPE_WHILE:
572 // Write down the instruction to go back to the start of the loop
573 w->Write (DH_GOTO);
574 w->AddReference (SCOPE(0).mark1);
575
576 // Move the closing mark here since we're at the end of the while loop
577 w->MoveMark (SCOPE(0).mark2);
578 break;
579 case SCOPETYPE_DO: {
580 MustNext ("while");
581 MustNext ("(");
582 MustNext ();
583 DataBuffer* expr = ParseExpression (TYPE_INT);
584 MustNext (")");
585 MustNext (";");
586
587 // If the condition runs true, go back to the start.
588 w->WriteBuffer (expr);
589 w->Write (DH_IFGOTO);
590 w->AddReference (SCOPE(0).mark1);
591 break;
592 }
593 case SCOPETYPE_SWITCH: {
594 // Switch closes. Move down to the record buffer of
595 // the lower block.
596 if (SCOPE(1).casecursor != -1)
597 w->SwitchBuffer = SCOPE(1).casebuffers[SCOPE(1).casecursor];
598 else
599 w->SwitchBuffer = null;
600
601 // If there was a default in the switch, write its header down now.
602 // If not, write instruction to jump to the end of switch after
603 // the headers (thus won't fall-through if no case matched)
604 if (SCOPE(0).buffer1)
605 w->WriteBuffer (SCOPE(0).buffer1);
606 else {
607 w->Write (DH_DROP);
608 w->Write (DH_GOTO);
609 w->AddReference (SCOPE(0).mark1);
610 }
611
612 // Go through all of the buffers we
613 // recorded down and write them.
614 for (unsigned int u = 0; u < MAX_CASE; u++) {
615 if (!SCOPE(0).casebuffers[u])
616 continue;
617
618 w->MoveMark (SCOPE(0).casemarks[u]);
619 w->WriteBuffer (SCOPE(0).casebuffers[u]);
620 }
621
622 // Move the closing mark here
623 w->MoveMark (SCOPE(0).mark1);
624 break;
625 }
626 case SCOPETYPE_UNKNOWN:
627 break;
628 }
629
630 // Descend down the stack
631 g_ScopeCursor--;
632 continue;
633 }
634
635 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT :
636 (g_CurMode == MODE_MAINLOOP) ? DH_ENDMAINLOOP :
637 (g_CurMode == MODE_ONENTER) ? DH_ENDONENTER :
638 (g_CurMode == MODE_ONEXIT) ? DH_ENDONEXIT : -1;
639
640 if (dataheader == -1)
641 ParserError ("unexpected `}`");
642
643 // Data header must be written before mode is changed because
644 // onenter and mainloop go into special buffers, and we want
645 // the closing data headers into said buffers too.
646 w->Write (dataheader);
647 g_CurMode = MODE_TOPLEVEL;
648
649 if (PeekNext() == ";")
650 MustNext (";");
651 continue;
652 }
653
654 // Check if it's a command
655 CommandDef* comm = FindCommand (token);
656 if (comm) {
657 w->GetCurrentBuffer()->Merge (ParseCommand (comm));
658 MustNext (";");
659 continue;
660 }
661
662 // ============================================================
663 // If nothing else, parse it as a statement
664 DataBuffer* b = ParseStatement (w);
665 if (!b)
666 ParserError ("unknown token `%s`", token.chars());
667
668 w->WriteBuffer (b);
669 MustNext (";");
670 }
671
672 // =============================================================================== 802 // ===============================================================================
673 // Script file ended. Do some last checks and write the last things to main buffer 803 // Script file ended. Do some last checks and write the last things to main buffer
674 if (g_CurMode != MODE_TOPLEVEL) 804 if (g_CurMode != MODE_TOPLEVEL)
675 ParserError ("script did not end at top level; did you forget a `}`?"); 805 error ("script did not end at top level; a `}` is missing somewhere");
676 806
677 // stateSpawn must be defined! 807 // stateSpawn must be defined!
678 if (!g_stateSpawnDefined) 808 if (!g_stateSpawnDefined)
679 ParserError ("script must have a state named `stateSpawn`!"); 809 error ("script must have a state named `stateSpawn`!");
680 810
681 for (int i = 0; i < MAX_MARKS; i++) 811 for (int i = 0; i < MAX_MARKS; i++)
682 if (g_UndefinedLabels[i]) 812 if (g_UndefinedLabels[i])
683 ParserError ("label `%s` is referenced via `goto` but isn't defined\n", g_UndefinedLabels[i]->chars()); 813 error ("label `%s` is referenced via `goto` but isn't defined\n", g_UndefinedLabels[i]->chars());
684 814
685 // Dump the last state's onenter and mainloop 815 // Dump the last state's onenter and mainloop
686 w->WriteBuffers (); 816 w->write_member_buffers();
687 817
688 // String table 818 // String table
689 w->WriteStringTable (); 819 w->write_string_table();
690 } 820 }
691 821
692 // ============================================================================ 822 // ============================================================================
693 // Parses a command call 823 // Parses a command call
694 DataBuffer* ScriptReader::ParseCommand (CommandDef* comm) { 824 data_buffer* botscript_parser::ParseCommand (CommandDef* comm)
695 DataBuffer* r = new DataBuffer(64); 825 {
826 data_buffer* r = new data_buffer (64);
827
696 if (g_CurMode == MODE_TOPLEVEL) 828 if (g_CurMode == MODE_TOPLEVEL)
697 ParserError ("command call at top level"); 829 error ("command call at top level");
698 830
699 MustNext ("("); 831 m_lx->must_get_next (tk_paren_start);
700 MustNext (); 832 m_lx->must_get_next();
701 833
702 int curarg = 0; 834 int curarg = 0;
703 while (1) { 835
704 if (token == ")") { 836 while (1)
837 {
838 if (m_lx->get_token() == tk_paren_end)
839 {
705 if (curarg < comm->numargs) 840 if (curarg < comm->numargs)
706 ParserError ("too few arguments passed to %s\n\tprototype: %s", 841 error ("too few arguments passed to %s\n\tprototype: %s",
707 comm->name.chars(), GetCommandPrototype (comm).chars()); 842 comm->name.chars(), GetCommandPrototype (comm).chars());
843
708 break; 844 break;
709 curarg++; 845 curarg++;
710 } 846 }
711 847
712 if (curarg >= comm->maxargs) 848 if (curarg >= comm->maxargs)
713 ParserError ("too many arguments passed to %s\n\tprototype: %s", 849 error ("too many arguments passed to %s\n\tprototype: %s",
714 comm->name.chars(), GetCommandPrototype (comm).chars()); 850 comm->name.chars(), GetCommandPrototype (comm).chars());
715 851
716 r->Merge (ParseExpression (comm->argtypes[curarg])); 852 r->merge (parse_expression (comm->argtypes[curarg]));
717 MustNext (); 853 m_lx->must_get_next();
718 854
719 if (curarg < comm->numargs - 1) { 855 if (curarg < comm->numargs - 1)
720 MustThis (","); 856 {
721 MustNext (); 857 m_lx->must_be (tk_comma);
722 } else if (curarg < comm->maxargs - 1) { 858 m_lx->must_get_next();
859 }
860 else if (curarg < comm->maxargs - 1)
861 {
723 // Can continue, but can terminate as well. 862 // Can continue, but can terminate as well.
724 if (token == ")") { 863 if (m_lx->get_token() == tk_paren_end)
864 {
725 curarg++; 865 curarg++;
726 break; 866 break;
727 } else { 867 }
728 MustThis (","); 868 else
729 MustNext (); 869 {
870 m_lx->must_be (tk_comma);
871 m_lx->must_get_next();
730 } 872 }
731 } 873 }
732 874
733 curarg++; 875 curarg++;
734 } 876 }
735 877
736 // If the script skipped any optional arguments, fill in defaults. 878 // If the script skipped any optional arguments, fill in defaults.
737 while (curarg < comm->maxargs) { 879 while (curarg < comm->maxargs)
738 r->Write (DH_PUSHNUMBER); 880 {
739 r->Write (comm->defvals[curarg]); 881 r->write (DH_PUSHNUMBER);
882 r->write (comm->defvals[curarg]);
740 curarg++; 883 curarg++;
741 } 884 }
742 885
743 r->Write (DH_COMMAND); 886 r->write (DH_COMMAND);
744 r->Write (comm->number); 887 r->write (comm->number);
745 r->Write (comm->maxargs); 888 r->write (comm->maxargs);
746 889
747 return r; 890 return r;
748 } 891 }
749 892
750 // ============================================================================ 893 // ============================================================================
751 // Is the given operator an assignment operator? 894 // Is the given operator an assignment operator?
752 static bool IsAssignmentOperator (int oper) { 895 static bool is_assignment_operator (int oper)
753 switch (oper) { 896 {
754 case OPER_ASSIGNADD: 897 switch (oper)
755 case OPER_ASSIGNSUB: 898 {
756 case OPER_ASSIGNMUL: 899 case OPER_ASSIGNADD:
757 case OPER_ASSIGNDIV: 900 case OPER_ASSIGNSUB:
758 case OPER_ASSIGNMOD: 901 case OPER_ASSIGNMUL:
759 case OPER_ASSIGNLEFTSHIFT: 902 case OPER_ASSIGNDIV:
760 case OPER_ASSIGNRIGHTSHIFT: 903 case OPER_ASSIGNMOD:
761 case OPER_ASSIGN: 904 case OPER_ASSIGNLEFTSHIFT:
762 return true; 905 case OPER_ASSIGNRIGHTSHIFT:
763 } 906 case OPER_ASSIGN:
907 return true;
908 }
909
764 return false; 910 return false;
765 } 911 }
766 912
767 // ============================================================================ 913 // ============================================================================
768 // Finds an operator's corresponding dataheader 914 // Finds an operator's corresponding dataheader
769 static word DataHeaderByOperator (ScriptVar* var, int oper) { 915 static word get_data_header_by_operator (script_variable* var, int oper)
770 if (IsAssignmentOperator (oper)) { 916 {
917 if (is_assignment_operator (oper))
918 {
771 if (!var) 919 if (!var)
772 error ("operator %d requires left operand to be a variable\n", oper); 920 error ("operator %d requires left operand to be a variable\n", oper);
773 921
774 // TODO: At the moment, vars only are global 922 // TODO: At the moment, vars only are global
775 // OPER_ASSIGNLEFTSHIFT and OPER_ASSIGNRIGHTSHIFT do not 923 // OPER_ASSIGNLEFTSHIFT and OPER_ASSIGNRIGHTSHIFT do not
776 // have data headers, instead they are expanded out in 924 // have data headers, instead they are expanded out in
777 // the operator parser 925 // the operator parser
778 switch (oper) { 926 switch (oper)
779 case OPER_ASSIGNADD: return DH_ADDGLOBALVAR; 927 {
780 case OPER_ASSIGNSUB: return DH_SUBGLOBALVAR; 928 case OPER_ASSIGNADD: return DH_ADDGLOBALVAR;
781 case OPER_ASSIGNMUL: return DH_MULGLOBALVAR; 929 case OPER_ASSIGNSUB: return DH_SUBGLOBALVAR;
782 case OPER_ASSIGNDIV: return DH_DIVGLOBALVAR; 930 case OPER_ASSIGNMUL: return DH_MULGLOBALVAR;
783 case OPER_ASSIGNMOD: return DH_MODGLOBALVAR; 931 case OPER_ASSIGNDIV: return DH_DIVGLOBALVAR;
784 case OPER_ASSIGN: return DH_ASSIGNGLOBALVAR; 932 case OPER_ASSIGNMOD: return DH_MODGLOBALVAR;
785 default: error ("bad assignment operator!!\n"); 933 case OPER_ASSIGN: return DH_ASSIGNGLOBALVAR;
934
935 default: error ("bad assignment operator!!\n");
786 } 936 }
787 } 937 }
788 938
789 switch (oper) { 939 switch (oper)
940 {
790 case OPER_ADD: return DH_ADD; 941 case OPER_ADD: return DH_ADD;
791 case OPER_SUBTRACT: return DH_SUBTRACT; 942 case OPER_SUBTRACT: return DH_SUBTRACT;
792 case OPER_MULTIPLY: return DH_MULTIPLY; 943 case OPER_MULTIPLY: return DH_MULTIPLY;
793 case OPER_DIVIDE: return DH_DIVIDE; 944 case OPER_DIVIDE: return DH_DIVIDE;
794 case OPER_MODULUS: return DH_MODULUS; 945 case OPER_MODULUS: return DH_MODULUS;
804 case OPER_AND: return DH_ANDLOGICAL; 955 case OPER_AND: return DH_ANDLOGICAL;
805 case OPER_BITWISEOR: return DH_ORBITWISE; 956 case OPER_BITWISEOR: return DH_ORBITWISE;
806 case OPER_BITWISEEOR: return DH_EORBITWISE; 957 case OPER_BITWISEEOR: return DH_EORBITWISE;
807 case OPER_BITWISEAND: return DH_ANDBITWISE; 958 case OPER_BITWISEAND: return DH_ANDBITWISE;
808 } 959 }
809 960
810 error ("DataHeaderByOperator: couldn't find dataheader for operator %d!\n", oper); 961 error ("DataHeaderByOperator: couldn't find dataheader for operator %d!\n", oper);
811 return 0; 962 return 0;
812 } 963 }
813 964
814 // ============================================================================ 965 // ============================================================================
815 // Parses an expression, potentially recursively 966 // Parses an expression, potentially recursively
816 DataBuffer* ScriptReader::ParseExpression (type_e reqtype) { 967 data_buffer* botscript_parser::parse_expression (type_e reqtype)
817 DataBuffer* retbuf = new DataBuffer (64); 968 {
818 969 data_buffer* retbuf = new data_buffer (64);
970
819 // Parse first operand 971 // Parse first operand
820 retbuf->Merge (ParseExprValue (reqtype)); 972 retbuf->merge (parse_expr_value (reqtype));
821 973
822 // Parse any and all operators we get 974 // Parse any and all operators we get
823 int oper; 975 int oper;
824 while ((oper = ParseOperator (true)) != -1) { 976
977 while ( (oper = parse_operator (true)) != -1)
978 {
825 // We peeked the operator, move forward now 979 // We peeked the operator, move forward now
826 Next (); 980 Next();
827 981
828 // Can't be an assignement operator, those belong in assignments. 982 // Can't be an assignement operator, those belong in assignments.
829 if (IsAssignmentOperator (oper)) 983 if (is_assignment_operator (oper))
830 ParserError ("assignment operator inside expression"); 984 error ("assignment operator inside expression");
831 985
832 // Parse the right operand. 986 // Parse the right operand.
833 MustNext (); 987 m_lx->must_get_next();
834 DataBuffer* rb = ParseExprValue (reqtype); 988 data_buffer* rb = parse_expr_value (reqtype);
835 989
836 if (oper == OPER_TERNARY) { 990 if (oper == OPER_TERNARY)
991 {
837 // Ternary operator requires - naturally - a third operand. 992 // Ternary operator requires - naturally - a third operand.
838 MustNext (":"); 993 m_lx->must_get_next (tk_colon);
839 MustNext (); 994 m_lx->must_get_next();
840 DataBuffer* tb = ParseExprValue (reqtype); 995 data_buffer* tb = parse_expr_value (reqtype);
841 996
842 // It also is handled differently: there isn't a dataheader for ternary 997 // It also is handled differently: there isn't a dataheader for ternary
843 // operator. Instead, we abuse PUSHNUMBER and IFNOTGOTO for this. 998 // operator. Instead, we abuse PUSHNUMBER and IFNOTGOTO for this.
844 // Behold, big block of writing madness! :P 999 // Behold, big block of writing madness! :P
845 int mark1 = retbuf->AddMark (""); // start of "else" case 1000 int mark1 = retbuf->add_mark (""); // start of "else" case
846 int mark2 = retbuf->AddMark (""); // end of expression 1001 int mark2 = retbuf->add_mark (""); // end of expression
847 retbuf->Write (DH_IFNOTGOTO); // if the first operand (condition) 1002 retbuf->write (DH_IFNOTGOTO); // if the first operand (condition)
848 retbuf->AddMarkReference (mark1); // didn't eval true, jump into mark1 1003 retbuf->add_reference (mark1); // didn't eval true, jump into mark1
849 retbuf->Merge (rb); // otherwise, perform second operand (true case) 1004 retbuf->merge (rb); // otherwise, perform second operand (true case)
850 retbuf->Write (DH_GOTO); // afterwards, jump to the end, which is 1005 retbuf->write (DH_GOTO); // afterwards, jump to the end, which is
851 retbuf->AddMarkReference (mark2); // marked by mark2. 1006 retbuf->add_reference (mark2); // marked by mark2.
852 retbuf->MoveMark (mark1); // move mark1 at the end of the true case 1007 retbuf->move_mark (mark1); // move mark1 at the end of the true case
853 retbuf->Merge (tb); // perform third operand (false case) 1008 retbuf->merge (tb); // perform third operand (false case)
854 retbuf->MoveMark (mark2); // move the ending mark2 here 1009 retbuf->move_mark (mark2); // move the ending mark2 here
855 } else {
856 // Write to buffer
857 retbuf->Merge (rb);
858 retbuf->Write (DataHeaderByOperator (null, oper));
859 } 1010 }
860 } 1011 else
861 1012 {
1013 // write to buffer
1014 retbuf->merge (rb);
1015 retbuf->write (get_data_header_by_operator (null, oper));
1016 }
1017 }
1018
862 return retbuf; 1019 return retbuf;
863 } 1020 }
864 1021
865 // ============================================================================ 1022 // ============================================================================
866 // Parses an operator string. Returns the operator number code. 1023 // Parses an operator string. Returns the operator number code.
867 #define ISNEXT(C) (PeekNext (peek ? 1 : 0) == C) 1024 #define ISNEXT(C) (PeekNext (peek ? 1 : 0) == C)
868 int ScriptReader::ParseOperator (bool peek) { 1025 int botscript_parser::parse_operator (bool peek)
1026 {
869 string oper; 1027 string oper;
1028
870 if (peek) 1029 if (peek)
871 oper += PeekNext (); 1030 oper += PeekNext();
872 else 1031 else
873 oper += token; 1032 oper += TOKEN;
874 1033
875 if (-oper == "strlen") 1034 if (-oper == "strlen")
876 return OPER_STRLEN; 1035 return OPER_STRLEN;
877 1036
878 // Check one-char operators 1037 // Check one-char operators
879 bool equalsnext = ISNEXT ("="); 1038 bool equalsnext = ISNEXT ("=");
880 1039
881 int o = (oper == "=" && !equalsnext) ? OPER_ASSIGN : 1040 int o = (oper == "=" && !equalsnext) ? OPER_ASSIGN :
882 (oper == ">" && !equalsnext && !ISNEXT (">")) ? OPER_GREATERTHAN : 1041 (oper == ">" && !equalsnext && !ISNEXT (">")) ? OPER_GREATERTHAN :
883 (oper == "<" && !equalsnext && !ISNEXT ("<")) ? OPER_LESSTHAN : 1042 (oper == "<" && !equalsnext && !ISNEXT ("<")) ? OPER_LESSTHAN :
884 (oper == "&" && !ISNEXT ("&")) ? OPER_BITWISEAND : 1043 (oper == "&" && !ISNEXT ("&")) ? OPER_BITWISEAND :
885 (oper == "|" && !ISNEXT ("|")) ? OPER_BITWISEOR : 1044 (oper == "|" && !ISNEXT ("|")) ? OPER_BITWISEOR :
886 (oper == "+" && !equalsnext) ? OPER_ADD : 1045 (oper == "+" && !equalsnext) ? OPER_ADD :
887 (oper == "-" && !equalsnext) ? OPER_SUBTRACT : 1046 (oper == "-" && !equalsnext) ? OPER_SUBTRACT :
888 (oper == "*" && !equalsnext) ? OPER_MULTIPLY : 1047 (oper == "*" && !equalsnext) ? OPER_MULTIPLY :
889 (oper == "/" && !equalsnext) ? OPER_DIVIDE : 1048 (oper == "/" && !equalsnext) ? OPER_DIVIDE :
890 (oper == "%" && !equalsnext) ? OPER_MODULUS : 1049 (oper == "%" && !equalsnext) ? OPER_MODULUS :
891 (oper == "^") ? OPER_BITWISEEOR : 1050 (oper == "^") ? OPER_BITWISEEOR :
892 (oper == "?") ? OPER_TERNARY : 1051 (oper == "?") ? OPER_TERNARY :
893 -1; 1052 -1;
894 1053
895 if (o != -1) { 1054 if (o != -1)
1055 {
896 return o; 1056 return o;
897 } 1057 }
898 1058
899 // Two-char operators 1059 // Two-char operators
900 oper += PeekNext (peek ? 1 : 0); 1060 oper += PeekNext (peek ? 1 : 0);
901 equalsnext = PeekNext (peek ? 2 : 1) == ("="); 1061 equalsnext = PeekNext (peek ? 2 : 1) == ("=");
902 1062
903 o = (oper == "+=") ? OPER_ASSIGNADD : 1063 o = (oper == "+=") ? OPER_ASSIGNADD :
904 (oper == "-=") ? OPER_ASSIGNSUB : 1064 (oper == "-=") ? OPER_ASSIGNSUB :
905 (oper == "*=") ? OPER_ASSIGNMUL : 1065 (oper == "*=") ? OPER_ASSIGNMUL :
906 (oper == "/=") ? OPER_ASSIGNDIV : 1066 (oper == "/=") ? OPER_ASSIGNDIV :
907 (oper == "%=") ? OPER_ASSIGNMOD : 1067 (oper == "%=") ? OPER_ASSIGNMOD :
912 (oper == "&&") ? OPER_AND : 1072 (oper == "&&") ? OPER_AND :
913 (oper == "||") ? OPER_OR : 1073 (oper == "||") ? OPER_OR :
914 (oper == "<<" && !equalsnext) ? OPER_LEFTSHIFT : 1074 (oper == "<<" && !equalsnext) ? OPER_LEFTSHIFT :
915 (oper == ">>" && !equalsnext) ? OPER_RIGHTSHIFT : 1075 (oper == ">>" && !equalsnext) ? OPER_RIGHTSHIFT :
916 -1; 1076 -1;
917 1077
918 if (o != -1) { 1078 if (o != -1)
919 MustNext (); 1079 {
1080 m_lx->must_get_next();
920 return o; 1081 return o;
921 } 1082 }
922 1083
923 // Three-char opers 1084 // Three-char opers
924 oper += PeekNext (peek ? 2 : 1); 1085 oper += PeekNext (peek ? 2 : 1);
925 o = oper == "<<=" ? OPER_ASSIGNLEFTSHIFT : 1086 o = oper == "<<=" ? OPER_ASSIGNLEFTSHIFT :
926 oper == ">>=" ? OPER_ASSIGNRIGHTSHIFT : 1087 oper == ">>=" ? OPER_ASSIGNRIGHTSHIFT :
927 -1; 1088 -1;
928 1089
929 if (o != -1) { 1090 if (o != -1)
930 MustNext (); 1091 {
931 MustNext (); 1092 m_lx->must_get_next();
932 } 1093 m_lx->must_get_next();
933 1094 }
1095
934 return o; 1096 return o;
935 } 1097 }
936 1098
937 // ============================================================================ 1099 // ============================================================================
938 string ScriptReader::ParseFloat () { 1100 string botscript_parser::parse_float()
939 MustNumber (true); 1101 {
940 string floatstring = token; 1102 m_lx->must_be (tk_number);
941 1103 string floatstring = TOKEN;
1104 lexer::token* tok;
1105
942 // Go after the decimal point 1106 // Go after the decimal point
943 if (PeekNext () == ".") { 1107 if (m_lx->peek_next (tok) && tok->type == tk_dot)
944 Next ("."); 1108 {
945 MustNumber (false); 1109 m_lx->skip();
1110 m_lx->must_get_next (tk_number);
946 floatstring += "."; 1111 floatstring += ".";
947 floatstring += token; 1112 floatstring += token_string();
948 } 1113 }
949 1114
950 return floatstring; 1115 return floatstring;
951 } 1116 }
952 1117
953 // ============================================================================ 1118 // ============================================================================
954 // Parses a value in the expression and returns the data needed to push 1119 // Parses a value in the expression and returns the data needed to push
955 // it, contained in a data buffer. A value can be either a variable, a command, 1120 // it, contained in a data buffer. A value can be either a variable, a command,
956 // a literal or an expression. 1121 // a literal or an expression.
957 DataBuffer* ScriptReader::ParseExprValue (type_e reqtype) { 1122 data_buffer* botscript_parser::parse_expr_value (type_e reqtype)
958 DataBuffer* b = new DataBuffer(16); 1123 {
959 1124 data_buffer* b = new data_buffer (16);
960 ScriptVar* g; 1125
961 1126 script_variable* g;
1127
962 // Prefixing "!" means negation. 1128 // Prefixing "!" means negation.
963 bool negate = (token == "!"); 1129 bool negate = (m_lx->get_token() == tk_exclamation_mark);
1130
964 if (negate) // Jump past the "!" 1131 if (negate) // Jump past the "!"
965 Next (); 1132 m_lx->skip();
966 1133
967 // Handle strlen 1134 // Handle strlen
968 if (token == "strlen") { 1135 if (TOKEN == "strlen")
969 MustNext ("("); 1136 {
970 MustNext (); 1137 m_lx->must_get_next (tk_paren_start);
971 1138 m_lx->must_get_next();
972 // By this token we should get a string constant. 1139
973 constinfo_t* constant = FindConstant (token); 1140 // By this TOKEN we should get a string constant.
1141 constant_info* constant = find_constant (TOKEN);
1142
974 if (!constant || constant->type != TYPE_STRING) 1143 if (!constant || constant->type != TYPE_STRING)
975 ParserError ("strlen only works with const str"); 1144 error ("strlen only works with const str");
976 1145
977 if (reqtype != TYPE_INT) 1146 if (reqtype != TYPE_INT)
978 ParserError ("strlen returns int but %s is expected\n", GetTypeName (reqtype).c_str()); 1147 error ("strlen returns int but %s is expected\n", GetTypeName (reqtype).c_str());
979 1148
980 b->Write (DH_PUSHNUMBER); 1149 b->write (DH_PUSHNUMBER);
981 b->Write (constant->val.len ()); 1150 b->write (constant->val.len());
982 1151
983 MustNext (")"); 1152 m_lx->must_get_next (tk_paren_end);
984 } else if (token == "(") { 1153 }
1154 else if (TOKEN == "(")
1155 {
985 // Expression 1156 // Expression
986 MustNext (); 1157 m_lx->must_get_next();
987 DataBuffer* c = ParseExpression (reqtype); 1158 data_buffer* c = parse_expression (reqtype);
988 b->Merge (c); 1159 b->merge (c);
989 MustNext (")"); 1160 m_lx->must_get_next (tk_paren_end);
990 } else if (CommandDef* comm = FindCommand (token)) { 1161 }
1162 else if (CommandDef* comm = FindCommand (TOKEN))
1163 {
991 delete b; 1164 delete b;
992 1165
993 // Command 1166 // Command
994 if (reqtype && comm->returnvalue != reqtype) 1167 if (reqtype && comm->returnvalue != reqtype)
995 ParserError ("%s returns an incompatible data type", comm->name.chars()); 1168 error ("%s returns an incompatible data type", comm->name.chars());
1169
996 b = ParseCommand (comm); 1170 b = ParseCommand (comm);
997 } else if (constinfo_t* constant = FindConstant (token)) { 1171 }
1172 else if (constant_info* constant = find_constant (TOKEN))
1173 {
998 // Type check 1174 // Type check
999 if (reqtype != constant->type) 1175 if (reqtype != constant->type)
1000 ParserError ("constant `%s` is %s, expression requires %s\n", 1176 error ("constant `%s` is %s, expression requires %s\n",
1001 constant->name.c_str(), GetTypeName (constant->type).c_str(), 1177 constant->name.c_str(), GetTypeName (constant->type).c_str(),
1002 GetTypeName (reqtype).c_str()); 1178 GetTypeName (reqtype).c_str());
1003 1179
1004 switch (constant->type) { 1180 switch (constant->type)
1181 {
1182 case TYPE_BOOL:
1183 case TYPE_INT:
1184 b->write (DH_PUSHNUMBER);
1185 b->write (atoi (constant->val));
1186 break;
1187
1188 case TYPE_STRING:
1189 b->write_string (constant->val);
1190 break;
1191
1192 case TYPE_VOID:
1193 case TYPE_UNKNOWN:
1194 break;
1195 }
1196 }
1197 else if ((g = FindGlobalVariable (TOKEN)))
1198 {
1199 // Global variable
1200 b->write (DH_PUSHGLOBALVAR);
1201 b->write (g->index);
1202 }
1203 else
1204 {
1205 // If nothing else, check for literal
1206 switch (reqtype)
1207 {
1208 case TYPE_VOID:
1209 case TYPE_UNKNOWN:
1210 error ("unknown identifier `%s` (expected keyword, function or variable)", TOKEN.chars());
1211 break;
1212
1005 case TYPE_BOOL: 1213 case TYPE_BOOL:
1006 case TYPE_INT: 1214 case TYPE_INT:
1007 b->Write (DH_PUSHNUMBER); 1215 {
1008 b->Write (atoi (constant->val)); 1216 m_lx->must_be (tk_number);
1009 break; 1217
1010 case TYPE_STRING:
1011 b->WriteString (constant->val);
1012 break;
1013 case TYPE_VOID:
1014 case TYPE_UNKNOWN:
1015 break;
1016 }
1017 } else if ((g = FindGlobalVariable (token))) {
1018 // Global variable
1019 b->Write (DH_PUSHGLOBALVAR);
1020 b->Write (g->index);
1021 } else {
1022 // If nothing else, check for literal
1023 switch (reqtype) {
1024 case TYPE_VOID:
1025 case TYPE_UNKNOWN:
1026 ParserError ("unknown identifier `%s` (expected keyword, function or variable)", token.chars());
1027 break;
1028 case TYPE_BOOL:
1029 case TYPE_INT: {
1030 MustNumber (true);
1031
1032 // All values are written unsigned - thus we need to write the value's 1218 // All values are written unsigned - thus we need to write the value's
1033 // absolute value, followed by an unary minus for negatives. 1219 // absolute value, followed by an unary minus for negatives.
1034 b->Write (DH_PUSHNUMBER); 1220 b->write (DH_PUSHNUMBER);
1035 1221
1036 long v = atol (token); 1222 long v = atol (TOKEN);
1037 b->Write (static_cast<word> (abs (v))); 1223 b->write (static_cast<word> (abs (v)));
1224
1038 if (v < 0) 1225 if (v < 0)
1039 b->Write (DH_UNARYMINUS); 1226 b->write (DH_UNARYMINUS);
1227
1040 break; 1228 break;
1041 } 1229 }
1230
1042 case TYPE_STRING: 1231 case TYPE_STRING:
1043 // PushToStringTable either returns the string index of the 1232 // PushToStringTable either returns the string index of the
1044 // string if it finds it in the table, or writes it to the 1233 // string if it finds it in the table, or writes it to the
1045 // table and returns it index if it doesn't find it there. 1234 // table and returns it index if it doesn't find it there.
1046 MustString (true); 1235 MustString (true);
1047 b->WriteString (token); 1236 b->write_string (TOKEN);
1048 break; 1237 break;
1049 } 1238 }
1050 } 1239 }
1051 1240
1052 // Negate it now if desired 1241 // Negate it now if desired
1053 if (negate) 1242 if (negate)
1054 b->Write (DH_NEGATELOGICAL); 1243 b->write (DH_NEGATELOGICAL);
1055 1244
1056 return b; 1245 return b;
1057 } 1246 }
1058 1247
1059 // ============================================================================ 1248 // ============================================================================
1060 // Parses an assignment. An assignment starts with a variable name, followed 1249 // Parses an assignment. An assignment starts with a variable name, followed
1061 // by an assignment operator, followed by an expression value. Expects current 1250 // by an assignment operator, followed by an expression value. Expects current
1062 // token to be the name of the variable, and expects the variable to be given. 1251 // TOKEN to be the name of the variable, and expects the variable to be given.
1063 DataBuffer* ScriptReader::ParseAssignment (ScriptVar* var) { 1252 data_buffer* botscript_parser::ParseAssignment (script_variable* var)
1064 bool global = !var->statename.len (); 1253 {
1065 1254 bool global = !var->statename.len();
1255
1066 // Get an operator 1256 // Get an operator
1067 MustNext (); 1257 m_lx->must_get_next();
1068 int oper = ParseOperator (); 1258 int oper = parse_operator();
1069 if (!IsAssignmentOperator (oper)) 1259
1070 ParserError ("expected assignment operator"); 1260 if (!is_assignment_operator (oper))
1071 1261 error ("expected assignment operator");
1262
1072 if (g_CurMode == MODE_TOPLEVEL) // TODO: lift this restriction 1263 if (g_CurMode == MODE_TOPLEVEL) // TODO: lift this restriction
1073 ParserError ("can't alter variables at top level"); 1264 error ("can't alter variables at top level");
1074 1265
1075 // Parse the right operand 1266 // Parse the right operand
1076 MustNext (); 1267 m_lx->must_get_next();
1077 DataBuffer* retbuf = new DataBuffer; 1268 data_buffer* retbuf = new data_buffer;
1078 DataBuffer* expr = ParseExpression (var->type); 1269 data_buffer* expr = parse_expression (var->type);
1079 1270
1080 // <<= and >>= do not have data headers. Solution: expand them. 1271 // <<= and >>= do not have data headers. Solution: expand them.
1081 // a <<= b -> a = a << b 1272 // a <<= b -> a = a << b
1082 // a >>= b -> a = a >> b 1273 // a >>= b -> a = a >> b
1083 if (oper == OPER_ASSIGNLEFTSHIFT || oper == OPER_ASSIGNRIGHTSHIFT) { 1274 if (oper == OPER_ASSIGNLEFTSHIFT || oper == OPER_ASSIGNRIGHTSHIFT)
1084 retbuf->Write (global ? DH_PUSHGLOBALVAR : DH_PUSHLOCALVAR); 1275 {
1085 retbuf->Write (var->index); 1276 retbuf->write (global ? DH_PUSHGLOBALVAR : DH_PUSHLOCALVAR);
1086 retbuf->Merge (expr); 1277 retbuf->write (var->index);
1087 retbuf->Write ((oper == OPER_ASSIGNLEFTSHIFT) ? DH_LSHIFT : DH_RSHIFT); 1278 retbuf->merge (expr);
1088 retbuf->Write (global ? DH_ASSIGNGLOBALVAR : DH_ASSIGNLOCALVAR); 1279 retbuf->write ( (oper == OPER_ASSIGNLEFTSHIFT) ? DH_LSHIFT : DH_RSHIFT);
1089 retbuf->Write (var->index); 1280 retbuf->write (global ? DH_ASSIGNGLOBALVAR : DH_ASSIGNLOCALVAR);
1090 } else { 1281 retbuf->write (var->index);
1091 retbuf->Merge (expr); 1282 }
1092 long dh = DataHeaderByOperator (var, oper); 1283 else
1093 retbuf->Write (dh); 1284 {
1094 retbuf->Write (var->index); 1285 retbuf->merge (expr);
1095 } 1286 long dh = get_data_header_by_operator (var, oper);
1096 1287 retbuf->write (dh);
1288 retbuf->write (var->index);
1289 }
1290
1097 return retbuf; 1291 return retbuf;
1098 } 1292 }
1099 1293
1100 void ScriptReader::PushScope () { 1294 void botscript_parser::push_scope()
1295 {
1101 g_ScopeCursor++; 1296 g_ScopeCursor++;
1297
1102 if (g_ScopeCursor >= MAX_SCOPE) 1298 if (g_ScopeCursor >= MAX_SCOPE)
1103 ParserError ("too deep scope"); 1299 error ("too deep scope");
1104 1300
1105 ScopeInfo* info = &SCOPE(0); 1301 ScopeInfo* info = &SCOPE (0);
1106 info->type = SCOPETYPE_UNKNOWN; 1302 info->type = SCOPETYPE_UNKNOWN;
1107 info->mark1 = 0; 1303 info->mark1 = 0;
1108 info->mark2 = 0; 1304 info->mark2 = 0;
1109 info->buffer1 = null; 1305 info->buffer1 = null;
1110 info->casecursor = -1; 1306 info->casecursor = -1;
1111 for (int i = 0; i < MAX_CASE; i++) { 1307
1308 for (int i = 0; i < MAX_CASE; i++)
1309 {
1112 info->casemarks[i] = MAX_MARKS; 1310 info->casemarks[i] = MAX_MARKS;
1113 info->casebuffers[i] = null; 1311 info->casebuffers[i] = null;
1114 info->casenumbers[i] = -1; 1312 info->casenumbers[i] = -1;
1115 } 1313 }
1116 } 1314 }
1117 1315
1118 DataBuffer* ScriptReader::ParseStatement (ObjWriter* w) { 1316 data_buffer* botscript_parser::parse_statement (object_writer* w)
1119 if (FindConstant (token)) // There should not be constants here. 1317 {
1120 ParserError ("invalid use for constant\n"); 1318 if (find_constant (TOKEN)) // There should not be constants here.
1121 1319 error ("invalid use for constant\n");
1320
1122 // If it's a variable, expect assignment. 1321 // If it's a variable, expect assignment.
1123 if (ScriptVar* var = FindGlobalVariable (token)) 1322 if (script_variable* var = FindGlobalVariable (TOKEN))
1124 return ParseAssignment (var); 1323 return ParseAssignment (var);
1125 1324
1126 return null; 1325 return null;
1127 } 1326 }
1128 1327
1129 void ScriptReader::AddSwitchCase (ObjWriter* w, DataBuffer* b) { 1328 void botscript_parser::add_switch_case (object_writer* w, data_buffer* b)
1130 ScopeInfo* info = &SCOPE(0); 1329 {
1131 1330 ScopeInfo* info = &SCOPE (0);
1331
1132 info->casecursor++; 1332 info->casecursor++;
1333
1133 if (info->casecursor >= MAX_CASE) 1334 if (info->casecursor >= MAX_CASE)
1134 ParserError ("too many cases in one switch"); 1335 error ("too many cases in one switch");
1135 1336
1136 // Init a mark for the case buffer 1337 // Init a mark for the case buffer
1137 int m = w->AddMark (""); 1338 int m = w->add_mark ("");
1138 info->casemarks[info->casecursor] = m; 1339 info->casemarks[info->casecursor] = m;
1139 1340
1140 // Add a reference to the mark. "case" and "default" both 1341 // Add a reference to the mark. "case" and "default" both
1141 // add the necessary bytecode before the reference. 1342 // add the necessary bytecode before the reference.
1142 if (b) 1343 if (b)
1143 b->AddMarkReference (m); 1344 b->add_reference (m);
1144 else 1345 else
1145 w->AddReference (m); 1346 w->add_reference (m);
1146 1347
1147 // Init a buffer for the case block and tell the object 1348 // Init a buffer for the case block and tell the object
1148 // writer to record all written data to it. 1349 // writer to record all written data to it.
1149 info->casebuffers[info->casecursor] = w->SwitchBuffer = new DataBuffer; 1350 info->casebuffers[info->casecursor] = w->SwitchBuffer = new data_buffer;
1150 } 1351 }
1151 1352
1152 constinfo_t* FindConstant (string token) { 1353 constant_info* find_constant (string TOKEN)
1153 for (uint i = 0; i < g_ConstInfo.size(); i++) 1354 {
1154 if (g_ConstInfo[i].name == token) 1355 for (int i = 0; i < g_ConstInfo.size(); i++)
1356 if (g_ConstInfo[i].name == TOKEN)
1155 return &g_ConstInfo[i]; 1357 return &g_ConstInfo[i];
1358
1156 return null; 1359 return null;
1157 } 1360 }
1361
1362 // ============================================================================
1363 //
1364 bool botscript_parser::token_is (e_token a)
1365 {
1366 return (m_lx->get_token() == a);
1367 }
1368
1369 // ============================================================================
1370 //
1371 string botscript_parser::token_string()
1372 {
1373 return m_lx->get_token()->text;
1374 }
1375
1376 // ============================================================================
1377 //
1378 string botscript_parser::describe_position() const
1379 {
1380 lexer::token* tok = m_lx->get_token();
1381 return tok->file + ":" + string (tok->line) + ":" + string (tok->column);
1382 }

mercurial