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