src/parser.cc

changeset 86
43fe4be38a58
parent 85
264a61e9eba0
child 87
8f65914e7046
equal deleted inserted replaced
85:264a61e9eba0 86:43fe4be38a58
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include "object_writer.h"
30 #include "parser.h" 29 #include "parser.h"
31 #include "events.h" 30 #include "events.h"
32 #include "commands.h" 31 #include "commands.h"
33 #include "stringtable.h" 32 #include "stringtable.h"
34 #include "variables.h" 33 #include "variables.h"
35 #include "containers.h" 34 #include "containers.h"
36 #include "lexer.h" 35 #include "lexer.h"
37 36 #include "data_buffer.h"
38 #define SCOPE(n) scopestack[g_ScopeCursor - n] 37
39 38 #define SCOPE(n) (m_scope_stack[m_scope_cursor - n])
40 // TODO: make these static
41 int g_NumStates = 0;
42 int g_NumEvents = 0;
43 parsermode_e g_current_mode = MODE_TOPLEVEL;
44 string g_CurState = "";
45 bool g_stateSpawnDefined = false;
46 bool g_GotMainLoop = false;
47 int g_ScopeCursor = 0;
48 data_buffer* g_IfExpression = null;
49 bool g_CanElse = false;
50 static string* g_undefined_labels[MAX_MARKS]; // TODO: make a list
51 list<constant_info> g_ConstInfo;
52 39
53 // ============================================================================ 40 // ============================================================================
54 // 41 //
55 botscript_parser::botscript_parser() : 42 botscript_parser::botscript_parser() :
56 m_lx (new lexer) {} 43 m_lx (new lexer) {}
64 51
65 // ============================================================================ 52 // ============================================================================
66 // 53 //
67 void botscript_parser::check_toplevel() 54 void botscript_parser::check_toplevel()
68 { 55 {
69 if (g_current_mode != MODE_TOPLEVEL) 56 if (m_current_mode != MODE_TOPLEVEL)
70 error ("%1-statements may only be defined at top level!", token_string()); 57 error ("%1-statements may only be defined at top level!", token_string());
71 } 58 }
72 59
73 // ============================================================================ 60 // ============================================================================
74 // 61 //
75 void botscript_parser::check_not_toplevel() 62 void botscript_parser::check_not_toplevel()
76 { 63 {
77 if (g_current_mode == MODE_TOPLEVEL) 64 if (m_current_mode == MODE_TOPLEVEL)
78 error ("%1-statements must not be defined at top level!", token_string()); 65 error ("%1-statements must not be defined at top level!", token_string());
79 } 66 }
80 67
81 // ============================================================================ 68 // ============================================================================
82 // Main parser code. Begins read of the script file, checks the syntax of it 69 // Main parser code. Begins read of the script file, checks the syntax of it
83 // 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
84 // of necessary buffering so stuff is written in the correct order. 71 // of necessary buffering so stuff is written in the correct order.
85 void botscript_parser::parse_botscript (string file_name, object_writer* w) 72 void botscript_parser::parse_botscript (string file_name)
86 { 73 {
87 m_writer = w;
88
89 // Lex and preprocess the file 74 // Lex and preprocess the file
90 m_lx->process_file (file_name); 75 m_lx->process_file (file_name);
76
77 m_current_mode = MODE_TOPLEVEL;
78 m_num_states = 0;
79 m_num_events = 0;
80 m_scope_cursor = 0;
81 m_state_spawn_defined = false;
82 m_got_main_loop = false;
83 m_if_expression = null;
84 m_can_else = false;
91 85
92 // Zero the entire block stack first 86 // Zero the entire block stack first
93 // TODO: this shouldn't be necessary 87 // TODO: this shouldn't be necessary
94 for (int i = 0; i < MAX_SCOPE; i++) 88 for (int i = 0; i < MAX_SCOPE; i++)
95 ZERO (scopestack[i]); 89 ZERO (m_scope_stack[i]);
96
97 for (int i = 0; i < MAX_MARKS; i++)
98 g_undefined_labels[i] = null;
99 90
100 while (m_lx->get_next()) 91 while (m_lx->get_next())
101 { 92 {
102 // Check if else is potentically valid 93 // Check if else is potentically valid
103 if (token_is (tk_else) && !g_CanElse) 94 if (token_is (tk_else) && !m_can_else)
104 error ("else without preceding if"); 95 error ("else without preceding if");
105 96
106 if (!token_is (tk_else)) 97 if (!token_is (tk_else))
107 g_CanElse = false; 98 m_can_else = false;
108 99
109 switch (m_lx->get_token()->type) 100 switch (m_lx->get_token()->type)
110 { 101 {
111 case tk_state: 102 case tk_state:
112 parse_state_block(); 103 parse_state_block();
207 // Check if it's a command 198 // Check if it's a command
208 command_info* comm = find_command_by_name (token_string()); 199 command_info* comm = find_command_by_name (token_string());
209 200
210 if (comm) 201 if (comm)
211 { 202 {
212 m_writer->get_current_buffer()->merge (ParseCommand (comm)); 203 buffer()->merge_and_destroy (parse_command (comm));
213 m_lx->must_get_next (tk_semicolon); 204 m_lx->must_get_next (tk_semicolon);
214 continue; 205 continue;
215 } 206 }
216 207
217 // If nothing else, parse it as a statement 208 // If nothing else, parse it as a statement
218 data_buffer* b = parse_statement(); 209 data_buffer* b = parse_statement();
219 210
220 if (!b) 211 if (!b)
221 error ("unknown token `%1`", token_string()); 212 error ("unknown token `%1`", token_string());
222 213
223 m_writer->write_buffer (b); 214 buffer()->merge_and_destroy (b);
224 m_lx->must_get_next (tk_semicolon); 215 m_lx->must_get_next (tk_semicolon);
225 } 216 }
226 break; 217 break;
227 } 218 }
228 } 219 }
229 220
230 // =============================================================================== 221 // ===============================================================================
231 // Script file ended. Do some last checks and write the last things to main buffer 222 // Script file ended. Do some last checks and write the last things to main buffer
232 if (g_current_mode != MODE_TOPLEVEL) 223 if (m_current_mode != MODE_TOPLEVEL)
233 error ("script did not end at top level; a `}` is missing somewhere"); 224 error ("script did not end at top level; a `}` is missing somewhere");
234 225
235 // stateSpawn must be defined! 226 // stateSpawn must be defined!
236 if (!g_stateSpawnDefined) 227 if (!m_state_spawn_defined)
237 error ("script must have a state named `stateSpawn`!"); 228 error ("script must have a state named `stateSpawn`!");
238 229
239 for (int i = 0; i < MAX_MARKS; i++) 230 // Ensure no goto target is left undefined
240 if (g_undefined_labels[i]) 231 if (m_undefined_labels.is_empty() == false)
241 error ("label `%1` is referenced via `goto` but isn't defined\n", g_undefined_labels[i]); 232 {
233 string_list names;
234
235 for (undefined_label& undf : m_undefined_labels)
236 names << undf.name;
237
238 error ("labels `%1` are referenced via `goto` but are not defined\n", names);
239 }
242 240
243 // Dump the last state's onenter and mainloop 241 // Dump the last state's onenter and mainloop
244 m_writer->write_member_buffers(); 242 write_member_buffers();
245 243
246 // String table 244 // String table
247 m_writer->write_string_table(); 245 write_string_table();
248 } 246 }
249 247
250 // ============================================================================ 248 // ============================================================================
251 // 249 //
252 void botscript_parser::parse_state_block() 250 void botscript_parser::parse_state_block()
260 error ("state name must be a single word, got `%1`", statename); 258 error ("state name must be a single word, got `%1`", statename);
261 259
262 // stateSpawn is special - it *must* be defined. If we 260 // stateSpawn is special - it *must* be defined. If we
263 // encountered it, then mark down that we have it. 261 // encountered it, then mark down that we have it.
264 if (-statename == "statespawn") 262 if (-statename == "statespawn")
265 g_stateSpawnDefined = true; 263 m_state_spawn_defined = true;
266 264
267 // Must end in a colon 265 // Must end in a colon
268 m_lx->must_get_next (tk_colon); 266 m_lx->must_get_next (tk_colon);
269 267
270 // write the previous state's onenter and 268 // write the previous state's onenter and
271 // mainloop buffers to file now 269 // mainloop buffers to file now
272 if (g_CurState.is_empty() == false) 270 if (m_current_state.is_empty() == false)
273 m_writer->write_member_buffers(); 271 write_member_buffers();
274 272
275 m_writer->write (dh_state_name); 273 buffer()->write_dword (dh_state_name);
276 m_writer->write_string (statename); 274 buffer()->write_string (statename);
277 m_writer->write (dh_state_index); 275 buffer()->write_dword (dh_state_index);
278 m_writer->write (g_NumStates); 276 buffer()->write_dword (m_num_states);
279 277
280 g_NumStates++; 278 m_num_states++;
281 g_CurState = statename; 279 m_current_state = statename;
282 g_GotMainLoop = false; 280 m_got_main_loop = false;
283 } 281 }
284 282
285 // ============================================================================ 283 // ============================================================================
286 // 284 //
287 void botscript_parser::parse_event_block() 285 void botscript_parser::parse_event_block()
293 291
294 if (!e) 292 if (!e)
295 error ("bad event, got `%1`\n", token_string()); 293 error ("bad event, got `%1`\n", token_string());
296 294
297 m_lx->must_get_next (tk_brace_start); 295 m_lx->must_get_next (tk_brace_start);
298 g_current_mode = MODE_EVENT; 296 m_current_mode = MODE_EVENT;
299 m_writer->write (dh_event); 297 buffer()->write_dword (dh_event);
300 m_writer->write (e->number); 298 buffer()->write_dword (e->number);
301 g_NumEvents++; 299 m_num_events++;
302 } 300 }
303 301
304 // ============================================================================ 302 // ============================================================================
305 // 303 //
306 void botscript_parser::parse_mainloop() 304 void botscript_parser::parse_mainloop()
307 { 305 {
308 check_toplevel(); 306 check_toplevel();
309 m_lx->must_get_next (tk_brace_start); 307 m_lx->must_get_next (tk_brace_start);
310 308
311 // Mode must be set before dataheader is written here! 309 m_current_mode = MODE_MAINLOOP;
312 g_current_mode = MODE_MAINLOOP; 310 m_main_loop_buffer->write_dword (dh_main_loop);
313 m_writer->write (dh_main_loop);
314 } 311 }
315 312
316 // ============================================================================ 313 // ============================================================================
317 // 314 //
318 void botscript_parser::parse_on_enter_exit() 315 void botscript_parser::parse_on_enter_exit()
319 { 316 {
320 check_toplevel(); 317 check_toplevel();
321 bool onenter = (token_is (tk_onenter)); 318 bool onenter = (token_is (tk_onenter));
322 m_lx->must_get_next (tk_brace_start); 319 m_lx->must_get_next (tk_brace_start);
323 320
324 // Mode must be set before dataheader is written here, 321 m_current_mode = onenter ? MODE_ONENTER : MODE_ONEXIT;
325 // because onenter goes to a separate buffer. 322 buffer()->write_dword (onenter ? dh_on_enter : dh_on_exit);
326 g_current_mode = onenter ? MODE_ONENTER : MODE_ONEXIT;
327 m_writer->write (onenter ? dh_on_enter : dh_on_exit);
328 } 323 }
329 324
330 // ============================================================================ 325 // ============================================================================
331 // 326 //
332 void botscript_parser::parse_variable_declaration() 327 void botscript_parser::parse_variable_declaration()
333 { 328 {
334 // For now, only globals are supported 329 // For now, only globals are supported
335 if (g_current_mode != MODE_TOPLEVEL || g_CurState.is_empty() == false) 330 if (m_current_mode != MODE_TOPLEVEL || m_current_state.is_empty() == false)
336 error ("variables must only be global for now"); 331 error ("variables must only be global for now");
337 332
338 type_e type = (token_is (tk_int)) ? TYPE_INT : 333 type_e type = (token_is (tk_int)) ? TYPE_INT :
339 (token_is (tk_str)) ? TYPE_STRING : 334 (token_is (tk_str)) ? TYPE_STRING :
340 TYPE_BOOL; 335 TYPE_BOOL;
360 // Get the name of the label 355 // Get the name of the label
361 m_lx->must_get_next(); 356 m_lx->must_get_next();
362 357
363 // Find the mark this goto statement points to 358 // Find the mark this goto statement points to
364 string target = token_string(); 359 string target = token_string();
365 int m = m_writer->find_byte_mark (target); 360 byte_mark* mark = buffer()->find_mark_by_name (target);
366 361
367 // If not set, define it 362 // If not set, define it
368 if (m == MAX_MARKS) 363 if (!mark)
369 { 364 {
370 m = m_writer->add_mark (target); 365 undefined_label undf;
371 g_undefined_labels[m] = new string (target); 366 undf.name = target;
367 undf.target = buffer()->add_mark (target);
368 m_undefined_labels << undf;
372 } 369 }
373 370
374 // Add a reference to the mark. 371 // Add a reference to the mark.
375 m_writer->write (dh_goto); 372 buffer()->write_dword (dh_goto);
376 m_writer->add_reference (m); 373 buffer()->add_reference (mark);
377 m_lx->must_get_next (tk_semicolon); 374 m_lx->must_get_next (tk_semicolon);
378 } 375 }
379 376
380 // ============================================================================ 377 // ============================================================================
381 // 378 //
388 m_lx->must_get_next (tk_paren_start); 385 m_lx->must_get_next (tk_paren_start);
389 386
390 // Read the expression and write it. 387 // Read the expression and write it.
391 m_lx->must_get_next(); 388 m_lx->must_get_next();
392 data_buffer* c = parse_expression (TYPE_INT); 389 data_buffer* c = parse_expression (TYPE_INT);
393 m_writer->write_buffer (c); 390 buffer()->merge_and_destroy (c);
394 391
395 m_lx->must_get_next (tk_paren_end); 392 m_lx->must_get_next (tk_paren_end);
396 m_lx->must_get_next (tk_brace_start); 393 m_lx->must_get_next (tk_brace_start);
397 394
398 // Add a mark - to here temporarily - and add a reference to it. 395 // Add a mark - to here temporarily - and add a reference to it.
399 // Upon a closing brace, the mark will be adjusted. 396 // Upon a closing brace, the mark will be adjusted.
400 int marknum = m_writer->add_mark (""); 397 byte_mark* mark = buffer()->add_mark ("");
401 398
402 // Use dh_if_not_goto - if the expression is not true, we goto the mark 399 // Use dh_if_not_goto - if the expression is not true, we goto the mark
403 // we just defined - and this mark will be at the end of the scope block. 400 // we just defined - and this mark will be at the end of the scope block.
404 m_writer->write (dh_if_not_goto); 401 buffer()->write_dword (dh_if_not_goto);
405 m_writer->add_reference (marknum); 402 buffer()->add_reference (mark);
406 403
407 // Store it 404 // Store it
408 SCOPE (0).mark1 = marknum; 405 SCOPE (0).mark1 = mark;
409 SCOPE (0).type = e_if_scope; 406 SCOPE (0).type = e_if_scope;
410 } 407 }
411 408
412 // ============================================================================ 409 // ============================================================================
413 // 410 //
415 { 412 {
416 check_not_toplevel(); 413 check_not_toplevel();
417 m_lx->must_get_next (tk_brace_start); 414 m_lx->must_get_next (tk_brace_start);
418 415
419 // Don't use PushScope as it resets the scope 416 // Don't use PushScope as it resets the scope
420 g_ScopeCursor++; 417 m_scope_cursor++;
421 418
422 if (g_ScopeCursor >= MAX_SCOPE) 419 if (m_scope_cursor >= MAX_SCOPE)
423 error ("too deep scope"); 420 error ("too deep scope");
424 421
425 if (SCOPE (0).type != e_if_scope) 422 if (SCOPE (0).type != e_if_scope)
426 error ("else without preceding if"); 423 error ("else without preceding if");
427 424
428 // write down to jump to the end of the else statement 425 // write down to jump to the end of the else statement
429 // Otherwise we have fall-throughs 426 // Otherwise we have fall-throughs
430 SCOPE (0).mark2 = m_writer->add_mark (""); 427 SCOPE (0).mark2 = buffer()->add_mark ("");
431 428
432 // Instruction to jump to the end after if block is complete 429 // Instruction to jump to the end after if block is complete
433 m_writer->write (dh_goto); 430 buffer()->write_dword (dh_goto);
434 m_writer->add_reference (SCOPE (0).mark2); 431 buffer()->add_reference (SCOPE (0).mark2);
435 432
436 // Move the ifnot mark here and set type to else 433 // Move the ifnot mark here and set type to else
437 m_writer->move_mark (SCOPE (0).mark1); 434 buffer()->adjust_mark (SCOPE (0).mark1);
438 SCOPE (0).type = e_else_scope; 435 SCOPE (0).type = e_else_scope;
439 } 436 }
440 437
441 // ============================================================================ 438 // ============================================================================
442 // 439 //
447 444
448 // While loops need two marks - one at the start of the loop and one at the 445 // While loops need two marks - one at the start of the loop and one at the
449 // end. The condition is checked at the very start of the loop, if it fails, 446 // end. The condition is checked at the very start of the loop, if it fails,
450 // we use goto to skip to the end of the loop. At the end, we loop back to 447 // we use goto to skip to the end of the loop. At the end, we loop back to
451 // the beginning with a go-to statement. 448 // the beginning with a go-to statement.
452 int mark1 = m_writer->add_mark (""); // start 449 byte_mark* mark1 = buffer()->add_mark (""); // start
453 int mark2 = m_writer->add_mark (""); // end 450 byte_mark* mark2 = buffer()->add_mark (""); // end
454 451
455 // Condition 452 // Condition
456 m_lx->must_get_next (tk_paren_start); 453 m_lx->must_get_next (tk_paren_start);
457 m_lx->must_get_next(); 454 m_lx->must_get_next();
458 data_buffer* expr = parse_expression (TYPE_INT); 455 data_buffer* expr = parse_expression (TYPE_INT);
459 m_lx->must_get_next (tk_paren_end); 456 m_lx->must_get_next (tk_paren_end);
460 m_lx->must_get_next (tk_brace_start); 457 m_lx->must_get_next (tk_brace_start);
461 458
462 // write condition 459 // write condition
463 m_writer->write_buffer (expr); 460 buffer()->merge_and_destroy (expr);
464 461
465 // Instruction to go to the end if it fails 462 // Instruction to go to the end if it fails
466 m_writer->write (dh_if_not_goto); 463 buffer()->write_dword (dh_if_not_goto);
467 m_writer->add_reference (mark2); 464 buffer()->add_reference (mark2);
468 465
469 // Store the needed stuff 466 // Store the needed stuff
470 SCOPE (0).mark1 = mark1; 467 SCOPE (0).mark1 = mark1;
471 SCOPE (0).mark2 = mark2; 468 SCOPE (0).mark2 = mark2;
472 SCOPE (0).type = e_while_scope; 469 SCOPE (0).type = e_while_scope;
507 504
508 m_lx->must_get_next (tk_paren_end); 505 m_lx->must_get_next (tk_paren_end);
509 m_lx->must_get_next (tk_brace_start); 506 m_lx->must_get_next (tk_brace_start);
510 507
511 // First, write out the initializer 508 // First, write out the initializer
512 m_writer->write_buffer (init); 509 buffer()->merge_and_destroy (init);
513 510
514 // Init two marks 511 // Init two marks
515 int mark1 = m_writer->add_mark (""); 512 byte_mark* mark1 = buffer()->add_mark ("");
516 int mark2 = m_writer->add_mark (""); 513 byte_mark* mark2 = buffer()->add_mark ("");
517 514
518 // Add the condition 515 // Add the condition
519 m_writer->write_buffer (cond); 516 buffer()->merge_and_destroy (cond);
520 m_writer->write (dh_if_not_goto); 517 buffer()->write_dword (dh_if_not_goto);
521 m_writer->add_reference (mark2); 518 buffer()->add_reference (mark2);
522 519
523 // Store the marks and incrementor 520 // Store the marks and incrementor
524 SCOPE (0).mark1 = mark1; 521 SCOPE (0).mark1 = mark1;
525 SCOPE (0).mark2 = mark2; 522 SCOPE (0).mark2 = mark2;
526 SCOPE (0).buffer1 = incr; 523 SCOPE (0).buffer1 = incr;
532 void botscript_parser::parse_do_block() 529 void botscript_parser::parse_do_block()
533 { 530 {
534 check_not_toplevel(); 531 check_not_toplevel();
535 push_scope(); 532 push_scope();
536 m_lx->must_get_next (tk_brace_start); 533 m_lx->must_get_next (tk_brace_start);
537 SCOPE (0).mark1 = m_writer->add_mark (""); 534 SCOPE (0).mark1 = buffer()->add_mark ("");
538 SCOPE (0).type = e_do_scope; 535 SCOPE (0).type = e_do_scope;
539 } 536 }
540 537
541 // ============================================================================ 538 // ============================================================================
542 // 539 //
557 554
558 check_not_toplevel(); 555 check_not_toplevel();
559 push_scope(); 556 push_scope();
560 m_lx->must_get_next (tk_paren_start); 557 m_lx->must_get_next (tk_paren_start);
561 m_lx->must_get_next(); 558 m_lx->must_get_next();
562 m_writer->write_buffer (parse_expression (TYPE_INT)); 559 buffer()->merge_and_destroy (parse_expression (TYPE_INT));
563 m_lx->must_get_next (tk_paren_end); 560 m_lx->must_get_next (tk_paren_end);
564 m_lx->must_get_next (tk_brace_start); 561 m_lx->must_get_next (tk_brace_start);
565 SCOPE (0).type = e_switch_scope; 562 SCOPE (0).type = e_switch_scope;
566 SCOPE (0).mark1 = m_writer->add_mark (""); // end mark 563 SCOPE (0).mark1 = buffer()->add_mark (""); // end mark
567 SCOPE (0).buffer1 = null; // default header 564 SCOPE (0).buffer1 = null; // default header
568 } 565 }
569 566
570 // ============================================================================ 567 // ============================================================================
571 // 568 //
582 579
583 for (int i = 0; i < MAX_CASE; i++) 580 for (int i = 0; i < MAX_CASE; i++)
584 if (SCOPE (0).casenumbers[i] == num) 581 if (SCOPE (0).casenumbers[i] == num)
585 error ("multiple case %d labels in one switch", num); 582 error ("multiple case %d labels in one switch", num);
586 583
587 // write down the expression and case-go-to. This builds 584 // Write down the expression and case-go-to. This builds
588 // the case tree. The closing event will write the actual 585 // the case tree. The closing event will write the actual
589 // blocks and move the marks appropriately. 586 // blocks and move the marks appropriately.
590 // AddSwitchCase will add the reference to the mark 587 //
588 // AddSwitchCase will add the reference to the mark
591 // for the case block that this heralds, and takes care 589 // for the case block that this heralds, and takes care
592 // of buffering setup and stuff like that. 590 // of buffering setup and stuff like that.
593 // null the switch buffer for the case-go-to statement, 591 //
592 // We null the switch buffer for the case-go-to statement as
594 // we want it all under the switch, not into the case-buffers. 593 // we want it all under the switch, not into the case-buffers.
595 m_writer->SwitchBuffer = null; 594 m_switch_buffer = null;
596 m_writer->write (dh_case_goto); 595 buffer()->write_dword (dh_case_goto);
597 m_writer->write (num); 596 buffer()->write_dword (num);
598 add_switch_case (null); 597 add_switch_case (null);
599 SCOPE (0).casenumbers[SCOPE (0).casecursor] = num; 598 SCOPE (0).casenumbers[SCOPE (0).casecursor] = num;
600 } 599 }
601 600
602 // ============================================================================ 601 // ============================================================================
618 // and is only popped when case succeeds, we have 617 // and is only popped when case succeeds, we have
619 // to pop it with dh_drop manually if we end up in 618 // to pop it with dh_drop manually if we end up in
620 // a default. 619 // a default.
621 data_buffer* b = new data_buffer; 620 data_buffer* b = new data_buffer;
622 SCOPE (0).buffer1 = b; 621 SCOPE (0).buffer1 = b;
623 b->write (dh_drop); 622 b->write_dword (dh_drop);
624 b->write (dh_goto); 623 b->write_dword (dh_goto);
625 add_switch_case (b); 624 add_switch_case (b);
626 } 625 }
627 626
628 // ============================================================================ 627 // ============================================================================
629 // 628 //
630 void botscript_parser::parse_break() 629 void botscript_parser::parse_break()
631 { 630 {
632 if (!g_ScopeCursor) 631 if (!m_scope_cursor)
633 error ("unexpected `break`"); 632 error ("unexpected `break`");
634 633
635 m_writer->write (dh_goto); 634 buffer()->write_dword (dh_goto);
636 635
637 // switch and if use mark1 for the closing point, 636 // switch and if use mark1 for the closing point,
638 // for and while use mark2. 637 // for and while use mark2.
639 switch (SCOPE (0).type) 638 switch (SCOPE (0).type)
640 { 639 {
641 case e_if_scope: 640 case e_if_scope:
642 case e_switch_scope: 641 case e_switch_scope:
643 { 642 {
644 m_writer->add_reference (SCOPE (0).mark1); 643 buffer()->add_reference (SCOPE (0).mark1);
645 } break; 644 } break;
646 645
647 case e_for_scope: 646 case e_for_scope:
648 case e_while_scope: 647 case e_while_scope:
649 { 648 {
650 m_writer->add_reference (SCOPE (0).mark2); 649 buffer()->add_reference (SCOPE (0).mark2);
651 } break; 650 } break;
652 651
653 default: 652 default:
654 { 653 {
655 error ("unexpected `break`"); 654 error ("unexpected `break`");
667 666
668 int curs; 667 int curs;
669 bool found = false; 668 bool found = false;
670 669
671 // Fall through the scope until we find a loop block 670 // Fall through the scope until we find a loop block
672 for (curs = g_ScopeCursor; curs > 0 && !found; curs--) 671 for (curs = m_scope_cursor; curs > 0 && !found; curs--)
673 { 672 {
674 switch (scopestack[curs].type) 673 switch (m_scope_stack[curs].type)
675 { 674 {
676 case e_for_scope: 675 case e_for_scope:
677 case e_while_scope: 676 case e_while_scope:
678 case e_do_scope: 677 case e_do_scope:
679 { 678 {
680 m_writer->write (dh_goto); 679 buffer()->write_dword (dh_goto);
681 m_writer->add_reference (scopestack[curs].mark1); 680 buffer()->add_reference (m_scope_stack[curs].mark1);
682 found = true; 681 found = true;
683 } break; 682 } break;
684 683
685 default: 684 default:
686 break; 685 break;
696 // 695 //
697 void botscript_parser::parse_block_end() 696 void botscript_parser::parse_block_end()
698 { 697 {
699 // Closing brace 698 // Closing brace
700 // If we're in the block stack, we're descending down from it now 699 // If we're in the block stack, we're descending down from it now
701 if (g_ScopeCursor > 0) 700 if (m_scope_cursor > 0)
702 { 701 {
703 switch (SCOPE (0).type) 702 switch (SCOPE (0).type)
704 { 703 {
705 case e_if_scope: 704 case e_if_scope:
706 // Adjust the closing mark. 705 // Adjust the closing mark.
707 m_writer->move_mark (SCOPE (0).mark1); 706 buffer()->adjust_mark (SCOPE (0).mark1);
708 707
709 // We're returning from if, thus else can be next 708 // We're returning from if, thus else can be next
710 g_CanElse = true; 709 m_can_else = true;
711 break; 710 break;
712 711
713 case e_else_scope: 712 case e_else_scope:
714 // else instead uses mark1 for itself (so if expression 713 // else instead uses mark1 for itself (so if expression
715 // fails, jump to else), mark2 means end of else 714 // fails, jump to else), mark2 means end of else
716 m_writer->move_mark (SCOPE (0).mark2); 715 buffer()->adjust_mark (SCOPE (0).mark2);
717 break; 716 break;
718 717
719 case e_for_scope: 718 case e_for_scope:
720 // write the incrementor at the end of the loop block 719 // write the incrementor at the end of the loop block
721 m_writer->write_buffer (SCOPE (0).buffer1); 720 buffer()->merge_and_destroy (SCOPE (0).buffer1);
722 721
723 // fall-thru 722 // fall-thru
724 case e_while_scope: 723 case e_while_scope:
725 // write down the instruction to go back to the start of the loop 724 // write down the instruction to go back to the start of the loop
726 m_writer->write (dh_goto); 725 buffer()->write_dword (dh_goto);
727 m_writer->add_reference (SCOPE (0).mark1); 726 buffer()->add_reference (SCOPE (0).mark1);
728 727
729 // Move the closing mark here since we're at the end of the while loop 728 // Move the closing mark here since we're at the end of the while loop
730 m_writer->move_mark (SCOPE (0).mark2); 729 buffer()->adjust_mark (SCOPE (0).mark2);
731 break; 730 break;
732 731
733 case e_do_scope: 732 case e_do_scope:
734 { 733 {
735 m_lx->must_get_next (tk_while); 734 m_lx->must_get_next (tk_while);
738 data_buffer* expr = parse_expression (TYPE_INT); 737 data_buffer* expr = parse_expression (TYPE_INT);
739 m_lx->must_get_next (tk_paren_end); 738 m_lx->must_get_next (tk_paren_end);
740 m_lx->must_get_next (tk_semicolon); 739 m_lx->must_get_next (tk_semicolon);
741 740
742 // If the condition runs true, go back to the start. 741 // If the condition runs true, go back to the start.
743 m_writer->write_buffer (expr); 742 buffer()->merge_and_destroy (expr);
744 m_writer->write (dh_if_goto); 743 buffer()->write_dword (dh_if_goto);
745 m_writer->add_reference (SCOPE (0).mark1); 744 buffer()->add_reference (SCOPE (0).mark1);
746 break; 745 break;
747 } 746 }
748 747
749 case e_switch_scope: 748 case e_switch_scope:
750 { 749 {
751 // Switch closes. Move down to the record buffer of 750 // Switch closes. Move down to the record buffer of
752 // the lower block. 751 // the lower block.
753 if (SCOPE (1).casecursor != -1) 752 if (SCOPE (1).casecursor != -1)
754 m_writer->SwitchBuffer = SCOPE (1).casebuffers[SCOPE (1).casecursor]; 753 m_switch_buffer = SCOPE (1).casebuffers[SCOPE (1).casecursor];
755 else 754 else
756 m_writer->SwitchBuffer = null; 755 m_switch_buffer = null;
757 756
758 // If there was a default in the switch, write its header down now. 757 // If there was a default in the switch, write its header down now.
759 // If not, write instruction to jump to the end of switch after 758 // If not, write instruction to jump to the end of switch after
760 // the headers (thus won't fall-through if no case matched) 759 // the headers (thus won't fall-through if no case matched)
761 if (SCOPE (0).buffer1) 760 if (SCOPE (0).buffer1)
762 m_writer->write_buffer (SCOPE (0).buffer1); 761 buffer()->merge_and_destroy (SCOPE (0).buffer1);
763 else 762 else
764 { 763 {
765 m_writer->write (dh_drop); 764 buffer()->write_dword (dh_drop);
766 m_writer->write (dh_goto); 765 buffer()->write_dword (dh_goto);
767 m_writer->add_reference (SCOPE (0).mark1); 766 buffer()->add_reference (SCOPE (0).mark1);
768 } 767 }
769 768
770 // Go through all of the buffers we 769 // Go through all of the buffers we
771 // recorded down and write them. 770 // recorded down and write them.
772 for (int u = 0; u < MAX_CASE; u++) 771 for (int u = 0; u < MAX_CASE; u++)
773 { 772 {
774 if (!SCOPE (0).casebuffers[u]) 773 if (!SCOPE (0).casebuffers[u])
775 continue; 774 continue;
776 775
777 m_writer->move_mark (SCOPE (0).casemarks[u]); 776 buffer()->adjust_mark (SCOPE (0).casemarks[u]);
778 m_writer->write_buffer (SCOPE (0).casebuffers[u]); 777 buffer()->merge_and_destroy (SCOPE (0).casebuffers[u]);
779 } 778 }
780 779
781 // Move the closing mark here 780 // Move the closing mark here
782 m_writer->move_mark (SCOPE (0).mark1); 781 buffer()->adjust_mark (SCOPE (0).mark1);
783 break; 782 break;
784 } 783 }
785 784
786 case e_unknown_scope: 785 case e_unknown_scope:
787 break; 786 break;
788 } 787 }
789 788
790 // Descend down the stack 789 // Descend down the stack
791 g_ScopeCursor--; 790 m_scope_cursor--;
792 return; 791 return;
793 } 792 }
794 793
795 int dataheader = (g_current_mode == MODE_EVENT) ? dh_end_event : 794 int dataheader = (m_current_mode == MODE_EVENT) ? dh_end_event :
796 (g_current_mode == MODE_MAINLOOP) ? dh_end_main_loop : 795 (m_current_mode == MODE_MAINLOOP) ? dh_end_main_loop :
797 (g_current_mode == MODE_ONENTER) ? dh_end_on_enter : 796 (m_current_mode == MODE_ONENTER) ? dh_end_on_enter :
798 (g_current_mode == MODE_ONEXIT) ? dh_end_on_exit : -1; 797 (m_current_mode == MODE_ONEXIT) ? dh_end_on_exit : -1;
799 798
800 if (dataheader == -1) 799 if (dataheader == -1)
801 error ("unexpected `}`"); 800 error ("unexpected `}`");
802 801
803 // Data header must be written before mode is changed because 802 // Data header must be written before mode is changed because
804 // onenter and mainloop go into special buffers, and we want 803 // onenter and mainloop go into special buffers, and we want
805 // the closing data headers into said buffers too. 804 // the closing data headers into said buffers too.
806 m_writer->write (dataheader); 805 buffer()->write_dword (dataheader);
807 g_current_mode = MODE_TOPLEVEL; 806 m_current_mode = MODE_TOPLEVEL;
808 m_lx->get_next (tk_semicolon); 807 m_lx->get_next (tk_semicolon);
809 } 808 }
810 809
811 // ============================================================================ 810 // ============================================================================
812 // 811 //
844 case TYPE_VOID: 843 case TYPE_VOID:
845 break; 844 break;
846 } 845 }
847 846
848 info.val = m_lx->get_token()->text; 847 info.val = m_lx->get_token()->text;
849 g_ConstInfo << info; 848 m_constants << info;
850 849
851 m_lx->must_get_next (tk_semicolon); 850 m_lx->must_get_next (tk_semicolon);
852 } 851 }
853 852
854 // ============================================================================ 853 // ============================================================================
855 // 854 //
856 void botscript_parser::parse_label() 855 void botscript_parser::parse_label()
857 { 856 {
858 check_not_toplevel(); 857 check_not_toplevel();
859 string label_name = token_string(); 858 string label_name = token_string();
859 byte_mark* mark = null;
860 860
861 // want no conflicts.. 861 // want no conflicts..
862 if (find_command_by_name (label_name)) 862 if (find_command_by_name (label_name))
863 error ("label name `%1` conflicts with command name\n", label_name); 863 error ("label name `%1` conflicts with command name\n", label_name);
864 864
865 if (find_global_variable (label_name)) 865 if (find_global_variable (label_name))
866 error ("label name `%1` conflicts with variable\n", label_name); 866 error ("label name `%1` conflicts with variable\n", label_name);
867 867
868 // See if a mark already exists for this label 868 // See if a mark already exists for this label
869 int mark = -1; 869 for (undefined_label& undf : m_undefined_labels)
870 870 {
871 for (int i = 0; i < MAX_MARKS; i++) 871 if (undf.name != label_name)
872 { 872 continue;
873 if (g_undefined_labels[i] && *g_undefined_labels[i] == label_name) 873
874 { 874 mark = undf.target;
875 mark = i; 875 buffer()->adjust_mark (mark);
876 m_writer->move_mark (i); 876
877 877 // No longer undefined
878 // No longer undefinde 878 m_undefined_labels.remove (undf);
879 delete g_undefined_labels[i]; 879 break;
880 g_undefined_labels[i] = null;
881 }
882 } 880 }
883 881
884 // Not found in unmarked lists, define it now 882 // Not found in unmarked lists, define it now
885 if (mark == -1) 883 if (mark == null)
886 m_writer->add_mark (label_name); 884 buffer()->add_mark (label_name);
887 885
888 m_lx->must_get_next (tk_colon); 886 m_lx->must_get_next (tk_colon);
889 } 887 }
890 888
891 // ============================================================================= 889 // =============================================================================
919 917
920 // Name 918 // Name
921 m_lx->must_get_next (tk_symbol); 919 m_lx->must_get_next (tk_symbol);
922 comm->name = m_lx->get_token()->text; 920 comm->name = m_lx->get_token()->text;
923 921
924 if (IsKeyword (comm->name))
925 error ("function name `%1` conflicts with keyword", comm->name);
926
927 m_lx->must_get_next (tk_colon); 922 m_lx->must_get_next (tk_colon);
928 923
929 // Return value 924 // Return value
930 m_lx->must_get_any_of ({tk_int, tk_void, tk_bool, tk_str}); 925 m_lx->must_get_any_of ({tk_int, tk_void, tk_bool, tk_str});
931 comm->returnvalue = GetTypeByName (m_lx->get_token()->text); // TODO 926 comm->returnvalue = GetTypeByName (m_lx->get_token()->text); // TODO
992 add_command_definition (comm); 987 add_command_definition (comm);
993 } 988 }
994 989
995 // ============================================================================ 990 // ============================================================================
996 // Parses a command call 991 // Parses a command call
997 data_buffer* botscript_parser::ParseCommand (command_info* comm) 992 data_buffer* botscript_parser::parse_command (command_info* comm)
998 { 993 {
999 data_buffer* r = new data_buffer (64); 994 data_buffer* r = new data_buffer (64);
1000 995
1001 if (g_current_mode == MODE_TOPLEVEL) 996 if (m_current_mode == MODE_TOPLEVEL)
1002 error ("command call at top level"); 997 error ("command call at top level");
1003 998
1004 m_lx->must_get_next (tk_paren_start); 999 m_lx->must_get_next (tk_paren_start);
1005 m_lx->must_get_next(); 1000 m_lx->must_get_next();
1006 1001
1020 1015
1021 if (curarg >= comm->maxargs) 1016 if (curarg >= comm->maxargs)
1022 error ("too many arguments passed to %1\n\tprototype: %2", 1017 error ("too many arguments passed to %1\n\tprototype: %2",
1023 comm->name, get_command_signature (comm)); 1018 comm->name, get_command_signature (comm));
1024 1019
1025 r->merge (parse_expression (comm->args[curarg].type)); 1020 r->merge_and_destroy (parse_expression (comm->args[curarg].type));
1026 m_lx->must_get_next(); 1021 m_lx->must_get_next();
1027 1022
1028 if (curarg < comm->numargs - 1) 1023 if (curarg < comm->numargs - 1)
1029 { 1024 {
1030 m_lx->must_be (tk_comma); 1025 m_lx->must_be (tk_comma);
1049 } 1044 }
1050 1045
1051 // If the script skipped any optional arguments, fill in defaults. 1046 // If the script skipped any optional arguments, fill in defaults.
1052 while (curarg < comm->maxargs) 1047 while (curarg < comm->maxargs)
1053 { 1048 {
1054 r->write (dh_push_number); 1049 r->write_dword (dh_push_number);
1055 r->write (comm->args[curarg].defvalue); 1050 r->write_dword (comm->args[curarg].defvalue);
1056 curarg++; 1051 curarg++;
1057 } 1052 }
1058 1053
1059 r->write (dh_command); 1054 r->write_dword (dh_command);
1060 r->write (comm->number); 1055 r->write_dword (comm->number);
1061 r->write (comm->maxargs); 1056 r->write_dword (comm->maxargs);
1062 1057
1063 return r; 1058 return r;
1064 } 1059 }
1065 1060
1066 // ============================================================================ 1061 // ============================================================================
1143 data_buffer* botscript_parser::parse_expression (type_e reqtype) 1138 data_buffer* botscript_parser::parse_expression (type_e reqtype)
1144 { 1139 {
1145 data_buffer* retbuf = new data_buffer (64); 1140 data_buffer* retbuf = new data_buffer (64);
1146 1141
1147 // Parse first operand 1142 // Parse first operand
1148 retbuf->merge (parse_expr_value (reqtype)); 1143 retbuf->merge_and_destroy (parse_expr_value (reqtype));
1149 1144
1150 // Parse any and all operators we get 1145 // Parse any and all operators we get
1151 int oper; 1146 int oper;
1152 1147
1153 while ( (oper = parse_operator (true)) != -1) 1148 while ( (oper = parse_operator (true)) != -1)
1171 data_buffer* tb = parse_expr_value (reqtype); 1166 data_buffer* tb = parse_expr_value (reqtype);
1172 1167
1173 // It also is handled differently: there isn't a dataheader for ternary 1168 // It also is handled differently: there isn't a dataheader for ternary
1174 // operator. Instead, we abuse PUSHNUMBER and IFNOTGOTO for this. 1169 // operator. Instead, we abuse PUSHNUMBER and IFNOTGOTO for this.
1175 // Behold, big block of writing madness! :P 1170 // Behold, big block of writing madness! :P
1176 int mark1 = retbuf->add_mark (""); // start of "else" case 1171 byte_mark* mark1 = retbuf->add_mark (""); // start of "else" case
1177 int mark2 = retbuf->add_mark (""); // end of expression 1172 byte_mark* mark2 = retbuf->add_mark (""); // end of expression
1178 retbuf->write (dh_if_not_goto); // if the first operand (condition) 1173 retbuf->write_dword (dh_if_not_goto); // if the first operand (condition)
1179 retbuf->add_reference (mark1); // didn't eval true, jump into mark1 1174 retbuf->add_reference (mark1); // didn't eval true, jump into mark1
1180 retbuf->merge (rb); // otherwise, perform second operand (true case) 1175 retbuf->merge_and_destroy (rb); // otherwise, perform second operand (true case)
1181 retbuf->write (dh_goto); // afterwards, jump to the end, which is 1176 retbuf->write_dword (dh_goto); // afterwards, jump to the end, which is
1182 retbuf->add_reference (mark2); // marked by mark2. 1177 retbuf->add_reference (mark2); // marked by mark2.
1183 retbuf->move_mark (mark1); // move mark1 at the end of the true case 1178 retbuf->adjust_mark (mark1); // move mark1 at the end of the true case
1184 retbuf->merge (tb); // perform third operand (false case) 1179 retbuf->merge_and_destroy (tb); // perform third operand (false case)
1185 retbuf->move_mark (mark2); // move the ending mark2 here 1180 retbuf->adjust_mark (mark2); // move the ending mark2 here
1186 } 1181 }
1187 else 1182 else
1188 { 1183 {
1189 // write to buffer 1184 // write to buffer
1190 retbuf->merge (rb); 1185 retbuf->merge_and_destroy (rb);
1191 retbuf->write (get_data_header_by_operator (null, oper)); 1186 retbuf->write_dword (get_data_header_by_operator (null, oper));
1192 } 1187 }
1193 } 1188 }
1194 1189
1195 return retbuf; 1190 return retbuf;
1196 } 1191 }
1323 error ("strlen only works with const str"); 1318 error ("strlen only works with const str");
1324 1319
1325 if (reqtype != TYPE_INT) 1320 if (reqtype != TYPE_INT)
1326 error ("strlen returns int but %1 is expected\n", GetTypeName (reqtype)); 1321 error ("strlen returns int but %1 is expected\n", GetTypeName (reqtype));
1327 1322
1328 b->write (dh_push_number); 1323 b->write_dword (dh_push_number);
1329 b->write (constant->val.len()); 1324 b->write_dword (constant->val.len());
1330 1325
1331 m_lx->must_get_next (tk_paren_end); 1326 m_lx->must_get_next (tk_paren_end);
1332 } 1327 }
1333 else */ 1328 else */
1334 if (token_is (tk_paren_start)) 1329 if (token_is (tk_paren_start))
1335 { 1330 {
1336 // Expression 1331 // Expression
1337 m_lx->must_get_next(); 1332 m_lx->must_get_next();
1338 data_buffer* c = parse_expression (reqtype); 1333 data_buffer* c = parse_expression (reqtype);
1339 b->merge (c); 1334 b->merge_and_destroy (c);
1340 m_lx->must_get_next (tk_paren_end); 1335 m_lx->must_get_next (tk_paren_end);
1341 } 1336 }
1342 else if (command_info* comm = find_command_by_name (token_string())) 1337 else if (command_info* comm = find_command_by_name (token_string()))
1343 { 1338 {
1344 delete b; 1339 delete b;
1345 1340
1346 // Command 1341 // Command
1347 if (reqtype && comm->returnvalue != reqtype) 1342 if (reqtype && comm->returnvalue != reqtype)
1348 error ("%1 returns an incompatible data type", comm->name); 1343 error ("%1 returns an incompatible data type", comm->name);
1349 1344
1350 b = ParseCommand (comm); 1345 b = parse_command (comm);
1351 } 1346 }
1352 else if (constant_info* constant = find_constant (token_string())) 1347 else if (constant_info* constant = find_constant (token_string()))
1353 { 1348 {
1354 // Type check 1349 // Type check
1355 if (reqtype != constant->type) 1350 if (reqtype != constant->type)
1359 1354
1360 switch (constant->type) 1355 switch (constant->type)
1361 { 1356 {
1362 case TYPE_BOOL: 1357 case TYPE_BOOL:
1363 case TYPE_INT: 1358 case TYPE_INT:
1364 b->write (dh_push_number); 1359 b->write_dword (dh_push_number);
1365 b->write (atoi (constant->val)); 1360 b->write_dword (atoi (constant->val));
1366 break; 1361 break;
1367 1362
1368 case TYPE_STRING: 1363 case TYPE_STRING:
1369 b->write_string (constant->val); 1364 b->write_string_index (constant->val);
1370 break; 1365 break;
1371 1366
1372 case TYPE_VOID: 1367 case TYPE_VOID:
1373 case TYPE_UNKNOWN: 1368 case TYPE_UNKNOWN:
1374 break; 1369 break;
1375 } 1370 }
1376 } 1371 }
1377 else if ((g = find_global_variable (token_string()))) 1372 else if ((g = find_global_variable (token_string())))
1378 { 1373 {
1379 // Global variable 1374 // Global variable
1380 b->write (dh_push_global_var); 1375 b->write_dword (dh_push_global_var);
1381 b->write (g->index); 1376 b->write_dword (g->index);
1382 } 1377 }
1383 else 1378 else
1384 { 1379 {
1385 // If nothing else, check for literal 1380 // If nothing else, check for literal
1386 switch (reqtype) 1381 switch (reqtype)
1395 { 1390 {
1396 m_lx->must_be (tk_number); 1391 m_lx->must_be (tk_number);
1397 1392
1398 // All values are written unsigned - thus we need to write the value's 1393 // All values are written unsigned - thus we need to write the value's
1399 // absolute value, followed by an unary minus for negatives. 1394 // absolute value, followed by an unary minus for negatives.
1400 b->write (dh_push_number); 1395 b->write_dword (dh_push_number);
1401 1396
1402 long v = token_string().to_long(); 1397 long v = token_string().to_long();
1403 b->write (static_cast<word> (abs (v))); 1398 b->write_dword (static_cast<word> (abs (v)));
1404 1399
1405 if (v < 0) 1400 if (v < 0)
1406 b->write (dh_unary_minus); 1401 b->write_dword (dh_unary_minus);
1407 1402
1408 break; 1403 break;
1409 } 1404 }
1410 1405
1411 case TYPE_STRING: 1406 case TYPE_STRING:
1412 // PushToStringTable either returns the string index of the 1407 // PushToStringTable either returns the string index of the
1413 // string if it finds it in the table, or writes it to the 1408 // string if it finds it in the table, or writes it to the
1414 // table and returns it index if it doesn't find it there. 1409 // table and returns it index if it doesn't find it there.
1415 m_lx->must_be (tk_string); 1410 m_lx->must_be (tk_string);
1416 b->write_string (token_string()); 1411 b->write_string_index (token_string());
1417 break; 1412 break;
1418 } 1413 }
1419 } 1414 }
1420 1415
1421 // Negate it now if desired 1416 // Negate it now if desired
1422 if (negate) 1417 if (negate)
1423 b->write (dh_negate_logical); 1418 b->write_dword (dh_negate_logical);
1424 1419
1425 return b; 1420 return b;
1426 } 1421 }
1427 1422
1428 // ============================================================================ 1423 // ============================================================================
1430 // by an assignment operator, followed by an expression value. Expects current 1425 // by an assignment operator, followed by an expression value. Expects current
1431 // token to be the name of the variable, and expects the variable to be given. 1426 // token to be the name of the variable, and expects the variable to be given.
1432 // 1427 //
1433 data_buffer* botscript_parser::parse_assignment (script_variable* var) 1428 data_buffer* botscript_parser::parse_assignment (script_variable* var)
1434 { 1429 {
1435 bool global = !var->statename.len();
1436
1437 // Get an operator 1430 // Get an operator
1438 m_lx->must_get_next(); 1431 m_lx->must_get_next();
1439 int oper = parse_operator(); 1432 int oper = parse_operator();
1440 1433
1441 if (!is_assignment_operator (oper)) 1434 if (!is_assignment_operator (oper))
1442 error ("expected assignment operator"); 1435 error ("expected assignment operator");
1443 1436
1444 if (g_current_mode == MODE_TOPLEVEL) 1437 if (m_current_mode == MODE_TOPLEVEL)
1445 error ("can't alter variables at top level"); 1438 error ("can't alter variables at top level");
1446 1439
1447 // Parse the right operand 1440 // Parse the right operand
1448 m_lx->must_get_next(); 1441 m_lx->must_get_next();
1449 data_buffer* retbuf = new data_buffer; 1442 data_buffer* retbuf = new data_buffer;
1452 // <<= and >>= do not have data headers. Solution: expand them. 1445 // <<= and >>= do not have data headers. Solution: expand them.
1453 // a <<= b -> a = a << b 1446 // a <<= b -> a = a << b
1454 // a >>= b -> a = a >> b 1447 // a >>= b -> a = a >> b
1455 if (oper == OPER_ASSIGNLEFTSHIFT || oper == OPER_ASSIGNRIGHTSHIFT) 1448 if (oper == OPER_ASSIGNLEFTSHIFT || oper == OPER_ASSIGNRIGHTSHIFT)
1456 { 1449 {
1457 retbuf->write (global ? dh_push_global_var : dh_push_local_var); 1450 retbuf->write_dword (var->is_global() ? dh_push_global_var : dh_push_local_var);
1458 retbuf->write (var->index); 1451 retbuf->write_dword (var->index);
1459 retbuf->merge (expr); 1452 retbuf->merge_and_destroy (expr);
1460 retbuf->write ((oper == OPER_ASSIGNLEFTSHIFT) ? dh_left_shift : dh_right_shift); 1453 retbuf->write_dword ((oper == OPER_ASSIGNLEFTSHIFT) ? dh_left_shift : dh_right_shift);
1461 retbuf->write (global ? dh_assign_global_var : dh_assign_local_var); 1454 retbuf->write_dword (var->is_global() ? dh_assign_global_var : dh_assign_local_var);
1462 retbuf->write (var->index); 1455 retbuf->write_dword (var->index);
1463 } 1456 }
1464 else 1457 else
1465 { 1458 {
1466 retbuf->merge (expr); 1459 retbuf->merge_and_destroy (expr);
1467 long dh = get_data_header_by_operator (var, oper); 1460 long dh = get_data_header_by_operator (var, oper);
1468 retbuf->write (dh); 1461 retbuf->write_dword (dh);
1469 retbuf->write (var->index); 1462 retbuf->write_dword (var->index);
1470 } 1463 }
1471 1464
1472 return retbuf; 1465 return retbuf;
1473 } 1466 }
1474 1467
1475 // ============================================================================ 1468 // ============================================================================
1476 // 1469 //
1477 void botscript_parser::push_scope() 1470 void botscript_parser::push_scope()
1478 { 1471 {
1479 g_ScopeCursor++; 1472 m_scope_cursor++;
1480 1473
1481 if (g_ScopeCursor >= MAX_SCOPE) 1474 if (m_scope_cursor >= MAX_SCOPE)
1482 error ("too deep scope"); 1475 error ("too deep scope");
1483 1476
1484 ScopeInfo* info = &SCOPE (0); 1477 ScopeInfo* info = &SCOPE (0);
1485 info->type = e_unknown_scope; 1478 info->type = e_unknown_scope;
1486 info->mark1 = 0; 1479 info->mark1 = null;
1487 info->mark2 = 0; 1480 info->mark2 = null;
1488 info->buffer1 = null; 1481 info->buffer1 = null;
1489 info->casecursor = -1; 1482 info->casecursor = -1;
1490 1483
1491 for (int i = 0; i < MAX_CASE; i++) 1484 for (int i = 0; i < MAX_CASE; i++)
1492 { 1485 {
1493 info->casemarks[i] = MAX_MARKS; 1486 info->casemarks[i] = null;
1494 info->casebuffers[i] = null; 1487 info->casebuffers[i] = null;
1495 info->casenumbers[i] = -1; 1488 info->casenumbers[i] = -1;
1496 } 1489 }
1497 } 1490 }
1498 1491
1520 1513
1521 if (info->casecursor >= MAX_CASE) 1514 if (info->casecursor >= MAX_CASE)
1522 error ("too many cases in one switch"); 1515 error ("too many cases in one switch");
1523 1516
1524 // Init a mark for the case buffer 1517 // Init a mark for the case buffer
1525 int m = m_writer->add_mark (""); 1518 byte_mark* casemark = buffer()->add_mark ("");
1526 info->casemarks[info->casecursor] = m; 1519 info->casemarks[info->casecursor] = casemark;
1527 1520
1528 // Add a reference to the mark. "case" and "default" both 1521 // Add a reference to the mark. "case" and "default" both
1529 // add the necessary bytecode before the reference. 1522 // add the necessary bytecode before the reference.
1530 if (b) 1523 if (b)
1531 b->add_reference (m); 1524 b->add_reference (casemark);
1532 else 1525 else
1533 m_writer->add_reference (m); 1526 buffer()->add_reference (casemark);
1534 1527
1535 // Init a buffer for the case block and tell the object 1528 // Init a buffer for the case block and tell the object
1536 // writer to record all written data to it. 1529 // writer to record all written data to it.
1537 info->casebuffers[info->casecursor] = m_writer->SwitchBuffer = new data_buffer; 1530 info->casebuffers[info->casecursor] = m_switch_buffer = new data_buffer;
1538 } 1531 }
1539 1532
1540 // ============================================================================ 1533 // ============================================================================
1541 // 1534 //
1542 constant_info* find_constant (const string& tok) 1535 constant_info* botscript_parser::find_constant (const string& tok)
1543 { 1536 {
1544 for (int i = 0; i < g_ConstInfo.size(); i++) 1537 for (int i = 0; i < m_constants.size(); i++)
1545 if (g_ConstInfo[i].name == tok) 1538 if (m_constants[i].name == tok)
1546 return &g_ConstInfo[i]; 1539 return &m_constants[i];
1547 1540
1548 return null; 1541 return null;
1549 } 1542 }
1550 1543
1551 // ============================================================================ 1544 // ============================================================================
1567 string botscript_parser::describe_position() const 1560 string botscript_parser::describe_position() const
1568 { 1561 {
1569 lexer::token* tok = m_lx->get_token(); 1562 lexer::token* tok = m_lx->get_token();
1570 return tok->file + ":" + string (tok->line) + ":" + string (tok->column); 1563 return tok->file + ":" + string (tok->line) + ":" + string (tok->column);
1571 } 1564 }
1565
1566 // ============================================================================
1567 //
1568 data_buffer* botscript_parser::buffer()
1569 {
1570 if (m_switch_buffer != null)
1571 return m_switch_buffer;
1572
1573 if (m_current_mode == MODE_MAINLOOP)
1574 return m_main_loop_buffer;
1575
1576 if (m_current_mode == MODE_ONENTER)
1577 return m_on_enter_buffer;
1578
1579 return m_main_buffer;
1580 }
1581
1582 // ============================================================================
1583 //
1584 void botscript_parser::write_member_buffers()
1585 {
1586 // If there was no mainloop defined, write a dummy one now.
1587 if (!m_got_main_loop)
1588 {
1589 m_main_loop_buffer->write_dword (dh_main_loop);
1590 m_main_loop_buffer->write_dword (dh_end_main_loop);
1591 }
1592
1593 // Write the onenter and mainloop buffers, in that order in particular.
1594 for (data_buffer** bufp : list<data_buffer**> ({&m_on_enter_buffer, &m_main_loop_buffer}))
1595 {
1596 buffer()->merge_and_destroy (*bufp);
1597
1598 // Clear the buffer afterwards for potential next state
1599 *bufp = new data_buffer;
1600 }
1601
1602 // Next state definitely has no mainloop yet
1603 m_got_main_loop = false;
1604 }
1605
1606 // ============================================================================
1607 //
1608 // Write string table
1609 //
1610 void botscript_parser::write_string_table()
1611 {
1612 int stringcount = num_strings_in_table();
1613
1614 if (!stringcount)
1615 return;
1616
1617 // Write header
1618 m_main_buffer->write_dword (dh_string_list);
1619 m_main_buffer->write_dword (stringcount);
1620
1621 // Write all strings
1622 for (int i = 0; i < stringcount; i++)
1623 m_main_buffer->write_string (get_string_table()[i]);
1624 }
1625
1626 // ============================================================================
1627 //
1628 // Write the compiled bytecode to a file
1629 //
1630 void botscript_parser::write_to_file (string outfile)
1631 {
1632 FILE* fp = fopen (outfile, "w");
1633 CHECK_FILE (fp, outfile, "writing");
1634
1635 // First, resolve references
1636 for (int u = 0; u < MAX_MARKS; u++)
1637 {
1638 mark_reference* ref = m_main_buffer->get_refs()[u];
1639
1640 if (!ref)
1641 continue;
1642
1643 // Substitute the placeholder with the mark position
1644 generic_union<word> uni;
1645 uni.as_word = static_cast<word> (ref->target->pos);
1646
1647 for (int v = 0; v < (int) sizeof (word); v++)
1648 memset (m_main_buffer->get_buffer() + ref->pos + v, uni.as_bytes[v], 1);
1649
1650 /*
1651 printf ("reference %u at %d resolved to %u at %d\n",
1652 u, ref->pos, ref->num, MainBuffer->marks[ref->num]->pos);
1653 */
1654 }
1655
1656 // Then, dump the main buffer to the file
1657 fwrite (m_main_buffer->get_buffer(), 1, m_main_buffer->get_write_size(), fp);
1658 print ("-- %1 byte%s1 written to %2\n", m_main_buffer->get_write_size(), outfile);
1659 fclose (fp);
1660 }

mercurial