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