xref: /plan9-contrib/sys/src/cmd/cc/cc.y (revision 57cfc11b7a49e970955da9d0087883424be80acb)
1 %{
2 #include "cc.h"
3 %}
4 %union	{
5 	Node*	node;
6 	Sym*	sym;
7 	Type*	type;
8 	struct
9 	{
10 		Type*	t;
11 		uchar	c;
12 	} tycl;
13 	struct
14 	{
15 		Type*	t1;
16 		Type*	t2;
17 		Type*	t3;
18 		uchar	c;
19 	} tyty;
20 	struct
21 	{
22 		char*	s;
23 		long	l;
24 	} sval;
25 	long	lval;
26 	double	dval;
27 	vlong	vval;
28 }
29 %type	<sym>	ltag
30 %type	<lval>	gctname gcname cname gname tname
31 %type	<lval>	gctnlist gcnlist zgnlist
32 %type	<type>	tlist sbody complex
33 %type	<tycl>	types
34 %type	<node>	zarglist arglist zcexpr
35 %type	<node>	name block stmnt cexpr expr xuexpr pexpr
36 %type	<node>	zelist elist adecl slist uexpr string lstring
37 %type	<node>	xdecor xdecor2 labels label ulstmnt
38 %type	<node>	adlist edecor tag qual qlist
39 %type	<node>	abdecor abdecor1 abdecor2 abdecor3
40 %type	<node>	zexpr lexpr init ilist forexpr
41 
42 %left	';'
43 %left	','
44 %right	'=' LPE LME LMLE LDVE LMDE LRSHE LLSHE LANDE LXORE LORE
45 %right	'?' ':'
46 %left	LOROR
47 %left	LANDAND
48 %left	'|'
49 %left	'^'
50 %left	'&'
51 %left	LEQ LNE
52 %left	'<' '>' LLE LGE
53 %left	LLSH LRSH
54 %left	'+' '-'
55 %left	'*' '/' '%'
56 %right	LMM LPP LMG '.' '[' '('
57 
58 %token	<sym>	LNAME LTYPE
59 %token	<dval>	LFCONST LDCONST
60 %token	<vval>	LCONST LLCONST LUCONST LULCONST LVLCONST LUVLCONST
61 %token	<sval>	LSTRING LLSTRING
62 %token		LAUTO LBREAK LCASE LCHAR LCONTINUE LDEFAULT LDO
63 %token		LDOUBLE LELSE LEXTERN LFLOAT LFOR LGOTO
64 %token	LIF LINT LLONG LREGISTER LRETURN LSHORT LSIZEOF LUSED
65 %token	LSTATIC LSTRUCT LSWITCH LTYPEDEF LTYPESTR LUNION LUNSIGNED
66 %token	LWHILE LVOID LENUM LSIGNED LCONSTNT LVOLATILE LSET LSIGNOF
67 %token	LRESTRICT LINLINE
68 %%
69 prog:
70 |	prog xdecl
71 
72 /*
73  * external declarator
74  */
75 xdecl:
76 	zctlist ';'
77 	{
78 		dodecl(xdecl, lastclass, lasttype, Z);
79 	}
80 |	zctlist xdlist ';'
81 |	zctlist xdecor
82 	{
83 		lastdcl = T;
84 		firstarg = S;
85 		dodecl(xdecl, lastclass, lasttype, $2);
86 		if(lastdcl == T || lastdcl->etype != TFUNC) {
87 			diag($2, "not a function");
88 			lastdcl = types[TFUNC];
89 		}
90 		thisfn = lastdcl;
91 		markdcl();
92 		firstdcl = dclstack;
93 		argmark($2, 0);
94 	}
95 	pdecl
96 	{
97 		argmark($2, 1);
98 	}
99 	block
100 	{
101 		Node *n;
102 
103 		n = revertdcl();
104 		if(n)
105 			$6 = new(OLIST, n, $6);
106 		if(!debug['a'] && !debug['Z'])
107 			codgen($6, $2);
108 	}
109 
110 xdlist:
111 	xdecor
112 	{
113 		dodecl(xdecl, lastclass, lasttype, $1);
114 	}
115 |	xdecor
116 	{
117 		$1 = dodecl(xdecl, lastclass, lasttype, $1);
118 	}
119 	'=' init
120 	{
121 		doinit($1->sym, $1->type, 0L, $4);
122 	}
123 |	xdlist ',' xdlist
124 
125 xdecor:
126 	xdecor2
127 |	'*' zgnlist xdecor
128 	{
129 		$$ = new(OIND, $3, Z);
130 		$$->garb = simpleg($2);
131 	}
132 
133 xdecor2:
134 	tag
135 |	'(' xdecor ')'
136 	{
137 		$$ = $2;
138 	}
139 |	xdecor2 '(' zarglist ')'
140 	{
141 		$$ = new(OFUNC, $1, $3);
142 	}
143 |	xdecor2 '[' zexpr ']'
144 	{
145 		$$ = new(OARRAY, $1, $3);
146 	}
147 
148 /*
149  * automatic declarator
150  */
151 adecl:
152 	ctlist ';'
153 	{
154 		$$ = dodecl(adecl, lastclass, lasttype, Z);
155 	}
156 |	ctlist adlist ';'
157 	{
158 		$$ = $2;
159 	}
160 
161 adlist:
162 	xdecor
163 	{
164 		dodecl(adecl, lastclass, lasttype, $1);
165 		$$ = Z;
166 	}
167 |	xdecor
168 	{
169 		$1 = dodecl(adecl, lastclass, lasttype, $1);
170 	}
171 	'=' init
172 	{
173 		long w;
174 
175 		w = $1->sym->type->width;
176 		$$ = doinit($1->sym, $1->type, 0L, $4);
177 		$$ = contig($1->sym, $$, w);
178 	}
179 |	adlist ',' adlist
180 	{
181 		$$ = $1;
182 		if($3 != Z) {
183 			$$ = $3;
184 			if($1 != Z)
185 				$$ = new(OLIST, $1, $3);
186 		}
187 	}
188 
189 /*
190  * parameter declarator
191  */
192 pdecl:
193 |	pdecl ctlist pdlist ';'
194 
195 pdlist:
196 	xdecor
197 	{
198 		dodecl(pdecl, lastclass, lasttype, $1);
199 	}
200 |	pdlist ',' pdlist
201 
202 /*
203  * structure element declarator
204  */
205 edecl:
206 	tlist
207 	{
208 		lasttype = $1;
209 	}
210 	zedlist ';'
211 |	edecl tlist
212 	{
213 		lasttype = $2;
214 	}
215 	zedlist ';'
216 
217 zedlist:					/* extension */
218 	{
219 		lastfield = 0;
220 		edecl(CXXX, lasttype, S);
221 	}
222 |	edlist
223 
224 edlist:
225 	edecor
226 	{
227 		dodecl(edecl, CXXX, lasttype, $1);
228 	}
229 |	edlist ',' edlist
230 
231 edecor:
232 	xdecor
233 	{
234 		lastbit = 0;
235 		firstbit = 1;
236 	}
237 |	tag ':' lexpr
238 	{
239 		$$ = new(OBIT, $1, $3);
240 	}
241 |	':' lexpr
242 	{
243 		$$ = new(OBIT, Z, $2);
244 	}
245 
246 /*
247  * abstract declarator
248  */
249 abdecor:
250 	{
251 		$$ = (Z);
252 	}
253 |	abdecor1
254 
255 abdecor1:
256 	'*' zgnlist
257 	{
258 		$$ = new(OIND, (Z), Z);
259 		$$->garb = simpleg($2);
260 	}
261 |	'*' zgnlist abdecor1
262 	{
263 		$$ = new(OIND, $3, Z);
264 		$$->garb = simpleg($2);
265 	}
266 |	abdecor2
267 
268 abdecor2:
269 	abdecor3
270 |	abdecor2 '(' zarglist ')'
271 	{
272 		$$ = new(OFUNC, $1, $3);
273 	}
274 |	abdecor2 '[' zexpr ']'
275 	{
276 		$$ = new(OARRAY, $1, $3);
277 	}
278 
279 abdecor3:
280 	'(' ')'
281 	{
282 		$$ = new(OFUNC, (Z), Z);
283 	}
284 |	'[' zexpr ']'
285 	{
286 		$$ = new(OARRAY, (Z), $2);
287 	}
288 |	'(' abdecor1 ')'
289 	{
290 		$$ = $2;
291 	}
292 
293 init:
294 	expr
295 |	'{' ilist '}'
296 	{
297 		$$ = new(OINIT, invert($2), Z);
298 	}
299 
300 qual:
301 	'[' lexpr ']'
302 	{
303 		$$ = new(OARRAY, $2, Z);
304 	}
305 |	'.' ltag
306 	{
307 		$$ = new(OELEM, Z, Z);
308 		$$->sym = $2;
309 	}
310 |	qual '='
311 
312 qlist:
313 	init ','
314 |	qlist init ','
315 	{
316 		$$ = new(OLIST, $1, $2);
317 	}
318 |	qual
319 |	qlist qual
320 	{
321 		$$ = new(OLIST, $1, $2);
322 	}
323 
324 ilist:
325 	qlist
326 |	init
327 |	qlist init
328 	{
329 		$$ = new(OLIST, $1, $2);
330 	}
331 
332 zarglist:
333 	{
334 		$$ = Z;
335 	}
336 |	arglist
337 	{
338 		$$ = invert($1);
339 	}
340 
341 
342 arglist:
343 	name
344 |	tlist abdecor
345 	{
346 		$$ = new(OPROTO, $2, Z);
347 		$$->type = $1;
348 	}
349 |	tlist xdecor
350 	{
351 		$$ = new(OPROTO, $2, Z);
352 		$$->type = $1;
353 	}
354 |	'.' '.' '.'
355 	{
356 		$$ = new(ODOTDOT, Z, Z);
357 	}
358 |	arglist ',' arglist
359 	{
360 		$$ = new(OLIST, $1, $3);
361 	}
362 
363 block:
364 	'{' slist '}'
365 	{
366 		$$ = invert($2);
367 	//	if($2 != Z)
368 	//		$$ = new(OLIST, $2, $$);
369 		if($$ == Z)
370 			$$ = new(OLIST, Z, Z);
371 	}
372 
373 slist:
374 	{
375 		$$ = Z;
376 	}
377 |	slist adecl
378 	{
379 		$$ = new(OLIST, $1, $2);
380 	}
381 |	slist stmnt
382 	{
383 		$$ = new(OLIST, $1, $2);
384 	}
385 
386 labels:
387 	label
388 |	labels label
389 	{
390 		$$ = new(OLIST, $1, $2);
391 	}
392 
393 label:
394 	LCASE expr ':'
395 	{
396 		$$ = new(OCASE, $2, Z);
397 	}
398 |	LDEFAULT ':'
399 	{
400 		$$ = new(OCASE, Z, Z);
401 	}
402 |	LNAME ':'
403 	{
404 		$$ = new(OLABEL, dcllabel($1, 1), Z);
405 	}
406 
407 stmnt:
408 	error ';'
409 	{
410 		$$ = Z;
411 	}
412 |	ulstmnt
413 |	labels ulstmnt
414 	{
415 		$$ = new(OLIST, $1, $2);
416 	}
417 
418 forexpr:
419 	zcexpr
420 |	ctlist adlist
421 	{
422 		$$ = $2;
423 	}
424 
425 ulstmnt:
426 	zcexpr ';'
427 |	{
428 		markdcl();
429 	}
430 	block
431 	{
432 		$$ = revertdcl();
433 		if($$)
434 			$$ = new(OLIST, $$, $2);
435 		else
436 			$$ = $2;
437 	}
438 |	LIF '(' cexpr ')' stmnt
439 	{
440 		$$ = new(OIF, $3, new(OLIST, $5, Z));
441 		if($5 == Z)
442 			warn($3, "empty if body");
443 	}
444 |	LIF '(' cexpr ')' stmnt LELSE stmnt
445 	{
446 		$$ = new(OIF, $3, new(OLIST, $5, $7));
447 		if($5 == Z)
448 			warn($3, "empty if body");
449 		if($7 == Z)
450 			warn($3, "empty else body");
451 	}
452 |	{ markdcl(); } LFOR '(' forexpr ';' zcexpr ';' zcexpr ')' stmnt
453 	{
454 		$$ = revertdcl();
455 		if($$){
456 			if($4)
457 				$4 = new(OLIST, $$, $4);
458 			else
459 				$4 = $$;
460 		}
461 		$$ = new(OFOR, new(OLIST, $6, new(OLIST, $4, $8)), $10);
462 	}
463 |	LWHILE '(' cexpr ')' stmnt
464 	{
465 		$$ = new(OWHILE, $3, $5);
466 	}
467 |	LDO stmnt LWHILE '(' cexpr ')' ';'
468 	{
469 		$$ = new(ODWHILE, $5, $2);
470 	}
471 |	LRETURN zcexpr ';'
472 	{
473 		$$ = new(ORETURN, $2, Z);
474 		$$->type = thisfn->link;
475 	}
476 |	LSWITCH '(' cexpr ')' stmnt
477 	{
478 		$$ = new(OCONST, Z, Z);
479 		$$->vconst = 0;
480 		$$->type = types[TINT];
481 		$3 = new(OSUB, $$, $3);
482 
483 		$$ = new(OCONST, Z, Z);
484 		$$->vconst = 0;
485 		$$->type = types[TINT];
486 		$3 = new(OSUB, $$, $3);
487 
488 		$$ = new(OSWITCH, $3, $5);
489 	}
490 |	LBREAK ';'
491 	{
492 		$$ = new(OBREAK, Z, Z);
493 	}
494 |	LCONTINUE ';'
495 	{
496 		$$ = new(OCONTINUE, Z, Z);
497 	}
498 |	LGOTO ltag ';'
499 	{
500 		$$ = new(OGOTO, dcllabel($2, 0), Z);
501 	}
502 |	LUSED '(' zelist ')' ';'
503 	{
504 		$$ = new(OUSED, $3, Z);
505 	}
506 |	LSET '(' zelist ')' ';'
507 	{
508 		$$ = new(OSET, $3, Z);
509 	}
510 
511 zcexpr:
512 	{
513 		$$ = Z;
514 	}
515 |	cexpr
516 
517 zexpr:
518 	{
519 		$$ = Z;
520 	}
521 |	lexpr
522 
523 lexpr:
524 	expr
525 	{
526 		$$ = new(OCAST, $1, Z);
527 		$$->type = types[TLONG];
528 	}
529 
530 cexpr:
531 	expr
532 |	cexpr ',' cexpr
533 	{
534 		$$ = new(OCOMMA, $1, $3);
535 	}
536 
537 expr:
538 	xuexpr
539 |	expr '*' expr
540 	{
541 		$$ = new(OMUL, $1, $3);
542 	}
543 |	expr '/' expr
544 	{
545 		$$ = new(ODIV, $1, $3);
546 	}
547 |	expr '%' expr
548 	{
549 		$$ = new(OMOD, $1, $3);
550 	}
551 |	expr '+' expr
552 	{
553 		$$ = new(OADD, $1, $3);
554 	}
555 |	expr '-' expr
556 	{
557 		$$ = new(OSUB, $1, $3);
558 	}
559 |	expr LRSH expr
560 	{
561 		$$ = new(OASHR, $1, $3);
562 	}
563 |	expr LLSH expr
564 	{
565 		$$ = new(OASHL, $1, $3);
566 	}
567 |	expr '<' expr
568 	{
569 		$$ = new(OLT, $1, $3);
570 	}
571 |	expr '>' expr
572 	{
573 		$$ = new(OGT, $1, $3);
574 	}
575 |	expr LLE expr
576 	{
577 		$$ = new(OLE, $1, $3);
578 	}
579 |	expr LGE expr
580 	{
581 		$$ = new(OGE, $1, $3);
582 	}
583 |	expr LEQ expr
584 	{
585 		$$ = new(OEQ, $1, $3);
586 	}
587 |	expr LNE expr
588 	{
589 		$$ = new(ONE, $1, $3);
590 	}
591 |	expr '&' expr
592 	{
593 		$$ = new(OAND, $1, $3);
594 	}
595 |	expr '^' expr
596 	{
597 		$$ = new(OXOR, $1, $3);
598 	}
599 |	expr '|' expr
600 	{
601 		$$ = new(OOR, $1, $3);
602 	}
603 |	expr LANDAND expr
604 	{
605 		$$ = new(OANDAND, $1, $3);
606 	}
607 |	expr LOROR expr
608 	{
609 		$$ = new(OOROR, $1, $3);
610 	}
611 |	expr '?' cexpr ':' expr
612 	{
613 		$$ = new(OCOND, $1, new(OLIST, $3, $5));
614 	}
615 |	expr '=' expr
616 	{
617 		$$ = new(OAS, $1, $3);
618 	}
619 |	expr LPE expr
620 	{
621 		$$ = new(OASADD, $1, $3);
622 	}
623 |	expr LME expr
624 	{
625 		$$ = new(OASSUB, $1, $3);
626 	}
627 |	expr LMLE expr
628 	{
629 		$$ = new(OASMUL, $1, $3);
630 	}
631 |	expr LDVE expr
632 	{
633 		$$ = new(OASDIV, $1, $3);
634 	}
635 |	expr LMDE expr
636 	{
637 		$$ = new(OASMOD, $1, $3);
638 	}
639 |	expr LLSHE expr
640 	{
641 		$$ = new(OASASHL, $1, $3);
642 	}
643 |	expr LRSHE expr
644 	{
645 		$$ = new(OASASHR, $1, $3);
646 	}
647 |	expr LANDE expr
648 	{
649 		$$ = new(OASAND, $1, $3);
650 	}
651 |	expr LXORE expr
652 	{
653 		$$ = new(OASXOR, $1, $3);
654 	}
655 |	expr LORE expr
656 	{
657 		$$ = new(OASOR, $1, $3);
658 	}
659 
660 xuexpr:
661 	uexpr
662 |	'(' tlist abdecor ')' xuexpr
663 	{
664 		$$ = new(OCAST, $5, Z);
665 		dodecl(NODECL, CXXX, $2, $3);
666 		$$->type = lastdcl;
667 		$$->xcast = 1;
668 	}
669 |	'(' tlist abdecor ')' '{' ilist '}'	/* extension */
670 	{
671 		$$ = new(OSTRUCT, $6, Z);
672 		dodecl(NODECL, CXXX, $2, $3);
673 		$$->type = lastdcl;
674 	}
675 
676 uexpr:
677 	pexpr
678 |	'*' xuexpr
679 	{
680 		$$ = new(OIND, $2, Z);
681 	}
682 |	'&' xuexpr
683 	{
684 		$$ = new(OADDR, $2, Z);
685 	}
686 |	'+' xuexpr
687 	{
688 		$$ = new(OPOS, $2, Z);
689 	}
690 |	'-' xuexpr
691 	{
692 		$$ = new(ONEG, $2, Z);
693 	}
694 |	'!' xuexpr
695 	{
696 		$$ = new(ONOT, $2, Z);
697 	}
698 |	'~' xuexpr
699 	{
700 		$$ = new(OCOM, $2, Z);
701 	}
702 |	LPP xuexpr
703 	{
704 		$$ = new(OPREINC, $2, Z);
705 	}
706 |	LMM xuexpr
707 	{
708 		$$ = new(OPREDEC, $2, Z);
709 	}
710 |	LSIZEOF uexpr
711 	{
712 		$$ = new(OSIZE, $2, Z);
713 	}
714 |	LSIGNOF uexpr
715 	{
716 		$$ = new(OSIGN, $2, Z);
717 	}
718 
719 pexpr:
720 	'(' cexpr ')'
721 	{
722 		$$ = $2;
723 	}
724 |	LSIZEOF '(' tlist abdecor ')'
725 	{
726 		$$ = new(OSIZE, Z, Z);
727 		dodecl(NODECL, CXXX, $3, $4);
728 		$$->type = lastdcl;
729 	}
730 |	LSIGNOF '(' tlist abdecor ')'
731 	{
732 		$$ = new(OSIGN, Z, Z);
733 		dodecl(NODECL, CXXX, $3, $4);
734 		$$->type = lastdcl;
735 	}
736 |	pexpr '(' zelist ')'
737 	{
738 		$$ = new(OFUNC, $1, Z);
739 		if($1->op == ONAME)
740 		if($1->type == T)
741 			dodecl(xdecl, CXXX, types[TINT], $$);
742 		$$->right = invert($3);
743 	}
744 |	pexpr '[' cexpr ']'
745 	{
746 		$$ = new(OIND, new(OADD, $1, $3), Z);
747 	}
748 |	pexpr LMG ltag
749 	{
750 		$$ = new(ODOT, new(OIND, $1, Z), Z);
751 		$$->sym = $3;
752 	}
753 |	pexpr '.' ltag
754 	{
755 		$$ = new(ODOT, $1, Z);
756 		$$->sym = $3;
757 	}
758 |	pexpr LPP
759 	{
760 		$$ = new(OPOSTINC, $1, Z);
761 	}
762 |	pexpr LMM
763 	{
764 		$$ = new(OPOSTDEC, $1, Z);
765 	}
766 |	name
767 |	LCONST
768 	{
769 		$$ = new(OCONST, Z, Z);
770 		$$->type = types[TINT];
771 		$$->vconst = $1;
772 		$$->cstring = strdup(symb);
773 	}
774 |	LLCONST
775 	{
776 		$$ = new(OCONST, Z, Z);
777 		$$->type = types[TLONG];
778 		$$->vconst = $1;
779 		$$->cstring = strdup(symb);
780 	}
781 |	LUCONST
782 	{
783 		$$ = new(OCONST, Z, Z);
784 		$$->type = types[TUINT];
785 		$$->vconst = $1;
786 		$$->cstring = strdup(symb);
787 	}
788 |	LULCONST
789 	{
790 		$$ = new(OCONST, Z, Z);
791 		$$->type = types[TULONG];
792 		$$->vconst = $1;
793 		$$->cstring = strdup(symb);
794 	}
795 |	LDCONST
796 	{
797 		$$ = new(OCONST, Z, Z);
798 		$$->type = types[TDOUBLE];
799 		$$->fconst = $1;
800 		$$->cstring = strdup(symb);
801 	}
802 |	LFCONST
803 	{
804 		$$ = new(OCONST, Z, Z);
805 		$$->type = types[TFLOAT];
806 		$$->fconst = $1;
807 		$$->cstring = strdup(symb);
808 	}
809 |	LVLCONST
810 	{
811 		$$ = new(OCONST, Z, Z);
812 		$$->type = types[TVLONG];
813 		$$->vconst = $1;
814 		$$->cstring = strdup(symb);
815 	}
816 |	LUVLCONST
817 	{
818 		$$ = new(OCONST, Z, Z);
819 		$$->type = types[TUVLONG];
820 		$$->vconst = $1;
821 		$$->cstring = strdup(symb);
822 	}
823 |	string
824 |	lstring
825 
826 string:
827 	LSTRING
828 	{
829 		$$ = new(OSTRING, Z, Z);
830 		$$->type = typ(TARRAY, types[TCHAR]);
831 		$$->type->width = $1.l + 1;
832 		$$->cstring = $1.s;
833 		$$->sym = symstring;
834 		$$->etype = TARRAY;
835 		$$->class = CSTATIC;
836 	}
837 |	string LSTRING
838 	{
839 		char *s;
840 		int n;
841 
842 		n = $1->type->width - 1;
843 		s = alloc(n+$2.l+MAXALIGN);
844 
845 		memcpy(s, $1->cstring, n);
846 		memcpy(s+n, $2.s, $2.l);
847 		s[n+$2.l] = 0;
848 
849 		$$ = $1;
850 		$$->type->width += $2.l;
851 		$$->cstring = s;
852 	}
853 
854 lstring:
855 	LLSTRING
856 	{
857 		$$ = new(OLSTRING, Z, Z);
858 		$$->type = typ(TARRAY, types[TRUNE]);
859 		$$->type->width = $1.l + sizeof(TRune);
860 		$$->rstring = (TRune*)$1.s;
861 		$$->sym = symstring;
862 		$$->etype = TARRAY;
863 		$$->class = CSTATIC;
864 	}
865 |	lstring LLSTRING
866 	{
867 		char *s;
868 		int n;
869 
870 		n = $1->type->width - sizeof(TRune);
871 		s = alloc(n+$2.l+MAXALIGN);
872 
873 		memcpy(s, $1->rstring, n);
874 		memcpy(s+n, $2.s, $2.l);
875 		*(TRune*)(s+n+$2.l) = 0;
876 
877 		$$ = $1;
878 		$$->type->width += $2.l;
879 		$$->rstring = (TRune*)s;
880 	}
881 
882 zelist:
883 	{
884 		$$ = Z;
885 	}
886 |	elist
887 
888 elist:
889 	expr
890 |	elist ',' elist
891 	{
892 		$$ = new(OLIST, $1, $3);
893 	}
894 
895 sbody:
896 	'{'
897 	{
898 		$<tyty>$.t1 = strf;
899 		$<tyty>$.t2 = strl;
900 		$<tyty>$.t3 = lasttype;
901 		$<tyty>$.c = lastclass;
902 		strf = T;
903 		strl = T;
904 		lastbit = 0;
905 		firstbit = 1;
906 		lastclass = CXXX;
907 		lasttype = T;
908 	}
909 	edecl '}'
910 	{
911 		$$ = strf;
912 		strf = $<tyty>2.t1;
913 		strl = $<tyty>2.t2;
914 		lasttype = $<tyty>2.t3;
915 		lastclass = $<tyty>2.c;
916 	}
917 
918 zctlist:
919 	{
920 		lastclass = CXXX;
921 		lasttype = types[TINT];
922 	}
923 |	ctlist
924 
925 types:
926 	complex
927 	{
928 		$$.t = $1;
929 		$$.c = CXXX;
930 	}
931 |	tname
932 	{
933 		$$.t = simplet($1);
934 		$$.c = CXXX;
935 	}
936 |	gcnlist
937 	{
938 		$$.t = simplet($1);
939 		$$.c = simplec($1);
940 		$$.t = garbt($$.t, $1);
941 	}
942 |	complex gctnlist
943 	{
944 		$$.t = $1;
945 		$$.c = simplec($2);
946 		$$.t = garbt($$.t, $2);
947 		if($2 & ~BCLASS & ~BGARB)
948 			diag(Z, "duplicate types given: %T and %Q", $1, $2);
949 	}
950 |	tname gctnlist
951 	{
952 		$$.t = simplet(typebitor($1, $2));
953 		$$.c = simplec($2);
954 		$$.t = garbt($$.t, $2);
955 	}
956 |	gcnlist complex zgnlist
957 	{
958 		$$.t = $2;
959 		$$.c = simplec($1);
960 		$$.t = garbt($$.t, $1|$3);
961 	}
962 |	gcnlist tname
963 	{
964 		$$.t = simplet($2);
965 		$$.c = simplec($1);
966 		$$.t = garbt($$.t, $1);
967 	}
968 |	gcnlist tname gctnlist
969 	{
970 		$$.t = simplet(typebitor($2, $3));
971 		$$.c = simplec($1|$3);
972 		$$.t = garbt($$.t, $1|$3);
973 	}
974 
975 tlist:
976 	types
977 	{
978 		$$ = $1.t;
979 		if($1.c != CXXX)
980 			diag(Z, "illegal combination of class 4: %s", cnames[$1.c]);
981 	}
982 
983 ctlist:
984 	types
985 	{
986 		lasttype = $1.t;
987 		lastclass = $1.c;
988 	}
989 
990 complex:
991 	LSTRUCT ltag
992 	{
993 		dotag($2, TSTRUCT, 0);
994 		$$ = $2->suetag;
995 	}
996 |	LSTRUCT ltag
997 	{
998 		dotag($2, TSTRUCT, autobn);
999 	}
1000 	sbody
1001 	{
1002 		$$ = $2->suetag;
1003 		if($$->link != T)
1004 			diag(Z, "redeclare tag: %s", $2->name);
1005 		$$->link = $4;
1006 		sualign($$);
1007 	}
1008 |	LSTRUCT sbody
1009 	{
1010 		taggen++;
1011 		snprint(symb, sizeof symb, "_%d_", taggen);
1012 		$$ = dotag(lookup(), TSTRUCT, autobn);
1013 		$$->link = $2;
1014 		sualign($$);
1015 	}
1016 |	LUNION ltag
1017 	{
1018 		dotag($2, TUNION, 0);
1019 		$$ = $2->suetag;
1020 	}
1021 |	LUNION ltag
1022 	{
1023 		dotag($2, TUNION, autobn);
1024 	}
1025 	sbody
1026 	{
1027 		$$ = $2->suetag;
1028 		if($$->link != T)
1029 			diag(Z, "redeclare tag: %s", $2->name);
1030 		$$->link = $4;
1031 		sualign($$);
1032 	}
1033 |	LUNION sbody
1034 	{
1035 		taggen++;
1036 		snprint(symb, sizeof symb, "_%d_", taggen);
1037 		$$ = dotag(lookup(), TUNION, autobn);
1038 		$$->link = $2;
1039 		sualign($$);
1040 	}
1041 |	LENUM ltag
1042 	{
1043 		dotag($2, TENUM, 0);
1044 		$$ = $2->suetag;
1045 		if($$->link == T)
1046 			$$->link = types[TINT];
1047 		$$ = $$->link;
1048 	}
1049 |	LENUM ltag
1050 	{
1051 		dotag($2, TENUM, autobn);
1052 	}
1053 	'{'
1054 	{
1055 		en.tenum = T;
1056 		en.cenum = T;
1057 	}
1058 	enum '}'
1059 	{
1060 		$$ = $2->suetag;
1061 		if($$->link != T)
1062 			diag(Z, "redeclare tag: %s", $2->name);
1063 		if(en.tenum == T) {
1064 			diag(Z, "enum type ambiguous: %s", $2->name);
1065 			en.tenum = types[TINT];
1066 		}
1067 		$$->link = en.tenum;
1068 		$$ = en.tenum;
1069 	}
1070 |	LENUM '{'
1071 	{
1072 		en.tenum = T;
1073 		en.cenum = T;
1074 	}
1075 	enum '}'
1076 	{
1077 		$$ = en.tenum;
1078 	}
1079 |	LTYPE
1080 	{
1081 		$$ = tcopy($1->type);
1082 	}
1083 
1084 gctnlist:
1085 	gctname
1086 |	gctnlist gctname
1087 	{
1088 		$$ = typebitor($1, $2);
1089 	}
1090 
1091 zgnlist:
1092 	{
1093 		$$ = 0;
1094 	}
1095 |	zgnlist gname
1096 	{
1097 		$$ = typebitor($1, $2);
1098 	}
1099 
1100 gctname:
1101 	tname
1102 |	gname
1103 |	cname
1104 
1105 gcnlist:
1106 	gcname
1107 |	gcnlist gcname
1108 	{
1109 		$$ = typebitor($1, $2);
1110 	}
1111 
1112 gcname:
1113 	gname
1114 |	cname
1115 
1116 enum:
1117 	LNAME
1118 	{
1119 		doenum($1, Z);
1120 	}
1121 |	LNAME '=' expr
1122 	{
1123 		doenum($1, $3);
1124 	}
1125 |	enum ','
1126 |	enum ',' enum
1127 
1128 tname:	/* type words */
1129 	LCHAR { $$ = BCHAR; }
1130 |	LSHORT { $$ = BSHORT; }
1131 |	LINT { $$ = BINT; }
1132 |	LLONG { $$ = BLONG; }
1133 |	LSIGNED { $$ = BSIGNED; }
1134 |	LUNSIGNED { $$ = BUNSIGNED; }
1135 |	LFLOAT { $$ = BFLOAT; }
1136 |	LDOUBLE { $$ = BDOUBLE; }
1137 |	LVOID { $$ = BVOID; }
1138 
1139 cname:	/* class words */
1140 	LAUTO { $$ = BAUTO; }
1141 |	LSTATIC { $$ = BSTATIC; }
1142 |	LEXTERN { $$ = BEXTERN; }
1143 |	LTYPEDEF { $$ = BTYPEDEF; }
1144 |	LTYPESTR { $$ = BTYPESTR; }
1145 |	LREGISTER { $$ = BREGISTER; }
1146 |	LINLINE { $$ = 0; }
1147 
1148 gname:	/* garbage words */
1149 	LCONSTNT { $$ = BCONSTNT; }
1150 |	LVOLATILE { $$ = BVOLATILE; }
1151 |	LRESTRICT { $$ = 0; }
1152 
1153 name:
1154 	LNAME
1155 	{
1156 		$$ = new(ONAME, Z, Z);
1157 		if($1->class == CLOCAL)
1158 			$1 = mkstatic($1);
1159 		$$->sym = $1;
1160 		$$->type = $1->type;
1161 		$$->etype = TVOID;
1162 		if($$->type != T)
1163 			$$->etype = $$->type->etype;
1164 		$$->xoffset = $1->offset;
1165 		$$->class = $1->class;
1166 		$1->aused = 1;
1167 	}
1168 tag:
1169 	ltag
1170 	{
1171 		$$ = new(ONAME, Z, Z);
1172 		$$->sym = $1;
1173 		$$->type = $1->type;
1174 		$$->etype = TVOID;
1175 		if($$->type != T)
1176 			$$->etype = $$->type->etype;
1177 		$$->xoffset = $1->offset;
1178 		$$->class = $1->class;
1179 	}
1180 ltag:
1181 	LNAME
1182 |	LTYPE
1183 %%
1184