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