xref: /csrg-svn/usr.bin/pascal/src/pas.y (revision 15928)
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 1.12 02/04/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 1.12 02/04/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 ':' type
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 param_list:
344 	param
345 		= $$.tr_entry = newlist($1.tr_entry);
346 		|
347 	param_list ';' param
348 		= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
349 		;
350 
351 /*
352  * CONSTANTS
353  */
354 
355 const:
356 	YSTRING
357 		= $$.tr_entry = tree2(T_CSTRNG, $1.i_entry);
358 		|
359 	number
360 		|
361 	'+' number
362 		= $$.tr_entry = tree2(T_PLUSC, $2.i_entry);
363 		|
364 	'-' number
365 		= $$.tr_entry = tree2(T_MINUSC, $2.i_entry);
366 		;
367 number:
368 	const_id
369 		= $$.tr_entry = tree2(T_ID, $1.i_entry);
370 		|
371 	YINT
372 		= $$.tr_entry = tree2(T_CINT, $1.i_entry);
373 		|
374 	YBINT
375 		= $$.tr_entry = tree2(T_CBINT, $1.i_entry);
376 		|
377 	YNUMB
378 		= $$.tr_entry = tree2(T_CFINT, $1.i_entry);
379 		;
380 const_list:
381 	const
382 		= $$.tr_entry = newlist($1.tr_entry);
383 		|
384 	const_list ',' const
385 		= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
386 		;
387 
388 /*
389  * TYPES
390  */
391 
392 type:
393 	simple_type
394 		|
395 	'^' YID
396 		= $$.tr_entry = tree3(T_TYPTR, lineof($1.i_entry), tree2(T_ID,
397 								$2.i_entry));
398 		|
399 	struct_type
400 		|
401 	YPACKED struct_type
402 		= $$.tr_entry = tree3(T_TYPACK, lineof($1.i_entry), $2.tr_entry);
403 		;
404 simple_type:
405 	type_id
406 		|
407 	'(' id_list ')'
408 		= $$.tr_entry = tree3(T_TYSCAL, lineof($1.i_entry), fixlist($2.tr_entry));
409 		|
410 	const YDOTDOT const
411 		= $$.tr_entry = tree4(T_TYRANG, lineof($2.i_entry), $1.tr_entry,
412 				$3.tr_entry);
413 		;
414 struct_type:
415 	YARRAY '[' simple_type_list ']' YOF type
416 		= $$.tr_entry = tree4(T_TYARY, lineof($1.i_entry),
417 					fixlist($3.tr_entry), $6.tr_entry);
418 		|
419 	YFILE YOF type
420 		= $$.tr_entry = tree3(T_TYFILE, lineof($1.i_entry), $3.tr_entry);
421 		|
422 	YSET YOF simple_type
423 		= $$.tr_entry = tree3(T_TYSET, lineof($1.i_entry), $3.tr_entry);
424 		|
425 	YRECORD field_list YEND
426 		= {
427 			$$.tr_entry = setuptyrec( lineof( $1.i_entry ) , $2.tr_entry);
428 			if ($3.i_entry < 0)
429 				brerror($1.i_entry, "record");
430 		  }
431 		;
432 simple_type_list:
433 	simple_type
434 		= $$.tr_entry = newlist($1.tr_entry);
435 		|
436 	simple_type_list ',' simple_type
437 		= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
438 		;
439 
440 /*
441  * RECORD TYPE
442  */
443 field_list:
444 	fixed_part variant_part
445 		= $$.tr_entry = tree4(T_FLDLST, lineof(NIL),
446 				fixlist($1.tr_entry), $2.tr_entry);
447 		;
448 fixed_part:
449 	field
450 		= $$.tr_entry = newlist($1.tr_entry);
451 		|
452 	fixed_part ';' field
453 		= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
454 		|
455 	fixed_part error
456 		= yyPerror("Malformed record declaration", PDECL);
457 		;
458 field:
459 	/* lambda */
460 		= $$.tr_entry = TR_NIL;
461 		|
462 	id_list ':' type
463 		= $$.tr_entry = tree4(T_RFIELD, lineof($2.i_entry),
464 				fixlist($1.tr_entry), $3.tr_entry);
465 		;
466 
467 variant_part:
468 	/* lambda */
469 		= $$.tr_entry = TR_NIL;
470 		|
471 	YCASE type_id YOF variant_list
472 		= $$.tr_entry = tree5(T_TYVARPT, lineof($1.i_entry), TR_NIL,
473 				$2.tr_entry, fixlist($4.tr_entry));
474 		|
475 	YCASE YID ':' type_id YOF variant_list
476 		= $$.tr_entry = tree5(T_TYVARPT, lineof($1.i_entry),
477 				$2.tr_entry, $4.tr_entry,
478 					fixlist($6.tr_entry));
479 		;
480 variant_list:
481 	variant
482 		= $$.tr_entry = newlist($1.tr_entry);
483 		|
484 	variant_list ';' variant
485 		= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
486 		|
487 	variant_list error
488 		= yyPerror("Malformed record declaration", PDECL);
489 		;
490 variant:
491 	/* lambda */
492 		= $$.tr_entry = TR_NIL;
493 		|
494 	const_list ':' '(' field_list ')'
495 		= $$.tr_entry = tree4(T_TYVARNT,lineof($2.i_entry), fixlist($1.tr_entry),
496 				$4.tr_entry);
497 		;
498 
499 /*
500  * STATEMENT LIST
501  */
502 
503 stat_list:
504 	stat
505 		= $$.tr_entry = newlist($1.tr_entry);
506 		|
507 	stat_lsth stat
508 		= {
509 			if ((p = $1.tr_entry) != TR_NIL && (q = p->list_node.list)->tag == T_IFX) {
510 				q->tag = T_IFEL;
511 				q->if_node.else_stmnt = $2.tr_entry;
512 			} else
513 				$$.tr_entry= addlist($1.tr_entry, $2.tr_entry);
514 		  }
515 		;
516 
517 stat_lsth:
518 	stat_list ';'
519 		= if ((q = $1.tr_entry) != TR_NIL && (p = q->list_node.list) != TR_NIL && p->tag == T_IF) {
520 			if (yychar < 0)
521 				yychar = yylex();
522 			if (yyshifts >= 2 && yychar == YELSE) {
523 				recovered();
524 				copy((char *) (&Y), (char *) (&OY), sizeof Y);
525 				yerror("Deleted ';' before keyword else");
526 				yychar = yylex();
527 				p->tag = T_IFX;
528 			}
529 		  }
530 		;
531 
532 /*
533  * CASE STATEMENT LIST
534  */
535 
536 cstat_list:
537 	cstat
538 		= $$.tr_entry = newlist($1.tr_entry);
539 		|
540 	cstat_list ';' cstat
541 		= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
542 		|
543 	error
544 		= {
545 			$$.tr_entry = TR_NIL;
546 Kerror:
547 			yyPerror("Malformed statement in case", PSTAT);
548 		  }
549 		|
550 	cstat_list error
551 		= goto Kerror;
552 		;
553 
554 cstat:
555 	const_list ':' stat
556 		= $$.tr_entry = tree4(T_CSTAT, lineof($2.i_entry),
557 				fixlist($1.tr_entry), $3.tr_entry);
558 		|
559 	YCASELAB stat
560 		= $$.tr_entry = tree4(T_CSTAT, lineof($1.i_entry), TR_NIL,
561 					$2.tr_entry);
562 		|
563 	/* lambda */
564 		= $$.tr_entry = TR_NIL;
565 		;
566 
567 /*
568  * STATEMENT
569  */
570 
571 stat:
572 	/* lambda */
573 		= $$.tr_entry = TR_NIL;
574 		|
575 	YINT ':' stat
576 		= $$.tr_entry = tree4(T_LABEL, lineof($2.i_entry),
577 				$1.tr_entry == TR_NIL ? TR_NIL :
578 					    (struct tnode *) *hash($1.cptr, 1), $3.tr_entry);
579 		|
580 	proc_id
581 		= $$.tr_entry = tree4(T_PCALL, lineof(yyline), $1.tr_entry,
582 						TR_NIL);
583 		|
584 	proc_id '(' wexpr_list ')'
585 		= $$.tr_entry = tree4(T_PCALL, lineof($2.i_entry), $1.tr_entry,
586 					fixlist($3.tr_entry));
587 		|
588 	YID error
589 		= goto NSerror;
590 		|
591 	assign
592 		|
593 	YBEGIN stat_list YEND
594 		= {
595 			$$.tr_entry = tree3(T_BLOCK, lineof($1.i_entry),
596 						fixlist($2.tr_entry));
597 			if ($3.i_entry < 0)
598 				brerror($1.i_entry, "begin");
599 		  }
600 		|
601 	YCASE expr YOF cstat_list YEND
602 		= {
603 			$$.tr_entry = tree4(T_CASE, lineof($1.i_entry),
604 					$2.tr_entry, fixlist($4.tr_entry));
605 			if ($5.i_entry < 0)
606 				brerror($1.i_entry, "case");
607 		  }
608 		|
609 	YWITH var_list YDO stat
610 		= $$.tr_entry = tree4(T_WITH, lineof($1.i_entry),
611 				fixlist($2.tr_entry), $4.tr_entry);
612 		|
613 	YWHILE expr YDO stat
614 		= $$.tr_entry = tree4(T_WHILE, lineof($1.i_entry), $2.tr_entry,
615 					$4.tr_entry);
616 		|
617 	YREPEAT stat_list YUNTIL expr
618 		= $$.tr_entry = tree4(T_REPEAT, lineof($3.i_entry),
619 				fixlist($2.tr_entry), $4.tr_entry);
620 		|
621 	YFOR assign YTO expr YDO stat
622 		= $$.tr_entry = tree5(T_FORU, lineof($1.i_entry), $2.tr_entry,
623 				$4.tr_entry, $6.tr_entry);
624 		|
625 	YFOR assign YDOWNTO expr YDO stat
626 		= $$.tr_entry = tree5(T_FORD, lineof($1.i_entry), $2.tr_entry,
627 				$4.tr_entry, $6.tr_entry);
628 		|
629 	YGOTO YINT
630 		= $$.tr_entry = tree3(T_GOTO, lineof($1.i_entry),
631 				(struct tnode *) *hash($2.cptr, 1));
632 		|
633 	YIF expr YTHEN stat
634 		= $$.tr_entry = tree5(T_IF, lineof($1.i_entry), $2.tr_entry,
635 				$4.tr_entry, TR_NIL);
636 		|
637 	YIF expr YTHEN stat YELSE stat
638 		= $$.tr_entry = tree5(T_IFEL, lineof($1.i_entry), $2.tr_entry,
639 					$4.tr_entry, $6.tr_entry);
640 		|
641 	error
642 		= {
643 NSerror:
644 			$$.tr_entry = TR_NIL;
645 			yyPerror("Malformed statement", PSTAT);
646 		  }
647 		;
648 assign:
649 	variable ':' '=' expr
650 		= $$.tr_entry = tree4(T_ASGN, lineof($2.i_entry), $1.tr_entry,
651 				    $4.tr_entry);
652 		;
653 
654 /*
655  * EXPRESSION
656  */
657 
658 expr:
659 	error
660 		= {
661 NEerror:
662 			$$.tr_entry = TR_NIL;
663 			yyPerror("Missing/malformed expression", PEXPR);
664 		  }
665 		|
666 	expr relop expr			%prec '<'
667 		= $$.tr_entry = tree4($2.i_entry,
668 			$1.tr_entry->expr_node.const_tag == SAWCON ?
669 			$3.tr_entry->expr_node.const_tag :
670 			$1.tr_entry->expr_node.const_tag,
671 			$1.tr_entry, $3.tr_entry);
672 		|
673 	'+' expr			%prec UNARYSIGN
674 		= $$.tr_entry = tree3(T_PLUS, $2.tr_entry->expr_node.const_tag,
675 				$2.tr_entry);
676 		|
677 	'-' expr			%prec UNARYSIGN
678 		= $$.tr_entry = tree3(T_MINUS, $2.tr_entry->expr_node.const_tag,
679 				$2.tr_entry);
680 		|
681 	expr addop expr			%prec '+'
682 		= $$.tr_entry = tree4($2.i_entry,
683 			$1.tr_entry->expr_node.const_tag == SAWCON ?
684 			$3.tr_entry->expr_node.const_tag :
685 			$1.tr_entry->expr_node.const_tag, $1.tr_entry,
686 			$3.tr_entry);
687 		|
688 	expr divop 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 	YNIL
696 		= $$.tr_entry = tree2(T_NIL, NOCON);
697 		|
698 	YSTRING
699 		= $$.tr_entry = tree3(T_STRNG, SAWCON, $1.tr_entry);
700 		|
701 	YINT
702 		= $$.tr_entry = tree3(T_INT, NOCON, $1.tr_entry);
703 		|
704 	YBINT
705 		= $$.tr_entry = tree3(T_BINT, NOCON, $1.tr_entry);
706 		|
707 	YNUMB
708 		= $$.tr_entry = tree3(T_FINT, NOCON, $1.tr_entry);
709 		|
710 	variable
711 		|
712 	YID error
713 		= goto NEerror;
714 		|
715 	func_id '(' wexpr_list ')'
716 		= $$.tr_entry = tree4(T_FCALL, NOCON, $1.tr_entry,
717 			fixlist($3.tr_entry));
718 		|
719 	'(' expr ')'
720 		= $$.tr_entry = $2.tr_entry;
721 		|
722 	negop expr			%prec YNOT
723 		= $$.tr_entry = tree3(T_NOT, NOCON, $2.tr_entry);
724 		|
725 	'[' element_list ']'
726 		= $$.tr_entry = tree3(T_CSET, SAWCON, fixlist($2.tr_entry));
727 		|
728 	'[' ']'
729 		= $$.tr_entry = tree3(T_CSET, SAWCON, TR_NIL);
730 		;
731 
732 element_list:
733 	element
734 		= $$.tr_entry = newlist($1.tr_entry);
735 		|
736 	element_list ',' element
737 		= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
738 		;
739 element:
740 	expr
741 		|
742 	expr YDOTDOT expr
743 		= $$.tr_entry = tree3(T_RANG, $1.i_entry, $3.tr_entry);
744 		;
745 
746 /*
747  * QUALIFIED VARIABLES
748  */
749 
750 variable:
751 	YID
752 		= {
753 			@@ return (identis(var, VAR));
754 			$$.tr_entry = setupvar($1.cptr, TR_NIL);
755 		  }
756 		|
757 	qual_var
758 		= $1.tr_entry->var_node.qual =
759 					fixlist($1.tr_entry->var_node.qual);
760 		;
761 qual_var:
762 	array_id '[' expr_list ']'
763 		= $$.tr_entry = setupvar($1.cptr, tree2(T_ARY,
764 				(int) fixlist($3.tr_entry)));
765 		|
766 	qual_var '[' expr_list ']'
767 		= $1.tr_entry->var_node.qual =
768 				addlist($1.tr_entry->var_node.qual,
769 				tree2(T_ARY, (int) fixlist($3.tr_entry)));
770 		|
771 	record_id '.' field_id
772 		= $$.tr_entry = setupvar($1.cptr, setupfield($3.tr_entry,
773 							TR_NIL));
774 		|
775 	qual_var '.' field_id
776 		= $1.tr_entry->var_node.qual =
777 		    addlist($1.tr_entry->var_node.qual,
778 		    setupfield($3.tr_entry, TR_NIL));
779 		|
780 	ptr_id '^'
781 		= $$.tr_entry = setupvar($1.cptr, tree1(T_PTR));
782 		|
783 	qual_var '^'
784 		= $1.tr_entry->var_node.qual =
785 			addlist($1.tr_entry->var_node.qual, tree1(T_PTR));
786 		;
787 
788 /*
789  * Expression with write widths
790  */
791 wexpr:
792 	expr
793 		|
794 	expr ':' expr
795 		= $$.tr_entry = tree4(T_WEXP, $1.i_entry, $3.tr_entry, TR_NIL);
796 		|
797 	expr ':' expr ':' expr
798 		= $$.tr_entry = tree4(T_WEXP, $1.i_entry, $3.tr_entry,
799 						$5.tr_entry);
800 		|
801 	expr octhex
802 		= $$.tr_entry = tree4(T_WEXP, $1.i_entry, TR_NIL, $2.tr_entry);
803 		|
804 	expr ':' expr octhex
805 		= $$.tr_entry = tree4(T_WEXP, $1.i_entry, $3.tr_entry,
806 					$4.tr_entry);
807 		;
808 octhex:
809 	YOCT
810 		= $$.i_entry = OCT;
811 		|
812 	YHEX
813 		= $$.i_entry = HEX;
814 		;
815 
816 expr_list:
817 	expr
818 		= $$.tr_entry = newlist($1.tr_entry);
819 		|
820 	expr_list ',' expr
821 		= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
822 		;
823 
824 wexpr_list:
825 	wexpr
826 		= $$.tr_entry = newlist($1.tr_entry);
827 		|
828 	wexpr_list ',' wexpr
829 		= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
830 		;
831 
832 /*
833  * OPERATORS
834  */
835 
836 relop:
837 	'='	= $$.i_entry = T_EQ;
838 		|
839 	'<'	= $$.i_entry = T_LT;
840 		|
841 	'>'	= $$.i_entry = T_GT;
842 		|
843 	'<' '>'	= $$.i_entry = T_NE;
844 		|
845 	'<' '='	= $$.i_entry = T_LE;
846 		|
847 	'>' '='	= $$.i_entry = T_GE;
848 		|
849 	YIN	= $$.i_entry = T_IN;
850 		;
851 addop:
852 	'+'	= $$.i_entry = T_ADD;
853 		|
854 	'-'	= $$.i_entry = T_SUB;
855 		|
856 	YOR	= $$.i_entry = T_OR;
857 		|
858 	'|'	= $$.i_entry = T_OR;
859 		;
860 divop:
861 	'*'	= $$.i_entry = T_MULT;
862 		|
863 	'/'	= $$.i_entry = T_DIVD;
864 		|
865 	YDIV	= $$.i_entry = T_DIV;
866 		|
867 	YMOD	= $$.i_entry = T_MOD;
868 		|
869 	YAND	= $$.i_entry = T_AND;
870 		|
871 	'&'	= $$.i_entry = T_AND;
872 		;
873 
874 negop:
875 	YNOT
876 		|
877 	'~'
878 		;
879 
880 /*
881  * LISTS
882  */
883 
884 var_list:
885 	variable
886 		= $$.tr_entry = newlist($1.tr_entry);
887 		|
888 	var_list ',' variable
889 		= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
890 		;
891 
892 id_list:
893 	YID
894 		= $$.tr_entry = newlist($1.tr_entry);
895 		|
896 	id_list ',' YID
897 		= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
898 		;
899 
900 /*
901  * Identifier productions with semantic restrictions
902  *
903  * For these productions, the characters @@ signify
904  * that the associated C statement is to provide
905  * the semantic restriction for this reduction.
906  * These lines are made into a procedure yyEactr, similar to
907  * yyactr, which determines whether the corresponding reduction
908  * is permitted, or whether an error is to be signaled.
909  * A zero return from yyEactr is considered an error.
910  * YyEactr is called with an argument "var" giving the string
911  * name of the variable in question, essentially $1, although
912  * $1 will not work because yyEactr is called from loccor in
913  * the recovery routines.
914  */
915 
916 const_id:
917 	YID
918 		= @@ return (identis(var, CONST));
919 		;
920 type_id:
921 	YID
922 		= {
923 			@@ return (identis(var, TYPE));
924 			$$.tr_entry = tree3(T_TYID, lineof(yyline), $1.tr_entry);
925 		  }
926 		;
927 var_id:
928 	YID
929 		= @@ return (identis(var, VAR));
930 		;
931 array_id:
932 	YID
933 		= @@ return (identis(var, ARRAY));
934 		;
935 ptr_id:
936 	YID
937 		= @@ return (identis(var, PTRFILE));
938 		;
939 record_id:
940 	YID
941 		= @@ return (identis(var, RECORD));
942 		;
943 field_id:
944 	YID
945 		= @@ return (identis(var, FIELD));
946 		;
947 proc_id:
948 	YID
949 		= @@ return (identis(var, PROC));
950 		;
951 func_id:
952 	YID
953 		= @@ return (identis(var, FUNC));
954 		;
955