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