1 %{
2 #include <stdio.h>
3 #include "lburg.h"
4 static char rcsid[] = "$Id: gram.y 145 2001-10-17 21:53:10Z timo $";
5 /*lint -e616 -e527 -e652 -esym(552,yynerrs) -esym(563,yynewstate,yyerrlab) */
6 static int yylineno = 0;
7 %}
8 %union {
9 int n;
10 char *string;
11 Tree tree;
12 }
13 %term TERMINAL
14 %term START
15 %term PPERCENT
16
17 %token <string> ID TEMPLATE CODE
18 %token <n> INT
19 %type <string> nonterm cost
20 %type <tree> tree
21 %%
22 spec : decls PPERCENT rules { yylineno = 0; }
23 | decls { yylineno = 0; }
24 ;
25
26 decls : /* lambda */
27 | decls decl
28 ;
29
30 decl : TERMINAL blist '\n'
31 | START nonterm '\n' {
32 if (nonterm($2)->number != 1)
33 yyerror("redeclaration of the start symbol\n");
34 }
35 | '\n'
36 | error '\n' { yyerrok; }
37 ;
38
39 blist : /* lambda */
40 | blist ID '=' INT { term($2, $4); }
41 ;
42
43 rules : /* lambda */
44 | rules nonterm ':' tree TEMPLATE cost '\n' { rule($2, $4, $5, $6); }
45 | rules '\n'
46 | rules error '\n' { yyerrok; }
47 ;
48
49 nonterm : ID { nonterm($$ = $1); }
50 ;
51
52 tree : ID { $$ = tree($1, 0, 0); }
53 | ID '(' tree ')' { $$ = tree($1, $3, 0); }
54 | ID '(' tree ',' tree ')' { $$ = tree($1, $3, $5); }
55 ;
56
57 cost : CODE { if (*$1 == 0) $$ = "0"; }
58 ;
59 %%
60 #include <assert.h>
61 #include <stdarg.h>
62 #include <ctype.h>
63 #include <string.h>
64 #include <limits.h>
65
66 int errcnt = 0;
67 FILE *infp = NULL;
68 FILE *outfp = NULL;
69 static char buf[BUFSIZ], *bp = buf;
70 static int ppercent = 0;
71 static int code = 0;
72
get(void)73 static int get(void) {
74 if (*bp == 0) {
75 bp = buf;
76 *bp = 0;
77 if (fgets(buf, sizeof buf, infp) == NULL)
78 return EOF;
79 yylineno++;
80 while (buf[0] == '%' && buf[1] == '{' && buf[2] == '\n') {
81 for (;;) {
82 if (fgets(buf, sizeof buf, infp) == NULL) {
83 yywarn("unterminated %{...%}\n");
84 return EOF;
85 }
86 yylineno++;
87 if (strcmp(buf, "%}\n") == 0)
88 break;
89 fputs(buf, outfp);
90 }
91 if (fgets(buf, sizeof buf, infp) == NULL)
92 return EOF;
93 yylineno++;
94 }
95 }
96 return *bp++;
97 }
98
yyerror(char * fmt,...)99 void yyerror(char *fmt, ...) {
100 va_list ap;
101
102 va_start(ap, fmt);
103 if (yylineno > 0)
104 fprintf(stderr, "line %d: ", yylineno);
105 vfprintf(stderr, fmt, ap);
106 if (fmt[strlen(fmt)-1] != '\n')
107 fprintf(stderr, "\n");
108 errcnt++;
109 va_end(ap);
110 }
111
yylex(void)112 int yylex(void) {
113 int c;
114
115 if (code) {
116 char *p;
117 bp += strspn(bp, " \t\f");
118 p = strchr(bp, '\n');
119 if (p == NULL)
120 p = strchr(bp, '\n');
121 while (p > bp && isspace(p[-1]))
122 p--;
123 yylval.string = alloc(p - bp + 1);
124 strncpy(yylval.string, bp, p - bp);
125 yylval.string[p - bp] = 0;
126 bp = p;
127 code--;
128 return CODE;
129 }
130 while ((c = get()) != EOF) {
131 switch (c) {
132 case ' ': case '\f': case '\t':
133 continue;
134 case '\n':
135 case '(': case ')': case ',':
136 case ':': case '=':
137 return c;
138 }
139 if (c == '%' && *bp == '%') {
140 bp++;
141 return ppercent++ ? 0 : PPERCENT;
142 } else if (c == '%' && strncmp(bp, "term", 4) == 0
143 && isspace(bp[4])) {
144 bp += 4;
145 return TERMINAL;
146 } else if (c == '%' && strncmp(bp, "start", 5) == 0
147 && isspace(bp[5])) {
148 bp += 5;
149 return START;
150 } else if (c == '"') {
151 char *p = strchr(bp, '"');
152 if (p == NULL) {
153 yyerror("missing \" in assembler template\n");
154 p = strchr(bp, '\n');
155 if (p == NULL)
156 p = strchr(bp, '\0');
157 }
158 assert(p);
159 yylval.string = alloc(p - bp + 1);
160 strncpy(yylval.string, bp, p - bp);
161 yylval.string[p - bp] = 0;
162 bp = *p == '"' ? p + 1 : p;
163 code++;
164 return TEMPLATE;
165 } else if (isdigit(c)) {
166 int n = 0;
167 do {
168 int d = c - '0';
169 if (n > (INT_MAX - d)/10)
170 yyerror("integer greater than %d\n", INT_MAX);
171 else
172 n = 10*n + d;
173 c = get();
174 } while (c != EOF && isdigit(c));
175 bp--;
176 yylval.n = n;
177 return INT;
178 } else if (isalpha(c)) {
179 char *p = bp - 1;
180 while (isalpha(*bp) || isdigit(*bp) || *bp == '_')
181 bp++;
182 yylval.string = alloc(bp - p + 1);
183 strncpy(yylval.string, p, bp - p);
184 yylval.string[bp - p] = 0;
185 return ID;
186 } else if (isprint(c))
187 yyerror("invalid character `%c'\n", c);
188 else
189 yyerror("invalid character `\\%03o'\n", (unsigned char)c);
190 }
191 return 0;
192 }
193
yywarn(char * fmt,...)194 void yywarn(char *fmt, ...) {
195 va_list ap;
196
197 va_start(ap, fmt);
198 if (yylineno > 0)
199 fprintf(stderr, "line %d: ", yylineno);
200 fprintf(stderr, "warning: ");
201 vfprintf(stderr, fmt, ap);
202 }
203