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