Pristine Ack-5.5
[Ack-5.5.git] / util / ncgg / cgg.y
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 %{
6 #ifndef NORCSID
7 static char rcsid[]= "$Id: cgg.y,v 0.19 1994/06/24 10:36:56 ceriel Exp $";
8 #endif
9
10 #include "param.h"
11 #include "varinfo.h"
12 #include "lookup.h"
13 #include "set.h"
14 #include "iocc.h"
15 #include "instruct.h"
16 #include "expr.h"
17 #include "extern.h"
18 #include <cgg_cg.h>
19 #include <em_reg.h>
20
21 extern int lineno;
22 int instline,saveline;
23 int startline;
24 int npatterns;
25 int att_type;
26 int patindex[MAXPATTERNS];
27 extern set_t l_sets[];
28
29 int emhere=0;   /* lexical analyzer flag */
30 int optexact=0; /* Inside "with exact" rule */
31 int optstack=0; /* Inside with <blah> STACK rule */
32 int saferulefound=0;
33 int maxrule=0;
34 int in_em_repl=0;       /* set when in EM replacement part */
35 struct varinfo *defcost;
36 int Xstackflag=0; /* set in coercions, moves, and tests. %1 means something
37                      different then.
38                    */
39
40 struct varinfo *gen_inst(),*gen_move(),*gen_test(),*gen_preturn(),*gen_tlab();
41 struct varinfo *gen_label(), *make_erase();
42 expr_t make_expr(),ident_expr(),subreg_expr(),tokm_expr(),all_expr();
43 expr_t perc_ident_expr(),sum_expr(),regvar_expr();
44
45 set_t ident_to_set(),setproduct(),setsum(),setdiff();
46
47 iocc_t subr_iocc(),tokm_iocc(),ident_iocc(),all_iocc(),percident_iocc(), descr_iocc();
48
49 extern int narexpr;
50 extern expr_t arexp[];
51
52 int niops;
53 iocc_t iops[20];
54 %}
55
56 %union {
57         int yy_int;
58         char * yy_str;
59         varinfo * yy_varinfo;
60         set_t yy_set;
61         operand *yy_oplist;
62         expr_t yy_expr;
63         iocc_t yy_iocc;
64 }
65
66 %token PROPERTIES
67 %token REGISTERS
68 %token TOKENS
69 %token SETS
70 %token MOVES
71 %token TESTS
72 %token STACKINGRULES COERCIONS
73 %token INSTRUCTIONS
74 %token TOPELTSIZE FALLTHROUGH LABELDEF
75 %token PROC CALL EXAMPLE
76 %token FROM TO
77 %token TEST MOVE STACK RETURN
78 %token PATTERNS PAT WITH EXACT KILLS USES REUSING GEN YIELDS LEAVING
79 %token DEFINED SAMESIGN SFIT UFIT ROM LOWW HIGHW ISROM
80 %token CMPEQ CMPNE CMPLT CMPGT CMPLE CMPGE OR2 AND2 LSHIFT RSHIFT NOT COMP
81 %token INREG REGVAR REG_ANY REG_FLOAT REG_LOOP REG_POINTER
82 %token <yy_int> ADORNACCESS
83 %token <yy_int> ADORNCC
84 %token INT
85 %token ADDR
86 %token <yy_int> EMMNEM
87 %token <yy_int> NUMBER
88 %token <yy_int> DOLLAR PERCENT ALLREG
89 %token <yy_str> IDENT PERC_IDENT
90 %token <yy_str> STRING
91 %token TIMEFACTOR SIZEFACTOR
92 %token COST
93 %type <yy_varinfo> prop_list property ident_list ident_list_el
94 %type <yy_varinfo> att_list att_list_el att_list_el_list att_ident structdecl optcost optformat
95 %type <yy_varinfo> kills allocates yields leaving
96 %type <yy_varinfo> generates kill_list kill_list_el uselist uselist_el genlist yieldlist
97 %type <yy_varinfo> leavelist leavelist_el gen_instruction
98 %type <yy_varinfo> opt_erase_list erase_list erase_list_el
99 %type <yy_str> opt_par_string optstring
100 %type <yy_int> register propno att_list_el_type tokenset_no
101 %type <yy_int> adornlist optstar optuses optregvar regvartype optregvartype
102 %type <yy_int> emarg tokarg subreg allreg
103 %type <yy_expr> expr regvarexpr
104 %type <yy_iocc> tokeninstance
105 %type <yy_int> optexpr optexact optstack
106 %type <yy_set> tokenset
107 %type <yy_oplist> oplist oplist_el
108
109 %left OR2
110 %left AND2
111 %left '|'
112 %left '^'
113 %left '&'
114 %left CMPEQ,CMPNE
115 %left CMPLT,CMPLE,CMPGT,CMPGE
116 %left RSHIFT,LSHIFT
117 %left '+','-'
118 %left '*','/','%'
119 %nonassoc NOT,COMP,UMINUS
120
121 %start machtable
122
123 %%
124 /*
125  * The machine table consists of a number of sections, with their
126  * own associated parsers.
127  */
128 machtable
129         : constants
130           properties
131           registers
132           tokens
133                 { make_std_sets(); }
134           sets
135           instructions
136           moves
137           tests
138           stacks
139           coercs
140           code
141         ;
142
143 /*
144  * Constants are parsed as name=value pairs
145  */
146 constants
147         : constdeflist
148         ;
149 constdeflist
150         : /* empty */
151         | constdeflist constdef
152         ;
153 constdef
154         : IDENT'=' NUMBER
155                 { n_const($1,$3); free($1); }
156         | IDENT '=' STRING
157                 { n_sconst($1,$3); free($1); free($3); }
158         | TIMEFACTOR '=' NUMBER '/' NUMBER
159                 { fc1 = $3; fc2 = $5; }
160         | SIZEFACTOR '=' NUMBER '/' NUMBER
161                 { fc3 = $3; fc4 = $5; }
162         | error
163         ;
164
165 /*
166  * Properties are parsed as a list of names optionally followed by their size
167  */
168 properties
169         : PROPERTIES  { make_const(); } prdef_list
170         ;
171 prdef_list
172         : prdef_list_el
173         | prdef_list optcomma prdef_list_el
174         ;
175 prdef_list_el
176         : IDENT
177                 { n_prop($1,wordsize); free($1); }
178         | IDENT '(' NUMBER ')'
179                 { n_prop($1,$3); free($1); }
180         ;
181
182 /*
183  * Registers are rows of reglist:proplist pairs
184  */
185 registers
186         : REGISTERS regdef_list
187         ;
188 regdef_list
189         : regdef_list_el
190         | regdef_list regdef_list_el
191         ;
192 regdef_list_el
193         : ident_list ':' prop_list optregvar '.'
194                 { regline($1,$3,$4); free((char *) $1); free((char *) $3); }
195         | error '.'
196         ;
197 optregvar
198         : /* empty */
199                 { $$ = -1; }
200         | REGVAR
201                 { $$ = reg_any; }
202         | REGVAR '(' regvartype ')'
203                 { $$ = $3; }
204         ;
205
206 regvartype
207         : REG_ANY
208                 { $$ = reg_any;}
209         | REG_FLOAT
210                 { $$ = reg_float;}
211         | REG_LOOP
212                 { $$ = reg_loop;}
213         | REG_POINTER
214                 { $$ = reg_pointer;}
215         ;
216
217 ident_list
218         : ident_list_el
219         | ident_list optcomma ident_list_el
220                 { $3->vi_next = $1; $$ = $3; }
221         ;
222 ident_list_el
223         : IDENT opt_par_string
224                 { NEW($$,struct varinfo);
225                   $$->vi_next = 0;
226                   $$->vi_int[0] = n_reg($1,$2,0,0,0);
227                   free($1); if($2!=0) free($2);
228                 }
229         | IDENT opt_par_string '=' register
230                 { NEW($$,struct varinfo);
231                   $$->vi_next = 0;
232                   $$->vi_int[0] = n_reg($1,$2,1,$4,0);
233                   free($1); if($2!=0) free($2);
234                 }
235         | IDENT opt_par_string '=' register '+' register
236                 { NEW($$,struct varinfo);
237                   $$->vi_next = 0;
238                   $$->vi_int[0] = n_reg($1,$2,2,$4,$6);
239                   free($1); if($2!=0) free($2);
240                 }
241         ;
242 opt_par_string
243         : /* empty */
244                 { $$ = 0; }
245         | '(' STRING ')'
246                 { $$ = $2; }
247         ;
248 register
249         : IDENT
250                 { register symbol *sy_p;
251
252                   sy_p = lookup($1,symreg,mustexist);
253                   $$ = sy_p->sy_value.syv_regno;
254                   free($1);
255                 }
256         ;
257 prop_list
258         : property
259         | prop_list optcomma property
260                 { $3->vi_next = $1; $$ = $3; }
261         ;
262 property
263         : IDENT
264                 { register symbol *sy_p;
265                   sy_p = lookup($1,symprop,mustexist);
266                   NEW($$,struct varinfo);
267                   $$->vi_next=0;
268                   $$->vi_int[0]=sy_p->sy_value.syv_propno;
269                   free($1);
270                 }
271         ;
272 propno
273         : IDENT
274                 { register symbol *sy_p;
275                   sy_p = lookup($1,symprop,mustexist);
276                   $$ = sy_p->sy_value.syv_propno;
277                   free($1);
278                 }
279         ;
280
281 /* tokens are parsed as struct definitions
282  * types in the struct can be register properties, ADDR or INT
283  */
284
285 tokens
286         : TOKENS tokdeflist
287         ;
288 tokdeflist
289         : tokdeflist_el
290         | tokdeflist tokdeflist_el
291         ;
292 tokdeflist_el
293         : IDENT '=' structdecl NUMBER optcost optformat '.'
294                 { n_tok($1,$3,$4,$5,$6);
295                   free($1);
296                   freevi($3);
297                   freevi($5);
298                   freevi($6);
299                 }
300         | error '.'
301         ;
302 structdecl
303         : '{' att_list '}'
304                 { $$ = $2; }
305         ;
306 att_list
307         : /* empty */
308                 { $$ = 0; }
309         | att_list_el att_list
310                 { $$ = $1; while ($$->vi_next) $$ = $$->vi_next;
311                   $$->vi_next = $2; $$ = $1;
312                 }
313         ;
314 att_list_el
315         : att_list_el_type
316                 { att_type = $1; }
317           att_list_el_list
318           ';'
319                 { $$ = $3; }
320         ;
321 att_list_el_list
322         : att_ident
323         | att_ident ',' att_list_el_list
324                 { $1->vi_next = $3; $$ = $1; }
325         ;
326 att_ident
327         : IDENT
328                 { NEW($$, struct varinfo);
329                   $$->vi_next = 0;
330                   $$->vi_int[0] = att_type;
331                   $$->vi_str[0] = $1;
332                 }
333         ;
334 att_list_el_type
335         : INT
336                 { $$ = -1; }
337         | ADDR
338                 { $$ = -2; }
339         | propno
340         ;
341 optcost
342         :
343                 { if (defcost==VI_NULL)
344                         $$=VI_NULL;
345                   else {
346                         NEW($$,struct varinfo);
347                         *$$ = *defcost;
348                   }
349                 }
350         | COST '(' NUMBER ',' NUMBER ')'
351                 { NEW ($$,struct varinfo);
352                   $$->vi_int[0] = $3;
353                   $$->vi_int[1] = $5;
354                 }
355         ;
356 optformat
357         :
358                 { $$ = 0; }
359         | STRING optformat
360                 { NEW($$,struct varinfo);
361                   $$->vi_next = $2;
362                   $$->vi_int[0] = 0;
363                   $$->vi_str[0] = $1;
364                 }
365         | IDENT optformat
366                 { NEW($$,struct varinfo);
367                   $$->vi_next = $2;
368                   $$->vi_int[0] = 1;
369                   $$->vi_str[0] = $1;
370                 }
371         ;
372 optcomma
373         : ','
374         | /* empty */
375         ;
376
377 /* sets are parsed as ident = expression */
378
379 sets
380         : SETS setdeflist
381         ;
382 setdeflist
383         : setdeflist_el
384         | setdeflist setdeflist_el
385         ;
386 setdeflist_el
387         : IDENT '=' tokenset_no '.'
388                 { n_set($1,$3); free($1); }
389         | error '.'
390         ;
391 tokenset_no
392         : tokenset
393                 { $$ = setlookup($1); }
394         ;
395 tokenset
396         : IDENT
397                 { $$ = ident_to_set($1); free($1); }
398         | tokenset '*' tokenset
399                 { $$ = setproduct($1,$3); }
400         | tokenset '+' tokenset
401                 { $$ = setsum($1,$3); }
402         | tokenset '-' tokenset
403                 { $$ = setdiff($1,$3); }
404         | '(' tokenset ')'
405                 { $$ = $2; }
406         ;
407
408 instructions
409         : INSTRUCTIONS optcost instdef_list
410                 { defcost = $2; }
411         ;
412 instdef_list
413         : instdef_list_el
414         | instdef_list instdef_list_el
415         ;
416 instdef_list_el
417         : IDENT optstring oplist opt_erase_list optcost '.'
418                 { n_instr($1,$2,$3,$4,$5); freevi($5); }
419         | error '.'
420         ;
421 oplist
422         : /* empty */
423                 { $$ = 0; }
424         | oplist_el
425         | oplist_el ',' oplist
426                 { $$ = $1; $$->o_next = $3; }
427         ;
428 oplist_el
429         : tokenset_no adornlist
430                 { NEW($$,struct operand);
431                   $$->o_next  = 0 ;
432                   $$->o_setno = $1;
433                   $$->o_adorn = $2;
434                   checkprintformat($1);
435                 }
436         ;
437 adornlist
438         : /* empty */
439                 { $$ = 0; }
440         | ADORNACCESS adornlist
441                 { if ($2&AD_RWMASK)
442                         error("Only one of :ro,:wo,:rw allowed");
443                   $$ = $1 | $2;
444                 }
445         | ADORNCC adornlist
446                 { $$ = $1|$2; }
447         ;
448 opt_erase_list
449         : /* empty */
450                 { $$ = VI_NULL;}
451         | KILLS erase_list
452                 { $$ = $2; }
453         ;
454 erase_list
455         : erase_list_el
456                 { $$ = $1; }
457         | erase_list_el erase_list
458                 { $1->vi_next = $2; $$ = $1; }
459         ;
460 erase_list_el
461         : IDENT
462                 { $$ = make_erase($1); }
463         | ADORNCC
464                 { NEW($$, struct varinfo);
465                   $$->vi_int[0] = -1;
466                   $$->vi_next = VI_NULL;
467                 }
468         ;
469
470 /* Now the moves */
471
472 moves
473         : MOVES
474           movedeflist
475         | /* empty */
476         ;
477 movedeflist
478         : movedeflist_el
479         | movedeflist movedeflist_el
480         ;
481 movedeflist_el
482         : FROM
483                 {startline = lineno; }
484           tokenset_no
485                 { Xstackflag = 1;
486                   cursetno = $3;
487                 }
488           optexpr
489                 { Xstackflag = 0;
490                   cursetno = -1;
491                 }
492           TO tokenset_no
493                 { cursetno = $8;
494                   tokpatlen=2;
495                   tokpatset[0] = $3;
496                   tokpatset[1] = $8;
497                   tokpatro[0] = 1;
498                   Xstackflag = 1;
499                 }
500         optexpr
501                 { Xstackflag = 0;
502                   cursetno = -1;
503                 }
504         GEN genlist
505                 { tokpatlen=0;
506                   tokpatro[0]=0;
507                   n_move($3,$5,$8,$10,$13);
508                   freevi($13);
509                 }
510         | error
511         ;
512
513 /* Now the test part */
514
515 tests
516         : TESTS
517                 { Xstackflag = 1; }
518           testdeflist
519                 { Xstackflag = 0; }
520         | /* empty */
521         ;
522 testdeflist
523         : testdeflist_el
524         | testdeflist testdeflist_el
525         ;
526 testdeflist_el
527         : TO
528                 { startline = lineno;}
529           TEST tokenset_no
530                 { cursetno = $4;
531                   tokpatlen=1;
532                   tokpatset[0]=$4;
533                   tokpatro[0] = 1;
534                 }
535           optexpr GEN genlist
536                 { tokpatlen=0;
537                   tokpatro[0] = 0;
538                   n_test($4,$6,$8);
539                   freevi($8);
540                   cursetno = -1;
541                 }
542         | error
543         ;
544           
545 /* Now the stacks */
546
547 stacks
548         : STACKINGRULES
549                 { Xstackflag = 1; }
550           stackdeflist
551                 { Xstackflag = 0; }
552         ;
553 stackdeflist
554         : stackdeflist_el
555         | stackdeflist stackdeflist_el
556         ;
557 stackdeflist_el
558         : FROM
559                 {startline = lineno;}
560           tokenset_no
561                 { cursetno = $3; 
562                   tokpatlen=1; 
563                   tokpatset[0] = $3; 
564                   tokpatro[0] = 1;
565                 }
566           optexpr TO STACK optuses GEN genlist
567                 { tokpatro[0] = 0;
568                   n_stack($3,$5,$8,$10);
569                   freevi($10);
570                   cursetno = -1;
571                 }
572         ;
573 optuses
574         : /* empty */
575                 { $$ = -1; nallreg=0;}
576         | USES propno
577                 { $$ = $2; nallreg = 1; allreg[0] = $2; }
578         ;
579
580 /* Now the one-to-one coercion rules */
581
582 coercs
583         : COERCIONS
584                 { Xstackflag = 1; }
585           coercdeflist
586                 { Xstackflag = 0; }
587         ;
588 coercdeflist
589         : coercdeflist_el
590         | coercdeflist coercdeflist_el
591         ;
592 coercdeflist_el
593         : FROM
594                 {startline = lineno; tokpatlen=0; inithall();}
595           STACK allocates generates YIELDS tokeninstance
596                 { checkhall();
597                   n_coerc(0,0,$4,$5,(struct varinfo *) 0,$7);
598                   freevi($4);
599                   freevi($5);
600                 }
601         | FROM
602                 {startline = lineno;}
603           tokenset_no
604                 { cursetno = $3; 
605                   tokpatlen=1; 
606                   tokpatset[0]=$3; 
607                   tokpatro[0] = 1;
608                   inithall();
609                 }
610           optexpr allocates generates yields
611                 { tokpatro[0] = 0;
612                   checkhall();
613                   n_coerc($3,$5,$6,$7,$8);
614                   freevi($6);
615                   freevi($7);
616                   cursetno = -1;
617                 }
618         ;
619
620 /* Now the code part */
621
622 code
623         : PATTERNS coderules
624         ;
625 coderules
626         : coderule
627         | coderules coderule
628         ;
629 coderule
630         : PAT {emhere=1;} empattern {emhere=0;} optexpr
631                 { empatexpr = $5;
632                   npatterns = 0;
633                   saferulefound=0;
634                   if (empatlen>maxempatlen)
635                         maxempatlen=empatlen;
636                 }
637           patterns
638                 { if (!saferulefound)
639                         error("Previous rule impossible on empty stack");
640                   outpatterns();
641                 }
642         | PROC IDENT example
643                 { npatterns = 0; saferulefound=0; inproc=1; n_proc($2); }
644           patterns
645                 { if (!saferulefound)
646                         error("Previous rule impossible on empty stack");
647                   outpatterns(); inproc=0;
648                 }
649         | error
650                 { skipupto(PAT,"pat"); yyerrok; yyclearin; }
651         ;
652 example
653         : /* empty */
654                 { empatlen = 0; }
655         | EXAMPLE {emhere=1;} empattern {emhere=0;}
656         ;
657 empattern
658         : EMMNEM
659                 { empatlen = 1; emmnem[0] = $1; }
660         | empattern EMMNEM
661                 { NEXT(empatlen,EMPATMAX,"Em pattern");
662                   emmnem[empatlen-1] = $2;
663                 }
664         ;
665 patterns
666         : onepattern
667                 { saferulefound=1;
668                   callproc=0;
669                 }
670         | morepatterns
671                 { callproc=0;
672                   if (npatterns>maxrule)
673                         maxrule=npatterns;
674                 }
675         | CALL IDENT '(' stringlist ')'
676                 { register symbol *sy_p;
677                   saferulefound=1;
678                   sy_p=lookup($2,symproc,mustexist);
679                   callproc=sy_p->sy_value.syv_procoff;
680                   free($2);
681                   if (nprocargs > maxprocargs) maxprocargs = nprocargs;
682                 }
683         ;
684
685 stringlist
686         : STRING
687                 { nprocargs = 1; procarg[0] = strlookup($1); free($1); }
688         | stringlist ',' STRING
689                 { NEXT(nprocargs, MAXPROCARG, "Procedure argument list");
690                   procarg[nprocargs-1] = strlookup($3); free($3);
691                 }
692         ;
693
694 onepattern
695         :       { inithall(); startline=lineno;
696                   tokpatlen=0; optexact=0; optstack=0;
697                 }
698           kills allocates generates yields leaving
699                 { 
700                   patindex[npatterns++]=codeindex;
701                   checkhall();
702                   dopattern(0,$2,$3,$4,$5,$6);
703                   freevi($2);
704                   freevi($3);
705                   freevi($4);
706                   freevi($5);
707                   freevi($6);
708                 }
709         ;
710 morepatterns
711         : { inithall(); } pattern
712         | morepatterns { inithall(); } pattern
713         ;
714
715 pattern
716         : stackpattern kills allocates generates yields leaving
717                 { patindex[NEXT(npatterns,MAXPATTERNS,"Patterns")]=codeindex;
718                   if (hall() && !optexact) saferulefound=1;
719                   dopattern(0,$2,$3,$4,$5,$6);
720                   freevi($2);
721                   freevi($3);
722                   freevi($4);
723                   freevi($5);
724                   freevi($6);
725                 }
726         ;
727 stackpattern
728         : WITH optexact
729                 { startline = lineno; }
730           setlist optstack
731                 { if (tokpatlen > maxtokpatlen) maxtokpatlen = tokpatlen; }
732         ;
733 optexact
734         : /* empty */
735                 { $$ = optexact = 0; }
736         | EXACT
737                 { $$ = optexact = 1; }
738         ;
739 optstack
740         : /* empty */
741                 { $$ = optstack = 0; }
742         | STACK
743                 { $$ = optstack = 1; }
744         ;
745
746 setlist
747         : /* empty */
748                 { tokpatlen = 0; }
749         | setlist tokenset_no
750                 { NEXT(tokpatlen,TOKPATMAX,"Stack pattern");
751                   tokpatset[tokpatlen-1] = $2;
752                   checkunstacking($2);
753                   if (l_sets[$2].set_size == 0) {
754                         error("Tokenset is empty or has elements with different sizes");
755                   }
756                 }
757         ;
758 kills
759         : /* empty */
760                 { $$ = 0; }
761         | KILLS kill_list
762                 { $$ = $2;
763                 }
764         ;
765 kill_list
766         : kill_list_el
767         | kill_list_el ',' kill_list
768                 { $$=$1; $$->vi_next = $3; }
769         ;
770 kill_list_el
771         : tokenset_no { cursetno=$1; } optexpr
772                 { NEW($$,struct varinfo);
773                   $$->vi_next = 0;
774                   $$->vi_int[0]=$1;
775                   $$->vi_int[1]=$3;
776                   cursetno = -1;
777                 }
778         | regvarexpr
779                 { NEW($$,struct varinfo);
780                   $$->vi_next = 0;
781                   $$->vi_int[0] = -($1.ex_index + 1);
782                   $$->vi_int[1] = 0;
783                 }
784         ; 
785
786 allocates
787         : /* empty */
788                 { $$ = 0; nallreg=0;}
789         | USES uselist
790                 { $$ = $2; setallreg($2); }
791         ;
792 uselist
793         : uselist_el
794                 { prophall($1->vi_int[0]); }
795         | uselist_el ',' uselist
796                 { prophall($1->vi_int[0]); $$=$1; $$->vi_next=$3; }
797         ;
798 uselist_el
799         : property
800                 { $$=$1; $$->vi_int[1] = 0; }
801         | property '=' tokeninstance
802                 { if (!existalmove($3,$$->vi_int[0]))
803                         error("No such move defined");
804                   $$=$1; $$->vi_int[1] = $3.in_index; 
805                 }
806         | REUSING tokeninstance
807                 { NEW($$,struct varinfo);
808                   $$->vi_next = 0;
809                   $$->vi_int[0] = -1;
810                   $$->vi_int[1] = $2.in_index;
811                 }
812         ;
813
814
815 generates
816         : /* empty */
817                 { $$ = 0; }
818         | GEN genlist
819                 { $$ = $2; }
820         ;
821 genlist
822         : /* empty */
823                 { $$ = 0; }
824         | gen_instruction genlist
825                 { if ($1!=0) {
826                         register struct varinfo *tvip;
827                         $$=tvip=$1;
828                         while (tvip->vi_next!=VI_NULL)
829                                 tvip=tvip->vi_next;
830                         tvip->vi_next = $2;
831                   } else {
832                         $$ = $2;
833                   }
834                 }
835         ;
836 gen_instruction
837         : {instline = lineno; } IDENT optstar gen_oplist
838                 { saveline =lineno; lineno=instline;
839                   $$ = gen_inst($2,$3); free($2);
840                   lineno = saveline;
841                 }
842         | NUMBER ':'
843                 { $$ = gen_tlab($1); }
844         | MOVE tokeninstance ',' tokeninstance
845                 { $$ = gen_move($2,$4); }
846         | TEST tokeninstance
847                 { $$ = gen_test($2);}
848         | LABELDEF emarg
849                 { $$ = gen_label($2-1); use_tes++; }
850         | RETURN
851                 { $$ = gen_preturn(); }
852         ;
853 optstar
854         : /* empty */
855                 { $$=0; }
856         | '*'
857                 { $$=1; }
858         | '[' NUMBER ']'
859                 { $$=$2; }
860         ;
861 gen_oplist
862         : '.' /* empty gives conflicts */
863                 { niops=0; }
864         | tokeninstance
865                 { niops=1;iops[0]=$1; }
866         | gen_oplist ',' tokeninstance
867                 { iops[niops++] = $3; }
868         ;
869
870 yields
871         : /* empty */
872                 { $$ = 0; }
873         | YIELDS { tokrepllen = 0; } yieldlist
874                 { $$ = $3; if (tokrepllen > maxtokrepllen) maxtokrepllen = tokrepllen; }
875         ;
876 yieldlist
877         : /* empty */
878                 { $$ = 0; }
879         | tokeninstance yieldlist
880                 { checkstacking($1.in_set);
881                   NEW($$,struct varinfo);
882                   $$->vi_next = $2;
883                   $$->vi_int[0] = $1.in_index;
884                   tokrepllen++;
885                 }
886         ;
887
888 leaving
889         : /* empty */
890                 { $$ = 0; }
891         | LEAVING {emhere=1; in_em_repl=1; emrepllen = 0; } leavelist
892                 { emhere=0; in_em_repl=0; $$ = $3;
893                   if (emrepllen > maxemrepllen) maxemrepllen = emrepllen;
894                 }
895         ;
896 leavelist
897         : leavelist_el
898         | leavelist_el leavelist
899                 { $$=$1; $$->vi_next=$2; }
900         ;
901 leavelist_el
902         : EMMNEM optexpr
903                 { NEW($$,struct varinfo);
904                   $$->vi_next=0;
905                   $$->vi_int[0] = $1;
906                   $$->vi_int[1] = $2;
907                   emrepllen++;
908                 }
909         ;
910
911 optstring
912         : /* empty */
913                 { $$ = 0; }
914         | STRING
915         ;
916 optexpr
917         : /* empty */
918                 { $$ = 0; }
919         | expr
920                 { $$ = $1.ex_index; }   /* type checking ? */
921         ;
922
923 tokeninstance
924         : tokarg subreg
925                 { $$ = subr_iocc($1,$2); }
926         | tokarg '.' IDENT
927                 { $$ = tokm_iocc($1,$3); free($3); }
928         | IDENT
929                 { $$ = ident_iocc($1); free($1);}
930         | allreg subreg
931                 { $$ = all_iocc($1,$2); }
932         | PERC_IDENT
933                 { if (cursetno < 0) {
934                         error("%%<ident> not allowed here");
935                   }
936                   $$ = percident_iocc($1);
937                   free($1);
938                 }
939         | '{' IDENT attlist '}'
940                 { $$ = descr_iocc($2); free($2); }
941         ;
942 attlist
943         : /* empty */
944                 { narexpr = 0; }
945         | attlist ',' expr
946                 { arexp[narexpr++] = $3; }
947         ;
948
949 emarg
950         : DOLLAR
951                 { if ($1<1 || $1>empatlen)
952                         error("Only %d instructions in pattern",empatlen);
953                   $$ = $1;
954                 }
955         ;
956 tokarg
957         : PERCENT
958                 { $$ = $1;
959                   if (in_em_repl)
960                         error("No token references allowed in EM replacement part");
961                   if ($1<1 || $1>tokpatlen) {
962                         error("Only %d tokens in stackpattern",tokpatlen);
963                         $$ =1;
964                   }
965                   if (Xstackflag) $$ = 0;
966                 }
967         ;
968 subreg
969         : /* empty */
970                 { $$ = 0; }
971         | '.' NUMBER
972                 { if ($2<1 || $2>2) {
973                         error("Only 2 subregisters allowed");
974                         $$ = 1;
975                   } else {
976                         $$ = $2;
977                   }
978                 }
979         ;
980 allreg
981         : ALLREG
982                 { if ($1>=nallreg)
983                         fatal("Only %d registers allocated",nallreg);
984                   $$ = $1;
985                 }
986         ;
987
988 expr
989         : NUMBER
990                 { $$ = make_expr(TYPINT,EX_CON, (int) ($1 & 0xFFFF), (int) ($1>>16));
991                 }
992         | emarg
993                 { $$ = make_expr(argtyp(emmnem[$1-1]),EX_ARG,$1,0); }
994         | STRING
995                 { $$ = make_expr(TYPADDR,EX_STRING,strlookup($1),0); free($1); }
996         | IDENT
997                 { $$ = ident_expr($1); free($1); }
998         | tokarg subreg
999                 { $$ = subreg_expr($1,$2); }
1000         | tokarg '.' IDENT
1001                 { $$ = tokm_expr($1,$3); free($3); }
1002         | allreg subreg
1003                 { $$ = all_expr($1,$2); }
1004         | PERC_IDENT
1005                 { if (cursetno < 0) {
1006                         error("%%<ident> not allowed here");
1007                   }
1008                   $$ = perc_ident_expr($1);
1009                   free($1);
1010                 }
1011         | DEFINED '(' expr ')'
1012                 { $$ = make_expr(TYPBOOL,EX_DEFINED,i_expr($3),0); }
1013         | SAMESIGN '(' expr ',' expr ')'
1014                 { $$ = make_expr(TYPBOOL,EX_SAMESIGN,i_expr($3),i_expr($5)); }
1015         | TOPELTSIZE '(' emarg ')'
1016                 { $$ = make_expr(TYPINT,EX_TOPELTSIZE,$3-1,0); }
1017         | FALLTHROUGH '(' emarg ')'
1018                 { $$ = make_expr(TYPBOOL,EX_FALLTHROUGH,$3-1,0); }
1019         | SFIT '(' expr ',' expr ')'
1020                 { $$ = make_expr(TYPBOOL,EX_SFIT,i_expr($3),i_expr($5)); }
1021         | UFIT '(' expr ',' expr ')'
1022                 { $$ = make_expr(TYPBOOL,EX_UFIT,i_expr($3),i_expr($5)); }
1023         | ROM '(' emarg ',' NUMBER ')'
1024                 { $$ = make_expr(TYPINT,EX_ROM,$3-1,chkincl($5,1,3)-1); }
1025         | ISROM '(' emarg ')'
1026                 { $$ = make_expr(TYPBOOL,EX_ISROM,$3-1,0); }
1027         | LOWW '(' emarg ')'
1028                 { $$ = make_expr(TYPINT,EX_LOWW,$3-1,0); }
1029         | HIGHW '(' emarg ')'
1030                 { $$ = make_expr(TYPINT,EX_HIGHW,$3-1,0); }
1031 /* Excluded, because it causes a shift-reduce conflict
1032    (problems with a tokenset_no followed by an optexpr)
1033         | '-' expr %prec UMINUS
1034                 { $$ = make_expr(TYPINT,EX_CON, 0, 0);
1035                   $$ = make_expr(TYPINT,EX_MINUS,i_expr($$),i_expr($2)); 
1036                 }
1037 */
1038         | '(' expr ')'
1039                 { $$ = $2; }
1040         | expr CMPEQ expr
1041                 { $$ = make_expr(TYPBOOL,eq2expr($1,$3),$1.ex_index,$3.ex_index); }
1042         | expr CMPNE expr
1043                 { $$ = make_expr(TYPBOOL,ne2expr($1,$3),$1.ex_index,$3.ex_index); }
1044         | expr CMPLT expr
1045                 { $$ = make_expr(TYPBOOL,EX_NCPLT,i_expr($1),i_expr($3)); }
1046         | expr CMPGT expr
1047                 { $$ = make_expr(TYPBOOL,EX_NCPGT,i_expr($1),i_expr($3)); }
1048         | expr CMPLE expr
1049                 { $$ = make_expr(TYPBOOL,EX_NCPLE,i_expr($1),i_expr($3)); }
1050         | expr CMPGE expr
1051                 { $$ = make_expr(TYPBOOL,EX_NCPGE,i_expr($1),i_expr($3)); }
1052         | expr OR2 expr
1053                 { $$ = make_expr(TYPBOOL,EX_OR2,b_expr($1),b_expr($3)); }
1054         | expr AND2 expr
1055                 { $$ = make_expr(TYPBOOL,EX_AND2,b_expr($1),b_expr($3)); }
1056         | expr '|' expr
1057                 { $$ = make_expr(TYPINT,EX_OR,i_expr($1),i_expr($3)); }
1058         | expr '^' expr
1059                 { $$ = make_expr(TYPINT,EX_XOR,i_expr($1),i_expr($3)); }
1060         | expr '&' expr
1061                 { $$ = make_expr(TYPINT,EX_AND,i_expr($1),i_expr($3)); }
1062         | expr '+' expr
1063                 { $$ = sum_expr($1,$3); }
1064         | expr '-' expr
1065                 { $$ = make_expr(TYPINT,EX_MINUS,i_expr($1),i_expr($3)); }
1066         | expr '*' expr
1067                 { $$ = make_expr(TYPINT,EX_TIMES,i_expr($1),i_expr($3)); }
1068         | expr '/' expr
1069                 { $$ = make_expr(TYPINT,EX_DIVIDE,i_expr($1),i_expr($3)); }
1070         | expr '%' expr
1071                 { $$ = make_expr(TYPINT,EX_MOD,i_expr($1),i_expr($3)); }
1072         | expr LSHIFT expr
1073                 { $$ = make_expr(TYPINT,EX_LSHIFT,i_expr($1),i_expr($3)); }
1074         | expr RSHIFT expr
1075                 { $$ = make_expr(TYPINT,EX_RSHIFT,i_expr($1),i_expr($3)); }
1076         | NOT expr
1077                 { $$ = make_expr(TYPBOOL,EX_NOT,b_expr($2),0); }
1078         | COMP expr
1079                 { $$ = make_expr(TYPINT,EX_COMP,i_expr($2),0); }
1080         | INREG '(' expr ')'
1081                 { $$ = make_expr(TYPINT,EX_INREG,i_expr($3),0); }
1082         | regvartype
1083                 { $$ = make_expr(TYPINT,EX_CON, $1+1, 0); }
1084         | regvarexpr
1085         ;
1086
1087 regvarexpr
1088         : REGVAR '(' expr optregvartype ')'
1089                 { $$ = regvar_expr($3,$4); }
1090         ;
1091
1092 optregvartype
1093         : /* empty */
1094                 { $$ = reg_any; }
1095         | ',' regvartype
1096                 { $$ = $2; }
1097         ;
1098 %%
1099 #include "scan.c"