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