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