xref: /csrg-svn/usr.bin/pascal/src/pas.y (revision 837)
1798Speter /* Copyright (c) 1979 Regents of the University of California */
2798Speter 
3798Speter /*
4798Speter  * Yacc grammar for UNIX Pascal
5798Speter  *
6798Speter  * This grammar is processed by the commands in the shell script
7798Speter  * "gram" to yield parse tables and semantic routines in the file
8798Speter  * "y.tab.c" and a header defining the lexical tokens in "yy.h".
9798Speter  *
10798Speter  * In order for the syntactic error recovery possible with this
11798Speter  * grammar to work, the grammar must be processed by a yacc which
12798Speter  * has been modified to fully enumerate possibilities in states
13798Speter  * which involve the symbol "error".
14798Speter  * The parser used for Pascal also uses a different encoding of
15798Speter  * the test entries in the action table which speeds the parse.
16798Speter  * A version of yacc which will work for Pascal is included on
17798Speter  * the distribution table as "eyacc".
18798Speter  *
19798Speter  * The "gram" script also makes the following changes to the "y.tab.c"
20798Speter  * file:
21798Speter  *
22798Speter  *	1) Causes yyval to be declared int *.
23798Speter  *
24798Speter  *	2) Loads the variable yypv into a register as yyYpv so that
25798Speter  *	   the arguments $1, ... are available as yyYpv[1] etc.
26798Speter  *	   This produces much smaller code in the semantic actions.
27798Speter  *
28798Speter  *	3) Deletes the unused array yysterm.
29798Speter  *
30798Speter  *	4) Moves the declarations up to the flag line containing
31798Speter  *	   '##' to the file yy.h so that the routines which use
32798Speter  *	   these "magic numbers" don't have to all be compiled at
33798Speter  *	   the same time.
34798Speter  *
35798Speter  *	5) Creates the semantic restriction checking routine yyEactr
36804Speter  *	   by processing action lines containing `@@'.
37798Speter  *
38798Speter  * This compiler uses a different version of the yacc parser, a
39798Speter  * different yyerror which is called yerror, and requires more
40798Speter  * lookahead sets than normally provided by yacc.
41798Speter  *
42798Speter  * Source for the yacc used with this grammar is included on
43798Speter  * distribution tapes.
44798Speter  */
45798Speter 
46798Speter /*
47798Speter  * TERMINAL DECLARATIONS
48798Speter  *
49798Speter  * Some of the terminal declarations are out of the most natural
50798Speter  * alphabetic order because the error recovery
51798Speter  * will guess the first of equal cost non-terminals.
52798Speter  * This makes, e.g. YTO preferable to YDOWNTO.
53798Speter  */
54798Speter 
55798Speter %term
56798Speter 	YAND		YARRAY		YBEGIN		YCASE
57798Speter 	YCONST		YDIV		YDO		YDOTDOT
58798Speter 	YTO		YELSE		YEND		YFILE
59798Speter 	YFOR		YFORWARD	YFUNCTION	YGOTO
60798Speter 	YID		YIF		YIN		YINT
61798Speter 	YLABEL		YMOD		YNOT		YNUMB
62798Speter 	YOF		YOR		YPACKED		YNIL
63798Speter 	YPROCEDURE	YPROG		YRECORD		YREPEAT
64798Speter 	YSET		YSTRING		YTHEN		YDOWNTO
65798Speter 	YTYPE		YUNTIL		YVAR		YWHILE
66798Speter 	YWITH		YBINT		YOCT		YHEX
67*837Speter 	YASSERT		YCASELAB	YILLCH		YEXTERN
68*837Speter 	YLAST
69798Speter 
70798Speter /*
71798Speter  * PRECEDENCE DECLARATIONS
72798Speter  *
73798Speter  * Highest precedence is the unary logical NOT.
74798Speter  * Next are the multiplying operators, signified by '*'.
75798Speter  * Lower still are the binary adding operators, signified by '+'.
76798Speter  * Finally, at lowest precedence and non-associative are the relationals.
77798Speter  */
78798Speter 
79798Speter %binary	'<'	'='	'>'	YIN
80798Speter %left	'+'	'-'	YOR	'|'
81798Speter %left	UNARYSIGN
82798Speter %left	'*'	'/'	YDIV	YMOD	YAND	'&'
83798Speter %left	YNOT
84798Speter 
85798Speter %{
86798Speter /*
87798Speter  * GLOBALS FOR ACTIONS
88798Speter  */
89798Speter 
90798Speter /* Copyright (c) 1979 Regents of the University of California */
91798Speter 
92*837Speter /* static	char sccsid[] = "@(#)pas.y 1.3 09/02/80"; */
93798Speter 
94798Speter /*
95798Speter  * The following line marks the end of the yacc
96798Speter  * Constant definitions which are removed from
97798Speter  * y.tab.c and placed in the file y.tab.h.
98798Speter  */
99798Speter ##
100798Speter /* Copyright (c) 1979 Regents of the University of California */
101798Speter 
102*837Speter static	char sccsid[] = "@(#)pas.y 1.3 09/02/80";
103798Speter 
104798Speter #include "whoami.h"
105798Speter #include "0.h"
106798Speter #include "yy.h"
107798Speter #include "tree.h"
108798Speter 
109798Speter #ifdef PI
110798Speter #define	lineof(l)	l
111798Speter #define	line2of(l)	l
112798Speter #endif
113798Speter 
114798Speter %}
115798Speter 
116798Speter %%
117798Speter 
118798Speter /*
119798Speter  * PRODUCTIONS
120798Speter  */
121798Speter 
122798Speter goal:
123*837Speter 	prog_hedr decls block '.'
124*837Speter 		= funcend($1, $3, lineof($4));
125798Speter 		|
126*837Speter 	decls
127798Speter 		= segend();
128798Speter 		;
129798Speter 
130798Speter 
131798Speter prog_hedr:
132798Speter 	YPROG YID '(' id_list ')' ';'
133798Speter 		= $$ = funcbody(funchdr(tree5(T_PROG, lineof($1), $2, fixlist($4), NIL)));
134798Speter 		|
135798Speter 	YPROG error
136798Speter 		= {
137798Speter 			yyPerror("Malformed program statement", PPROG);
138798Speter 			/*
139798Speter 			 * Should make a program statement
140798Speter 			 * with "input" and "output" here.
141798Speter 			 */
142798Speter 			$$ = funcbody(funchdr(tree5(T_PROG, lineof($1), NIL, NIL, NIL)));
143798Speter 		  }
144798Speter 		;
145798Speter block:
146798Speter 	YBEGIN stat_list YEND
147798Speter 		= {
148798Speter 			$$ = tree3(T_BSTL, lineof($1), fixlist($2));
149798Speter 			if ($3 < 0)
150798Speter 				brerror($1, "begin");
151798Speter 		  }
152798Speter 		;
153798Speter 
154798Speter 
155798Speter /*
156798Speter  * DECLARATION PART
157798Speter  */
158798Speter decls:
159798Speter 	decls decl
160798Speter 		= trfree();
161798Speter 		|
162798Speter 	decls error
163798Speter 		= {
164798Speter Derror:
165798Speter 			constend(), typeend(), varend(), trfree();
166798Speter 			yyPerror("Malformed declaration", PDECL);
167798Speter 		  }
168798Speter 		|
169798Speter 	/* lambda */
170798Speter 		= trfree();
171798Speter 		;
172798Speter 
173798Speter decl:
174798Speter 	labels
175798Speter 		|
176798Speter 	const_decl
177798Speter 		= constend();
178798Speter 		|
179798Speter 	type_decl
180798Speter 		= typeend();
181798Speter 		|
182798Speter 	var_decl
183798Speter 		= varend();
184*837Speter 		|
185*837Speter 	proc_decl
186798Speter 		;
187798Speter 
188798Speter /*
189798Speter  * LABEL PART
190798Speter  */
191798Speter 
192798Speter labels:
193798Speter 	YLABEL label_decl ';'
194798Speter 		= label(fixlist($2), lineof($1));
195798Speter 		;
196798Speter label_decl:
197798Speter 	YINT
198798Speter 		= $$ = newlist($1 == NIL ? NIL : *hash($1, 1));
199798Speter 		|
200798Speter 	label_decl ',' YINT
201798Speter 		= $$ = addlist($1, $3 == NIL ? NIL : *hash($3, 1));
202798Speter 		;
203798Speter 
204798Speter /*
205798Speter  * CONST PART
206798Speter  */
207798Speter 
208798Speter const_decl:
209798Speter 	YCONST YID '=' const ';'
210798Speter 		= constbeg($1, line2of($2)), const(lineof($3), $2, $4);
211798Speter 		|
212798Speter 	const_decl YID '=' const ';'
213798Speter 		= const(lineof($3), $2, $4);
214798Speter 		|
215798Speter 	YCONST error
216798Speter 		= {
217798Speter 			constbeg($1, line2of($1));
218798Speter Cerror:
219798Speter 			yyPerror("Malformed const declaration", PDECL);
220798Speter 		  }
221798Speter 		|
222798Speter 	const_decl error
223798Speter 		= goto Cerror;
224798Speter 		;
225798Speter 
226798Speter /*
227798Speter  * TYPE PART
228798Speter  */
229798Speter 
230798Speter type_decl:
231798Speter 	YTYPE YID '=' type ';'
232798Speter 		= typebeg($1, line2of($2)), type(lineof($3), $2, $4);
233798Speter 		|
234798Speter 	type_decl YID '=' type ';'
235798Speter 		= type(lineof($3), $2, $4);
236798Speter 		|
237798Speter 	YTYPE error
238798Speter 		= {
239798Speter 			typebeg($1, line2of($1));
240798Speter Terror:
241798Speter 			yyPerror("Malformed type declaration", PDECL);
242798Speter 		  }
243798Speter 		|
244798Speter 	type_decl error
245798Speter 		= goto Terror;
246798Speter 		;
247798Speter 
248798Speter /*
249798Speter  * VAR PART
250798Speter  */
251798Speter 
252798Speter var_decl:
253798Speter 	YVAR id_list ':' type ';'
254798Speter 		= varbeg($1, line2of($3)), var(lineof($3), fixlist($2), $4);
255798Speter 		|
256798Speter 	var_decl id_list ':' type ';'
257798Speter 		= var(lineof($3), fixlist($2), $4);
258798Speter 		|
259798Speter 	YVAR error
260798Speter 		= {
261798Speter 			varbeg($1, line2of($1));
262798Speter Verror:
263798Speter 			yyPerror("Malformed var declaration", PDECL);
264798Speter 		  }
265798Speter 		|
266798Speter 	var_decl error
267798Speter 		= goto Verror;
268798Speter 		;
269798Speter 
270798Speter /*
271798Speter  * PROCEDURE AND FUNCTION DECLARATION PART
272798Speter  */
273798Speter 
274*837Speter proc_decl:
275798Speter 	phead YFORWARD ';'
276798Speter 		= funcfwd($1);
277798Speter 		|
278798Speter 	phead YEXTERN ';'
279798Speter 		= funcext($1);
280798Speter 		|
281*837Speter 	pheadres decls block ';'
282*837Speter 		= funcend($1, $3, lineof($4));
283798Speter 		;
284798Speter pheadres:
285798Speter 	phead
286798Speter 		= funcbody($1);
287798Speter 		;
288798Speter phead:
289798Speter 	porf YID params ftype ';'
290798Speter 		= $$ = funchdr(tree5($1, lineof($5), $2, $3, $4));
291798Speter 		;
292798Speter porf:
293798Speter 	YPROCEDURE
294798Speter 		= $$ = T_PDEC;
295798Speter 		|
296798Speter 	YFUNCTION
297798Speter 		= $$ = T_FDEC;
298798Speter 		;
299798Speter params:
300798Speter 	'(' param_list ')'
301798Speter 		= $$ = fixlist($2);
302798Speter 		|
303798Speter 	/* lambda */
304798Speter 		= $$ = NIL;
305798Speter 		;
306798Speter 
307798Speter /*
308798Speter  * PARAMETERS
309798Speter  */
310798Speter 
311798Speter param:
312798Speter 	id_list ':' type
313798Speter 		= $$ = tree3(T_PVAL, fixlist($1), $3);
314798Speter 		|
315798Speter 	YVAR id_list ':' type
316798Speter 		= $$ = tree3(T_PVAR, fixlist($2), $4);
317798Speter 		|
318798Speter 	YFUNCTION id_list ':' type
319798Speter 		= $$ = tree3(T_PFUNC, fixlist($2), $4);
320798Speter 		|
321798Speter 	YPROCEDURE id_list
322798Speter 		= $$ = tree2(T_PPROC, fixlist($2));
323798Speter 		;
324798Speter ftype:
325798Speter 	':' type
326798Speter 		= $$ = $2;
327798Speter 		|
328798Speter 	/* lambda */
329798Speter 		= $$ = NIL;
330798Speter 		;
331798Speter param_list:
332798Speter 	param
333798Speter 		= $$ = newlist($1);
334798Speter 		|
335798Speter 	param_list ';' param
336798Speter 		= $$ = addlist($1, $3);
337798Speter 		;
338798Speter 
339798Speter /*
340798Speter  * CONSTANTS
341798Speter  */
342798Speter 
343798Speter const:
344798Speter 	YSTRING
345798Speter 		= $$ = tree2(T_CSTRNG, $1);
346798Speter 		|
347798Speter 	number
348798Speter 		|
349798Speter 	'+' number
350798Speter 		= $$ = tree2(T_PLUSC, $2);
351798Speter 		|
352798Speter 	'-' number
353798Speter 		= $$ = tree2(T_MINUSC, $2);
354798Speter 		;
355798Speter number:
356798Speter 	const_id
357798Speter 		= $$ = tree2(T_ID, $1);
358798Speter 		|
359798Speter 	YINT
360798Speter 		= $$ = tree2(T_CINT, $1);
361798Speter 		|
362798Speter 	YBINT
363798Speter 		= $$ = tree2(T_CBINT, $1);
364798Speter 		|
365798Speter 	YNUMB
366798Speter 		= $$ = tree2(T_CFINT, $1);
367798Speter 		;
368798Speter const_list:
369798Speter 	const
370798Speter 		= $$ = newlist($1);
371798Speter 		|
372798Speter 	const_list ',' const
373798Speter 		= $$ = addlist($1, $3);
374798Speter 		;
375798Speter 
376798Speter /*
377798Speter  * TYPES
378798Speter  */
379798Speter 
380798Speter type:
381798Speter 	simple_type
382798Speter 		|
383798Speter 	'^' YID
384798Speter 		= $$ = tree3(T_TYPTR, lineof($1), tree2(T_ID, $2));
385798Speter 		|
386798Speter 	struct_type
387798Speter 		|
388798Speter 	YPACKED struct_type
389798Speter 		= $$ = tree3(T_TYPACK, lineof($1), $2);
390798Speter 		;
391798Speter simple_type:
392798Speter 	type_id
393798Speter 		|
394798Speter 	'(' id_list ')'
395798Speter 		= $$ = tree3(T_TYSCAL, lineof($1), fixlist($2));
396798Speter 		|
397798Speter 	const YDOTDOT const
398798Speter 		= $$ = tree4(T_TYRANG, lineof($2), $1, $3);
399798Speter 		;
400798Speter struct_type:
401798Speter 	YARRAY '[' simple_type_list ']' YOF type
402798Speter 		= $$ = tree4(T_TYARY, lineof($1), fixlist($3), $6);
403798Speter 		|
404798Speter 	YFILE YOF type
405798Speter 		= $$ = tree3(T_TYFILE, lineof($1), $3);
406798Speter 		|
407798Speter 	YSET YOF simple_type
408798Speter 		= $$ = tree3(T_TYSET, lineof($1), $3);
409798Speter 		|
410798Speter 	YRECORD field_list YEND
411798Speter 		= {
412798Speter 			$$ = setuptyrec( lineof( $1 ) , $2 );
413798Speter 			if ($3 < 0)
414798Speter 				brerror($1, "record");
415798Speter 		  }
416798Speter 		;
417798Speter simple_type_list:
418798Speter 	simple_type
419798Speter 		= $$ = newlist($1);
420798Speter 		|
421798Speter 	simple_type_list ',' simple_type
422798Speter 		= $$ = addlist($1, $3);
423798Speter 		;
424798Speter 
425798Speter /*
426798Speter  * RECORD TYPE
427798Speter  */
428798Speter field_list:
429798Speter 	fixed_part variant_part
430798Speter 		= $$ = tree4(T_FLDLST, lineof(NIL), fixlist($1), $2);
431798Speter 		;
432798Speter fixed_part:
433798Speter 	field
434798Speter 		= $$ = newlist($1);
435798Speter 		|
436798Speter 	fixed_part ';' field
437798Speter 		= $$ = addlist($1, $3);
438798Speter 		|
439798Speter 	fixed_part error
440798Speter 		= yyPerror("Malformed record declaration", PDECL);
441798Speter 		;
442798Speter field:
443798Speter 	/* lambda */
444798Speter 		= $$ = NIL;
445798Speter 		|
446798Speter 	id_list ':' type
447798Speter 		= $$ = tree4(T_RFIELD, lineof($2), fixlist($1), $3);
448798Speter 		;
449798Speter 
450798Speter variant_part:
451798Speter 	/* lambda */
452798Speter 		= $$ = NIL;
453798Speter 		|
454798Speter 	YCASE type_id YOF variant_list
455798Speter 		= $$ = tree5(T_TYVARPT, lineof($1), NIL, $2, fixlist($4));
456798Speter 		|
457798Speter 	YCASE YID ':' type_id YOF variant_list
458798Speter 		= $$ = tree5(T_TYVARPT, lineof($1), $2, $4, fixlist($6));
459798Speter 		;
460798Speter variant_list:
461798Speter 	variant
462798Speter 		= $$ = newlist($1);
463798Speter 		|
464798Speter 	variant_list ';' variant
465798Speter 		= $$ = addlist($1, $3);
466798Speter 		|
467798Speter 	variant_list error
468798Speter 		= yyPerror("Malformed record declaration", PDECL);
469798Speter 		;
470798Speter variant:
471798Speter 	/* lambda */
472798Speter 		= $$ = NIL;
473798Speter 		|
474798Speter 	const_list ':' '(' field_list ')'
475798Speter 		= $$ = tree4(T_TYVARNT, lineof($2), fixlist($1), $4);
476798Speter 		|
477798Speter 	const_list ':' '(' ')'
478798Speter 		= $$ = tree4(T_TYVARNT, lineof($2), fixlist($1), NIL);
479798Speter 		;
480798Speter 
481798Speter /*
482798Speter  * STATEMENT LIST
483798Speter  */
484798Speter 
485798Speter stat_list:
486798Speter 	stat
487798Speter 		= $$ = newlist($1);
488798Speter 		|
489798Speter 	stat_lsth stat
490798Speter 		= {
491798Speter 			if ((p = $1) != NIL && (q = p[1])[0] == T_IFX) {
492798Speter 				q[0] = T_IFEL;
493798Speter 				q[4] = $2;
494798Speter 			} else
495798Speter 				$$ = addlist($1, $2);
496798Speter 		  }
497798Speter 		;
498798Speter 
499798Speter stat_lsth:
500798Speter 	stat_list ';'
501798Speter 		= if ((q = $1) != NIL && (p = q[1]) != NIL && p[0] == T_IF) {
502798Speter 			if (yychar < 0)
503798Speter 				yychar = yylex();
504798Speter 			if (yyshifts >= 2 && yychar == YELSE) {
505798Speter 				recovered();
506798Speter 				copy(&Y, &OY, sizeof Y);
507798Speter 				yerror("Deleted ';' before keyword else");
508798Speter 				yychar = yylex();
509798Speter 				p[0] = T_IFX;
510798Speter 			}
511798Speter 		  }
512798Speter 		;
513798Speter 
514798Speter /*
515798Speter  * CASE STATEMENT LIST
516798Speter  */
517798Speter 
518798Speter cstat_list:
519798Speter 	cstat
520798Speter 		= $$ = newlist($1);
521798Speter 		|
522798Speter 	cstat_list ';' cstat
523798Speter 		= $$ = addlist($1, $3);
524798Speter 		|
525798Speter 	error
526798Speter 		= {
527798Speter 			$$ = NIL;
528798Speter Kerror:
529798Speter 			yyPerror("Malformed statement in case", PSTAT);
530798Speter 		  }
531798Speter 		|
532798Speter 	cstat_list error
533798Speter 		= goto Kerror;
534798Speter 		;
535798Speter 
536798Speter cstat:
537798Speter 	const_list ':' stat
538798Speter 		= $$ = tree4(T_CSTAT, lineof($2), fixlist($1), $3);
539798Speter 		|
540798Speter 	YCASELAB stat
541798Speter 		= $$ = tree4(T_CSTAT, lineof($1), NIL, $2);
542798Speter 		|
543798Speter 	/* lambda */
544798Speter 		= $$ = NIL;
545798Speter 		;
546798Speter 
547798Speter /*
548798Speter  * STATEMENT
549798Speter  */
550798Speter 
551798Speter stat:
552798Speter 	/* lambda */
553798Speter 		= $$ = NIL;
554798Speter 		|
555798Speter 	YINT ':' stat
556798Speter 		= $$ = tree4(T_LABEL, lineof($2), $1 == NIL ? NIL : *hash($1, 1), $3);
557798Speter 		|
558798Speter 	proc_id
559798Speter 		= $$ = tree4(T_PCALL, lineof(yyline), $1, NIL);
560798Speter 		|
561798Speter 	proc_id '(' wexpr_list ')'
562798Speter 		= $$ = tree4(T_PCALL, lineof($2), $1, fixlist($3));
563798Speter 		|
564798Speter 	YID error
565798Speter 		= goto NSerror;
566798Speter 		|
567798Speter 	assign
568798Speter 		|
569798Speter 	YBEGIN stat_list YEND
570798Speter 		= {
571798Speter 			$$ = tree3(T_BLOCK, lineof($1), fixlist($2));
572798Speter 			if ($3 < 0)
573798Speter 				brerror($1, "begin");
574798Speter 		  }
575798Speter 		|
576798Speter 	YCASE expr YOF cstat_list YEND
577798Speter 		= {
578798Speter 			$$ = tree4(T_CASE, lineof($1), $2, fixlist($4));
579798Speter 			if ($5 < 0)
580798Speter 				brerror($1, "case");
581798Speter 		  }
582798Speter 		|
583798Speter 	YWITH var_list YDO stat
584798Speter 		= $$ = tree4(T_WITH, lineof($1), fixlist($2), $4);
585798Speter 		|
586798Speter 	YWHILE expr YDO stat
587798Speter 		= $$ = tree4(T_WHILE, lineof($1), $2, $4);
588798Speter 		|
589798Speter 	YREPEAT stat_list YUNTIL expr
590798Speter 		= $$ = tree4(T_REPEAT, lineof($3), fixlist($2), $4);
591798Speter 		|
592798Speter 	YFOR assign YTO expr YDO stat
593798Speter 		= $$ = tree5(T_FORU, lineof($1), $2, $4, $6);
594798Speter 		|
595798Speter 	YFOR assign YDOWNTO expr YDO stat
596798Speter 		= $$ = tree5(T_FORD, lineof($1), $2, $4, $6);
597798Speter 		|
598798Speter 	YGOTO YINT
599798Speter 		= $$ = tree3(T_GOTO, lineof($1), *hash($2, 1));
600798Speter 		|
601798Speter 	YIF expr YTHEN stat
602798Speter 		= $$ = tree5(T_IF, lineof($1), $2, $4, NIL);
603798Speter 		|
604798Speter 	YIF expr YTHEN stat YELSE stat
605798Speter 		= $$ = tree5(T_IFEL, lineof($1), $2, $4, $6);
606798Speter 		|
607798Speter 	YIF expr YTHEN stat YELSE
608798Speter 		= $$ = tree5(T_IFEL, lineof($1), $2, $4, NIL);
609798Speter 		|
610798Speter 	YASSERT '(' expr ')'
611798Speter 		= $$ = tree3(T_ASRT, lineof($1), $3);
612798Speter 		|
613798Speter 	error
614798Speter 		= {
615798Speter NSerror:
616798Speter 			$$ = NIL;
617798Speter Serror:
618798Speter 			yyPerror("Malformed statement", PSTAT);
619798Speter 		  }
620798Speter 		;
621798Speter assign:
622798Speter 	variable ':' '=' expr
623798Speter 		= $$ = tree4(T_ASGN, lineof($2), $1, $4);
624798Speter 		;
625798Speter 
626798Speter /*
627798Speter  * EXPRESSION
628798Speter  */
629798Speter 
630798Speter expr:
631798Speter 	error
632798Speter 		= {
633798Speter NEerror:
634798Speter 			$$ = NIL;
635798Speter Eerror:
636798Speter 			yyPerror("Missing/malformed expression", PEXPR);
637798Speter 		  }
638798Speter 		|
639798Speter 	expr relop expr			%prec '<'
640798Speter 		= $$ = tree4($2, $1[1] == SAWCON ? $3[1] : $1[1], $1, $3);
641798Speter 		|
642798Speter 	'+' expr			%prec UNARYSIGN
643798Speter 		= $$ = tree3(T_PLUS, $2[1], $2);
644798Speter 		|
645798Speter 	'-' expr			%prec UNARYSIGN
646798Speter 		= $$ = tree3(T_MINUS, $2[1], $2);
647798Speter 		|
648798Speter 	expr addop expr			%prec '+'
649798Speter 		= $$ = tree4($2, $1[1] == SAWCON ? $3[1] : $1[1], $1, $3);
650798Speter 		|
651798Speter 	expr divop expr			%prec '*'
652798Speter 		= $$ = tree4($2, $1[1] == SAWCON ? $3[1] : $1[1], $1, $3);
653798Speter 		|
654798Speter 	YNIL
655798Speter 		= $$ = tree2(T_NIL, NOCON);
656798Speter 		|
657798Speter 	YSTRING
658798Speter 		= $$ = tree3(T_STRNG, SAWCON, $1);
659798Speter 		|
660798Speter 	YINT
661798Speter 		= $$ = tree3(T_INT, NOCON, $1);
662798Speter 		|
663798Speter 	YBINT
664798Speter 		= $$ = tree3(T_BINT, NOCON, $1);
665798Speter 		|
666798Speter 	YNUMB
667798Speter 		= $$ = tree3(T_FINT, NOCON, $1);
668798Speter 		|
669798Speter 	variable
670798Speter 		|
671798Speter 	YID error
672798Speter 		= goto NEerror;
673798Speter 		|
674798Speter 	func_id '(' wexpr_list ')'
675798Speter 		= $$ = tree4(T_FCALL, NOCON, $1, fixlist($3));
676798Speter 		|
677798Speter 	'(' expr ')'
678798Speter 		= $$ = $2;
679798Speter 		|
680798Speter 	negop expr			%prec YNOT
681798Speter 		= $$ = tree3(T_NOT, NOCON, $2);
682798Speter 		|
683798Speter 	'[' element_list ']'
684798Speter 		= $$ = tree3(T_CSET, SAWCON, fixlist($2));
685798Speter 		|
686798Speter 	'[' ']'
687798Speter 		= $$ = tree3(T_CSET, SAWCON, NIL);
688798Speter 		;
689798Speter 
690798Speter element_list:
691798Speter 	element
692798Speter 		= $$ = newlist($1);
693798Speter 		|
694798Speter 	element_list ',' element
695798Speter 		= $$ = addlist($1, $3);
696798Speter 		;
697798Speter element:
698798Speter 	expr
699798Speter 		|
700798Speter 	expr YDOTDOT expr
701798Speter 		= $$ = tree3(T_RANG, $1, $3);
702798Speter 		;
703798Speter 
704798Speter /*
705798Speter  * QUALIFIED VARIABLES
706798Speter  */
707798Speter 
708798Speter variable:
709798Speter 	YID
710798Speter 		= {
711804Speter 			@@ return (identis(var, VAR));
712798Speter 			$$ = setupvar($1, NIL);
713798Speter 		  }
714798Speter 		|
715798Speter 	qual_var
716798Speter 		= $1[3] = fixlist($1[3]);
717798Speter 		;
718798Speter qual_var:
719798Speter 	array_id '[' expr_list ']'
720798Speter 		= $$ = setupvar($1, tree2(T_ARY, fixlist($3)));
721798Speter 		|
722798Speter 	qual_var '[' expr_list ']'
723798Speter 		= $1[3] = addlist($1[3], tree2(T_ARY, fixlist($3)));
724798Speter 		|
725798Speter 	record_id '.' field_id
726798Speter 		= $$ = setupvar($1, setupfield($3, NIL));
727798Speter 		|
728798Speter 	qual_var '.' field_id
729798Speter 		= $1[3] = addlist($1[3], setupfield($3, NIL));
730798Speter 		|
731798Speter 	ptr_id '^'
732798Speter 		= $$ = setupvar($1, tree1(T_PTR));
733798Speter 		|
734798Speter 	qual_var '^'
735798Speter 		= $1[3] = addlist($1[3], tree1(T_PTR));
736798Speter 		;
737798Speter 
738798Speter /*
739798Speter  * Expression with write widths
740798Speter  */
741798Speter wexpr:
742798Speter 	expr
743798Speter 		|
744798Speter 	expr ':' expr
745798Speter 		= $$ = tree4(T_WEXP, $1, $3, NIL);
746798Speter 		|
747798Speter 	expr ':' expr ':' expr
748798Speter 		= $$ = tree4(T_WEXP, $1, $3, $5);
749798Speter 		|
750798Speter 	expr octhex
751798Speter 		= $$ = tree4(T_WEXP, $1, NIL, $2);
752798Speter 		|
753798Speter 	expr ':' expr octhex
754798Speter 		= $$ = tree4(T_WEXP, $1, $3, $4);
755798Speter 		;
756798Speter octhex:
757798Speter 	YOCT
758798Speter 		= $$ = OCT;
759798Speter 		|
760798Speter 	YHEX
761798Speter 		= $$ = HEX;
762798Speter 		;
763798Speter 
764798Speter expr_list:
765798Speter 	expr
766798Speter 		= $$ = newlist($1);
767798Speter 		|
768798Speter 	expr_list ',' expr
769798Speter 		= $$ = addlist($1, $3);
770798Speter 		;
771798Speter 
772798Speter wexpr_list:
773798Speter 	wexpr
774798Speter 		= $$ = newlist($1);
775798Speter 		|
776798Speter 	wexpr_list ',' wexpr
777798Speter 		= $$ = addlist($1, $3);
778798Speter 		;
779798Speter 
780798Speter /*
781798Speter  * OPERATORS
782798Speter  */
783798Speter 
784798Speter relop:
785798Speter 	'='	= $$ = T_EQ;
786798Speter 		|
787798Speter 	'<'	= $$ = T_LT;
788798Speter 		|
789798Speter 	'>'	= $$ = T_GT;
790798Speter 		|
791798Speter 	'<' '>'	= $$ = T_NE;
792798Speter 		|
793798Speter 	'<' '='	= $$ = T_LE;
794798Speter 		|
795798Speter 	'>' '='	= $$ = T_GE;
796798Speter 		|
797798Speter 	YIN	= $$ = T_IN;
798798Speter 		;
799798Speter addop:
800798Speter 	'+'	= $$ = T_ADD;
801798Speter 		|
802798Speter 	'-'	= $$ = T_SUB;
803798Speter 		|
804798Speter 	YOR	= $$ = T_OR;
805798Speter 		|
806798Speter 	'|'	= $$ = T_OR;
807798Speter 		;
808798Speter divop:
809798Speter 	'*'	= $$ = T_MULT;
810798Speter 		|
811798Speter 	'/'	= $$ = T_DIVD;
812798Speter 		|
813798Speter 	YDIV	= $$ = T_DIV;
814798Speter 		|
815798Speter 	YMOD	= $$ = T_MOD;
816798Speter 		|
817798Speter 	YAND	= $$ = T_AND;
818798Speter 		|
819798Speter 	'&'	= $$ = T_AND;
820798Speter 		;
821798Speter 
822798Speter negop:
823798Speter 	YNOT
824798Speter 		|
825798Speter 	'~'
826798Speter 		;
827798Speter 
828798Speter /*
829798Speter  * LISTS
830798Speter  */
831798Speter 
832798Speter var_list:
833798Speter 	variable
834798Speter 		= $$ = newlist($1);
835798Speter 		|
836798Speter 	var_list ',' variable
837798Speter 		= $$ = addlist($1, $3);
838798Speter 		;
839798Speter 
840798Speter id_list:
841798Speter 	YID
842798Speter 		= $$ = newlist($1);
843798Speter 		|
844798Speter 	id_list ',' YID
845798Speter 		= $$ = addlist($1, $3);
846798Speter 		;
847798Speter 
848798Speter /*
849798Speter  * Identifier productions with semantic restrictions
850798Speter  *
851804Speter  * For these productions, the characters @@ signify
852798Speter  * that the associated C statement is to provide
853798Speter  * the semantic restriction for this reduction.
854798Speter  * These lines are made into a procedure yyEactr, similar to
855798Speter  * yyactr, which determines whether the corresponding reduction
856798Speter  * is permitted, or whether an error is to be signaled.
857798Speter  * A zero return from yyEactr is considered an error.
858798Speter  * YyEactr is called with an argument "var" giving the string
859798Speter  * name of the variable in question, essentially $1, although
860798Speter  * $1 will not work because yyEactr is called from loccor in
861798Speter  * the recovery routines.
862798Speter  */
863798Speter 
864798Speter const_id:
865798Speter 	YID
866804Speter 		= @@ return (identis(var, CONST));
867798Speter 		;
868798Speter type_id:
869798Speter 	YID
870798Speter 		= {
871804Speter 			@@ return (identis(var, TYPE));
872798Speter 			$$ = tree3(T_TYID, lineof(yyline), $1);
873798Speter 		  }
874798Speter 		;
875798Speter var_id:
876798Speter 	YID
877804Speter 		= @@ return (identis(var, VAR));
878798Speter 		;
879798Speter array_id:
880798Speter 	YID
881804Speter 		= @@ return (identis(var, ARRAY));
882798Speter 		;
883798Speter ptr_id:
884798Speter 	YID
885804Speter 		= @@ return (identis(var, PTRFILE));
886798Speter 		;
887798Speter record_id:
888798Speter 	YID
889804Speter 		= @@ return (identis(var, RECORD));
890798Speter 		;
891798Speter field_id:
892798Speter 	YID
893804Speter 		= @@ return (identis(var, FIELD));
894798Speter 		;
895798Speter proc_id:
896798Speter 	YID
897804Speter 		= @@ return (identis(var, PROC));
898798Speter 		;
899798Speter func_id:
900798Speter 	YID
901804Speter 		= @@ return (identis(var, FUNC));
902798Speter 		;
903