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