169 |
|
|
170 |
#define YYERROR_VERBOSE 1 |
#define YYERROR_VERBOSE 1 |
171 |
#define YYDEBUG 1 |
#define YYDEBUG 1 |
172 |
/* #define YYPRINT yyprint */ |
#define YYPRINT yyprint |
|
|
|
|
static int yylex (void); |
|
|
static void yyerror (const char *msg); |
|
|
static void yyprint (FILE *out, int toknum, int tokval); |
|
173 |
%} |
%} |
174 |
|
%verbose |
175 |
%union |
%union |
176 |
{ |
{ |
177 |
int ival; |
int ival; |
178 |
} |
} |
179 |
%type <ival> thing 'x' |
%type <ival> 'x' thing line input |
180 |
|
%destructor { printf ("Freeing input %d\n", $$); } input |
181 |
|
%destructor { printf ("Freeing line %d\n", $$); } line |
182 |
%destructor { printf ("Freeing thing %d\n", $$); } thing |
%destructor { printf ("Freeing thing %d\n", $$); } thing |
183 |
%destructor { printf ("Freeing 'x' %d\n", $$); } 'x' |
%destructor { printf ("Freeing 'x' %d\n", $$); } 'x' |
184 |
|
|
185 |
|
%{ |
186 |
|
static int yylex (void); |
187 |
|
static void yyerror (const char *msg); |
188 |
|
static void yyprint (FILE *out, int num, YYSTYPE val); |
189 |
|
%} |
190 |
|
|
191 |
|
|
192 |
%% |
%% |
193 |
input: |
input: |
194 |
/* Nothing. */ |
/* Nothing. */ |
195 |
| input line |
{ |
196 |
|
$$ = 0; |
197 |
|
printf ("input(%d): /* Nothing */';'\n", $$); |
198 |
|
} |
199 |
|
| line input /* Right recursive to load the stack so that popping at |
200 |
|
EOF can be exercised. */ |
201 |
|
{ |
202 |
|
$$ = 2; |
203 |
|
printf ("input(%d): line(%d) input(%d)';'\n", $$, $1, $2); |
204 |
|
} |
205 |
; |
; |
206 |
|
|
207 |
line: |
line: |
208 |
thing thing thing ';' |
thing thing thing ';' |
209 |
{ printf ("input: thing(%d) thing(%d) thing(%d) ';'\n", $1, $2, $3); } |
{ |
210 |
|
$$ = $1; |
211 |
|
printf ("line(%d): thing(%d) thing(%d) thing(%d) ';'\n", $$, $1, $2, $3); |
212 |
|
} |
213 |
| thing thing ';' |
| thing thing ';' |
214 |
{ printf ("input: thing(%d) thing(%d) ';'\n", $1, $2); } |
{ |
215 |
|
$$ = $1; |
216 |
|
printf ("line(%d): thing(%d) thing(%d) ';'\n", $$, $1, $2); |
217 |
|
} |
218 |
| thing ';' |
| thing ';' |
219 |
{ printf ("input: thing(%d) ';'\n", $1); } |
{ |
220 |
|
$$ = $1; |
221 |
|
printf ("line(%d): thing(%d) ';'\n", $$, $1); |
222 |
|
} |
223 |
| error ';' |
| error ';' |
224 |
{ printf ("input: error ';'\n"); } |
{ |
225 |
|
$$ = -1; |
226 |
|
printf ("line(%d): error ';'\n", $$); |
227 |
|
} |
228 |
; |
; |
229 |
|
|
230 |
thing: |
thing: |
231 |
'x' { printf ("thing: 'x' (%d)\n", $1); $$ = $1; } |
'x' |
232 |
|
{ |
233 |
|
$$ = $1; |
234 |
|
printf ("thing(%d): 'x'(%d)\n", $$, $1); |
235 |
|
} |
236 |
; |
; |
237 |
%% |
%% |
238 |
static int |
static int |
239 |
yylex (void) |
yylex (void) |
240 |
{ |
{ |
241 |
static const int input[] = |
static const unsigned int input[] = |
242 |
{ |
{ |
243 |
|
/* Exericise the discarding of stack top and input until `error' |
244 |
|
can be reduced. */ |
245 |
'x', 'x', 'x', 'x', 'x', 'x', ';', |
'x', 'x', 'x', 'x', 'x', 'x', ';', |
246 |
|
|
247 |
|
/* Load the stack and provoke an error that cannot be caught be |
248 |
|
the grammar, and check that the stack is cleared. */ |
249 |
'x', 'x', ';', |
'x', 'x', ';', |
250 |
'x', ';', |
'x', ';', |
251 |
'x', 'y', ';' |
'y' |
252 |
}; |
}; |
253 |
static int counter = 0; |
static int counter = 0; |
254 |
|
|
255 |
if (counter < (sizeof(input) / sizeof (input[0]))) |
if (counter < (sizeof(input) / sizeof (input[0]))) |
256 |
{ |
{ |
257 |
yylval.ival = counter; |
yylval.ival = counter; |
258 |
|
printf ("sending: '%c'(%d)\n", input[counter], counter); |
259 |
return input[counter++]; |
return input[counter++]; |
260 |
} |
} |
261 |
else |
else |
262 |
return EOF; |
{ |
263 |
|
printf ("sending: EOF\n"); |
264 |
|
return EOF; |
265 |
|
} |
266 |
} |
} |
267 |
|
|
268 |
static void |
static void |
272 |
} |
} |
273 |
|
|
274 |
static void |
static void |
275 |
yyprint (FILE *out, int toknum, int tokval) |
yyprint (FILE *out, int num, YYSTYPE val) |
276 |
{ |
{ |
277 |
if (0 < toknum && toknum < 256) |
fprintf (out, " = %d", val.ival); |
|
fprintf (out, " = %d", tokval); |
|
278 |
} |
} |
279 |
|
|
280 |
int |
int |
293 |
|
|
294 |
AT_CHECK([bison input.y -d -v -o input.c]) |
AT_CHECK([bison input.y -d -v -o input.c]) |
295 |
AT_CHECK([$CC $CFLAGS $CPPFLAGS input.c -o input], 0, [], [ignore]) |
AT_CHECK([$CC $CFLAGS $CPPFLAGS input.c -o input], 0, [], [ignore]) |
296 |
AT_CHECK([./input], 0, |
AT_CHECK([./input], 1, |
297 |
[[thing: 'x' (0) |
[[sending: 'x'(0) |
298 |
thing: 'x' (1) |
thing(0): 'x'(0) |
299 |
thing: 'x' (2) |
sending: 'x'(1) |
300 |
|
thing(1): 'x'(1) |
301 |
|
sending: 'x'(2) |
302 |
|
thing(2): 'x'(2) |
303 |
|
sending: 'x'(3) |
304 |
parse error, unexpected 'x', expecting ';' |
parse error, unexpected 'x', expecting ';' |
305 |
Freeing thing 2 |
Freeing thing 2 |
306 |
Freeing thing 1 |
Freeing thing 1 |
307 |
Freeing thing 0 |
Freeing thing 0 |
308 |
Freeing 'x' 3 |
Freeing 'x' 3 |
309 |
|
sending: 'x'(4) |
310 |
Freeing 'x' 4 |
Freeing 'x' 4 |
311 |
|
sending: 'x'(5) |
312 |
Freeing 'x' 5 |
Freeing 'x' 5 |
313 |
input: error ';' |
sending: ';'(6) |
314 |
thing: 'x' (7) |
line(-1): error ';' |
315 |
thing: 'x' (8) |
sending: 'x'(7) |
316 |
input: thing(7) thing(8) ';' |
thing(7): 'x'(7) |
317 |
thing: 'x' (10) |
sending: 'x'(8) |
318 |
input: thing(10) ';' |
thing(8): 'x'(8) |
319 |
thing: 'x' (12) |
sending: ';'(9) |
320 |
parse error, unexpected $undefined., expecting 'x' or ';' |
line(7): thing(7) thing(8) ';' |
321 |
Freeing thing 12 |
sending: 'x'(10) |
322 |
input: error ';' |
thing(10): 'x'(10) |
323 |
Successful parse. |
sending: ';'(11) |
324 |
|
line(10): thing(10) ';' |
325 |
|
sending: 'y'(12) |
326 |
|
parse error, unexpected $undefined., expecting $ or error or 'x' |
327 |
|
sending: EOF |
328 |
|
Freeing line 10 |
329 |
|
Freeing line 7 |
330 |
|
Freeing line -1 |
331 |
|
Parsing FAILED. |
332 |
]]) |
]]) |
333 |
|
|
334 |
AT_CLEANUP |
AT_CLEANUP |