xref: /csrg-svn/usr.bin/pascal/src/pas.y (revision 8000)
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*8000Speter /* static	char sccsid[] = "@(#)pas.y 1.9 08/30/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*8000Speter static	char sccsid[] = "@(#)pas.y 1.9 08/30/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 		|
1347953Speter 	YPROG YID ';'
1357953Speter 		= $$ = funcbody(funchdr(tree5(T_PROG, lineof($1), $2, NIL, NIL)));
1367953Speter 		|
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));
285*8000Speter 		|
286*8000Speter 	phead error
287798Speter 		;
288798Speter pheadres:
289798Speter 	phead
290798Speter 		= funcbody($1);
291798Speter 		;
292798Speter phead:
293798Speter 	porf YID params ftype ';'
294798Speter 		= $$ = funchdr(tree5($1, lineof($5), $2, $3, $4));
295798Speter 		;
296798Speter porf:
297798Speter 	YPROCEDURE
298798Speter 		= $$ = T_PDEC;
299798Speter 		|
300798Speter 	YFUNCTION
301798Speter 		= $$ = T_FDEC;
302798Speter 		;
303798Speter params:
304798Speter 	'(' param_list ')'
305798Speter 		= $$ = fixlist($2);
306798Speter 		|
307798Speter 	/* lambda */
308798Speter 		= $$ = NIL;
309798Speter 		;
310798Speter 
311798Speter /*
312798Speter  * PARAMETERS
313798Speter  */
314798Speter 
315798Speter param:
316798Speter 	id_list ':' type
317798Speter 		= $$ = tree3(T_PVAL, fixlist($1), $3);
318798Speter 		|
319798Speter 	YVAR id_list ':' type
320798Speter 		= $$ = tree3(T_PVAR, fixlist($2), $4);
321798Speter 		|
3223298Smckusic 	YFUNCTION id_list params ftype
3233298Smckusic 		= $$ = tree5(T_PFUNC, fixlist($2), $4, $3, lineof($1));
324798Speter 		|
3253298Smckusic 	YPROCEDURE id_list params ftype
3263298Smckusic 		= $$ = tree5(T_PPROC, fixlist($2), $4, $3, lineof($1));
327798Speter 		;
328798Speter ftype:
329798Speter 	':' type
330798Speter 		= $$ = $2;
331798Speter 		|
332798Speter 	/* lambda */
333798Speter 		= $$ = NIL;
334798Speter 		;
335798Speter param_list:
336798Speter 	param
337798Speter 		= $$ = newlist($1);
338798Speter 		|
339798Speter 	param_list ';' param
340798Speter 		= $$ = addlist($1, $3);
341798Speter 		;
342798Speter 
343798Speter /*
344798Speter  * CONSTANTS
345798Speter  */
346798Speter 
347798Speter const:
348798Speter 	YSTRING
349798Speter 		= $$ = tree2(T_CSTRNG, $1);
350798Speter 		|
351798Speter 	number
352798Speter 		|
353798Speter 	'+' number
354798Speter 		= $$ = tree2(T_PLUSC, $2);
355798Speter 		|
356798Speter 	'-' number
357798Speter 		= $$ = tree2(T_MINUSC, $2);
358798Speter 		;
359798Speter number:
360798Speter 	const_id
361798Speter 		= $$ = tree2(T_ID, $1);
362798Speter 		|
363798Speter 	YINT
364798Speter 		= $$ = tree2(T_CINT, $1);
365798Speter 		|
366798Speter 	YBINT
367798Speter 		= $$ = tree2(T_CBINT, $1);
368798Speter 		|
369798Speter 	YNUMB
370798Speter 		= $$ = tree2(T_CFINT, $1);
371798Speter 		;
372798Speter const_list:
373798Speter 	const
374798Speter 		= $$ = newlist($1);
375798Speter 		|
376798Speter 	const_list ',' const
377798Speter 		= $$ = addlist($1, $3);
378798Speter 		;
379798Speter 
380798Speter /*
381798Speter  * TYPES
382798Speter  */
383798Speter 
384798Speter type:
385798Speter 	simple_type
386798Speter 		|
387798Speter 	'^' YID
388798Speter 		= $$ = tree3(T_TYPTR, lineof($1), tree2(T_ID, $2));
389798Speter 		|
390798Speter 	struct_type
391798Speter 		|
392798Speter 	YPACKED struct_type
393798Speter 		= $$ = tree3(T_TYPACK, lineof($1), $2);
394798Speter 		;
395798Speter simple_type:
396798Speter 	type_id
397798Speter 		|
398798Speter 	'(' id_list ')'
399798Speter 		= $$ = tree3(T_TYSCAL, lineof($1), fixlist($2));
400798Speter 		|
401798Speter 	const YDOTDOT const
402798Speter 		= $$ = tree4(T_TYRANG, lineof($2), $1, $3);
403798Speter 		;
404798Speter struct_type:
405798Speter 	YARRAY '[' simple_type_list ']' YOF type
406798Speter 		= $$ = tree4(T_TYARY, lineof($1), fixlist($3), $6);
407798Speter 		|
408798Speter 	YFILE YOF type
409798Speter 		= $$ = tree3(T_TYFILE, lineof($1), $3);
410798Speter 		|
411798Speter 	YSET YOF simple_type
412798Speter 		= $$ = tree3(T_TYSET, lineof($1), $3);
413798Speter 		|
414798Speter 	YRECORD field_list YEND
415798Speter 		= {
416798Speter 			$$ = setuptyrec( lineof( $1 ) , $2 );
417798Speter 			if ($3 < 0)
418798Speter 				brerror($1, "record");
419798Speter 		  }
420798Speter 		;
421798Speter simple_type_list:
422798Speter 	simple_type
423798Speter 		= $$ = newlist($1);
424798Speter 		|
425798Speter 	simple_type_list ',' simple_type
426798Speter 		= $$ = addlist($1, $3);
427798Speter 		;
428798Speter 
429798Speter /*
430798Speter  * RECORD TYPE
431798Speter  */
432798Speter field_list:
433798Speter 	fixed_part variant_part
434798Speter 		= $$ = tree4(T_FLDLST, lineof(NIL), fixlist($1), $2);
435798Speter 		;
436798Speter fixed_part:
437798Speter 	field
438798Speter 		= $$ = newlist($1);
439798Speter 		|
440798Speter 	fixed_part ';' field
441798Speter 		= $$ = addlist($1, $3);
442798Speter 		|
443798Speter 	fixed_part error
444798Speter 		= yyPerror("Malformed record declaration", PDECL);
445798Speter 		;
446798Speter field:
447798Speter 	/* lambda */
448798Speter 		= $$ = NIL;
449798Speter 		|
450798Speter 	id_list ':' type
451798Speter 		= $$ = tree4(T_RFIELD, lineof($2), fixlist($1), $3);
452798Speter 		;
453798Speter 
454798Speter variant_part:
455798Speter 	/* lambda */
456798Speter 		= $$ = NIL;
457798Speter 		|
458798Speter 	YCASE type_id YOF variant_list
459798Speter 		= $$ = tree5(T_TYVARPT, lineof($1), NIL, $2, fixlist($4));
460798Speter 		|
461798Speter 	YCASE YID ':' type_id YOF variant_list
462798Speter 		= $$ = tree5(T_TYVARPT, lineof($1), $2, $4, fixlist($6));
463798Speter 		;
464798Speter variant_list:
465798Speter 	variant
466798Speter 		= $$ = newlist($1);
467798Speter 		|
468798Speter 	variant_list ';' variant
469798Speter 		= $$ = addlist($1, $3);
470798Speter 		|
471798Speter 	variant_list error
472798Speter 		= yyPerror("Malformed record declaration", PDECL);
473798Speter 		;
474798Speter variant:
475798Speter 	/* lambda */
476798Speter 		= $$ = NIL;
477798Speter 		|
478798Speter 	const_list ':' '(' field_list ')'
479798Speter 		= $$ = tree4(T_TYVARNT, lineof($2), fixlist($1), $4);
480798Speter 		;
481798Speter 
482798Speter /*
483798Speter  * STATEMENT LIST
484798Speter  */
485798Speter 
486798Speter stat_list:
487798Speter 	stat
488798Speter 		= $$ = newlist($1);
489798Speter 		|
490798Speter 	stat_lsth stat
491798Speter 		= {
492798Speter 			if ((p = $1) != NIL && (q = p[1])[0] == T_IFX) {
493798Speter 				q[0] = T_IFEL;
494798Speter 				q[4] = $2;
495798Speter 			} else
496798Speter 				$$ = addlist($1, $2);
497798Speter 		  }
498798Speter 		;
499798Speter 
500798Speter stat_lsth:
501798Speter 	stat_list ';'
502798Speter 		= if ((q = $1) != NIL && (p = q[1]) != NIL && p[0] == T_IF) {
503798Speter 			if (yychar < 0)
504798Speter 				yychar = yylex();
505798Speter 			if (yyshifts >= 2 && yychar == YELSE) {
506798Speter 				recovered();
507798Speter 				copy(&Y, &OY, sizeof Y);
508798Speter 				yerror("Deleted ';' before keyword else");
509798Speter 				yychar = yylex();
510798Speter 				p[0] = T_IFX;
511798Speter 			}
512798Speter 		  }
513798Speter 		;
514798Speter 
515798Speter /*
516798Speter  * CASE STATEMENT LIST
517798Speter  */
518798Speter 
519798Speter cstat_list:
520798Speter 	cstat
521798Speter 		= $$ = newlist($1);
522798Speter 		|
523798Speter 	cstat_list ';' cstat
524798Speter 		= $$ = addlist($1, $3);
525798Speter 		|
526798Speter 	error
527798Speter 		= {
528798Speter 			$$ = NIL;
529798Speter Kerror:
530798Speter 			yyPerror("Malformed statement in case", PSTAT);
531798Speter 		  }
532798Speter 		|
533798Speter 	cstat_list error
534798Speter 		= goto Kerror;
535798Speter 		;
536798Speter 
537798Speter cstat:
538798Speter 	const_list ':' stat
539798Speter 		= $$ = tree4(T_CSTAT, lineof($2), fixlist($1), $3);
540798Speter 		|
541798Speter 	YCASELAB stat
542798Speter 		= $$ = tree4(T_CSTAT, lineof($1), NIL, $2);
543798Speter 		|
544798Speter 	/* lambda */
545798Speter 		= $$ = NIL;
546798Speter 		;
547798Speter 
548798Speter /*
549798Speter  * STATEMENT
550798Speter  */
551798Speter 
552798Speter stat:
553798Speter 	/* lambda */
554798Speter 		= $$ = NIL;
555798Speter 		|
556798Speter 	YINT ':' stat
557798Speter 		= $$ = tree4(T_LABEL, lineof($2), $1 == NIL ? NIL : *hash($1, 1), $3);
558798Speter 		|
559798Speter 	proc_id
560798Speter 		= $$ = tree4(T_PCALL, lineof(yyline), $1, NIL);
561798Speter 		|
562798Speter 	proc_id '(' wexpr_list ')'
563798Speter 		= $$ = tree4(T_PCALL, lineof($2), $1, fixlist($3));
564798Speter 		|
565798Speter 	YID error
566798Speter 		= goto NSerror;
567798Speter 		|
568798Speter 	assign
569798Speter 		|
570798Speter 	YBEGIN stat_list YEND
571798Speter 		= {
572798Speter 			$$ = tree3(T_BLOCK, lineof($1), fixlist($2));
573798Speter 			if ($3 < 0)
574798Speter 				brerror($1, "begin");
575798Speter 		  }
576798Speter 		|
577798Speter 	YCASE expr YOF cstat_list YEND
578798Speter 		= {
579798Speter 			$$ = tree4(T_CASE, lineof($1), $2, fixlist($4));
580798Speter 			if ($5 < 0)
581798Speter 				brerror($1, "case");
582798Speter 		  }
583798Speter 		|
584798Speter 	YWITH var_list YDO stat
585798Speter 		= $$ = tree4(T_WITH, lineof($1), fixlist($2), $4);
586798Speter 		|
587798Speter 	YWHILE expr YDO stat
588798Speter 		= $$ = tree4(T_WHILE, lineof($1), $2, $4);
589798Speter 		|
590798Speter 	YREPEAT stat_list YUNTIL expr
591798Speter 		= $$ = tree4(T_REPEAT, lineof($3), fixlist($2), $4);
592798Speter 		|
593798Speter 	YFOR assign YTO expr YDO stat
594798Speter 		= $$ = tree5(T_FORU, lineof($1), $2, $4, $6);
595798Speter 		|
596798Speter 	YFOR assign YDOWNTO expr YDO stat
597798Speter 		= $$ = tree5(T_FORD, lineof($1), $2, $4, $6);
598798Speter 		|
599798Speter 	YGOTO YINT
600798Speter 		= $$ = tree3(T_GOTO, lineof($1), *hash($2, 1));
601798Speter 		|
602798Speter 	YIF expr YTHEN stat
603798Speter 		= $$ = tree5(T_IF, lineof($1), $2, $4, NIL);
604798Speter 		|
605798Speter 	YIF expr YTHEN stat YELSE stat
606798Speter 		= $$ = tree5(T_IFEL, lineof($1), $2, $4, $6);
607798Speter 		|
608798Speter 	error
609798Speter 		= {
610798Speter NSerror:
611798Speter 			$$ = NIL;
612798Speter Serror:
613798Speter 			yyPerror("Malformed statement", PSTAT);
614798Speter 		  }
615798Speter 		;
616798Speter assign:
617798Speter 	variable ':' '=' expr
618798Speter 		= $$ = tree4(T_ASGN, lineof($2), $1, $4);
619798Speter 		;
620798Speter 
621798Speter /*
622798Speter  * EXPRESSION
623798Speter  */
624798Speter 
625798Speter expr:
626798Speter 	error
627798Speter 		= {
628798Speter NEerror:
629798Speter 			$$ = NIL;
630798Speter Eerror:
631798Speter 			yyPerror("Missing/malformed expression", PEXPR);
632798Speter 		  }
633798Speter 		|
634798Speter 	expr relop expr			%prec '<'
635798Speter 		= $$ = tree4($2, $1[1] == SAWCON ? $3[1] : $1[1], $1, $3);
636798Speter 		|
637798Speter 	'+' expr			%prec UNARYSIGN
638798Speter 		= $$ = tree3(T_PLUS, $2[1], $2);
639798Speter 		|
640798Speter 	'-' expr			%prec UNARYSIGN
641798Speter 		= $$ = tree3(T_MINUS, $2[1], $2);
642798Speter 		|
643798Speter 	expr addop expr			%prec '+'
644798Speter 		= $$ = tree4($2, $1[1] == SAWCON ? $3[1] : $1[1], $1, $3);
645798Speter 		|
646798Speter 	expr divop expr			%prec '*'
647798Speter 		= $$ = tree4($2, $1[1] == SAWCON ? $3[1] : $1[1], $1, $3);
648798Speter 		|
649798Speter 	YNIL
650798Speter 		= $$ = tree2(T_NIL, NOCON);
651798Speter 		|
652798Speter 	YSTRING
653798Speter 		= $$ = tree3(T_STRNG, SAWCON, $1);
654798Speter 		|
655798Speter 	YINT
656798Speter 		= $$ = tree3(T_INT, NOCON, $1);
657798Speter 		|
658798Speter 	YBINT
659798Speter 		= $$ = tree3(T_BINT, NOCON, $1);
660798Speter 		|
661798Speter 	YNUMB
662798Speter 		= $$ = tree3(T_FINT, NOCON, $1);
663798Speter 		|
664798Speter 	variable
665798Speter 		|
666798Speter 	YID error
667798Speter 		= goto NEerror;
668798Speter 		|
669798Speter 	func_id '(' wexpr_list ')'
670798Speter 		= $$ = tree4(T_FCALL, NOCON, $1, fixlist($3));
671798Speter 		|
672798Speter 	'(' expr ')'
673798Speter 		= $$ = $2;
674798Speter 		|
675798Speter 	negop expr			%prec YNOT
676798Speter 		= $$ = tree3(T_NOT, NOCON, $2);
677798Speter 		|
678798Speter 	'[' element_list ']'
679798Speter 		= $$ = tree3(T_CSET, SAWCON, fixlist($2));
680798Speter 		|
681798Speter 	'[' ']'
682798Speter 		= $$ = tree3(T_CSET, SAWCON, NIL);
683798Speter 		;
684798Speter 
685798Speter element_list:
686798Speter 	element
687798Speter 		= $$ = newlist($1);
688798Speter 		|
689798Speter 	element_list ',' element
690798Speter 		= $$ = addlist($1, $3);
691798Speter 		;
692798Speter element:
693798Speter 	expr
694798Speter 		|
695798Speter 	expr YDOTDOT expr
696798Speter 		= $$ = tree3(T_RANG, $1, $3);
697798Speter 		;
698798Speter 
699798Speter /*
700798Speter  * QUALIFIED VARIABLES
701798Speter  */
702798Speter 
703798Speter variable:
704798Speter 	YID
705798Speter 		= {
706804Speter 			@@ return (identis(var, VAR));
707798Speter 			$$ = setupvar($1, NIL);
708798Speter 		  }
709798Speter 		|
710798Speter 	qual_var
711798Speter 		= $1[3] = fixlist($1[3]);
712798Speter 		;
713798Speter qual_var:
714798Speter 	array_id '[' expr_list ']'
715798Speter 		= $$ = setupvar($1, tree2(T_ARY, fixlist($3)));
716798Speter 		|
717798Speter 	qual_var '[' expr_list ']'
718798Speter 		= $1[3] = addlist($1[3], tree2(T_ARY, fixlist($3)));
719798Speter 		|
720798Speter 	record_id '.' field_id
721798Speter 		= $$ = setupvar($1, setupfield($3, NIL));
722798Speter 		|
723798Speter 	qual_var '.' field_id
724798Speter 		= $1[3] = addlist($1[3], setupfield($3, NIL));
725798Speter 		|
726798Speter 	ptr_id '^'
727798Speter 		= $$ = setupvar($1, tree1(T_PTR));
728798Speter 		|
729798Speter 	qual_var '^'
730798Speter 		= $1[3] = addlist($1[3], tree1(T_PTR));
731798Speter 		;
732798Speter 
733798Speter /*
734798Speter  * Expression with write widths
735798Speter  */
736798Speter wexpr:
737798Speter 	expr
738798Speter 		|
739798Speter 	expr ':' expr
740798Speter 		= $$ = tree4(T_WEXP, $1, $3, NIL);
741798Speter 		|
742798Speter 	expr ':' expr ':' expr
743798Speter 		= $$ = tree4(T_WEXP, $1, $3, $5);
744798Speter 		|
745798Speter 	expr octhex
746798Speter 		= $$ = tree4(T_WEXP, $1, NIL, $2);
747798Speter 		|
748798Speter 	expr ':' expr octhex
749798Speter 		= $$ = tree4(T_WEXP, $1, $3, $4);
750798Speter 		;
751798Speter octhex:
752798Speter 	YOCT
753798Speter 		= $$ = OCT;
754798Speter 		|
755798Speter 	YHEX
756798Speter 		= $$ = HEX;
757798Speter 		;
758798Speter 
759798Speter expr_list:
760798Speter 	expr
761798Speter 		= $$ = newlist($1);
762798Speter 		|
763798Speter 	expr_list ',' expr
764798Speter 		= $$ = addlist($1, $3);
765798Speter 		;
766798Speter 
767798Speter wexpr_list:
768798Speter 	wexpr
769798Speter 		= $$ = newlist($1);
770798Speter 		|
771798Speter 	wexpr_list ',' wexpr
772798Speter 		= $$ = addlist($1, $3);
773798Speter 		;
774798Speter 
775798Speter /*
776798Speter  * OPERATORS
777798Speter  */
778798Speter 
779798Speter relop:
780798Speter 	'='	= $$ = T_EQ;
781798Speter 		|
782798Speter 	'<'	= $$ = T_LT;
783798Speter 		|
784798Speter 	'>'	= $$ = T_GT;
785798Speter 		|
786798Speter 	'<' '>'	= $$ = T_NE;
787798Speter 		|
788798Speter 	'<' '='	= $$ = T_LE;
789798Speter 		|
790798Speter 	'>' '='	= $$ = T_GE;
791798Speter 		|
792798Speter 	YIN	= $$ = T_IN;
793798Speter 		;
794798Speter addop:
795798Speter 	'+'	= $$ = T_ADD;
796798Speter 		|
797798Speter 	'-'	= $$ = T_SUB;
798798Speter 		|
799798Speter 	YOR	= $$ = T_OR;
800798Speter 		|
801798Speter 	'|'	= $$ = T_OR;
802798Speter 		;
803798Speter divop:
804798Speter 	'*'	= $$ = T_MULT;
805798Speter 		|
806798Speter 	'/'	= $$ = T_DIVD;
807798Speter 		|
808798Speter 	YDIV	= $$ = T_DIV;
809798Speter 		|
810798Speter 	YMOD	= $$ = T_MOD;
811798Speter 		|
812798Speter 	YAND	= $$ = T_AND;
813798Speter 		|
814798Speter 	'&'	= $$ = T_AND;
815798Speter 		;
816798Speter 
817798Speter negop:
818798Speter 	YNOT
819798Speter 		|
820798Speter 	'~'
821798Speter 		;
822798Speter 
823798Speter /*
824798Speter  * LISTS
825798Speter  */
826798Speter 
827798Speter var_list:
828798Speter 	variable
829798Speter 		= $$ = newlist($1);
830798Speter 		|
831798Speter 	var_list ',' variable
832798Speter 		= $$ = addlist($1, $3);
833798Speter 		;
834798Speter 
835798Speter id_list:
836798Speter 	YID
837798Speter 		= $$ = newlist($1);
838798Speter 		|
839798Speter 	id_list ',' YID
840798Speter 		= $$ = addlist($1, $3);
841798Speter 		;
842798Speter 
843798Speter /*
844798Speter  * Identifier productions with semantic restrictions
845798Speter  *
846804Speter  * For these productions, the characters @@ signify
847798Speter  * that the associated C statement is to provide
848798Speter  * the semantic restriction for this reduction.
849798Speter  * These lines are made into a procedure yyEactr, similar to
850798Speter  * yyactr, which determines whether the corresponding reduction
851798Speter  * is permitted, or whether an error is to be signaled.
852798Speter  * A zero return from yyEactr is considered an error.
853798Speter  * YyEactr is called with an argument "var" giving the string
854798Speter  * name of the variable in question, essentially $1, although
855798Speter  * $1 will not work because yyEactr is called from loccor in
856798Speter  * the recovery routines.
857798Speter  */
858798Speter 
859798Speter const_id:
860798Speter 	YID
861804Speter 		= @@ return (identis(var, CONST));
862798Speter 		;
863798Speter type_id:
864798Speter 	YID
865798Speter 		= {
866804Speter 			@@ return (identis(var, TYPE));
867798Speter 			$$ = tree3(T_TYID, lineof(yyline), $1);
868798Speter 		  }
869798Speter 		;
870798Speter var_id:
871798Speter 	YID
872804Speter 		= @@ return (identis(var, VAR));
873798Speter 		;
874798Speter array_id:
875798Speter 	YID
876804Speter 		= @@ return (identis(var, ARRAY));
877798Speter 		;
878798Speter ptr_id:
879798Speter 	YID
880804Speter 		= @@ return (identis(var, PTRFILE));
881798Speter 		;
882798Speter record_id:
883798Speter 	YID
884804Speter 		= @@ return (identis(var, RECORD));
885798Speter 		;
886798Speter field_id:
887798Speter 	YID
888804Speter 		= @@ return (identis(var, FIELD));
889798Speter 		;
890798Speter proc_id:
891798Speter 	YID
892804Speter 		= @@ return (identis(var, PROC));
893798Speter 		;
894798Speter func_id:
895798Speter 	YID
896804Speter 		= @@ return (identis(var, FUNC));
897798Speter 		;
898