1%{ 2/** 3 ** Ucparse.y - Usecode parser. 4 ** 5 ** Written: 12/30/2000 - JSF 6 **/ 7 8/* 9Copyright (C) 2000 The Exult Team 10 11This program is free software; you can redistribute it and/or 12modify it under the terms of the GNU General Public License 13as published by the Free Software Foundation; either version 2 14of the License, or (at your option) any later version. 15 16This program is distributed in the hope that it will be useful, 17but WITHOUT ANY WARRANTY; without even the implied warranty of 18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19GNU General Public License for more details. 20 21You should have received a copy of the GNU General Public License 22along with this program; if not, write to the Free Software 23Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 24*/ 25 26#ifdef HAVE_CONFIG_H 27# include <config.h> 28#endif 29#include <cstdio> 30#include <cstdlib> 31#include <cstring> 32#include <iostream> 33#include <string> 34#include <vector> 35 36#include "ucfun.h" 37#include "ucclass.h" 38#include "ucexpr.h" 39#include "ucstmt.h" 40#include "opcodes.h" 41#include "ucscriptop.h" 42 43using std::string; 44using std::vector; 45 46void yyerror(const char *); 47void yywarning(const char *); 48extern int yylex(); 49extern void start_script(), end_script(); 50extern void start_loop(), end_loop(); 51extern void start_breakable(), end_breakable(); 52extern void start_fun_id(), end_fun_id(); 53static Uc_array_expression *Create_array(int, Uc_expression *); 54static Uc_array_expression *Create_array(int, Uc_expression *, 55 Uc_expression *); 56static Uc_class *Find_class(const char *nm); 57static bool Class_unexpected_error(Uc_expression *expr); 58static bool Nonclass_unexpected_error(Uc_expression *expr); 59static bool Incompatible_classes_error(Uc_class *src, Uc_class *trg); 60static Uc_call_expression *cls_method_call(Uc_expression *ths, Uc_class *curcls, 61 Uc_class *clsscope, char *nm, Uc_array_expression *parms); 62static Uc_call_expression *cls_function_call(Uc_expression *ths, 63 Uc_class *curcls, char *nm, bool original, Uc_array_expression *parms); 64 65 66#define YYERROR_VERBOSE 1 67 68std::vector<Uc_design_unit *> units; // THIS is what we produce. 69 70static Uc_function *cur_fun = nullptr; // Current function being parsed. 71static Uc_class *cur_class = nullptr; // ...or, current class being parsed. 72static Uc_struct_symbol *cur_struct = nullptr; // ...or, current struct being parsed. 73static int enum_val = -1; // Keeps track of enum elements. 74static bool is_extern = false; // Marks a function symbol as being an extern 75static Uc_class *class_type = nullptr; // For declaration of class variables. 76static Uc_struct_symbol *struct_type = nullptr; // For declaration of struct variables. 77static bool has_ret = false; 78static int repeat_nesting = 0; 79static std::vector<UsecodeOps> const_opcode; 80static int converse = 0; // If we are in a converse block. 81 82struct Fun_id_info 83 { 84 Uc_function_symbol::Function_kind kind; 85 int id; 86 Fun_id_info(Uc_function_symbol::Function_kind k, int i) 87 : kind(k), id(i) 88 { } 89 }; 90 91struct Member_selector 92 { 93 Uc_expression *expr; 94 char *name; 95 Member_selector(Uc_expression *e, char *n) 96 : expr(e), name(n) 97 { } 98 }; 99 100#ifdef __GNUC__ 101#pragma GCC diagnostic push 102#pragma GCC diagnostic ignored "-Wold-style-cast" 103#pragma GCC diagnostic ignored "-Wcast-qual" 104#pragma GCC diagnostic ignored "-Wredundant-tags" 105#endif // __GNUC__ 106 107%} 108 109%union 110 { 111 class Uc_symbol *sym; 112 class Uc_var_symbol *var; 113 class Uc_class *cls; 114 class Uc_struct_symbol *struc; 115 class Uc_expression *expr; 116 class Uc_call_expression *funcall; 117 class Uc_function_symbol *funsym; 118 class Uc_statement *stmt; 119 class std::vector<Uc_var_symbol *> *varvec; 120 class Uc_block_statement *block; 121 class Uc_arrayloop_statement *arrayloop; 122 class Uc_array_expression *exprlist; 123 class std::vector<int> *intlist; 124 class std::vector<Uc_statement *> *stmtlist; 125 struct Fun_id_info *funid; 126 struct Member_selector *membersel; 127 int intval; 128 char *strval; 129 } 130 131/* 132 * Keywords: 133 */ 134%token IF ELSE RETURN DO WHILE FOR UCC_IN WITH TO EXTERN BREAK GOTO CASE 135%token VAR VOID ALIAS STRUCT UCC_CHAR UCC_INT UCC_LONG UCC_CONST STRING ENUM 136%token CONVERSE NESTED SAY MESSAGE RESPONSE EVENT FLAG ITEM UCTRUE UCFALSE REMOVE 137%token ADD HIDE SCRIPT AFTER TICKS STATIC_ ORIGINAL SHAPENUM OBJECTNUM 138%token CLASS NEW DELETE RUNSCRIPT UCC_INSERT SWITCH DEFAULT 139%token ADD_EQ SUB_EQ MUL_EQ DIV_EQ MOD_EQ CHOICE TRY CATCH ABORT THROW 140 141/* 142 * Script keywords: 143 */ 144 /* Script commands. */ 145%token CONTINUE REPEAT NOP NOHALT WAIT /*REMOVE*/ RISE DESCEND FRAME HATCH 146%token NEXT PREVIOUS CYCLE STEP MUSIC CALL SPEECH SFX FACE HIT HOURS ACTOR 147%token ATTACK FINISH RESURRECT SETEGG MINUTES RESET WEATHER NEAR FAR 148%token NORTH SOUTH EAST WEST NE NW SE SW 149%token STANDING STEP_RIGHT STEP_LEFT READY RAISE_1H REACH_1H STRIKE_1H RAISE_2H 150%token REACH_2H STRIKE_2H SITTING BOWING KNEELING SLEEPING CAST_UP CAST_OUT 151%token CACHED_IN PARTY_NEAR AVATAR_NEAR AVATAR_FAR AVATAR_FOOTPAD 152%token PARTY_FOOTPAD SOMETHING_ON EXTERNAL_CRITERIA NORMAL_DAMAGE FIRE_DAMAGE 153%token MAGIC_DAMAGE LIGHTNING_DAMAGE ETHEREAL_DAMAGE SONIC_DAMAGE 154 155 156/* 157 * Other tokens: 158 */ 159%token <strval> STRING_LITERAL STRING_PREFIX IDENTIFIER 160%token <intval> INT_LITERAL 161 162/* 163 * Handle if-then-else conflict. 164 */ 165%left IF 166%right ELSE 167 168/* 169 * Expression precedence rules (lowest to highest): 170 */ 171%left UCC_INSERT ADD_EQ SUB_EQ MUL_EQ DIV_EQ MOD_EQ '=' 172%left AND OR 173%left EQUALS NEQUALS 174%left LTEQUALS GTEQUALS '<' '>' UCC_IN 175%left '-' '+' '&' 176%left '*' '/' '%' 177%right NOT ADDRESSOF UMINUS UPLUS NEW DELETE UCC_CAST 178%left UCC_SYM 179%left UCC_POINTS '.' '(' ')' '[' ']' 180%left UCC_SCOPE 181 182/* 183 * Production types: 184 */ 185%type <expr> expression primary declared_var_value opt_script_delay item 186%type <expr> script_command start_call addressof new_expr class_expr 187%type <expr> nonclass_expr opt_delay appended_element int_literal 188%type <intval> opt_int direction converse_options actor_frames egg_criteria 189%type <intval> opt_original assignment_operator const_int_val opt_const_int_val 190%type <intval> const_int_type int_cast dam_type opt_nest 191%type <funid> opt_funid 192%type <membersel> member_selector 193%type <intlist> string_list response_expression 194%type <sym> declared_sym 195%type <var> declared_var param 196%type <cls> opt_inheritance defined_class 197%type <struc> defined_struct 198%type <funsym> function_proto function_decl 199%type <varvec> param_list opt_param_list 200%type <stmt> statement assignment_statement if_statement while_statement 201%type <stmt> statement_block return_statement function_call_statement 202%type <stmt> special_method_call_statement trycatch_statement trystart_statement 203%type <stmt> array_loop_statement var_decl var_decl_list stmt_declaration 204%type <stmt> class_decl class_decl_list struct_decl_list struct_decl 205%type <stmt> break_statement converse_statement 206%type <stmt> converse_case switch_case script_statement switch_statement 207%type <stmt> label_statement goto_statement answer_statement 208%type <stmt> delete_statement continue_statement response_case 209%type <block> statement_list 210%type <arrayloop> start_array_loop 211%type <exprlist> opt_expression_list expression_list script_command_list 212%type <exprlist> opt_nonclass_expr_list nonclass_expr_list appended_element_list 213%type <stmtlist> switch_case_list converse_case_list response_case_list 214%type <funcall> function_call 215 216%% 217 218design: 219 design global_decl 220 | global_decl 221 ; 222 223global_decl: 224 function 225 | function_decl 226 { 227 if (!Uc_function::add_global_function_symbol($1)) 228 delete $1; 229 } 230 | const_int_decl 231 | enum_decl 232 | static_decl 233 | class_definition 234 | struct_definition 235 ; 236 237class_definition: 238 CLASS IDENTIFIER opt_inheritance 239 { $3 ? cur_class = new Uc_class($2, $3) 240 : cur_class = new Uc_class($2); } 241 '{' class_item_list '}' 242 { 243 units.push_back(cur_class); 244 // Add to 'globals' symbol table. 245 Uc_class_symbol::create($2, cur_class); 246 cur_class = nullptr; 247 } 248 ; 249 250opt_inheritance: 251 ':' defined_class 252 { $$ = $2; } 253 | /* Empty */ 254 { $$ = nullptr; } 255 ; 256 257class_item_list: 258 class_item_list class_item 259 | /* Empty */ 260 ; 261 262class_item: 263 VAR { has_ret = true; } class_var_def 264 { has_ret = false; } 265 | VAR alias_tok IDENTIFIER '=' declared_var ';' 266 { cur_class->add_alias($3, $5); } 267 | STRUCT '<' defined_struct '>' { struct_type = $3; } class_struct_def 268 { struct_type = nullptr; } 269 | STRUCT '<' defined_struct '>' alias_tok IDENTIFIER '=' declared_var ';' 270 { cur_class->add_alias($6, $8, $3); } 271 | CLASS '<' defined_class '>' { class_type = $3; } method 272 { class_type = nullptr; } 273 | opt_void method 274 ; 275 276class_var_def: 277 var_decl_list ';' 278 | method 279 ; 280 281class_struct_def: 282 struct_decl_list ';' 283 | method 284 ; 285 286method: 287 IDENTIFIER '(' opt_param_list ')' 288 { 289 $3->insert($3->begin(), // So it's local[0]. 290 new Uc_class_inst_symbol("this", cur_class, 0)); 291 auto *funsym = 292 Uc_function_symbol::create($1, -1, *$3, false, 293 cur_class->get_scope(), Uc_function_symbol::utility_fun); 294 delete $3; // A copy was made. 295 296 // Set return type. 297 if (has_ret) 298 funsym->set_ret_type(true); 299 else if (class_type) 300 funsym->set_ret_type(class_type); 301 else if (struct_type) 302 funsym->set_ret_type(struct_type); 303 has_ret = false; 304 class_type = nullptr; 305 struct_type = nullptr; 306 307 cur_fun = new Uc_function(funsym, cur_class->get_scope()); 308 } 309 function_body 310 { 311 cur_class->add_method(cur_fun); 312 cur_fun = nullptr; 313 } 314 ; 315 316struct_definition: 317 STRUCT IDENTIFIER 318 { cur_struct = new Uc_struct_symbol($2); } 319 '{' struct_item_list '}' 320 { 321 // Add to 'globals' symbol table. 322 Uc_function::add_global_struct_symbol(cur_struct); 323 cur_struct = nullptr; 324 } 325 ; 326 327struct_item_list: 328 struct_item_list struct_item 329 | /* Empty */ 330 ; 331 332struct_item: 333 VAR IDENTIFIER ';' 334 { cur_struct->add($2); } 335 | STRUCT '<' defined_struct '>' ';' 336 { cur_struct->merge_struct($3); } 337 | STRUCT '<' defined_struct '>' IDENTIFIER ';' 338 { cur_struct->merge_struct($3); } 339 ; 340 341function: 342 function_proto { cur_fun = new Uc_function($1); } 343 function_body 344 { 345 units.push_back(cur_fun); 346 cur_fun = nullptr; 347 } 348 ; 349 350function_body: 351 '{' statement_list '}' 352 { 353 cur_fun->set_statement($2); 354 } 355 | '{' statement_list label_statement '}' 356 { // Function ends in label. 357 $2->add($3); 358 cur_fun->set_statement($2); 359 } 360 ; 361 362 /* Opt_int assigns function #. */ 363function_proto: 364 ret_type IDENTIFIER { start_fun_id(); } opt_funid '(' opt_param_list ')' 365 { 366 end_fun_id(); 367 if ($4->kind != Uc_function_symbol::utility_fun) 368 { 369 char buf[180]; 370 if (has_ret || struct_type) 371 { 372 sprintf(buf, "Functions declared with '%s#' cannot return a value", 373 $4->kind == Uc_function_symbol::shape_fun ? "shape" : "object"); 374 yyerror(buf); 375 } 376 if (!$6->empty()) 377 { 378 sprintf(buf, "Functions declared with '%s#' cannot have arguments", 379 $4->kind == Uc_function_symbol::shape_fun ? "shape" : "object"); 380 yyerror(buf); 381 } 382 } 383 $$ = Uc_function_symbol::create($2, $4->id, *$6, is_extern, nullptr, $4->kind); 384 if (has_ret) 385 $$->set_ret_type(true); 386 else if (struct_type) 387 $$->set_ret_type(struct_type); 388 delete $6; // A copy was made. 389 delete $4; 390 has_ret = false; 391 struct_type = nullptr; 392 } 393 | CLASS '<' defined_class '>' IDENTIFIER opt_int '(' opt_param_list ')' 394 { 395 $$ = Uc_function_symbol::create($5, $6, *$8, is_extern, nullptr, 396 Uc_function_symbol::utility_fun); 397 $$->set_ret_type($3); 398 delete $8; // A copy was made. 399 } 400 ; 401 402opt_funid: 403 SHAPENUM '(' const_int_val ')' 404 { 405 $$ = new Fun_id_info(Uc_function_symbol::shape_fun, $3 < 0 ? -1 : $3); 406 if ($3 < 0) 407 yyerror("Shape number cannot be negative"); 408 } 409 | OBJECTNUM '(' opt_const_int_val ')' 410 { $$ = new Fun_id_info(Uc_function_symbol::object_fun, $3); } 411 | opt_const_int_val 412 { $$ = new Fun_id_info(Uc_function_symbol::utility_fun, $1); } 413 ; 414 415opt_const_int_val: 416 const_int_val 417 | /* Empty. */ 418 { $$ = -1; } 419 ; 420 421const_int_val: 422 INT_LITERAL 423 | IDENTIFIER 424 { 425 Uc_symbol *sym = Uc_function::search_globals($1); 426 Uc_const_int_symbol *var; 427 char buf[180]; 428 if (!sym) 429 { 430 sprintf(buf, "'%s' not declared", $1); 431 yyerror(buf); 432 $$ = -1; 433 } 434 else if ((var = dynamic_cast<Uc_const_int_symbol *>(sym)) == nullptr) 435 { 436 sprintf(buf, "'%s' is not a constant integer", $1); 437 yyerror(buf); 438 $$ = -1; 439 } 440 else 441 $$ = var->get_value(); 442 } 443 ; 444 445opt_int: 446 const_int_val 447 | /* Empty. */ 448 { $$ = -1; } 449 ; 450 451statement_block: 452 statement_block_start statement_list '}' 453 { 454 $$ = $2; 455 cur_fun->pop_scope(); 456 } 457 | statement_block_start statement_list label_statement '}' 458 { // Block ends in label. 459 $2->add($3); 460 $$ = $2; 461 cur_fun->pop_scope(); 462 } 463 | label_statement statement 464 { // Label followed by statements; "grab" next statement for label. 465 if ($2) 466 { 467 auto *stmt = new Uc_block_statement(); 468 stmt->add($1); 469 stmt->add($2); 470 $$ = stmt; 471 } 472 else // This is the case for the "null" statement ';'. 473 $$ = $1; 474 } 475 ; 476 477statement_block_start: 478 '{' 479 { cur_fun->push_scope(); } 480 ; 481 482statement_list: 483 statement_list statement 484 { 485 if ($2) 486 $$->add($2); 487 } 488 | /* Empty. */ 489 { $$ = new Uc_block_statement(); } 490 ; 491 492statement: 493 stmt_declaration 494 | assignment_statement 495 | if_statement 496 | trycatch_statement 497 | while_statement 498 | array_loop_statement 499 | function_call_statement 500 | special_method_call_statement 501 | return_statement 502 | statement_block 503 | converse_statement 504 | switch_statement 505 | script_statement 506 | break_statement 507 | continue_statement 508 | goto_statement 509 | delete_statement 510 | SAY '(' opt_nonclass_expr_list ')' ';' 511 { $$ = new Uc_say_statement($3); } 512 | MESSAGE '(' opt_nonclass_expr_list ')' ';' 513 { $$ = new Uc_message_statement($3); } 514 | answer_statement 515 | throwabort_statement ';' 516 { $$ = new Uc_abort_statement(); } 517 | throwabort_statement expression ';' 518 { $$ = new Uc_abort_statement($2); } 519 | ';' /* Null statement */ 520 { $$ = nullptr; } 521 ; 522 523throwabort_statement: 524 ABORT 525 | THROW 526 ; 527 528alias_tok: 529 ALIAS 530 | '&' 531 ; 532 533stmt_declaration: 534 VAR var_decl_list ';' 535 { $$ = $2; } 536 | VAR alias_tok IDENTIFIER '=' declared_var ';' 537 { cur_fun->add_alias($3, $5); $$ = nullptr; } 538 | STRUCT '<' defined_struct '>' { struct_type = $3; } struct_decl_list ';' 539 { struct_type = nullptr; $$ = $6; } 540 | STRUCT '<' defined_struct '>' alias_tok IDENTIFIER '=' declared_var ';' 541 { cur_fun->add_alias($6, $8, $3); $$ = nullptr; } 542 | CLASS '<' defined_class '>' { class_type = $3; } class_decl_list ';' 543 { class_type = nullptr; $$ = $6; } 544 | CLASS '<' defined_class '>' alias_tok IDENTIFIER '=' declared_var ';' 545 { 546 if (!$8->get_cls()) 547 yyerror("Can't convert non-class into class."); 548 else if (!Incompatible_classes_error($8->get_cls(), $3)) 549 // Alias may be of different (compatible) class. 550 cur_fun->add_alias($6, $8, $3); 551 $$ = nullptr; 552 } 553 | STRING string_decl_list ';' 554 { $$ = nullptr; } 555 | const_int_decl 556 { $$ = nullptr; } 557 | enum_decl 558 { $$ = nullptr; } 559 | function_decl 560 { 561 if (!cur_fun->add_function_symbol($1, cur_class ? 562 cur_class->get_scope() : nullptr)) 563 delete $1; 564 $$ = nullptr; 565 } 566 | static_decl 567 { $$ = nullptr; } 568 ; 569 570var_decl_list: 571 var_decl_list ',' var_decl 572 { 573 if (!$3) 574 $$ = $1; 575 else if (!$1) 576 $$ = $3; 577 else /* Both nonzero. Need a list. */ 578 { 579 auto *b = dynamic_cast<Uc_block_statement *>($1); 580 if (!b) 581 { 582 b = new Uc_block_statement(); 583 b->add($1); 584 } 585 b->add($3); 586 $$ = b; 587 } 588 } 589 | var_decl 590 { $$ = $1; } 591 ; 592 593enum_decl: /* Decls. the elems, not the enum. */ 594 ENUM IDENTIFIER { enum_val = -1; } 595 opt_enum_type '{' enum_item_list '}' ';' 596 { const_opcode.pop_back(); } 597 ; 598 599const_int_type: 600 UCC_INT 601 { $$ = UC_PUSHI; } 602 | UCC_CHAR 603 { $$ = UC_PUSHB; } 604 | UCC_LONG 605 { $$ = UC_PUSHI32; } 606 | UCC_LONG UCC_INT 607 { $$ = UC_PUSHI32; } 608 ; 609 610opt_enum_type: 611 ':' const_int_type 612 { const_opcode.push_back(static_cast<UsecodeOps>($2)); } 613 | /* Empty. */ 614 { const_opcode.push_back(UC_PUSHI); } 615 ; 616 617enum_item_list: 618 enum_item_list ',' enum_item 619 | enum_item 620 ; 621 622enum_item: 623 const_int 624 | IDENTIFIER 625 { /* Increment last value. */ 626 ++enum_val; 627 int op = const_opcode.back(); 628 if (cur_fun) 629 cur_fun->add_int_const_symbol($1, enum_val, op); 630 else // Global. 631 Uc_function::add_global_int_const_symbol($1, enum_val, op); 632 } 633 ; 634 635const_int_decl: 636 UCC_CONST const_int_type { const_opcode.push_back(static_cast<UsecodeOps>($2)); } 637 const_int_decl_list ';' 638 { const_opcode.pop_back(); } 639 ; 640 641const_int_decl_list: 642 const_int_decl_list ',' const_int 643 | const_int 644 ; 645 646const_int: 647 IDENTIFIER '=' nonclass_expr 648 { 649 int val; // Get constant. 650 if ($3->eval_const(val)) 651 { 652 int op = const_opcode.back(); 653 if (cur_fun) 654 cur_fun->add_int_const_symbol($1, val, op); 655 else // Global. 656 Uc_function::add_global_int_const_symbol($1, val, op); 657 enum_val = val; // In case we're in an enum. 658 } 659 else 660 yyerror("Integer constant expected."); 661 } 662 ; 663 664var_decl: 665 IDENTIFIER 666 { 667 if (cur_fun) 668 cur_fun->add_symbol($1); 669 else 670 cur_class->add_symbol($1); 671 $$ = nullptr; 672 } 673 | IDENTIFIER '=' nonclass_expr 674 { 675 if (cur_class && !cur_fun) 676 { 677 char buf[180]; 678 sprintf(buf, "Initialization of class member var '%s' must be done through constructor", $1); 679 yyerror(buf); 680 $$ = nullptr; 681 } 682 else 683 { 684 auto *var = cur_fun ? cur_fun->add_symbol($1) 685 : cur_class->add_symbol($1); 686 var->set_is_obj_fun($3->is_object_function(false)); 687 $$ = new Uc_assignment_statement(new Uc_var_expression(var), $3); 688 } 689 } 690 ; 691 692class_decl_list: 693 class_decl_list ',' class_decl 694 { 695 if (!$3) 696 $$ = $1; 697 else if (!$1) 698 $$ = $3; 699 else /* Both nonzero; need a list. */ 700 { 701 auto *b = dynamic_cast<Uc_block_statement *>($1); 702 if (!b) 703 { 704 b = new Uc_block_statement(); 705 b->add($1); 706 } 707 b->add($3); 708 $$ = b; 709 } 710 } 711 | class_decl 712 { $$ = $1; } 713 ; 714 715class_decl: 716 IDENTIFIER 717 { 718 if (class_type && cur_fun) 719 cur_fun->add_symbol($1, class_type); 720 else 721 // Unsupported for now 722 { } 723 $$ = nullptr; 724 } 725 | IDENTIFIER '=' class_expr 726 { 727 if (!class_type || !$3 || Nonclass_unexpected_error($3)) 728 $$ = nullptr; 729 else 730 { 731 Uc_class *src = $3->get_cls(); 732 if (Incompatible_classes_error(src, class_type)) 733 $$ = nullptr; 734 else 735 { 736 auto *v = cur_fun->add_symbol($1, class_type); 737 $$ = new Uc_assignment_statement(new Uc_class_expression(v), $3); 738 } 739 } 740 } 741 ; 742 743struct_decl_list: 744 struct_decl_list ',' struct_decl 745 { 746 if (!$3) 747 $$ = $1; 748 else if (!$1) 749 $$ = $3; 750 else /* Both nonzero; need a list. */ 751 { 752 auto *b = dynamic_cast<Uc_block_statement *>($1); 753 if (!b) 754 { 755 b = new Uc_block_statement(); 756 b->add($1); 757 } 758 b->add($3); 759 $$ = b; 760 } 761 } 762 | struct_decl 763 { $$ = $1; } 764 ; 765 766struct_decl: 767 IDENTIFIER 768 { 769 if (cur_fun) 770 cur_fun->add_symbol($1, struct_type); 771 else 772 cur_class->add_symbol($1, struct_type); 773 $$ = nullptr; 774 } 775 | IDENTIFIER '=' nonclass_expr 776 { 777 if (cur_class && !cur_fun) 778 { 779 char buf[180]; 780 sprintf(buf, "Initialization of class member struct '%s' must be done through constructor", $1); 781 yyerror(buf); 782 $$ = nullptr; 783 } 784 else 785 { 786 auto *var = cur_fun ? cur_fun->add_symbol($1, struct_type) 787 : cur_class->add_symbol($1, struct_type); 788 var->set_is_obj_fun($3->is_object_function(false)); 789 $$ = new Uc_assignment_statement(new Uc_var_expression(var), $3); 790 } 791 } 792 ; 793 794 795class_expr: 796 new_expr 797 { $$ = $1; } 798 | IDENTIFIER 799 { 800 Uc_symbol *sym = cur_fun->search_up($1); 801 if (!sym) 802 { 803 char buf[150]; 804 sprintf(buf, "'%s' not declared", $1); 805 yyerror(buf); 806 cur_fun->add_symbol($1); 807 $$ = nullptr; 808 } 809 else if (sym->get_sym_type() != Uc_symbol::Class) 810 { 811 char buf[150]; 812 sprintf(buf, "'%s' not a class", $1); 813 yyerror(buf); 814 $$ = nullptr; 815 } 816 else 817 { 818 // Tests above guarantee this will always work. 819 auto *cls = 820 dynamic_cast<Uc_class_inst_symbol *>(sym->get_sym()); 821 $$ = new Uc_class_expression(cls); 822 } 823 } 824 | function_call 825 { 826 $$ = $1; 827 } 828 ; 829 830static_decl: 831 STATIC_ VAR static_var_decl_list ';' 832 | STATIC_ STRUCT '<' defined_struct '>' 833 { struct_type = $4; } 834 static_struct_var_decl_list ';' 835 { struct_type = nullptr; } 836 | STATIC_ CLASS '<' defined_class '>' 837 { class_type = $4; } 838 static_cls_decl_list ';' 839 { class_type = nullptr; } 840 ; 841 842static_var_decl_list: 843 static_var 844 | static_var_decl_list ',' static_var 845 ; 846 847static_var: 848 IDENTIFIER 849 { 850 if (cur_fun) 851 cur_fun->add_static($1); 852 else 853 Uc_function::add_global_static($1); 854 } 855 ; 856 857static_struct_var_decl_list: 858 static_struct_var 859 | static_struct_var_decl_list ',' static_struct_var 860 ; 861 862static_struct_var: 863 IDENTIFIER 864 { 865 if (cur_fun) 866 cur_fun->add_static($1, struct_type); 867 else 868 Uc_function::add_global_static($1, struct_type); 869 } 870 ; 871 872static_cls_decl_list: 873 static_cls 874 | static_cls_decl_list ',' static_cls 875 ; 876 877static_cls: 878 IDENTIFIER 879 { 880 if (cur_fun) 881 cur_fun->add_static($1, class_type); 882 else 883 Uc_function::add_global_static($1, class_type); 884 } 885 ; 886 887string_decl_list: 888 string_decl_list ',' string_decl 889 | string_decl 890 ; 891 892string_decl: 893 IDENTIFIER '=' STRING_LITERAL 894 { 895 cur_fun->add_string_symbol($1, $3); 896 } 897 ; 898 899function_decl: 900 EXTERN { is_extern = true; } function_proto ';' 901 { $$ = $3; is_extern = false; } 902 ; 903 904assignment_statement: 905 expression '=' expression ';' 906 { 907 // Some rudimentary type-checking for classes 908 if ($1->is_class()) 909 { 910 if (Nonclass_unexpected_error($3)) 911 $$ = nullptr; 912 else 913 { 914 Uc_class *trg = $1->get_cls(); 915 Uc_class *src = $3->get_cls(); 916 if (Incompatible_classes_error(src, trg)) 917 $$ = nullptr; 918 else 919 { 920 $1->set_is_obj_fun($3->is_object_function(false)); 921 $$ = new Uc_assignment_statement($1, $3); 922 } 923 } 924 } 925 else if (Class_unexpected_error($3)) 926 $$ = nullptr; 927 else 928 { 929 $1->set_is_obj_fun($3->is_object_function(false)); 930 $$ = new Uc_assignment_statement($1, $3); 931 } 932 } 933 | nonclass_expr assignment_operator nonclass_expr ';' 934 { 935 $1->set_is_obj_fun(-1); 936 $$ = new Uc_assignment_statement($1, 937 new Uc_binary_expression(static_cast<UsecodeOps>($2), $1, $3)); 938 } 939 | nonclass_expr UCC_INSERT appended_element_list ';' 940 { 941 $1->set_is_obj_fun(-1); 942 $$ = new Uc_assignment_statement( 943 $1, new Uc_array_expression($1, $3)); 944 } 945 ; 946 947assignment_operator: 948 ADD_EQ 949 { $$ = UC_ADD; } 950 | SUB_EQ 951 { $$ = UC_SUB; } 952 | MUL_EQ 953 { $$ = UC_MUL; } 954 | DIV_EQ 955 { $$ = UC_DIV; } 956 | MOD_EQ 957 { $$ = UC_MOD; } 958 ; 959 960appended_element_list: 961 appended_element_list UCC_INSERT appended_element 962 { $$->add($3); } 963 | appended_element 964 { 965 $$ = new Uc_array_expression(); 966 $$->add($1); 967 } 968 ; 969 970appended_element: 971 nonclass_expr 972 | '{' { start_script(); } script_command_list '}' 973 { 974 $$ = $3; 975 end_script(); 976 } 977 ; 978 979if_statement: 980 IF '(' expression ')' statement %prec IF 981 { 982 int val; 983 if ($3->eval_const(val)) 984 { 985 if (val) 986 { 987 $3->warning("'if' clause will always be executed"); 988 $$ = $5; 989 } 990 else 991 { // Need this because of those pesky GOTOs... 992 $3->warning("'if' clause may never be executed"); 993 $$ = new Uc_if_statement(nullptr, $5, nullptr); 994 } 995 delete $3; 996 } 997 else 998 $$ = new Uc_if_statement($3, $5, nullptr); 999 } 1000 | IF '(' expression ')' statement ELSE statement 1001 { 1002 int val; 1003 if ($3->eval_const(val)) 1004 { 1005 if (val) 1006 { 1007 // Need this because of those pesky GOTOs... 1008 $3->warning("'else' clause may never be executed"); 1009 $$ = new Uc_if_statement(new Uc_int_expression(val == 0), $5, $7); 1010 } 1011 else 1012 { 1013 // Need this because of those pesky GOTOs... 1014 $3->warning("'if' clause may never be executed"); 1015 $$ = new Uc_if_statement(nullptr, $5, $7); 1016 } 1017 delete $3; 1018 } 1019 else 1020 $$ = new Uc_if_statement($3, $5, $7); 1021 } 1022 ; 1023 1024trycatch_statement: 1025 trystart_statement '{' statement_list '}' 1026 { 1027 auto *stmt = dynamic_cast<Uc_trycatch_statement*>($1); 1028 if (!stmt) { 1029 yyerror("try/catch statement is not a try/catch statement"); 1030 } else { 1031 stmt->set_catch_statement($3); 1032 } 1033 $$ = stmt; 1034 } 1035 ; 1036 1037trystart_statement: 1038 TRY '{' statement_list '}' CATCH '(' ')' 1039 { 1040 cur_fun->push_scope(); 1041 $$ = new Uc_trycatch_statement($3); 1042 } 1043 | TRY '{' statement_list '}' CATCH '(' IDENTIFIER ')' 1044 { 1045 cur_fun->push_scope(); 1046 auto *stmt = new Uc_trycatch_statement($3); 1047 stmt->set_catch_variable(cur_fun->add_symbol($7)); 1048 $$ = stmt; 1049 } 1050 ; 1051 1052while_statement: 1053 WHILE '(' nonclass_expr ')' { start_loop(); } statement 1054 { 1055 int val; 1056 if ($3->eval_const(val)) 1057 { 1058 if (val) 1059 { 1060 $3->warning("Infinite loop detected"); 1061 $$ = new Uc_infinite_loop_statement($6); 1062 } 1063 else 1064 { // Need this because of those pesky GOTOs... 1065 $3->warning("Body of 'while' statement may never be executed"); 1066 $$ = new Uc_while_statement(nullptr, $6); 1067 } 1068 delete $3; 1069 } 1070 else 1071 $$ = new Uc_while_statement($3, $6); 1072 end_loop(); 1073 } 1074 | DO { start_loop(); } statement WHILE '(' nonclass_expr ')' ';' 1075 { 1076 int val; 1077 if ($6->eval_const(val)) 1078 { 1079 if (val) 1080 { 1081 $6->warning("Infinite loop detected"); 1082 $$ = new Uc_infinite_loop_statement($3); 1083 } 1084 else // Optimize loop away. 1085 $$ = new Uc_breakable_statement($3); 1086 delete $6; 1087 } 1088 else 1089 $$ = new Uc_dowhile_statement($6, $3); 1090 end_loop(); 1091 } 1092 ; 1093 1094array_loop_statement: 1095 start_array_loop ')' { start_loop(); } statement 1096 { 1097 end_loop(); 1098 $1->set_statement($4); 1099 $1->finish(cur_fun); 1100 cur_fun->pop_scope(); 1101 end_loop(); 1102 } 1103 | start_array_loop WITH IDENTIFIER 1104 { $1->set_index(cur_fun->add_symbol($3)); } 1105 ')' { start_loop(); } statement 1106 { 1107 end_loop(); 1108 $1->set_statement($7); 1109 $1->finish(cur_fun); 1110 cur_fun->pop_scope(); 1111 end_loop(); 1112 } 1113 | start_array_loop WITH IDENTIFIER 1114 { $1->set_index(cur_fun->add_symbol($3)); } 1115 TO IDENTIFIER 1116 { $1->set_array_size(cur_fun->add_symbol($6)); } 1117 ')' { start_loop(); } statement 1118 { 1119 end_loop(); 1120 $1->set_statement($10); 1121 cur_fun->pop_scope(); 1122 end_loop(); 1123 } 1124 ; 1125 1126start_array_loop: 1127 start_for IDENTIFIER UCC_IN declared_var 1128 { 1129 if ($4->get_cls()) 1130 { 1131 char buf[150]; 1132 sprintf(buf, "Can't convert class '%s' into non-class", 1133 $4->get_name()); 1134 yyerror(buf); 1135 } 1136 auto *var = cur_fun->add_symbol($2); 1137 $$ = new Uc_arrayloop_statement(var, $4); 1138 } 1139 ; 1140 1141start_for: 1142 FOR '(' 1143 { 1144 cur_fun->push_scope(); 1145 start_loop(); 1146 } 1147 ; 1148 1149function_call_statement: 1150 function_call ';' 1151 { $$ = new Uc_call_statement($1); } 1152 ; 1153 1154special_method_call_statement: 1155 /* Have 'primary' say something.*/ 1156 primary hierarchy_tok SAY '(' opt_nonclass_expr_list ')' ';' 1157 { 1158 auto *stmts = new Uc_block_statement(); 1159 /* Set up 'show' call. */ 1160 stmts->add(new Uc_call_statement( 1161 new Uc_call_expression(Uc_function::get_show_face(), 1162 new Uc_array_expression($1, new Uc_int_expression(0)), 1163 cur_fun))); 1164 stmts->add(new Uc_say_statement($5)); 1165 $$ = stmts; 1166 } 1167 | primary hierarchy_tok HIDE '(' ')' ';' 1168 { 1169 $$ = new Uc_call_statement( 1170 new Uc_call_expression(Uc_function::get_remove_face(), 1171 new Uc_array_expression($1), cur_fun)); 1172 } 1173 | primary hierarchy_tok RUNSCRIPT '(' declared_var opt_delay ')' ';' 1174 { 1175 if ($5->get_cls()) 1176 { 1177 char buf[150]; 1178 sprintf(buf, "Can't convert class '%s' into non-class", 1179 $5->get_name()); 1180 yyerror(buf); 1181 } 1182 auto *parms = new Uc_array_expression(); 1183 parms->add($1); // Itemref. 1184 parms->add(new Uc_var_expression($5)); // Script. 1185 if ($6) 1186 parms->add($6); // Delay. 1187 // Get the script intrinsic. 1188 Uc_symbol *sym = Uc_function::get_intrinsic($6 ? 2 : 1); 1189 $$ = new Uc_call_statement( 1190 new Uc_call_expression(sym, parms, cur_fun)); 1191 } 1192 ; 1193 1194opt_delay: 1195 ',' nonclass_expr 1196 { $$ = $2; } 1197 | /* Empty */ 1198 { $$ = nullptr; } 1199 ; 1200 1201return_statement: 1202 RETURN expression ';' 1203 { 1204 if (!cur_fun->has_ret()) 1205 { 1206 char buf[180]; 1207 sprintf(buf, "Function '%s' can't return a value", 1208 cur_fun->get_name()); 1209 yyerror(buf); 1210 $$ = nullptr; 1211 } 1212 else 1213 { 1214 Uc_class *src = $2->get_cls(); 1215 Uc_class *trg = cur_fun->get_cls(); 1216 if (!src && !trg) 1217 $$ = new Uc_return_statement($2); 1218 else if (!src || !trg) 1219 { 1220 int ival; 1221 if (trg && $2->eval_const(ival) && ival == 0) 1222 $$ = new Uc_return_statement($2); 1223 else 1224 { 1225 char buf[210]; 1226 sprintf(buf, "Function '%s' expects a return of %s '%s' but supplied value is %s'%s'", 1227 cur_fun->get_name(), 1228 trg ? "class" : "type", 1229 trg ? trg->get_name() : "var", 1230 src ? "class " : "", 1231 src ? src->get_name() : "var"); 1232 yyerror(buf); 1233 $$ = nullptr; 1234 } 1235 } 1236 else if (Incompatible_classes_error(src, trg)) 1237 $$ = nullptr; 1238 else 1239 $$ = new Uc_return_statement($2); 1240 } 1241 } 1242 | RETURN ';' 1243 { 1244 if (cur_fun->has_ret()) 1245 { 1246 Uc_class *cls = cur_fun->get_cls(); 1247 char buf[180]; 1248 sprintf(buf, "Function '%s' must return a '%s'", 1249 cur_fun->get_name(), cls ? cls->get_name() : "var"); 1250 yyerror(buf); 1251 $$ = nullptr; 1252 } 1253 else 1254 $$ = new Uc_return_statement(); 1255 } 1256 ; 1257 1258opt_nest: 1259 ':' NESTED 1260 { $$ = 1; } 1261 | /* Empty */ 1262 { $$ = 0; } 1263 ; 1264 1265converse_statement: 1266 start_conv '{' response_case_list '}' 1267 { 1268 end_loop(); 1269 --converse; 1270 $$ = new Uc_converse_statement(nullptr, $3, false); 1271 } 1272 1273 | start_conv opt_nest '(' expression ')' '{' converse_case_list '}' 1274 { 1275 end_loop(); 1276 --converse; 1277 if (Class_unexpected_error($4)) 1278 $$ = nullptr; 1279 else 1280 $$ = new Uc_converse_statement($4, $7, $2); 1281 } 1282 ; 1283 1284start_conv: 1285 CONVERSE 1286 { 1287 start_loop(); 1288 ++converse; 1289 } 1290 ; 1291 1292converse_case_list: 1293 converse_case_list converse_case 1294 { 1295 if ($2) 1296 $$->push_back($2); 1297 } 1298 | /* Empty */ 1299 { $$ = new vector<Uc_statement *>; } 1300 ; 1301 1302converse_case: 1303 CASE string_list converse_options ':' 1304 { cur_fun->push_scope(); } statement_list 1305 { 1306 $$ = new Uc_converse_case_statement(*$2, 1307 ($3 ? true : false), $6); 1308 delete $2; // A copy was made. 1309 cur_fun->pop_scope(); 1310 } 1311 | DEFAULT converse_options ':' 1312 { cur_fun->push_scope(); } statement_list 1313 { 1314 $$ = new Uc_converse_case_statement(std::vector<int>(), 1315 ($2 ? true : false), $5); 1316 cur_fun->pop_scope(); 1317 } 1318 ; 1319 1320response_case_list: 1321 response_case_list ELSE response_case 1322 { 1323 if ($3) 1324 $$->push_back($3); 1325 } 1326 | response_case %prec IF 1327 { 1328 $$ = new vector<Uc_statement *>; 1329 $$->push_back($1); 1330 } 1331 ; 1332 1333response_case: 1334 response_expression 1335 { cur_fun->push_scope(); } statement_list 1336 { 1337 $$ = new Uc_converse_case_statement(*$1, false, $3); 1338 delete $1; // A copy was made. 1339 cur_fun->pop_scope(); 1340 } 1341 ; 1342 1343response_expression: 1344 IF '(' RESPONSE EQUALS STRING_LITERAL ')' 1345 { 1346 $$ = new vector<int>; 1347 $$->push_back(cur_fun->add_string($5)); 1348 } 1349 | IF '(' RESPONSE UCC_IN '[' string_list ']' ')' 1350 { $$ = $6; } 1351 ; 1352 1353string_list: 1354 string_list ',' STRING_LITERAL 1355 { $$->push_back(cur_fun->add_string($3)); } 1356 | STRING_LITERAL 1357 { 1358 $$ = new vector<int>; 1359 $$->push_back(cur_fun->add_string($1)); 1360 } 1361 ; 1362 1363converse_options: 1364 '(' REMOVE ')' /* For now, just one. */ 1365 { $$ = 1; } 1366 | /* Empty */ 1367 { $$ = 0; } 1368 ; 1369 1370switch_statement: 1371 SWITCH '(' 1372 { cur_fun->push_scope(); } 1373 expression ')' '{' 1374 { start_breakable(); } switch_case_list '}' 1375 { 1376 if (Class_unexpected_error($4)) 1377 $$ = nullptr; 1378 else 1379 { 1380 end_breakable(); 1381 $$ = new Uc_switch_statement($4, $8); 1382 delete $8; // a copy has been made. 1383 cur_fun->pop_scope(); 1384 } 1385 } 1386 ; 1387 1388switch_case_list: 1389 switch_case_list switch_case 1390 { $$->push_back($2); } 1391 | switch_case 1392 { 1393 $$ = new vector<Uc_statement *>; 1394 $$->push_back($1); 1395 } 1396 ; 1397 1398switch_case: 1399 CASE int_literal ':' statement_list 1400 { $$ = new Uc_switch_expression_case_statement($2, $4); } 1401 | CASE STRING_LITERAL ':' statement_list 1402 { $$ = new Uc_switch_expression_case_statement( 1403 new Uc_string_expression(cur_fun->add_string($2)), $4); } 1404 | DEFAULT ':' statement_list 1405 { $$ = new Uc_switch_default_case_statement($3); } 1406 ; 1407 1408script_statement: /* Yes, this could be an intrinsic. */ 1409 SCRIPT { start_script(); } item opt_script_delay script_command 1410 { 1411 auto *parms = new Uc_array_expression(); 1412 parms->add($3); // Itemref. 1413 parms->add($5); // Script. 1414 if ($4) // Delay? 1415 parms->add($4); 1416 // Get the script intrinsic. 1417 Uc_symbol *sym = Uc_function::get_intrinsic($4 ? 2 : 1); 1418 auto *fcall = 1419 new Uc_call_expression(sym, parms, cur_fun); 1420 $$ = new Uc_call_statement(fcall); 1421 end_script(); 1422 } 1423 ; 1424 1425item: /* Any object, NPC. */ 1426 nonclass_expr 1427 ; 1428 1429script_command_list: 1430 script_command_list script_command 1431 { $$->concat($2); } 1432 | script_command 1433 { 1434 $$ = new Uc_array_expression(); 1435 $$->concat($1); 1436 } 1437 ; 1438 1439script_command: 1440 FINISH ';' 1441 { $$ = new Uc_int_expression(Ucscript::finish, UC_PUSHB); } 1442 | RESURRECT ';' 1443 { $$ = new Uc_int_expression(Ucscript::resurrect, UC_PUSHB); } 1444 | CONTINUE ';' /* Continue script without painting. */ 1445 { $$ = new Uc_int_expression(Ucscript::cont, UC_PUSHB); } 1446 | RESET ';' /* Go back to the beginning of the script */ 1447 { $$ = new Uc_int_expression(Ucscript::reset, UC_PUSHB); } 1448 | REPEAT nonclass_expr { repeat_nesting++; } script_command ';' 1449 { 1450 repeat_nesting--; 1451 auto *result = new Uc_array_expression(); 1452 result->concat($4); // Start with cmnds. to repeat. 1453 int sz = result->get_exprs().size(); 1454 result->add(new Uc_int_expression( 1455 repeat_nesting ? Ucscript::repeat2 : Ucscript::repeat, UC_PUSHB)); 1456 // Then -offset to start. 1457 result->add(new Uc_int_expression(-sz)); 1458 result->add($2); // Loop var for repeat2. 1459 if (repeat_nesting) 1460 result->add($2); // Then #times to repeat. 1461 $$ = result; 1462 } 1463 | REPEAT nonclass_expr ',' nonclass_expr { repeat_nesting++; } 1464 script_command ';' 1465 { // Allow setting a different initial number of repeats. 1466 repeat_nesting--; 1467 auto *result = new Uc_array_expression(); 1468 result->concat($6); // Start with cmnds. to repeat. 1469 int sz = result->get_exprs().size(); 1470 result->add(new Uc_int_expression(Ucscript::repeat2, UC_PUSHB)); 1471 // Then -offset to start. 1472 result->add(new Uc_int_expression(-sz)); 1473 result->add($2); // Loop var for repeat2. 1474 result->add($4); // Then #times to repeat. 1475 $$ = result; 1476 } 1477 | NOP ';' 1478 { $$ = new Uc_int_expression(Ucscript::nop, UC_PUSHB); } 1479 | NOHALT ';' 1480 { $$ = new Uc_int_expression(Ucscript::dont_halt, UC_PUSHB); } 1481 | WAIT nonclass_expr ';' /* Ticks. */ 1482 { $$ = Create_array(Ucscript::delay_ticks, $2); } 1483 | WAIT nonclass_expr MINUTES ';' /* Game minutes. */ 1484 { $$ = Create_array(Ucscript::delay_minutes, $2); } 1485 | WAIT nonclass_expr HOURS ';' /* Game hours. */ 1486 { $$ = Create_array(Ucscript::delay_hours, $2); } 1487 | WAIT WHILE NEAR nonclass_expr ';' /* Wait while avatar is near. */ 1488 { $$ = Create_array(Ucscript::wait_while_near, $4); } 1489 | WAIT WHILE FAR nonclass_expr ';' /* Wait while avatar is far. */ 1490 { $$ = Create_array(Ucscript::wait_while_far, $4); } 1491 | REMOVE ';' /* Remove item. */ 1492 { $$ = new Uc_int_expression(Ucscript::remove, UC_PUSHB); } 1493 | RISE ';' /* For flying barges. */ 1494 { $$ = new Uc_int_expression(Ucscript::rise, UC_PUSHB); } 1495 | DESCEND ';' 1496 { $$ = new Uc_int_expression(Ucscript::descend, UC_PUSHB); } 1497 | FRAME nonclass_expr ';' 1498 { $$ = Create_array(Ucscript::frame, $2); } 1499 | ACTOR FRAME nonclass_expr ';' 1500 { 1501 $$ = new Uc_binary_expression(UC_ADD, new Uc_int_expression(0x61), 1502 new Uc_binary_expression(UC_MOD, $3, new Uc_int_expression(16)), 1503 UC_PUSHB); // Want byte. 1504 } 1505 | ACTOR FRAME actor_frames ';' 1506 { $$ = new Uc_int_expression(0x61 + ($3 & 15), UC_PUSHB); } 1507 | HATCH ';' /* Assumes item is an egg. */ 1508 { $$ = new Uc_int_expression(Ucscript::egg, UC_PUSHB); } 1509 | SETEGG nonclass_expr ',' nonclass_expr ';' 1510 { $$ = Create_array(Ucscript::set_egg, $2, $4); } 1511 | SETEGG egg_criteria ',' nonclass_expr ';' 1512 { $$ = Create_array(Ucscript::set_egg, new Uc_int_expression($2), $4); } 1513 | NEXT FRAME ';' /* Next, but stop at last. */ 1514 { $$ = new Uc_int_expression(Ucscript::next_frame_max, UC_PUSHB); } 1515 | NEXT FRAME CYCLE ';' /* Next, or back to 0. */ 1516 { $$ = new Uc_int_expression(Ucscript::next_frame, UC_PUSHB); } 1517 | PREVIOUS FRAME ';' /* Prev. but stop at 0. */ 1518 { $$ = new Uc_int_expression(Ucscript::prev_frame_min, UC_PUSHB); } 1519 | PREVIOUS FRAME CYCLE ';' 1520 { $$ = new Uc_int_expression(Ucscript::prev_frame, UC_PUSHB); } 1521 | SAY nonclass_expr ';' 1522 { $$ = Create_array(Ucscript::say, $2); } 1523 | STEP nonclass_expr ';' /* Step in given direction (0-7). */ 1524 { 1525 $$ = Create_array(Ucscript::step, 1526 new Uc_binary_expression(UC_ADD, $2, 1527 new Uc_int_expression(0x30), UC_PUSHB), 1528 new Uc_int_expression(0)); 1529 } 1530 | STEP nonclass_expr ',' nonclass_expr ';' /* Step + dz. */ 1531 { 1532 $$ = Create_array(Ucscript::step, 1533 new Uc_binary_expression(UC_ADD, 1534 new Uc_binary_expression(UC_MOD, $2, 1535 new Uc_int_expression(8)), // dir is 0-7. 1536 new Uc_int_expression(0x30), UC_PUSHB), 1537 new Uc_binary_expression(UC_MOD, $4, 1538 new Uc_int_expression(16))); // Allow max |dz| == 15. 1539 } 1540 | STEP direction ';' 1541 { $$ = new Uc_int_expression(Ucscript::step_n + $2, UC_PUSHB); } 1542 | MUSIC nonclass_expr ';' 1543 { $$ = Create_array(Ucscript::music, $2); } 1544 | MUSIC nonclass_expr ',' nonclass_expr ';' 1545 { 1546 // This is the 'repeat' flag. 1547 Uc_expression *expr; 1548 int ival; 1549 if ($4->eval_const(ival)) 1550 expr = new Uc_int_expression(ival ? 256 : 0); 1551 else // Argh. 1552 expr = new Uc_binary_expression(UC_MUL, 1553 new Uc_int_expression(256), 1554 new Uc_binary_expression(UC_CMPNE, $4, 1555 new Uc_bool_expression(false))); 1556 $$ = Create_array(Ucscript::music, 1557 new Uc_binary_expression(UC_ADD, $2, expr)); 1558 } 1559 | start_call ';' 1560 { $$ = Create_array(Ucscript::usecode, $1); } 1561 | start_call ',' nonclass_expr ';' 1562 { $$ = Create_array(Ucscript::usecode2, $1, $3); } 1563 | SPEECH nonclass_expr ';' 1564 { $$ = Create_array(Ucscript::speech, $2); } 1565 | SFX nonclass_expr ';' 1566 { $$ = Create_array(Ucscript::sfx, $2); } 1567 | FACE nonclass_expr ';' 1568 { $$ = Create_array(Ucscript::face_dir, $2); } 1569 | FACE direction ';' 1570 { $$ = Create_array(Ucscript::face_dir, new Uc_int_expression($2)); } 1571 | WEATHER nonclass_expr ';' 1572 { $$ = Create_array(Ucscript::weather, $2); } 1573 | HIT nonclass_expr ',' nonclass_expr ';' 1574 { $$ = Create_array(Ucscript::hit, $2, $4); } 1575 | HIT nonclass_expr ',' dam_type ';' 1576 { $$ = Create_array(Ucscript::hit, $2, new Uc_int_expression($4)); } 1577 | ATTACK ';' 1578 { $$ = new Uc_int_expression(Ucscript::attack, UC_PUSHB); } 1579 | '{' script_command_list '}' 1580 { $$ = $2; } 1581 ; 1582 1583start_call: 1584 CALL nonclass_expr 1585 { 1586 if (!$2) 1587 $$ = new Uc_int_expression(0); 1588 else 1589 { 1590 // May generate errors. 1591 if ($2->is_object_function() == -1) 1592 { // Don't know. 1593 char buf[180]; 1594 sprintf(buf, "Please ensure that 'call' uses a function declared with 'shape#' or 'object#'"); 1595 yywarning(buf); 1596 } 1597 $$ = $2; 1598 } 1599 } 1600 ; 1601 1602dam_type: 1603 NORMAL_DAMAGE 1604 { $$ = 0; } 1605 | FIRE_DAMAGE 1606 { $$ = 1; } 1607 | MAGIC_DAMAGE 1608 { $$ = 2; } 1609 | LIGHTNING_DAMAGE 1610 { $$ = 3; } 1611 | ETHEREAL_DAMAGE 1612 { $$ = 4; } 1613 | SONIC_DAMAGE 1614 { $$ = 5; } 1615 ; 1616 1617direction: 1618 NORTH 1619 { $$ = 0; } 1620 | NE 1621 { $$ = 1; } 1622 | EAST 1623 { $$ = 2; } 1624 | SE 1625 { $$ = 3; } 1626 | SOUTH 1627 { $$ = 4; } 1628 | SW 1629 { $$ = 5; } 1630 | WEST 1631 { $$ = 6; } 1632 | NW 1633 { $$ = 7; } 1634 ; 1635 1636actor_frames: 1637 STANDING 1638 { $$ = 0; } 1639 | STEP_RIGHT 1640 { $$ = 1; } 1641 | STEP_LEFT 1642 { $$ = 2; } 1643 | READY 1644 { $$ = 3; } 1645 | RAISE_1H 1646 { $$ = 4; } 1647 | REACH_1H 1648 { $$ = 5; } 1649 | STRIKE_1H 1650 { $$ = 6; } 1651 | RAISE_2H 1652 { $$ = 7; } 1653 | REACH_2H 1654 { $$ = 8; } 1655 | STRIKE_2H 1656 { $$ = 9; } 1657 | SITTING 1658 { $$ = 10; } 1659 | BOWING 1660 { $$ = 11; } 1661 | KNEELING 1662 { $$ = 12; } 1663 | SLEEPING 1664 { $$ = 13; } 1665 | CAST_UP 1666 { $$ = 14; } 1667 | CAST_OUT 1668 { $$ = 15; } 1669 ; 1670 1671egg_criteria: 1672 CACHED_IN 1673 { $$ = 0; } 1674 | PARTY_NEAR 1675 { $$ = 1; } 1676 | AVATAR_NEAR 1677 { $$ = 2; } 1678 | AVATAR_FAR 1679 { $$ = 3; } 1680 | AVATAR_FOOTPAD 1681 { $$ = 4; } 1682 | PARTY_FOOTPAD 1683 { $$ = 5; } 1684 | SOMETHING_ON 1685 { $$ = 6; } 1686 | EXTERNAL_CRITERIA 1687 { $$ = 7; } 1688 ; 1689 1690opt_script_delay: 1691 AFTER nonclass_expr TICKS 1692 { $$ = $2; } 1693 | /* Empty */ 1694 { $$ = nullptr; } 1695 ; 1696 1697break_statement: 1698 BREAK ';' 1699 { $$ = new Uc_break_statement(); } 1700 ; 1701 1702continue_statement: 1703 CONTINUE ';' 1704 { $$ = new Uc_continue_statement(); } 1705 ; 1706 1707label_statement: 1708 IDENTIFIER ':' 1709 { 1710 if (cur_fun->search_label($1)) 1711 { 1712 char buf[150]; 1713 sprintf(buf, "duplicate label: '%s'", $1); 1714 yyerror(buf); 1715 $$ = nullptr; 1716 } 1717 else 1718 { 1719 cur_fun->add_label($1); 1720 $$ = new Uc_label_statement($1); 1721 } 1722 } 1723 ; 1724 1725goto_statement: 1726 GOTO IDENTIFIER 1727 { 1728 yywarning("You *really* shouldn't using goto statements..."); 1729 $$ = new Uc_goto_statement($2); 1730 } 1731 ; 1732 1733delete_statement: 1734 DELETE declared_var ';' 1735 { 1736 auto *cls = 1737 dynamic_cast<Uc_class_inst_symbol *>($2->get_sym()); 1738 if (!cls) 1739 { 1740 char buf[150]; 1741 sprintf(buf, "'%s' is not a class", $2->get_name()); 1742 yyerror(buf); 1743 $$ = nullptr; 1744 } 1745 else 1746 $$ = new Uc_delete_statement(new Uc_del_expression(cls)); 1747 } 1748 ; 1749 1750answer_statement: 1751 ADD '(' nonclass_expr_list ')' ';' 1752 { 1753 $$ = new Uc_call_statement( 1754 new Uc_call_expression(Uc_function::get_add_answer(), 1755 $3, cur_fun)); 1756 } 1757 | REMOVE '(' nonclass_expr_list ')' ';' 1758 { 1759 $$ = new Uc_call_statement(new Uc_call_expression( 1760 Uc_function::get_remove_answer(), 1761 $3, cur_fun)); 1762 } 1763 ; 1764 1765opt_nonclass_expr_list: 1766 nonclass_expr_list 1767 | /* Empty */ 1768 { $$ = new Uc_array_expression(); } 1769 ; 1770 1771nonclass_expr_list: 1772 nonclass_expr_list ',' nonclass_expr 1773 { $$->add($3); } 1774 | nonclass_expr 1775 { 1776 $$ = new Uc_array_expression(); 1777 $$->add($1); 1778 } 1779 ; 1780 1781nonclass_expr: 1782 expression 1783 { 1784 if (Class_unexpected_error($1)) 1785 $$ = nullptr; 1786 else 1787 $$ = $1; 1788 } 1789 ; 1790 1791expression: 1792 primary 1793 { $$ = $1; } 1794 | nonclass_expr '+' nonclass_expr 1795 { $$ = new Uc_binary_expression(UC_ADD, $1, $3); } 1796 | nonclass_expr '-' nonclass_expr 1797 { $$ = new Uc_binary_expression(UC_SUB, $1, $3); } 1798 | nonclass_expr '*' nonclass_expr 1799 { $$ = new Uc_binary_expression(UC_MUL, $1, $3); } 1800 | nonclass_expr '/' nonclass_expr 1801 { $$ = new Uc_binary_expression(UC_DIV, $1, $3); } 1802 | nonclass_expr '%' nonclass_expr 1803 { $$ = new Uc_binary_expression(UC_MOD, $1, $3); } 1804 | nonclass_expr EQUALS nonclass_expr 1805 { $$ = new Uc_binary_expression(UC_CMPEQ, $1, $3); } 1806 | NEW SCRIPT { start_script(); } script_command 1807 { 1808 $$ = $4; 1809 end_script(); 1810 } 1811 | CHOICE 1812 { 1813 if (!converse) /* Only valid in converse blocks */ 1814 { 1815 yyerror("'CHOICE' can only be used in a conversation block!"); 1816 $$ = nullptr; 1817 } 1818 $$ = new Uc_choice_expression(); 1819 } 1820 | nonclass_expr NEQUALS nonclass_expr 1821 { $$ = new Uc_binary_expression(UC_CMPNE, $1, $3); } 1822 | nonclass_expr '<' nonclass_expr 1823 { $$ = new Uc_binary_expression(UC_CMPLT, $1, $3); } 1824 | nonclass_expr LTEQUALS nonclass_expr 1825 { $$ = new Uc_binary_expression(UC_CMPLE, $1, $3); } 1826 | nonclass_expr '>' nonclass_expr 1827 { $$ = new Uc_binary_expression(UC_CMPGT, $1, $3); } 1828 | nonclass_expr GTEQUALS nonclass_expr 1829 { $$ = new Uc_binary_expression(UC_CMPGE, $1, $3); } 1830 | nonclass_expr AND nonclass_expr 1831 { $$ = new Uc_binary_expression(UC_AND, $1, $3); } 1832 | nonclass_expr OR nonclass_expr 1833 { $$ = new Uc_binary_expression(UC_OR, $1, $3); } 1834 | nonclass_expr UCC_IN nonclass_expr /* Value in array. */ 1835 { $$ = new Uc_binary_expression(UC_IN, $1, $3); } 1836 | nonclass_expr '&' nonclass_expr /* append arrays */ 1837 { $$ = new Uc_binary_expression(UC_ARRA, $1, $3); } 1838 | '+' primary %prec UPLUS 1839 { 1840 if (Class_unexpected_error($2)) 1841 $$ = nullptr; 1842 else 1843 $$ = $2; 1844 } 1845 | '-' primary %prec UMINUS 1846 { 1847 if (Class_unexpected_error($2)) 1848 $$ = nullptr; 1849 else 1850 $$ = new Uc_binary_expression(UC_SUB, 1851 new Uc_int_expression(0), $2); 1852 } 1853 | addressof 1854 { $$ = $1; } 1855 | NOT primary 1856 { $$ = new Uc_unary_expression(UC_NOT, $2); } 1857 | '[' opt_expression_list ']' /* Concat. into an array. */ 1858 { $$ = $2; } 1859 | STRING_LITERAL 1860 { $$ = new Uc_string_expression(cur_fun->add_string($1)); } 1861 | STRING_PREFIX 1862 { $$ = new Uc_string_prefix_expression(cur_fun, $1); } 1863 | new_expr 1864 ; 1865 1866addressof: 1867 '&' IDENTIFIER %prec ADDRESSOF 1868 { // A way to retrieve the function's assigned 1869 // usecode number 1870 Uc_symbol *sym = cur_fun->search_up($2); 1871 if (!sym) /* See if the symbol is defined */ 1872 { 1873 char buf[150]; 1874 sprintf(buf, "'%s' not declared", $2); 1875 yyerror(buf); 1876 $$ = nullptr; 1877 } 1878 auto *fun = dynamic_cast<Uc_function_symbol *>(sym); 1879 if (!fun) /* See if the symbol is a function */ 1880 { 1881 char buf[150]; 1882 sprintf(buf, "'%s' is not a function", $2); 1883 yyerror(buf); 1884 $$ = nullptr; 1885 } 1886 else /* Output the function's assigned number */ 1887 { 1888 int funid = fun->get_usecode_num(); 1889 UsecodeOps op = is_int_32bit(funid) ? UC_PUSHI32 : UC_PUSHI; 1890 $$ = new Uc_int_expression(funid, op); 1891 } 1892 } 1893 ; 1894 1895opt_expression_list: 1896 expression_list 1897 | /* Empty */ 1898 { $$ = new Uc_array_expression(); } 1899 ; 1900 1901expression_list: 1902 expression_list ',' expression 1903 { $$->add($3); } 1904 | expression 1905 { 1906 $$ = new Uc_array_expression(); 1907 $$->add($1); 1908 } 1909 ; 1910 1911int_cast: 1912 '(' const_int_type ')' 1913 { $$ = $2; } 1914 ; 1915 1916primary: 1917 INT_LITERAL 1918 { 1919 UsecodeOps op = !const_opcode.empty() ? const_opcode.back() : UC_PUSHI; 1920 if (is_sint_32bit($1) && op != UC_PUSHI32) 1921 { 1922 char buf[150]; 1923 if (is_int_32bit($1)) 1924 { 1925 sprintf(buf, "Literal integer '%d' cannot be represented as 16-bit integer. Assuming '(long)' cast.", 1926 $1); 1927 op = UC_PUSHI32; 1928 } 1929 else 1930 sprintf(buf, "Interpreting integer '%d' as the signed 16-bit integer '%d'. If this is incorrect, use '(long)' cast.", 1931 $1, static_cast<short>($1)); 1932 yywarning(buf); 1933 } 1934 $$ = new Uc_int_expression($1, op); 1935 } 1936 | int_cast INT_LITERAL %prec UCC_CAST 1937 { $$ = new Uc_int_expression($2, static_cast<UsecodeOps>($1)); } 1938 | member_selector 1939 { 1940 auto *expr = dynamic_cast<Uc_var_expression *>($1->expr); 1941 Uc_struct_symbol *base; 1942 if (!expr || !(base = expr->get_struct())) 1943 { 1944 yyerror("Expression is not a 'struct'"); 1945 $$ = new Uc_int_expression(0); 1946 } 1947 else 1948 { 1949 int offset = base->search($1->name); 1950 if (offset < 0) 1951 { 1952 char buf[150]; 1953 sprintf(buf, "'%s' does not belong to struct '%s'", 1954 $1->name, base->get_name()); 1955 yyerror(buf); 1956 $$ = new Uc_int_expression(0); 1957 } 1958 else 1959 { 1960 auto *var = expr->get_var(); 1961 auto *index = new Uc_int_expression(offset); 1962 if (var->is_static()) 1963 $$ = new Uc_static_arrayelem_expression(var, index); 1964 else if (var->get_sym_type() == Uc_symbol::Member_var) 1965 $$ = new Uc_class_arrayelem_expression(var, index); 1966 else 1967 $$ = new Uc_arrayelem_expression(var, index); 1968 } 1969 } 1970 delete $1; 1971 } 1972 | declared_var_value 1973 { $$ = $1; } 1974 | declared_var '[' expression ']' 1975 { 1976 if ($1->get_cls()) 1977 { 1978 char buf[150]; 1979 sprintf(buf, "Can't convert class '%s' into non-class", 1980 $1->get_name()); 1981 yyerror(buf); 1982 $$ = new Uc_arrayelem_expression($1, $3); 1983 } 1984 else if ($1->is_static()) 1985 $$ = new Uc_static_arrayelem_expression($1, $3); 1986 else if ($1->get_sym_type() == Uc_symbol::Member_var) 1987 $$ = new Uc_class_arrayelem_expression($1, $3); 1988 else 1989 $$ = new Uc_arrayelem_expression($1, $3); 1990 } 1991 | FLAG '[' nonclass_expr ']' 1992 { $$ = new Uc_flag_expression($3); } 1993 | function_call 1994 { 1995 if ($1) 1996 $$ = $1; 1997 else 1998 $$ = new Uc_int_expression(0); 1999 } 2000 | UCTRUE 2001 { $$ = new Uc_bool_expression(true); } 2002 | UCFALSE 2003 { $$ = new Uc_bool_expression(false); } 2004 | EVENT 2005 { $$ = new Uc_event_expression(); } 2006 | ITEM 2007 { $$ = new Uc_item_expression(); } 2008 | '(' expression ')' 2009 { $$ = $2; } 2010 ; 2011 2012new_expr: 2013 NEW defined_class '(' opt_nonclass_expr_list ')' 2014 { 2015 if ($2) 2016 $$ = new Uc_new_expression(new Uc_class_inst_symbol("", $2, 0), $4); 2017 else 2018 $$ = new Uc_int_expression(0); 2019 } 2020 ; 2021 2022hierarchy_tok: 2023 UCC_POINTS 2024 | '.' 2025 ; 2026 2027member_selector: 2028 primary hierarchy_tok IDENTIFIER 2029 { $$ = new Member_selector($1, $3); } 2030 ; 2031 2032function_call: 2033 member_selector opt_original '(' opt_expression_list ')' 2034 { 2035 $$ = cls_function_call($1->expr, cur_class, $1->name, $2, $4); 2036 delete $1; 2037 } 2038 | IDENTIFIER opt_original '(' opt_expression_list ')' 2039 { 2040 $$ = cls_function_call(nullptr, cur_class, $1, $2, $4); 2041 } 2042 | primary hierarchy_tok defined_class UCC_SCOPE IDENTIFIER '(' opt_expression_list ')' 2043 { 2044 $$ = cls_method_call($1, $1->get_cls(), $3, $5, $7); 2045 } 2046 | defined_class UCC_SCOPE IDENTIFIER '(' opt_expression_list ')' 2047 { 2048 $$ = cls_method_call(nullptr, cur_class, $1, $3, $5); 2049 } 2050 | primary hierarchy_tok '(' '*' primary ')' '(' opt_expression_list ')' 2051 { 2052 $$ = new Uc_call_expression($5, $8, cur_fun); 2053 $$->set_itemref($1); 2054 } 2055 | '(' '*' primary ')' '(' opt_expression_list ')' 2056 { 2057 $$ = new Uc_call_expression($3, $6, cur_fun); 2058 $$->set_itemref(nullptr); 2059 } 2060 | primary hierarchy_tok '(' '@' int_literal ')' '(' opt_expression_list ')' 2061 { 2062 int num; 2063 if (!$5->eval_const(num)) 2064 { 2065 yyerror("Failed to obtain value from integer constant"); 2066 $$ = nullptr; 2067 } 2068 else 2069 { 2070 $$ = new Uc_call_expression(Uc_function::get_intrinsic(num), 2071 $8, cur_fun); 2072 $$->set_itemref($1); 2073 $$->check_params(); 2074 } 2075 } 2076 | '(' '@' int_literal ')' '(' opt_expression_list ')' 2077 { 2078 int num; 2079 if (!$3->eval_const(num)) 2080 { 2081 yyerror("Failed to obtain value from integer constant"); 2082 $$ = nullptr; 2083 } 2084 else 2085 { 2086 $$ = new Uc_call_expression(Uc_function::get_intrinsic(num), 2087 $6, cur_fun); 2088 $$->check_params(); 2089 } 2090 } 2091 ; 2092 2093opt_original: 2094 ORIGINAL 2095 { $$ = 1; } 2096 | /* Empty */ 2097 { $$ = 0; } 2098 ; 2099 2100opt_param_list: 2101 param_list 2102 | /* Empty */ 2103 { $$ = new std::vector<Uc_var_symbol *>; } 2104 ; 2105 2106param_list: 2107 param_list ',' param 2108 { $1->push_back($3); } 2109 | param 2110 { 2111 $$ = new std::vector<Uc_var_symbol *>; 2112 $$->push_back($1); 2113 } 2114 ; 2115 2116param: 2117 IDENTIFIER 2118 { $$ = new Uc_var_symbol($1, 0); } 2119 | VAR IDENTIFIER 2120 { $$ = new Uc_var_symbol($2, 0); } 2121 | STRUCT '<' defined_struct '>' IDENTIFIER 2122 { $$ = new Uc_struct_var_symbol($5, $3, 0); } 2123 | CLASS '<' defined_class '>' IDENTIFIER 2124 { $$ = new Uc_class_inst_symbol($5, $3, 0); } 2125 ; 2126 2127int_literal: /* A const. integer value. */ 2128 INT_LITERAL 2129 { 2130 UsecodeOps op = !const_opcode.empty() ? const_opcode.back() : UC_PUSHI; 2131 if (is_sint_32bit($1) && op != UC_PUSHI32) 2132 { 2133 char buf[150]; 2134 if (is_int_32bit($1)) 2135 { 2136 sprintf(buf, "Literal integer '%d' cannot be represented as 16-bit integer. Assuming '(long)' cast.", 2137 $1); 2138 op = UC_PUSHI32; 2139 } 2140 else 2141 sprintf(buf, "Interpreting integer '%d' as the signed 16-bit integer '%d'. If this is incorrect, use '(long)' cast.", 2142 $1, static_cast<short>($1)); 2143 yywarning(buf); 2144 } 2145 $$ = new Uc_int_expression($1, op); 2146 } 2147 | int_cast INT_LITERAL %prec UCC_CAST 2148 { $$ = new Uc_int_expression($2, static_cast<UsecodeOps>($1)); } 2149 | declared_sym 2150 { 2151 auto *sym = 2152 dynamic_cast<Uc_const_int_symbol *>($1); 2153 if (!sym) 2154 { 2155 char buf[150]; 2156 sprintf(buf, "'%s' is not a const int", $1->get_name()); 2157 yyerror(buf); 2158 $$ = nullptr; 2159 } 2160 else 2161 $$ = sym->create_expression(); 2162 } 2163 | UCTRUE 2164 { $$ = new Uc_bool_expression(true); } 2165 | UCFALSE 2166 { $$ = new Uc_bool_expression(false); } 2167 ; 2168 2169opt_void: 2170 VOID 2171 | /* Empty */ 2172 { 2173 yywarning("You should prepend 'void' for functions that do not return a value."); 2174 } 2175 ; 2176 2177ret_type: 2178 VAR 2179 { has_ret = true; } 2180 | STRUCT '<' defined_struct '>' 2181 { struct_type = $3; } 2182 | opt_void 2183 { has_ret = false; } 2184 ; 2185 2186declared_var_value: 2187 declared_sym %prec UCC_SYM 2188 { 2189 $$ = $1->create_expression(); 2190 if (!$$) 2191 { 2192 char buf[150]; 2193 sprintf(buf, "Can't use '%s' here", $1->get_name()); 2194 yyerror(buf); 2195 $$ = new Uc_int_expression(0); 2196 } 2197 } 2198 ; 2199 2200declared_var: 2201 declared_sym %prec UCC_SYM 2202 { 2203 auto *var = dynamic_cast<Uc_var_symbol *>($1); 2204 if (!var) 2205 { 2206 char buf[150]; 2207 sprintf(buf, "'%s' not a 'var'", $1->get_name()); 2208 yyerror(buf); 2209 sprintf(buf, "%s_needvar", $1->get_name()); 2210 var = cur_fun->add_symbol(buf); 2211 } 2212 $$ = var; 2213 } 2214 ; 2215 2216declared_sym: 2217 IDENTIFIER 2218 { 2219 Uc_symbol *sym = cur_fun->search_up($1); 2220 if (!sym) 2221 { 2222 char buf[150]; 2223 sprintf(buf, "'%s' not declared", $1); 2224 yyerror(buf); 2225 sym = cur_fun->add_symbol($1); 2226 } 2227 $$ = sym; 2228 } 2229 ; 2230 2231defined_class: 2232 IDENTIFIER 2233 { $$ = Find_class($1); } 2234 ; 2235 2236defined_struct: 2237 IDENTIFIER 2238 { 2239 auto *sym = dynamic_cast<Uc_struct_symbol *>( 2240 Uc_function::search_globals($1)); 2241 if (!sym) 2242 { 2243 char buf[150]; 2244 sprintf(buf, "'%s' not found, or is not a struct.", $1); 2245 yyerror(buf); 2246 $$ = nullptr; 2247 } 2248 else 2249 $$ = sym; 2250 } 2251 ; 2252 2253%% 2254 2255#ifdef __GNUC__ 2256#pragma GCC diagnostic pop 2257#endif // __GNUC__ 2258 2259/* 2260 * Create an array with an integer as the first element. 2261 */ 2262 2263static Uc_array_expression *Create_array 2264 ( 2265 int e1, 2266 Uc_expression *e2 2267 ) 2268 { 2269 auto *arr = new Uc_array_expression(); 2270 arr->add(new Uc_int_expression(e1, UC_PUSHB)); 2271 arr->add(e2); 2272 return arr; 2273 } 2274static Uc_array_expression *Create_array 2275 ( 2276 int e1, 2277 Uc_expression *e2, 2278 Uc_expression *e3 2279 ) 2280 { 2281 auto *arr = new Uc_array_expression(); 2282 arr->add(new Uc_int_expression(e1, UC_PUSHB)); 2283 arr->add(e2); 2284 arr->add(e3); 2285 return arr; 2286 } 2287static Uc_class *Find_class 2288 ( 2289 const char *nm 2290 ) 2291 { 2292 auto *csym = dynamic_cast<Uc_class_symbol *>( 2293 Uc_function::search_globals(nm)); 2294 if (!csym) 2295 { 2296 char buf[150]; 2297 sprintf(buf, "'%s' not found, or is not a class.", nm); 2298 yyerror(buf); 2299 return nullptr; 2300 } 2301 return csym->get_cls(); 2302 } 2303 2304static bool Class_unexpected_error(Uc_expression *expr) 2305 { 2306 if (expr->is_class()) 2307 { 2308 yyerror("Can't convert class into non-class"); 2309 return true; 2310 } 2311 return false; 2312 } 2313 2314static bool Nonclass_unexpected_error(Uc_expression *expr) 2315 { 2316 if (!expr->is_class()) 2317 { 2318 yyerror("Can't convert non-class into class."); 2319 return true; 2320 } 2321 return false; 2322 } 2323 2324static bool Incompatible_classes_error(Uc_class *src, Uc_class *trg) 2325 { 2326 if (!src->is_class_compatible(trg->get_name())) 2327 { 2328 char buf[180]; 2329 sprintf(buf, "Class '%s' can't be converted into class '%s'", 2330 src->get_name(), trg->get_name()); 2331 yyerror(buf); 2332 return true; 2333 } 2334 return false; 2335 } 2336 2337static Uc_call_expression *cls_method_call 2338 ( 2339 Uc_expression *ths, 2340 Uc_class *curcls, 2341 Uc_class *clsscope, 2342 char *nm, 2343 Uc_array_expression *parms 2344 ) 2345 { 2346 if (!curcls) 2347 { 2348 char buf[150]; 2349 sprintf(buf, "'%s' requires a class object", nm); 2350 yyerror(buf); 2351 return nullptr; 2352 } 2353 2354 if (Incompatible_classes_error(curcls, clsscope)) 2355 return nullptr; 2356 2357 Uc_symbol *sym = clsscope->get_scope()->search(nm); 2358 if (!sym) 2359 { 2360 char buf[150]; 2361 sprintf(buf, "Function '%s' is not declared in class '%s'", 2362 nm, clsscope->get_name()); 2363 yyerror(buf); 2364 return nullptr; 2365 } 2366 2367 auto *fun = dynamic_cast<Uc_function_symbol *>(sym); 2368 if (!fun) 2369 { 2370 char buf[150]; 2371 sprintf(buf, "'%s' is not a function", nm); 2372 yyerror(buf); 2373 return nullptr; 2374 } 2375 2376 auto *ret = 2377 new Uc_call_expression(sym, parms, cur_fun, false); 2378 ret->set_itemref(ths); 2379 ret->set_call_scope(clsscope); 2380 ret->check_params(); 2381 return ret; 2382 } 2383 2384static bool Uc_is_valid_calle 2385 ( 2386 Uc_symbol *sym, 2387 Uc_expression *&ths, 2388 char *nm, 2389 bool original 2390 ) 2391 { 2392 if (original) 2393 return true; 2394 auto *fun = dynamic_cast<Uc_function_symbol *>(sym); 2395 if (!fun) // Most likely an intrinsic. 2396 return true; 2397 2398 if (fun->get_function_type() == Uc_function_symbol::utility_fun) 2399 { 2400 if (ths && !ths->is_class()) 2401 { 2402 char buf[150]; 2403 sprintf(buf, "'%s' is not an object or shape function", nm); 2404 yyerror(buf); 2405 return false; 2406 } 2407 else if (ths) 2408 { 2409 char buf[150]; 2410 sprintf(buf, "'%s' is not a member of class '%s'", 2411 nm, ths->get_cls()->get_name()); 2412 yyerror(buf); 2413 return false; 2414 } 2415 } 2416 else 2417 { 2418 if (!ths) 2419 { 2420 char buf[180]; 2421 sprintf(buf, "'%s' expects an itemref, but none was supplied; using current itemref", nm); 2422 ths = new Uc_item_expression(); 2423 yywarning(buf); 2424 return true; 2425 } 2426 } 2427 return true; 2428 } 2429 2430static Uc_call_expression *cls_function_call 2431 ( 2432 Uc_expression *ths, 2433 Uc_class *curcls, 2434 char *nm, 2435 bool original, 2436 Uc_array_expression *parms 2437 ) 2438 { 2439 Uc_symbol *sym = nullptr; 2440 // Check class methods first. 2441 if (!ths && curcls) 2442 sym = curcls->get_scope()->search(nm); 2443 else if (ths && ths->is_class()) 2444 sym = ths->get_cls()->get_scope()->search(nm); 2445 2446 // Search for defined functions. 2447 if (!sym) 2448 { 2449 sym = cur_fun->search_up(nm); 2450 if (original && !ths) 2451 ths = new Uc_item_expression(); 2452 if (!Uc_is_valid_calle(sym, ths, nm, original)) 2453 return nullptr; 2454 } 2455 2456 // Check for intrinsic name. 2457 if (!sym) 2458 { 2459 string iname = string("UI_") + nm; 2460 sym = cur_fun->search_up(iname.c_str()); 2461 // Treat as method call on 'item'. 2462 if (sym && !ths) 2463 ths = new Uc_item_expression(); 2464 } 2465 2466 if (!sym) 2467 { 2468 char buf[150]; 2469 sprintf(buf, "'%s' not declared", nm); 2470 yyerror(buf); 2471 return nullptr; 2472 } 2473 else 2474 { 2475 auto *ret = 2476 new Uc_call_expression(sym, parms, cur_fun, original); 2477 ret->set_itemref(ths); 2478 ret->check_params(); 2479 return ret; 2480 } 2481 } 2482