xref: /csrg-svn/usr.bin/pascal/src/pas.y (revision 798)
1*798Speter /* Copyright (c) 1979 Regents of the University of California */
2*798Speter 
3*798Speter /*
4*798Speter  * Yacc grammar for UNIX Pascal
5*798Speter  *
6*798Speter  * This grammar is processed by the commands in the shell script
7*798Speter  * "gram" to yield parse tables and semantic routines in the file
8*798Speter  * "y.tab.c" and a header defining the lexical tokens in "yy.h".
9*798Speter  *
10*798Speter  * In order for the syntactic error recovery possible with this
11*798Speter  * grammar to work, the grammar must be processed by a yacc which
12*798Speter  * has been modified to fully enumerate possibilities in states
13*798Speter  * which involve the symbol "error".
14*798Speter  * The parser used for Pascal also uses a different encoding of
15*798Speter  * the test entries in the action table which speeds the parse.
16*798Speter  * A version of yacc which will work for Pascal is included on
17*798Speter  * the distribution table as "eyacc".
18*798Speter  *
19*798Speter  * The "gram" script also makes the following changes to the "y.tab.c"
20*798Speter  * file:
21*798Speter  *
22*798Speter  *	1) Causes yyval to be declared int *.
23*798Speter  *
24*798Speter  *	2) Loads the variable yypv into a register as yyYpv so that
25*798Speter  *	   the arguments $1, ... are available as yyYpv[1] etc.
26*798Speter  *	   This produces much smaller code in the semantic actions.
27*798Speter  *
28*798Speter  *	3) Deletes the unused array yysterm.
29*798Speter  *
30*798Speter  *	4) Moves the declarations up to the flag line containing
31*798Speter  *	   '##' to the file yy.h so that the routines which use
32*798Speter  *	   these "magic numbers" don't have to all be compiled at
33*798Speter  *	   the same time.
34*798Speter  *
35*798Speter  *	5) Creates the semantic restriction checking routine yyEactr
36*798Speter  *	   by processing action lines containing `@'.
37*798Speter  *
38*798Speter  * This compiler uses a different version of the yacc parser, a
39*798Speter  * different yyerror which is called yerror, and requires more
40*798Speter  * lookahead sets than normally provided by yacc.
41*798Speter  *
42*798Speter  * Source for the yacc used with this grammar is included on
43*798Speter  * distribution tapes.
44*798Speter  */
45*798Speter 
46*798Speter /*
47*798Speter  * TERMINAL DECLARATIONS
48*798Speter  *
49*798Speter  * Some of the terminal declarations are out of the most natural
50*798Speter  * alphabetic order because the error recovery
51*798Speter  * will guess the first of equal cost non-terminals.
52*798Speter  * This makes, e.g. YTO preferable to YDOWNTO.
53*798Speter  */
54*798Speter 
55*798Speter %term
56*798Speter 	YAND		YARRAY		YBEGIN		YCASE
57*798Speter 	YCONST		YDIV		YDO		YDOTDOT
58*798Speter 	YTO		YELSE		YEND		YFILE
59*798Speter 	YFOR		YFORWARD	YFUNCTION	YGOTO
60*798Speter 	YID		YIF		YIN		YINT
61*798Speter 	YLABEL		YMOD		YNOT		YNUMB
62*798Speter 	YOF		YOR		YPACKED		YNIL
63*798Speter 	YPROCEDURE	YPROG		YRECORD		YREPEAT
64*798Speter 	YSET		YSTRING		YTHEN		YDOWNTO
65*798Speter 	YTYPE		YUNTIL		YVAR		YWHILE
66*798Speter 	YWITH		YBINT		YOCT		YHEX
67*798Speter 	YASSERT		YCASELAB	YILLCH		YLAST
68*798Speter 	YEXTERN
69*798Speter 
70*798Speter /*
71*798Speter  * PRECEDENCE DECLARATIONS
72*798Speter  *
73*798Speter  * Highest precedence is the unary logical NOT.
74*798Speter  * Next are the multiplying operators, signified by '*'.
75*798Speter  * Lower still are the binary adding operators, signified by '+'.
76*798Speter  * Finally, at lowest precedence and non-associative are the relationals.
77*798Speter  */
78*798Speter 
79*798Speter %binary	'<'	'='	'>'	YIN
80*798Speter %left	'+'	'-'	YOR	'|'
81*798Speter %left	UNARYSIGN
82*798Speter %left	'*'	'/'	YDIV	YMOD	YAND	'&'
83*798Speter %left	YNOT
84*798Speter 
85*798Speter %{
86*798Speter /*
87*798Speter  * GLOBALS FOR ACTIONS
88*798Speter  */
89*798Speter 
90*798Speter /* Copyright (c) 1979 Regents of the University of California */
91*798Speter 
92*798Speter /* static	char sccsid[] = "@(#)pas.y 1.1 08/27/80"; */
93*798Speter 
94*798Speter /*
95*798Speter  * The following line marks the end of the yacc
96*798Speter  * Constant definitions which are removed from
97*798Speter  * y.tab.c and placed in the file y.tab.h.
98*798Speter  */
99*798Speter ##
100*798Speter /* Copyright (c) 1979 Regents of the University of California */
101*798Speter 
102*798Speter static	char sccsid[] = "@(#)pas.y 1.1 08/27/80";
103*798Speter 
104*798Speter #include "whoami.h"
105*798Speter #include "0.h"
106*798Speter #include "yy.h"
107*798Speter #include "tree.h"
108*798Speter 
109*798Speter #ifdef PI
110*798Speter #define	lineof(l)	l
111*798Speter #define	line2of(l)	l
112*798Speter #endif
113*798Speter 
114*798Speter %}
115*798Speter 
116*798Speter %%
117*798Speter 
118*798Speter /*
119*798Speter  * PRODUCTIONS
120*798Speter  */
121*798Speter 
122*798Speter goal:
123*798Speter 	prog_hedr decls procs block '.'
124*798Speter 		= funcend($1, $4, lineof($5));
125*798Speter 		|
126*798Speter 	decls procs
127*798Speter 		= segend();
128*798Speter 		;
129*798Speter 
130*798Speter 
131*798Speter prog_hedr:
132*798Speter 	YPROG YID '(' id_list ')' ';'
133*798Speter 		= $$ = funcbody(funchdr(tree5(T_PROG, lineof($1), $2, fixlist($4), NIL)));
134*798Speter 		|
135*798Speter 	YPROG error
136*798Speter 		= {
137*798Speter 			yyPerror("Malformed program statement", PPROG);
138*798Speter 			/*
139*798Speter 			 * Should make a program statement
140*798Speter 			 * with "input" and "output" here.
141*798Speter 			 */
142*798Speter 			$$ = funcbody(funchdr(tree5(T_PROG, lineof($1), NIL, NIL, NIL)));
143*798Speter 		  }
144*798Speter 		;
145*798Speter block:
146*798Speter 	YBEGIN stat_list YEND
147*798Speter 		= {
148*798Speter 			$$ = tree3(T_BSTL, lineof($1), fixlist($2));
149*798Speter 			if ($3 < 0)
150*798Speter 				brerror($1, "begin");
151*798Speter 		  }
152*798Speter 		;
153*798Speter 
154*798Speter 
155*798Speter /*
156*798Speter  * DECLARATION PART
157*798Speter  */
158*798Speter decls:
159*798Speter 	decls decl
160*798Speter 		= trfree();
161*798Speter 		|
162*798Speter 	decls error
163*798Speter 		= {
164*798Speter Derror:
165*798Speter 			constend(), typeend(), varend(), trfree();
166*798Speter 			yyPerror("Malformed declaration", PDECL);
167*798Speter 		  }
168*798Speter 		|
169*798Speter 	/* lambda */
170*798Speter 		= trfree();
171*798Speter 		;
172*798Speter 
173*798Speter decl:
174*798Speter 	labels
175*798Speter 		|
176*798Speter 	const_decl
177*798Speter 		= constend();
178*798Speter 		|
179*798Speter 	type_decl
180*798Speter 		= typeend();
181*798Speter 		|
182*798Speter 	var_decl
183*798Speter 		= varend();
184*798Speter 		;
185*798Speter 
186*798Speter /*
187*798Speter  * LABEL PART
188*798Speter  */
189*798Speter 
190*798Speter labels:
191*798Speter 	YLABEL label_decl ';'
192*798Speter 		= label(fixlist($2), lineof($1));
193*798Speter 		;
194*798Speter label_decl:
195*798Speter 	YINT
196*798Speter 		= $$ = newlist($1 == NIL ? NIL : *hash($1, 1));
197*798Speter 		|
198*798Speter 	label_decl ',' YINT
199*798Speter 		= $$ = addlist($1, $3 == NIL ? NIL : *hash($3, 1));
200*798Speter 		;
201*798Speter 
202*798Speter /*
203*798Speter  * CONST PART
204*798Speter  */
205*798Speter 
206*798Speter const_decl:
207*798Speter 	YCONST YID '=' const ';'
208*798Speter 		= constbeg($1, line2of($2)), const(lineof($3), $2, $4);
209*798Speter 		|
210*798Speter 	const_decl YID '=' const ';'
211*798Speter 		= const(lineof($3), $2, $4);
212*798Speter 		|
213*798Speter 	YCONST error
214*798Speter 		= {
215*798Speter 			constbeg($1, line2of($1));
216*798Speter Cerror:
217*798Speter 			yyPerror("Malformed const declaration", PDECL);
218*798Speter 		  }
219*798Speter 		|
220*798Speter 	const_decl error
221*798Speter 		= goto Cerror;
222*798Speter 		;
223*798Speter 
224*798Speter /*
225*798Speter  * TYPE PART
226*798Speter  */
227*798Speter 
228*798Speter type_decl:
229*798Speter 	YTYPE YID '=' type ';'
230*798Speter 		= typebeg($1, line2of($2)), type(lineof($3), $2, $4);
231*798Speter 		|
232*798Speter 	type_decl YID '=' type ';'
233*798Speter 		= type(lineof($3), $2, $4);
234*798Speter 		|
235*798Speter 	YTYPE error
236*798Speter 		= {
237*798Speter 			typebeg($1, line2of($1));
238*798Speter Terror:
239*798Speter 			yyPerror("Malformed type declaration", PDECL);
240*798Speter 		  }
241*798Speter 		|
242*798Speter 	type_decl error
243*798Speter 		= goto Terror;
244*798Speter 		;
245*798Speter 
246*798Speter /*
247*798Speter  * VAR PART
248*798Speter  */
249*798Speter 
250*798Speter var_decl:
251*798Speter 	YVAR id_list ':' type ';'
252*798Speter 		= varbeg($1, line2of($3)), var(lineof($3), fixlist($2), $4);
253*798Speter 		|
254*798Speter 	var_decl id_list ':' type ';'
255*798Speter 		= var(lineof($3), fixlist($2), $4);
256*798Speter 		|
257*798Speter 	YVAR error
258*798Speter 		= {
259*798Speter 			varbeg($1, line2of($1));
260*798Speter Verror:
261*798Speter 			yyPerror("Malformed var declaration", PDECL);
262*798Speter 		  }
263*798Speter 		|
264*798Speter 	var_decl error
265*798Speter 		= goto Verror;
266*798Speter 		;
267*798Speter 
268*798Speter /*
269*798Speter  * PROCEDURE AND FUNCTION DECLARATION PART
270*798Speter  */
271*798Speter 
272*798Speter procs:
273*798Speter 	/* lambda */
274*798Speter 		|
275*798Speter 	procs proc
276*798Speter 		= trfree();
277*798Speter 		;
278*798Speter proc:
279*798Speter 	phead YFORWARD ';'
280*798Speter 		= funcfwd($1);
281*798Speter 		|
282*798Speter 	phead YEXTERN ';'
283*798Speter 		= funcext($1);
284*798Speter 		|
285*798Speter 	pheadres decls procs block ';'
286*798Speter 		= funcend($1, $4, lineof($5));
287*798Speter 		;
288*798Speter pheadres:
289*798Speter 	phead
290*798Speter 		= funcbody($1);
291*798Speter 		;
292*798Speter phead:
293*798Speter 	porf YID params ftype ';'
294*798Speter 		= $$ = funchdr(tree5($1, lineof($5), $2, $3, $4));
295*798Speter 		;
296*798Speter porf:
297*798Speter 	YPROCEDURE
298*798Speter 		= $$ = T_PDEC;
299*798Speter 		|
300*798Speter 	YFUNCTION
301*798Speter 		= $$ = T_FDEC;
302*798Speter 		;
303*798Speter params:
304*798Speter 	'(' param_list ')'
305*798Speter 		= $$ = fixlist($2);
306*798Speter 		|
307*798Speter 	/* lambda */
308*798Speter 		= $$ = NIL;
309*798Speter 		;
310*798Speter 
311*798Speter /*
312*798Speter  * PARAMETERS
313*798Speter  */
314*798Speter 
315*798Speter param:
316*798Speter 	id_list ':' type
317*798Speter 		= $$ = tree3(T_PVAL, fixlist($1), $3);
318*798Speter 		|
319*798Speter 	YVAR id_list ':' type
320*798Speter 		= $$ = tree3(T_PVAR, fixlist($2), $4);
321*798Speter 		|
322*798Speter 	YFUNCTION id_list ':' type
323*798Speter 		= $$ = tree3(T_PFUNC, fixlist($2), $4);
324*798Speter 		|
325*798Speter 	YPROCEDURE id_list
326*798Speter 		= $$ = tree2(T_PPROC, fixlist($2));
327*798Speter 		;
328*798Speter ftype:
329*798Speter 	':' type
330*798Speter 		= $$ = $2;
331*798Speter 		|
332*798Speter 	/* lambda */
333*798Speter 		= $$ = NIL;
334*798Speter 		;
335*798Speter param_list:
336*798Speter 	param
337*798Speter 		= $$ = newlist($1);
338*798Speter 		|
339*798Speter 	param_list ';' param
340*798Speter 		= $$ = addlist($1, $3);
341*798Speter 		;
342*798Speter 
343*798Speter /*
344*798Speter  * CONSTANTS
345*798Speter  */
346*798Speter 
347*798Speter const:
348*798Speter 	YSTRING
349*798Speter 		= $$ = tree2(T_CSTRNG, $1);
350*798Speter 		|
351*798Speter 	number
352*798Speter 		|
353*798Speter 	'+' number
354*798Speter 		= $$ = tree2(T_PLUSC, $2);
355*798Speter 		|
356*798Speter 	'-' number
357*798Speter 		= $$ = tree2(T_MINUSC, $2);
358*798Speter 		;
359*798Speter number:
360*798Speter 	const_id
361*798Speter 		= $$ = tree2(T_ID, $1);
362*798Speter 		|
363*798Speter 	YINT
364*798Speter 		= $$ = tree2(T_CINT, $1);
365*798Speter 		|
366*798Speter 	YBINT
367*798Speter 		= $$ = tree2(T_CBINT, $1);
368*798Speter 		|
369*798Speter 	YNUMB
370*798Speter 		= $$ = tree2(T_CFINT, $1);
371*798Speter 		;
372*798Speter const_list:
373*798Speter 	const
374*798Speter 		= $$ = newlist($1);
375*798Speter 		|
376*798Speter 	const_list ',' const
377*798Speter 		= $$ = addlist($1, $3);
378*798Speter 		;
379*798Speter 
380*798Speter /*
381*798Speter  * TYPES
382*798Speter  */
383*798Speter 
384*798Speter type:
385*798Speter 	simple_type
386*798Speter 		|
387*798Speter 	'^' YID
388*798Speter 		= $$ = tree3(T_TYPTR, lineof($1), tree2(T_ID, $2));
389*798Speter 		|
390*798Speter 	struct_type
391*798Speter 		|
392*798Speter 	YPACKED struct_type
393*798Speter 		= $$ = tree3(T_TYPACK, lineof($1), $2);
394*798Speter 		;
395*798Speter simple_type:
396*798Speter 	type_id
397*798Speter 		|
398*798Speter 	'(' id_list ')'
399*798Speter 		= $$ = tree3(T_TYSCAL, lineof($1), fixlist($2));
400*798Speter 		|
401*798Speter 	const YDOTDOT const
402*798Speter 		= $$ = tree4(T_TYRANG, lineof($2), $1, $3);
403*798Speter 		;
404*798Speter struct_type:
405*798Speter 	YARRAY '[' simple_type_list ']' YOF type
406*798Speter 		= $$ = tree4(T_TYARY, lineof($1), fixlist($3), $6);
407*798Speter 		|
408*798Speter 	YFILE YOF type
409*798Speter 		= $$ = tree3(T_TYFILE, lineof($1), $3);
410*798Speter 		|
411*798Speter 	YSET YOF simple_type
412*798Speter 		= $$ = tree3(T_TYSET, lineof($1), $3);
413*798Speter 		|
414*798Speter 	YRECORD field_list YEND
415*798Speter 		= {
416*798Speter 			$$ = setuptyrec( lineof( $1 ) , $2 );
417*798Speter 			if ($3 < 0)
418*798Speter 				brerror($1, "record");
419*798Speter 		  }
420*798Speter 		;
421*798Speter simple_type_list:
422*798Speter 	simple_type
423*798Speter 		= $$ = newlist($1);
424*798Speter 		|
425*798Speter 	simple_type_list ',' simple_type
426*798Speter 		= $$ = addlist($1, $3);
427*798Speter 		;
428*798Speter 
429*798Speter /*
430*798Speter  * RECORD TYPE
431*798Speter  */
432*798Speter field_list:
433*798Speter 	fixed_part variant_part
434*798Speter 		= $$ = tree4(T_FLDLST, lineof(NIL), fixlist($1), $2);
435*798Speter 		;
436*798Speter fixed_part:
437*798Speter 	field
438*798Speter 		= $$ = newlist($1);
439*798Speter 		|
440*798Speter 	fixed_part ';' field
441*798Speter 		= $$ = addlist($1, $3);
442*798Speter 		|
443*798Speter 	fixed_part error
444*798Speter 		= yyPerror("Malformed record declaration", PDECL);
445*798Speter 		;
446*798Speter field:
447*798Speter 	/* lambda */
448*798Speter 		= $$ = NIL;
449*798Speter 		|
450*798Speter 	id_list ':' type
451*798Speter 		= $$ = tree4(T_RFIELD, lineof($2), fixlist($1), $3);
452*798Speter 		;
453*798Speter 
454*798Speter variant_part:
455*798Speter 	/* lambda */
456*798Speter 		= $$ = NIL;
457*798Speter 		|
458*798Speter 	YCASE type_id YOF variant_list
459*798Speter 		= $$ = tree5(T_TYVARPT, lineof($1), NIL, $2, fixlist($4));
460*798Speter 		|
461*798Speter 	YCASE YID ':' type_id YOF variant_list
462*798Speter 		= $$ = tree5(T_TYVARPT, lineof($1), $2, $4, fixlist($6));
463*798Speter 		;
464*798Speter variant_list:
465*798Speter 	variant
466*798Speter 		= $$ = newlist($1);
467*798Speter 		|
468*798Speter 	variant_list ';' variant
469*798Speter 		= $$ = addlist($1, $3);
470*798Speter 		|
471*798Speter 	variant_list error
472*798Speter 		= yyPerror("Malformed record declaration", PDECL);
473*798Speter 		;
474*798Speter variant:
475*798Speter 	/* lambda */
476*798Speter 		= $$ = NIL;
477*798Speter 		|
478*798Speter 	const_list ':' '(' field_list ')'
479*798Speter 		= $$ = tree4(T_TYVARNT, lineof($2), fixlist($1), $4);
480*798Speter 		|
481*798Speter 	const_list ':' '(' ')'
482*798Speter 		= $$ = tree4(T_TYVARNT, lineof($2), fixlist($1), NIL);
483*798Speter 		;
484*798Speter 
485*798Speter /*
486*798Speter  * STATEMENT LIST
487*798Speter  */
488*798Speter 
489*798Speter stat_list:
490*798Speter 	stat
491*798Speter 		= $$ = newlist($1);
492*798Speter 		|
493*798Speter 	stat_lsth stat
494*798Speter 		= {
495*798Speter 			if ((p = $1) != NIL && (q = p[1])[0] == T_IFX) {
496*798Speter 				q[0] = T_IFEL;
497*798Speter 				q[4] = $2;
498*798Speter 			} else
499*798Speter 				$$ = addlist($1, $2);
500*798Speter 		  }
501*798Speter 		;
502*798Speter 
503*798Speter stat_lsth:
504*798Speter 	stat_list ';'
505*798Speter 		= if ((q = $1) != NIL && (p = q[1]) != NIL && p[0] == T_IF) {
506*798Speter 			if (yychar < 0)
507*798Speter 				yychar = yylex();
508*798Speter 			if (yyshifts >= 2 && yychar == YELSE) {
509*798Speter 				recovered();
510*798Speter 				copy(&Y, &OY, sizeof Y);
511*798Speter 				yerror("Deleted ';' before keyword else");
512*798Speter 				yychar = yylex();
513*798Speter 				p[0] = T_IFX;
514*798Speter 			}
515*798Speter 		  }
516*798Speter 		;
517*798Speter 
518*798Speter /*
519*798Speter  * CASE STATEMENT LIST
520*798Speter  */
521*798Speter 
522*798Speter cstat_list:
523*798Speter 	cstat
524*798Speter 		= $$ = newlist($1);
525*798Speter 		|
526*798Speter 	cstat_list ';' cstat
527*798Speter 		= $$ = addlist($1, $3);
528*798Speter 		|
529*798Speter 	error
530*798Speter 		= {
531*798Speter 			$$ = NIL;
532*798Speter Kerror:
533*798Speter 			yyPerror("Malformed statement in case", PSTAT);
534*798Speter 		  }
535*798Speter 		|
536*798Speter 	cstat_list error
537*798Speter 		= goto Kerror;
538*798Speter 		;
539*798Speter 
540*798Speter cstat:
541*798Speter 	const_list ':' stat
542*798Speter 		= $$ = tree4(T_CSTAT, lineof($2), fixlist($1), $3);
543*798Speter 		|
544*798Speter 	YCASELAB stat
545*798Speter 		= $$ = tree4(T_CSTAT, lineof($1), NIL, $2);
546*798Speter 		|
547*798Speter 	/* lambda */
548*798Speter 		= $$ = NIL;
549*798Speter 		;
550*798Speter 
551*798Speter /*
552*798Speter  * STATEMENT
553*798Speter  */
554*798Speter 
555*798Speter stat:
556*798Speter 	/* lambda */
557*798Speter 		= $$ = NIL;
558*798Speter 		|
559*798Speter 	YINT ':' stat
560*798Speter 		= $$ = tree4(T_LABEL, lineof($2), $1 == NIL ? NIL : *hash($1, 1), $3);
561*798Speter 		|
562*798Speter 	proc_id
563*798Speter 		= $$ = tree4(T_PCALL, lineof(yyline), $1, NIL);
564*798Speter 		|
565*798Speter 	proc_id '(' wexpr_list ')'
566*798Speter 		= $$ = tree4(T_PCALL, lineof($2), $1, fixlist($3));
567*798Speter 		|
568*798Speter 	YID error
569*798Speter 		= goto NSerror;
570*798Speter 		|
571*798Speter 	assign
572*798Speter 		|
573*798Speter 	YBEGIN stat_list YEND
574*798Speter 		= {
575*798Speter 			$$ = tree3(T_BLOCK, lineof($1), fixlist($2));
576*798Speter 			if ($3 < 0)
577*798Speter 				brerror($1, "begin");
578*798Speter 		  }
579*798Speter 		|
580*798Speter 	YCASE expr YOF cstat_list YEND
581*798Speter 		= {
582*798Speter 			$$ = tree4(T_CASE, lineof($1), $2, fixlist($4));
583*798Speter 			if ($5 < 0)
584*798Speter 				brerror($1, "case");
585*798Speter 		  }
586*798Speter 		|
587*798Speter 	YWITH var_list YDO stat
588*798Speter 		= $$ = tree4(T_WITH, lineof($1), fixlist($2), $4);
589*798Speter 		|
590*798Speter 	YWHILE expr YDO stat
591*798Speter 		= $$ = tree4(T_WHILE, lineof($1), $2, $4);
592*798Speter 		|
593*798Speter 	YREPEAT stat_list YUNTIL expr
594*798Speter 		= $$ = tree4(T_REPEAT, lineof($3), fixlist($2), $4);
595*798Speter 		|
596*798Speter 	YFOR assign YTO expr YDO stat
597*798Speter 		= $$ = tree5(T_FORU, lineof($1), $2, $4, $6);
598*798Speter 		|
599*798Speter 	YFOR assign YDOWNTO expr YDO stat
600*798Speter 		= $$ = tree5(T_FORD, lineof($1), $2, $4, $6);
601*798Speter 		|
602*798Speter 	YGOTO YINT
603*798Speter 		= $$ = tree3(T_GOTO, lineof($1), *hash($2, 1));
604*798Speter 		|
605*798Speter 	YIF expr YTHEN stat
606*798Speter 		= $$ = tree5(T_IF, lineof($1), $2, $4, NIL);
607*798Speter 		|
608*798Speter 	YIF expr YTHEN stat YELSE stat
609*798Speter 		= $$ = tree5(T_IFEL, lineof($1), $2, $4, $6);
610*798Speter 		|
611*798Speter 	YIF expr YTHEN stat YELSE
612*798Speter 		= $$ = tree5(T_IFEL, lineof($1), $2, $4, NIL);
613*798Speter 		|
614*798Speter 	YASSERT '(' expr ')'
615*798Speter 		= $$ = tree3(T_ASRT, lineof($1), $3);
616*798Speter 		|
617*798Speter 	error
618*798Speter 		= {
619*798Speter NSerror:
620*798Speter 			$$ = NIL;
621*798Speter Serror:
622*798Speter 			yyPerror("Malformed statement", PSTAT);
623*798Speter 		  }
624*798Speter 		;
625*798Speter assign:
626*798Speter 	variable ':' '=' expr
627*798Speter 		= $$ = tree4(T_ASGN, lineof($2), $1, $4);
628*798Speter 		;
629*798Speter 
630*798Speter /*
631*798Speter  * EXPRESSION
632*798Speter  */
633*798Speter 
634*798Speter expr:
635*798Speter 	error
636*798Speter 		= {
637*798Speter NEerror:
638*798Speter 			$$ = NIL;
639*798Speter Eerror:
640*798Speter 			yyPerror("Missing/malformed expression", PEXPR);
641*798Speter 		  }
642*798Speter 		|
643*798Speter 	expr relop expr			%prec '<'
644*798Speter 		= $$ = tree4($2, $1[1] == SAWCON ? $3[1] : $1[1], $1, $3);
645*798Speter 		|
646*798Speter 	'+' expr			%prec UNARYSIGN
647*798Speter 		= $$ = tree3(T_PLUS, $2[1], $2);
648*798Speter 		|
649*798Speter 	'-' expr			%prec UNARYSIGN
650*798Speter 		= $$ = tree3(T_MINUS, $2[1], $2);
651*798Speter 		|
652*798Speter 	expr addop expr			%prec '+'
653*798Speter 		= $$ = tree4($2, $1[1] == SAWCON ? $3[1] : $1[1], $1, $3);
654*798Speter 		|
655*798Speter 	expr divop expr			%prec '*'
656*798Speter 		= $$ = tree4($2, $1[1] == SAWCON ? $3[1] : $1[1], $1, $3);
657*798Speter 		|
658*798Speter 	YNIL
659*798Speter 		= $$ = tree2(T_NIL, NOCON);
660*798Speter 		|
661*798Speter 	YSTRING
662*798Speter 		= $$ = tree3(T_STRNG, SAWCON, $1);
663*798Speter 		|
664*798Speter 	YINT
665*798Speter 		= $$ = tree3(T_INT, NOCON, $1);
666*798Speter 		|
667*798Speter 	YBINT
668*798Speter 		= $$ = tree3(T_BINT, NOCON, $1);
669*798Speter 		|
670*798Speter 	YNUMB
671*798Speter 		= $$ = tree3(T_FINT, NOCON, $1);
672*798Speter 		|
673*798Speter 	variable
674*798Speter 		|
675*798Speter 	YID error
676*798Speter 		= goto NEerror;
677*798Speter 		|
678*798Speter 	func_id '(' wexpr_list ')'
679*798Speter 		= $$ = tree4(T_FCALL, NOCON, $1, fixlist($3));
680*798Speter 		|
681*798Speter 	'(' expr ')'
682*798Speter 		= $$ = $2;
683*798Speter 		|
684*798Speter 	negop expr			%prec YNOT
685*798Speter 		= $$ = tree3(T_NOT, NOCON, $2);
686*798Speter 		|
687*798Speter 	'[' element_list ']'
688*798Speter 		= $$ = tree3(T_CSET, SAWCON, fixlist($2));
689*798Speter 		|
690*798Speter 	'[' ']'
691*798Speter 		= $$ = tree3(T_CSET, SAWCON, NIL);
692*798Speter 		;
693*798Speter 
694*798Speter element_list:
695*798Speter 	element
696*798Speter 		= $$ = newlist($1);
697*798Speter 		|
698*798Speter 	element_list ',' element
699*798Speter 		= $$ = addlist($1, $3);
700*798Speter 		;
701*798Speter element:
702*798Speter 	expr
703*798Speter 		|
704*798Speter 	expr YDOTDOT expr
705*798Speter 		= $$ = tree3(T_RANG, $1, $3);
706*798Speter 		;
707*798Speter 
708*798Speter /*
709*798Speter  * QUALIFIED VARIABLES
710*798Speter  */
711*798Speter 
712*798Speter variable:
713*798Speter 	YID
714*798Speter 		= {
715*798Speter 			@ return (identis(var, VAR));
716*798Speter 			$$ = setupvar($1, NIL);
717*798Speter 		  }
718*798Speter 		|
719*798Speter 	qual_var
720*798Speter 		= $1[3] = fixlist($1[3]);
721*798Speter 		;
722*798Speter qual_var:
723*798Speter 	array_id '[' expr_list ']'
724*798Speter 		= $$ = setupvar($1, tree2(T_ARY, fixlist($3)));
725*798Speter 		|
726*798Speter 	qual_var '[' expr_list ']'
727*798Speter 		= $1[3] = addlist($1[3], tree2(T_ARY, fixlist($3)));
728*798Speter 		|
729*798Speter 	record_id '.' field_id
730*798Speter 		= $$ = setupvar($1, setupfield($3, NIL));
731*798Speter 		|
732*798Speter 	qual_var '.' field_id
733*798Speter 		= $1[3] = addlist($1[3], setupfield($3, NIL));
734*798Speter 		|
735*798Speter 	ptr_id '^'
736*798Speter 		= $$ = setupvar($1, tree1(T_PTR));
737*798Speter 		|
738*798Speter 	qual_var '^'
739*798Speter 		= $1[3] = addlist($1[3], tree1(T_PTR));
740*798Speter 		;
741*798Speter 
742*798Speter /*
743*798Speter  * Expression with write widths
744*798Speter  */
745*798Speter wexpr:
746*798Speter 	expr
747*798Speter 		|
748*798Speter 	expr ':' expr
749*798Speter 		= $$ = tree4(T_WEXP, $1, $3, NIL);
750*798Speter 		|
751*798Speter 	expr ':' expr ':' expr
752*798Speter 		= $$ = tree4(T_WEXP, $1, $3, $5);
753*798Speter 		|
754*798Speter 	expr octhex
755*798Speter 		= $$ = tree4(T_WEXP, $1, NIL, $2);
756*798Speter 		|
757*798Speter 	expr ':' expr octhex
758*798Speter 		= $$ = tree4(T_WEXP, $1, $3, $4);
759*798Speter 		;
760*798Speter octhex:
761*798Speter 	YOCT
762*798Speter 		= $$ = OCT;
763*798Speter 		|
764*798Speter 	YHEX
765*798Speter 		= $$ = HEX;
766*798Speter 		;
767*798Speter 
768*798Speter expr_list:
769*798Speter 	expr
770*798Speter 		= $$ = newlist($1);
771*798Speter 		|
772*798Speter 	expr_list ',' expr
773*798Speter 		= $$ = addlist($1, $3);
774*798Speter 		;
775*798Speter 
776*798Speter wexpr_list:
777*798Speter 	wexpr
778*798Speter 		= $$ = newlist($1);
779*798Speter 		|
780*798Speter 	wexpr_list ',' wexpr
781*798Speter 		= $$ = addlist($1, $3);
782*798Speter 		;
783*798Speter 
784*798Speter /*
785*798Speter  * OPERATORS
786*798Speter  */
787*798Speter 
788*798Speter relop:
789*798Speter 	'='	= $$ = T_EQ;
790*798Speter 		|
791*798Speter 	'<'	= $$ = T_LT;
792*798Speter 		|
793*798Speter 	'>'	= $$ = T_GT;
794*798Speter 		|
795*798Speter 	'<' '>'	= $$ = T_NE;
796*798Speter 		|
797*798Speter 	'<' '='	= $$ = T_LE;
798*798Speter 		|
799*798Speter 	'>' '='	= $$ = T_GE;
800*798Speter 		|
801*798Speter 	YIN	= $$ = T_IN;
802*798Speter 		;
803*798Speter addop:
804*798Speter 	'+'	= $$ = T_ADD;
805*798Speter 		|
806*798Speter 	'-'	= $$ = T_SUB;
807*798Speter 		|
808*798Speter 	YOR	= $$ = T_OR;
809*798Speter 		|
810*798Speter 	'|'	= $$ = T_OR;
811*798Speter 		;
812*798Speter divop:
813*798Speter 	'*'	= $$ = T_MULT;
814*798Speter 		|
815*798Speter 	'/'	= $$ = T_DIVD;
816*798Speter 		|
817*798Speter 	YDIV	= $$ = T_DIV;
818*798Speter 		|
819*798Speter 	YMOD	= $$ = T_MOD;
820*798Speter 		|
821*798Speter 	YAND	= $$ = T_AND;
822*798Speter 		|
823*798Speter 	'&'	= $$ = T_AND;
824*798Speter 		;
825*798Speter 
826*798Speter negop:
827*798Speter 	YNOT
828*798Speter 		|
829*798Speter 	'~'
830*798Speter 		;
831*798Speter 
832*798Speter /*
833*798Speter  * LISTS
834*798Speter  */
835*798Speter 
836*798Speter var_list:
837*798Speter 	variable
838*798Speter 		= $$ = newlist($1);
839*798Speter 		|
840*798Speter 	var_list ',' variable
841*798Speter 		= $$ = addlist($1, $3);
842*798Speter 		;
843*798Speter 
844*798Speter id_list:
845*798Speter 	YID
846*798Speter 		= $$ = newlist($1);
847*798Speter 		|
848*798Speter 	id_list ',' YID
849*798Speter 		= $$ = addlist($1, $3);
850*798Speter 		;
851*798Speter 
852*798Speter /*
853*798Speter  * Identifier productions with semantic restrictions
854*798Speter  *
855*798Speter  * For these productions, the character @ signifies
856*798Speter  * that the associated C statement is to provide
857*798Speter  * the semantic restriction for this reduction.
858*798Speter  * These lines are made into a procedure yyEactr, similar to
859*798Speter  * yyactr, which determines whether the corresponding reduction
860*798Speter  * is permitted, or whether an error is to be signaled.
861*798Speter  * A zero return from yyEactr is considered an error.
862*798Speter  * YyEactr is called with an argument "var" giving the string
863*798Speter  * name of the variable in question, essentially $1, although
864*798Speter  * $1 will not work because yyEactr is called from loccor in
865*798Speter  * the recovery routines.
866*798Speter  */
867*798Speter 
868*798Speter const_id:
869*798Speter 	YID
870*798Speter 		= @ return (identis(var, CONST));
871*798Speter 		;
872*798Speter type_id:
873*798Speter 	YID
874*798Speter 		= {
875*798Speter 			@ return (identis(var, TYPE));
876*798Speter 			$$ = tree3(T_TYID, lineof(yyline), $1);
877*798Speter 		  }
878*798Speter 		;
879*798Speter var_id:
880*798Speter 	YID
881*798Speter 		= @ return (identis(var, VAR));
882*798Speter 		;
883*798Speter array_id:
884*798Speter 	YID
885*798Speter 		= @ return (identis(var, ARRAY));
886*798Speter 		;
887*798Speter ptr_id:
888*798Speter 	YID
889*798Speter 		= @ return (identis(var, PTRFILE));
890*798Speter 		;
891*798Speter record_id:
892*798Speter 	YID
893*798Speter 		= @ return (identis(var, RECORD));
894*798Speter 		;
895*798Speter field_id:
896*798Speter 	YID
897*798Speter 		= @ return (identis(var, FIELD));
898*798Speter 		;
899*798Speter proc_id:
900*798Speter 	YID
901*798Speter 		= @ return (identis(var, PROC));
902*798Speter 		;
903*798Speter func_id:
904*798Speter 	YID
905*798Speter 		= @ return (identis(var, FUNC));
906*798Speter 		;
907