Pristine Ack-5.5
[Ack-5.5.git] / util / topgen / topgen.g
1 /* $Id: topgen.g,v 1.7 1994/06/24 10:42:36 ceriel Exp $ */
2 /*
3  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4  * See the copyright notice in the ACK home directory, in the file "Copyright".
5  */
6 /* t o p g e n . g
7  *
8  * Grammar of optimizer description, and some code generation
9  */
10
11 %token  LETTER, DIGIT, OTHER, SPACE;
12 %token  LINE_TERMINATOR, OPERAND_SEPARATOR, INSTRUCTION_SEPARATOR,
13         PATTERN_SEPARATOR, OPEN_BRACKET, CLOSE_BRACKET;
14 %lexical LLlex;
15 %start  LLparse, optim_description;
16
17 {
18 # include <stdio.h>
19 # include "token.h"
20 # include "symtab.h"
21 # include "misc.h"
22
23 char    idbuf[BUFSIZ], buf[BUFSIZ];
24 int     countid;                /* # of variables */
25 int     countpat;               /* # of patterns */
26 char *  malloc();
27 char *  strcpy();
28 static int patlen;              /* Maximum number of instructions in pattern */
29 static int maxoperand;          /* Maximum number of operands of instruction */
30 extern FILE *input;             /* file descriptor of inputfile */
31 }
32
33 optim_description
34         { struct symtab *p; } :
35         SPACE* parameter_line*
36                         {   p = findident("MAXOP",LOOKING,&deftable);
37                             if (p == 0) maxoperand = 2; /* default */
38                             else maxoperand = p->s_num;
39                         }
40         separator SPACE* mode_definitions
41         separator SPACE* patterns               
42         separator 
43                         {   register int c;
44                             fprintf(genc, linedir, lineno, inpfile);
45                             while ((c = getc(input)) != EOF) {
46                                 putc(c,genc);
47                             }
48                         }
49 ;
50
51 parameter_line
52         { struct symtab *p;} :
53         identifier
54                         {   p = findident(idbuf,ENTERING,&deftable);}
55         SPACE
56         value
57                         {   p->s_num = atoi(buf);}
58                         /* This action in fact only needed for MAXOP */
59         LINE_TERMINATOR
60         SPACE*
61                         {   fprintf(genh,"#define %s %s\n",p->s_name,buf);}
62 ;
63
64 value
65         { char *p1 = buf;} :
66         [
67             [   OPEN_BRACKET
68             |   CLOSE_BRACKET
69             |   OPERAND_SEPARATOR
70             |   PATTERN_SEPARATOR
71             |   INSTRUCTION_SEPARATOR
72             |   SPACE
73             |   LETTER
74             |   DIGIT
75             |   OTHER
76             |   '%'
77             ]
78                         {   *p1++ = dot.t_attrib;}
79         ]*
80                         {   *p1 = '\0';}
81 ;
82
83 mode_definitions
84         { int lin; } :
85                         {   fputs("tok_chk(varno) {\n\tint r;\n", genc);
86                             fputs("\tchar *VAL;\n\n",genc);
87                             fputs("\tVAL = var[varno].value;\n",genc);
88                             fputs("\tswitch(varno) {\n",genc);
89                         }
90         [
91             token_list
92             constraint(&lin)
93                         {   fprintf(genc,linedir,lin,inpfile);
94                             fprintf(genc,"\t\tr = (%s); break;\n",buf);
95                         }
96             LINE_TERMINATOR
97             SPACE*
98         ]*
99                         {   fputs("\tdefault :\n\t\tassert(0);\n",genc);
100                             fputs("\t}\n\treturn r;\n}\n\n",genc);
101                         }
102 ;
103
104 token_list :
105         new_identifier
106         SPACE*
107         [
108             OPERAND_SEPARATOR
109             SPACE*
110             new_identifier
111             SPACE*
112         ]*
113 ;
114
115 new_identifier
116         { struct symtab *p;} :
117         identifier
118                         {   p = findident(idbuf,ENTERING,&idtable);
119                             p->s_num = ++countid;
120                             fprintf(genc,"\tcase %d:\n", countid);
121                         }
122 ;
123
124 constraint (int *lin;)
125         { char *p = buf; } :
126         OPEN_BRACKET
127                         {   *lin = lineno;}
128         [
129             [   LINE_TERMINATOR
130             |   OPERAND_SEPARATOR
131             |   PATTERN_SEPARATOR
132             |   INSTRUCTION_SEPARATOR
133             |   LETTER
134             |   DIGIT
135             |   SPACE
136             |   OTHER
137             |   '%'
138             ]
139                         {   *p++ = dot.t_attrib;}
140         ]*
141                         {   *p = '\0';
142                             if (onlyspace(buf)) strcpy(buf,"TRUE");
143                         }
144         CLOSE_BRACKET
145         SPACE*
146 ;
147
148 patterns
149         { int lin;
150           char *constr;  
151           int np, nr;
152         } :
153 [
154                         {   countpat++;
155                             constr = (char *) 0;
156                             fprintf(genc,"struct instr_descr pat%d[] = {\n",
157                                          countpat);
158                         }
159         instruction_list(&np)
160                         {   if (np > patlen) patlen = np;
161                             fputs("\n};\n\n",genc);
162                         }
163         [
164             constraint(&lin)
165                         {   /* Save the constraint, we need it later on */
166                             constr = malloc((unsigned)(strlen(buf)+1));
167                             strcpy(constr,buf);
168                         }
169         ]?
170         PATTERN_SEPARATOR
171                         {   fprintf(genc,"struct instr_descr rep%d[] = {\n",
172                                          countpat);
173                         }
174         replacement(&nr)
175                         {   fputs("\n};\n\n",genc);}
176         LINE_TERMINATOR
177         SPACE*
178                         {   addpattern(constr,lin,np,nr);}
179 ]*
180                         {   printhashtable();
181                             printpatterns();
182                             fprintf(genh,"#define NRVARS %d\n",countid);
183                             fprintf(genh,"#define NRPATTERNS %d\n",countpat);
184                             fprintf(genh,"#define MIN_WINDOW_SIZE %d\n",
185                                         patlen+3);
186                             fclose(genh);
187                         }
188 ;
189
190 instruction_list(int *n;) :
191         instruction(1)
192                         {   *n = 1;}
193         [
194             INSTRUCTION_SEPARATOR
195                         {   fputs(",\n",genc);}
196             SPACE*
197             instruction(0)
198                         {   *n += 1;}
199         ]*
200 ;
201
202 instruction(int opt;)
203         { int count = 0;} :
204         opcode(opt)
205                         {   if (strcmp(buf,"ANY") != 0) {
206                                 fprintf(genc,"\t{\"%s\", {",buf);
207                             }
208                             else fputs("\t{(char *) 0, {",genc);
209                             count = 0;
210                         }
211         [
212             operand(' ')
213                         {   count = 1;}
214             [
215                 OPERAND_SEPARATOR
216                         {   count++;}
217                 SPACE*
218                 operand(',')
219             ]*
220                         {   if (count > maxoperand) {
221                                 error("Too many operands");
222                             }
223                         }
224         ]?
225                         {   while (count++ < maxoperand) {
226                                 fprintf(genc,"%c{\"\",-1,\"\"}",count == 1 ? ' ' : ',');
227                             }
228                             putc('}',genc);
229                             putc('}',genc);
230                         }
231 ;
232
233 opcode(int opt;)
234         { char *p = buf;} :
235         [
236             [   LETTER
237             |   DIGIT
238             |   OTHER
239             ]
240                         {   *p++ = dot.t_attrib;}
241         ]+
242         SPACE+
243                         {   *p = '\0';
244                             if (opt) addtohashtable(buf,countpat);
245                         }
246 ;
247
248 operand(int c;)
249         { register struct symtab *p = 0;} :
250                         {   fprintf(genc, "%c{\"", c);}
251         [
252             identifier
253                         {   if (!p) {
254                                 p = findident(idbuf,LOOKING,&idtable);
255                                 if (p) fprintf(genc,"\",%d,\"",p->s_num);
256                                 else fputs(idbuf,genc);
257                             }
258                             else fputs(idbuf,genc);
259                         }
260         |   DIGIT
261                         {   putc(dot.t_attrib,genc);}
262         |   OTHER
263                         {   putc(dot.t_attrib,genc);}
264         ]+
265                         {   if (p) fputs("\"}",genc);
266                             else fputs("\",0,\"\"}",genc);
267                         }
268         SPACE*
269 ;
270
271 replacement (int *n;)
272         {register i;} :
273         SPACE*
274                         {   *n = 0;}
275         [
276             instruction(0)
277                         {   *n = 1;}
278             [
279                 INSTRUCTION_SEPARATOR
280                         {   fputs(",\n", genc);}
281                 SPACE*
282                 instruction(0)
283                         {   *n += 1;}
284             ]*
285         |               /* empty replacement, but there must be a
286                          * structure initializer anyway
287                          */
288                         {   fputs("\t{\"\", {",genc);
289                             for (i = 0; i < maxoperand; i++) {
290                                 fprintf(genc, "%c{\"\",-1,\"\"}",i?',':' ');
291                             }
292                             fputs("}}",genc);
293                         }
294         ]
295 ;
296
297
298 identifier
299         { char *p = idbuf; } :
300         LETTER
301                                 { *p++ = dot.t_attrib;}
302         [ %while (1)
303             LETTER              { *p++ = dot.t_attrib;}
304         |   DIGIT               { *p++ = dot.t_attrib;}
305         ]*
306                                 { *p = '\0';}
307 ;
308
309 separator :
310         '%' '%' SPACE* LINE_TERMINATOR
311 ;