]>
Commit | Line | Data |
---|---|---|
3c31a486 | 1 | # Exercising Bison on conflicts. -*- Autotest -*- |
69363a9e | 2 | |
7d424de1 PE |
3 | # Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free |
4 | # Software Foundation, Inc. | |
3c31a486 | 5 | |
f16b0819 | 6 | # This program is free software: you can redistribute it and/or modify |
3c31a486 | 7 | # it under the terms of the GNU General Public License as published by |
f16b0819 PE |
8 | # the Free Software Foundation, either version 3 of the License, or |
9 | # (at your option) any later version. | |
10 | # | |
3c31a486 AD |
11 | # This program is distributed in the hope that it will be useful, |
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | # GNU General Public License for more details. | |
f16b0819 | 15 | # |
3c31a486 | 16 | # You should have received a copy of the GNU General Public License |
f16b0819 | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
3c31a486 AD |
18 | |
19 | AT_BANNER([[Conflicts.]]) | |
20 | ||
21 | ||
643a5994 AD |
22 | ## ---------------- ## |
23 | ## S/R in initial. ## | |
24 | ## ---------------- ## | |
25 | ||
26 | # I once hacked Bison in such a way that it lost its reductions on the | |
27 | # initial state (because it was confusing it with the last state). It | |
28 | # took me a while to strip down my failures to this simple case. So | |
29 | # make sure it finds the s/r conflict below. | |
30 | ||
31 | AT_SETUP([S/R in initial]) | |
32 | ||
33 | AT_DATA([[input.y]], | |
34 | [[%expect 1 | |
35 | %% | |
36 | exp: e 'e'; | |
37 | e: 'e' | /* Nothing. */; | |
38 | ]]) | |
39 | ||
da730230 | 40 | AT_BISON_CHECK([-o input.c input.y], 0, [], |
cff03fb2 | 41 | [[input.y:4.9: warning: rule useless in parser due to conflicts: e: /* empty */ |
e8832397 | 42 | ]]) |
643a5994 AD |
43 | |
44 | AT_CLEANUP | |
45 | ||
bc933ef1 | 46 | |
3c31a486 AD |
47 | ## ------------------- ## |
48 | ## %nonassoc and eof. ## | |
49 | ## ------------------- ## | |
50 | ||
51 | AT_SETUP([%nonassoc and eof]) | |
52 | ||
9501dc6e | 53 | AT_DATA_GRAMMAR([input.y], |
3c31a486 AD |
54 | [[ |
55 | %{ | |
56 | #include <stdio.h> | |
6e26ca8c | 57 | #include <stdlib.h> |
cf806753 | 58 | #include <string.h> |
1207eeac | 59 | |
3c31a486 | 60 | #define YYERROR_VERBOSE 1 |
1207eeac AD |
61 | static void |
62 | yyerror (const char *msg) | |
63 | { | |
64 | fprintf (stderr, "%s\n", msg); | |
1207eeac | 65 | } |
3c31a486 AD |
66 | |
67 | /* The current argument. */ | |
cf806753 | 68 | static const char *input; |
3c31a486 AD |
69 | |
70 | static int | |
71 | yylex (void) | |
72 | { | |
cf806753 PE |
73 | static size_t toknum; |
74 | if (! (toknum <= strlen (input))) | |
75 | abort (); | |
76 | return input[toknum++]; | |
3c31a486 AD |
77 | } |
78 | ||
79 | %} | |
80 | ||
81 | %nonassoc '<' '>' | |
82 | ||
83 | %% | |
84 | expr: expr '<' expr | |
85 | | expr '>' expr | |
86 | | '0' | |
87 | ; | |
88 | %% | |
89 | int | |
90 | main (int argc, const char *argv[]) | |
91 | { | |
9d774aff | 92 | input = argc <= 1 ? "" : argv[1]; |
3c31a486 AD |
93 | return yyparse (); |
94 | } | |
95 | ]]) | |
96 | ||
97 | # Specify the output files to avoid problems on different file systems. | |
da730230 | 98 | AT_BISON_CHECK([-o input.c input.y]) |
1154cced | 99 | AT_COMPILE([input]) |
3c31a486 | 100 | |
1154cced | 101 | AT_PARSER_CHECK([./input '0<0']) |
1154cced | 102 | AT_PARSER_CHECK([./input '0<0<0'], [1], [], |
53f036ce | 103 | [syntax error, unexpected '<' |
3c31a486 AD |
104 | ]) |
105 | ||
1154cced AD |
106 | AT_PARSER_CHECK([./input '0>0']) |
107 | AT_PARSER_CHECK([./input '0>0>0'], [1], [], | |
53f036ce | 108 | [syntax error, unexpected '>' |
3c31a486 AD |
109 | ]) |
110 | ||
1154cced | 111 | AT_PARSER_CHECK([./input '0<0>0'], [1], [], |
53f036ce | 112 | [syntax error, unexpected '>' |
3c31a486 AD |
113 | ]) |
114 | ||
d1cc31c5 JD |
115 | # We must disable default reductions in inconsistent states in order to |
116 | # have an explicit list of all expected tokens. (However, unless we use | |
117 | # canonical LR, lookahead sets are merged for different left contexts, | |
118 | # so it is still possible to have extra incorrect tokens in the expected | |
119 | # list. That just doesn't happen to be a problem for this test case.) | |
120 | ||
121 | AT_BISON_CHECK([-Dlr.default-reductions=consistent -o input.c input.y]) | |
122 | AT_COMPILE([input]) | |
123 | ||
124 | AT_PARSER_CHECK([./input '0<0']) | |
125 | AT_PARSER_CHECK([./input '0<0<0'], [1], [], | |
126 | [syntax error, unexpected '<', expecting $end | |
127 | ]) | |
128 | ||
129 | AT_PARSER_CHECK([./input '0>0']) | |
130 | AT_PARSER_CHECK([./input '0>0>0'], [1], [], | |
131 | [syntax error, unexpected '>', expecting $end | |
132 | ]) | |
133 | ||
134 | AT_PARSER_CHECK([./input '0<0>0'], [1], [], | |
135 | [syntax error, unexpected '>', expecting $end | |
136 | ]) | |
137 | ||
3c31a486 AD |
138 | AT_CLEANUP |
139 | ||
140 | ||
141 | ||
df222dfa JD |
142 | ## ------------------------------------------- ## |
143 | ## parse.error=verbose and consistent errors. ## | |
144 | ## ------------------------------------------- ## | |
145 | ||
146 | AT_SETUP([[parse.error=verbose and consistent errors]]) | |
147 | ||
148 | m4_pushdef([AT_CONSISTENT_ERRORS_CHECK], [ | |
149 | ||
df222dfa JD |
150 | AT_DATA_GRAMMAR([input.y], |
151 | [[%code { | |
152 | #include <assert.h> | |
153 | #include <stdio.h> | |
154 | int yylex (void); | |
155 | void yyerror (char const *); | |
156 | #define USE(Var) | |
157 | } | |
158 | ||
25a648d8 JD |
159 | ]$1[ |
160 | ||
df222dfa JD |
161 | %define parse.error verbose |
162 | ||
25a648d8 JD |
163 | %% |
164 | ||
165 | ]$2[ | |
166 | ||
167 | %% | |
168 | ||
169 | int | |
170 | yylex (void) | |
171 | { | |
172 | static char const *input = "]$3["; | |
173 | yylval = 1; | |
174 | return *input++; | |
175 | } | |
176 | ||
177 | void | |
178 | yyerror (char const *msg) | |
179 | { | |
180 | fprintf (stderr, "%s\n", msg); | |
181 | } | |
182 | ||
183 | int | |
184 | main (void) | |
185 | { | |
186 | return yyparse (); | |
187 | } | |
188 | ]]) | |
189 | AT_BISON_CHECK([[-o input.c input.y]]) | |
190 | AT_COMPILE([[input]]) | |
191 | ||
192 | m4_pushdef([AT_EXPECTING], [m4_if($5, [ab], [[, expecting 'a' or 'b']], | |
193 | $5, [a], [[, expecting 'a']], | |
194 | $5, [b], [[, expecting 'b']])]) | |
df222dfa | 195 | |
25a648d8 JD |
196 | AT_PARSER_CHECK([[./input]], [[1]], [[]], |
197 | [[syntax error, unexpected ]$4[]AT_EXPECTING[ | |
198 | ]]) | |
199 | ||
200 | m4_popdef([AT_EXPECTING]) | |
201 | ||
202 | ]) | |
203 | ||
204 | m4_pushdef([AT_USER_ACTION_GRAMMAR], | |
205 | [[%nonassoc 'a'; | |
df222dfa JD |
206 | |
207 | // If yylval=0 here, then we know that the 'a' destructor is being | |
208 | // invoked incorrectly for the 'b' set in the semantic action below. | |
209 | // All 'a' tokens are returned by yylex, which sets yylval=1. | |
210 | %destructor { | |
211 | if (!$$) | |
212 | fprintf (stderr, "Wrong destructor.\n"); | |
25a648d8 | 213 | } 'a'; |
df222dfa JD |
214 | |
215 | // The lookahead assigned by the semantic action isn't needed before | |
216 | // either error action is encountered. In a previous version of Bison, | |
217 | // this was a problem as it meant yychar was not translated into yytoken | |
218 | // before either error action. The second error action thus invoked a | |
219 | // destructor that it selected according to the incorrect yytoken. The | |
220 | // first error action would have reported an incorrect unexpected token | |
221 | // except that, due to another bug, the unexpected token is not reported | |
222 | // at all because the error action is the default action in a consistent | |
223 | // state. That bug still needs to be fixed. | |
25a648d8 | 224 | start: error-reduce consistent-error 'a' { USE ($][3); } ; |
df222dfa JD |
225 | |
226 | error-reduce: | |
227 | 'a' 'a' consistent-reduction consistent-error 'a' | |
25a648d8 | 228 | { USE (($][1, $][2, $][5)); } |
df222dfa | 229 | | 'a' error |
25a648d8 | 230 | { USE ($][1); } |
df222dfa JD |
231 | ; |
232 | ||
233 | consistent-reduction: /*empty*/ { | |
234 | assert (yychar == YYEMPTY); | |
235 | yylval = 0; | |
236 | yychar = 'b'; | |
237 | } ; | |
238 | ||
239 | consistent-error: | |
25a648d8 | 240 | 'a' { USE ($][1); } |
df222dfa JD |
241 | | /*empty*/ %prec 'a' |
242 | ; | |
243 | ||
244 | // Provide another context in which all rules are useful so that this | |
245 | // test case looks a little more realistic. | |
246 | start: 'b' consistent-error 'b' ; | |
df222dfa | 247 | ]]) |
25a648d8 | 248 | m4_pushdef([AT_USER_ACTION_INPUT], [[aa]]) |
df222dfa JD |
249 | |
250 | # See comments in grammar for why this test doesn't succeed. | |
251 | AT_XFAIL_IF([[:]]) | |
252 | ||
25a648d8 JD |
253 | AT_CONSISTENT_ERRORS_CHECK([[]], |
254 | [AT_USER_ACTION_GRAMMAR], | |
255 | [AT_USER_ACTION_INPUT], | |
256 | [['b']], [[none]]) | |
257 | AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reductions consistent]], | |
258 | [AT_USER_ACTION_GRAMMAR], | |
259 | [AT_USER_ACTION_INPUT], | |
df222dfa JD |
260 | [['b']], [[none]]) |
261 | ||
262 | # Canonical LR doesn't foresee the error for 'a'! | |
25a648d8 JD |
263 | AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reductions accepting]], |
264 | [AT_USER_ACTION_GRAMMAR], | |
265 | [AT_USER_ACTION_INPUT], | |
df222dfa | 266 | [[$end]], [[a]]) |
25a648d8 JD |
267 | AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr]], |
268 | [AT_USER_ACTION_GRAMMAR], | |
269 | [AT_USER_ACTION_INPUT], | |
270 | [[$end]], [[a]]) | |
271 | ||
272 | m4_popdef([AT_USER_ACTION_GRAMMAR]) | |
273 | m4_popdef([AT_USER_ACTION_INPUT]) | |
df222dfa JD |
274 | |
275 | m4_popdef([AT_CONSISTENT_ERRORS_CHECK]) | |
276 | ||
277 | AT_CLEANUP | |
278 | ||
279 | ||
280 | ||
3c31a486 AD |
281 | ## ------------------------- ## |
282 | ## Unresolved SR Conflicts. ## | |
283 | ## ------------------------- ## | |
284 | ||
285 | AT_SETUP([Unresolved SR Conflicts]) | |
286 | ||
6b98e4b5 AD |
287 | AT_KEYWORDS([report]) |
288 | ||
3c31a486 AD |
289 | AT_DATA([input.y], |
290 | [[%token NUM OP | |
291 | %% | |
292 | exp: exp OP exp | NUM; | |
293 | ]]) | |
294 | ||
da730230 | 295 | AT_BISON_CHECK([-o input.c --report=all input.y], 0, [], |
2c8ba4cd | 296 | [input.y: conflicts: 1 shift/reduce |
3c31a486 AD |
297 | ]) |
298 | ||
299 | # Check the contents of the report. | |
300 | AT_CHECK([cat input.output], [], | |
2c8ba4cd | 301 | [[State 5 conflicts: 1 shift/reduce |
3c31a486 AD |
302 | |
303 | ||
304 | Grammar | |
305 | ||
88bce5a2 | 306 | 0 $accept: exp $end |
6b98e4b5 AD |
307 | |
308 | 1 exp: exp OP exp | |
309 | 2 | NUM | |
3c31a486 AD |
310 | |
311 | ||
312 | Terminals, with rules where they appear | |
313 | ||
88bce5a2 | 314 | $end (0) 0 |
3c31a486 | 315 | error (256) |
007a50a4 AD |
316 | NUM (258) 2 |
317 | OP (259) 1 | |
3c31a486 AD |
318 | |
319 | ||
320 | Nonterminals, with rules where they appear | |
321 | ||
88bce5a2 | 322 | $accept (5) |
3c31a486 AD |
323 | on left: 0 |
324 | exp (6) | |
325 | on left: 1 2, on right: 0 1 | |
326 | ||
327 | ||
328 | state 0 | |
329 | ||
88bce5a2 | 330 | 0 $accept: . exp $end |
ce4ccb4b AD |
331 | 1 exp: . exp OP exp |
332 | 2 | . NUM | |
643a5994 | 333 | |
87675353 | 334 | NUM shift, and go to state 1 |
3c31a486 | 335 | |
87675353 | 336 | exp go to state 2 |
3c31a486 AD |
337 | |
338 | ||
339 | state 1 | |
340 | ||
ce4ccb4b | 341 | 2 exp: NUM . |
3c31a486 | 342 | |
87675353 | 343 | $default reduce using rule 2 (exp) |
3c31a486 AD |
344 | |
345 | ||
346 | state 2 | |
347 | ||
88bce5a2 | 348 | 0 $accept: exp . $end |
ce4ccb4b | 349 | 1 exp: exp . OP exp |
3c31a486 | 350 | |
88bce5a2 AD |
351 | $end shift, and go to state 3 |
352 | OP shift, and go to state 4 | |
3c31a486 AD |
353 | |
354 | ||
355 | state 3 | |
356 | ||
88bce5a2 | 357 | 0 $accept: exp $end . |
3c31a486 | 358 | |
e8832397 | 359 | $default accept |
3c31a486 AD |
360 | |
361 | ||
362 | state 4 | |
363 | ||
ce4ccb4b AD |
364 | 1 exp: . exp OP exp |
365 | 1 | exp OP . exp | |
366 | 2 | . NUM | |
3c31a486 | 367 | |
87675353 | 368 | NUM shift, and go to state 1 |
3c31a486 | 369 | |
87675353 | 370 | exp go to state 5 |
3c31a486 AD |
371 | |
372 | ||
373 | state 5 | |
374 | ||
a0de5091 | 375 | 1 exp: exp . OP exp |
88bce5a2 | 376 | 1 | exp OP exp . [$end, OP] |
3c31a486 | 377 | |
87675353 | 378 | OP shift, and go to state 4 |
3c31a486 | 379 | |
87675353 AD |
380 | OP [reduce using rule 1 (exp)] |
381 | $default reduce using rule 1 (exp) | |
3c31a486 AD |
382 | ]]) |
383 | ||
384 | AT_CLEANUP | |
385 | ||
386 | ||
3c31a486 | 387 | |
ce4ccb4b AD |
388 | ## ----------------------- ## |
389 | ## Resolved SR Conflicts. ## | |
390 | ## ----------------------- ## | |
391 | ||
392 | AT_SETUP([Resolved SR Conflicts]) | |
3c31a486 | 393 | |
6b98e4b5 AD |
394 | AT_KEYWORDS([report]) |
395 | ||
3c31a486 AD |
396 | AT_DATA([input.y], |
397 | [[%token NUM OP | |
ce4ccb4b | 398 | %left OP |
3c31a486 AD |
399 | %% |
400 | exp: exp OP exp | NUM; | |
401 | ]]) | |
402 | ||
da730230 | 403 | AT_BISON_CHECK([-o input.c --report=all input.y]) |
3c31a486 AD |
404 | |
405 | # Check the contents of the report. | |
406 | AT_CHECK([cat input.output], [], | |
ce4ccb4b | 407 | [[Grammar |
3c31a486 | 408 | |
88bce5a2 | 409 | 0 $accept: exp $end |
6b98e4b5 AD |
410 | |
411 | 1 exp: exp OP exp | |
412 | 2 | NUM | |
3c31a486 AD |
413 | |
414 | ||
415 | Terminals, with rules where they appear | |
416 | ||
88bce5a2 | 417 | $end (0) 0 |
3c31a486 | 418 | error (256) |
007a50a4 AD |
419 | NUM (258) 2 |
420 | OP (259) 1 | |
3c31a486 AD |
421 | |
422 | ||
423 | Nonterminals, with rules where they appear | |
424 | ||
88bce5a2 | 425 | $accept (5) |
3c31a486 AD |
426 | on left: 0 |
427 | exp (6) | |
428 | on left: 1 2, on right: 0 1 | |
429 | ||
430 | ||
431 | state 0 | |
432 | ||
88bce5a2 | 433 | 0 $accept: . exp $end |
ce4ccb4b AD |
434 | 1 exp: . exp OP exp |
435 | 2 | . NUM | |
643a5994 | 436 | |
87675353 | 437 | NUM shift, and go to state 1 |
3c31a486 | 438 | |
87675353 | 439 | exp go to state 2 |
3c31a486 AD |
440 | |
441 | ||
442 | state 1 | |
443 | ||
ce4ccb4b | 444 | 2 exp: NUM . |
3c31a486 | 445 | |
87675353 | 446 | $default reduce using rule 2 (exp) |
3c31a486 AD |
447 | |
448 | ||
449 | state 2 | |
450 | ||
88bce5a2 | 451 | 0 $accept: exp . $end |
ce4ccb4b | 452 | 1 exp: exp . OP exp |
3c31a486 | 453 | |
88bce5a2 AD |
454 | $end shift, and go to state 3 |
455 | OP shift, and go to state 4 | |
3c31a486 AD |
456 | |
457 | ||
458 | state 3 | |
459 | ||
88bce5a2 | 460 | 0 $accept: exp $end . |
3c31a486 | 461 | |
e8832397 | 462 | $default accept |
3c31a486 AD |
463 | |
464 | ||
465 | state 4 | |
466 | ||
ce4ccb4b AD |
467 | 1 exp: . exp OP exp |
468 | 1 | exp OP . exp | |
469 | 2 | . NUM | |
3c31a486 | 470 | |
87675353 | 471 | NUM shift, and go to state 1 |
3c31a486 | 472 | |
87675353 | 473 | exp go to state 5 |
3c31a486 AD |
474 | |
475 | ||
476 | state 5 | |
477 | ||
a0de5091 | 478 | 1 exp: exp . OP exp |
88bce5a2 | 479 | 1 | exp OP exp . [$end, OP] |
3c31a486 | 480 | |
87675353 | 481 | $default reduce using rule 1 (exp) |
7ea9a33f | 482 | |
4b3d3a8e | 483 | Conflict between rule 1 and token OP resolved as reduce (%left OP). |
bc933ef1 AD |
484 | ]]) |
485 | ||
486 | AT_CLEANUP | |
487 | ||
488 | ||
d78f0ac9 AD |
489 | ## ---------------------- ## |
490 | ## %precedence suffices. ## | |
491 | ## ---------------------- ## | |
492 | ||
493 | AT_SETUP([%precedence suffices]) | |
494 | ||
495 | AT_DATA([input.y], | |
496 | [[%precedence "then" | |
497 | %precedence "else" | |
498 | %% | |
499 | stmt: | |
500 | "if" cond "then" stmt | |
501 | | "if" cond "then" stmt "else" stmt | |
502 | | "stmt" | |
503 | ; | |
504 | ||
505 | cond: | |
506 | "exp" | |
507 | ; | |
508 | ]]) | |
509 | ||
510 | AT_BISON_CHECK([-o input.c input.y]) | |
511 | ||
512 | AT_CLEANUP | |
513 | ||
514 | ||
515 | ## ------------------------------ ## | |
516 | ## %precedence does not suffice. ## | |
517 | ## ------------------------------ ## | |
518 | ||
519 | AT_SETUP([%precedence does not suffice]) | |
520 | ||
521 | AT_DATA([input.y], | |
522 | [[%precedence "then" | |
523 | %precedence "else" | |
524 | %% | |
525 | stmt: | |
526 | "if" cond "then" stmt | |
527 | | "if" cond "then" stmt "else" stmt | |
528 | | "stmt" | |
529 | ; | |
530 | ||
531 | cond: | |
532 | "exp" | |
533 | | cond "then" cond | |
534 | ; | |
535 | ]]) | |
536 | ||
537 | AT_BISON_CHECK([-o input.c input.y], 0, [], | |
538 | [[input.y: conflicts: 1 shift/reduce | |
539 | input.y:12.3-18: warning: rule useless in parser due to conflicts: cond: cond "then" cond | |
540 | ]]) | |
541 | ||
542 | AT_CLEANUP | |
543 | ||
544 | ||
bc933ef1 AD |
545 | ## -------------------------------- ## |
546 | ## Defaulted Conflicted Reduction. ## | |
547 | ## -------------------------------- ## | |
548 | ||
549 | # When there are RR conflicts, some rules are disabled. Usually it is | |
550 | # simply displayed as: | |
551 | # | |
88bce5a2 AD |
552 | # $end reduce using rule 3 (num) |
553 | # $end [reduce using rule 4 (id)] | |
bc933ef1 AD |
554 | # |
555 | # But when `reduce 3' is the default action, we'd produce: | |
556 | # | |
88bce5a2 | 557 | # $end [reduce using rule 4 (id)] |
bc933ef1 AD |
558 | # $default reduce using rule 3 (num) |
559 | # | |
560 | # In this precise case (a reduction is masked by the default | |
561 | # reduction), we make the `reduce 3' explicit: | |
562 | # | |
88bce5a2 AD |
563 | # $end reduce using rule 3 (num) |
564 | # $end [reduce using rule 4 (id)] | |
bc933ef1 AD |
565 | # $default reduce using rule 3 (num) |
566 | # | |
567 | # Maybe that's not the best display, but then, please propose something | |
568 | # else. | |
569 | ||
570 | AT_SETUP([Defaulted Conflicted Reduction]) | |
571 | AT_KEYWORDS([report]) | |
572 | ||
573 | AT_DATA([input.y], | |
574 | [[%% | |
575 | exp: num | id; | |
576 | num: '0'; | |
577 | id : '0'; | |
578 | %% | |
579 | ]]) | |
580 | ||
da730230 | 581 | AT_BISON_CHECK([-o input.c --report=all input.y], 0, [], |
2c8ba4cd | 582 | [[input.y: conflicts: 1 reduce/reduce |
cff03fb2 | 583 | input.y:4.6-8: warning: rule useless in parser due to conflicts: id: '0' |
e8832397 | 584 | ]]) |
bc933ef1 AD |
585 | |
586 | # Check the contents of the report. | |
587 | AT_CHECK([cat input.output], [], | |
cff03fb2 | 588 | [[Rules useless in parser due to conflicts |
c8f002c7 AD |
589 | |
590 | 4 id: '0' | |
591 | ||
592 | ||
2c8ba4cd | 593 | State 1 conflicts: 1 reduce/reduce |
bc933ef1 AD |
594 | |
595 | ||
596 | Grammar | |
597 | ||
88bce5a2 | 598 | 0 $accept: exp $end |
bc933ef1 AD |
599 | |
600 | 1 exp: num | |
601 | 2 | id | |
602 | ||
603 | 3 num: '0' | |
604 | ||
605 | 4 id: '0' | |
606 | ||
607 | ||
608 | Terminals, with rules where they appear | |
609 | ||
88bce5a2 | 610 | $end (0) 0 |
bc933ef1 AD |
611 | '0' (48) 3 4 |
612 | error (256) | |
613 | ||
614 | ||
615 | Nonterminals, with rules where they appear | |
616 | ||
88bce5a2 | 617 | $accept (4) |
bc933ef1 AD |
618 | on left: 0 |
619 | exp (5) | |
620 | on left: 1 2, on right: 0 | |
621 | num (6) | |
622 | on left: 3, on right: 1 | |
623 | id (7) | |
624 | on left: 4, on right: 2 | |
625 | ||
626 | ||
627 | state 0 | |
628 | ||
88bce5a2 | 629 | 0 $accept: . exp $end |
ce4ccb4b AD |
630 | 1 exp: . num |
631 | 2 | . id | |
632 | 3 num: . '0' | |
633 | 4 id: . '0' | |
bc933ef1 | 634 | |
87675353 | 635 | '0' shift, and go to state 1 |
bc933ef1 | 636 | |
87675353 AD |
637 | exp go to state 2 |
638 | num go to state 3 | |
639 | id go to state 4 | |
bc933ef1 AD |
640 | |
641 | ||
642 | state 1 | |
643 | ||
88bce5a2 AD |
644 | 3 num: '0' . [$end] |
645 | 4 id: '0' . [$end] | |
bc933ef1 | 646 | |
88bce5a2 AD |
647 | $end reduce using rule 3 (num) |
648 | $end [reduce using rule 4 (id)] | |
87675353 | 649 | $default reduce using rule 3 (num) |
bc933ef1 AD |
650 | |
651 | ||
652 | state 2 | |
653 | ||
88bce5a2 | 654 | 0 $accept: exp . $end |
bc933ef1 | 655 | |
88bce5a2 | 656 | $end shift, and go to state 5 |
bc933ef1 AD |
657 | |
658 | ||
659 | state 3 | |
660 | ||
ce4ccb4b | 661 | 1 exp: num . |
bc933ef1 | 662 | |
87675353 | 663 | $default reduce using rule 1 (exp) |
bc933ef1 AD |
664 | |
665 | ||
666 | state 4 | |
667 | ||
ce4ccb4b | 668 | 2 exp: id . |
bc933ef1 | 669 | |
87675353 | 670 | $default reduce using rule 2 (exp) |
bc933ef1 AD |
671 | |
672 | ||
673 | state 5 | |
674 | ||
88bce5a2 | 675 | 0 $accept: exp $end . |
bc933ef1 | 676 | |
e8832397 | 677 | $default accept |
3c31a486 AD |
678 | ]]) |
679 | ||
680 | AT_CLEANUP | |
681 | ||
682 | ||
683 | ||
684 | ||
685 | ## -------------------- ## | |
686 | ## %expect not enough. ## | |
687 | ## -------------------- ## | |
688 | ||
689 | AT_SETUP([%expect not enough]) | |
690 | ||
691 | AT_DATA([input.y], | |
692 | [[%token NUM OP | |
693 | %expect 0 | |
694 | %% | |
695 | exp: exp OP exp | NUM; | |
696 | ]]) | |
697 | ||
da730230 | 698 | AT_BISON_CHECK([-o input.c input.y], 1, [], |
2c8ba4cd | 699 | [input.y: conflicts: 1 shift/reduce |
035aa4a0 | 700 | input.y: expected 0 shift/reduce conflicts |
3c31a486 AD |
701 | ]) |
702 | AT_CLEANUP | |
703 | ||
704 | ||
705 | ## --------------- ## | |
706 | ## %expect right. ## | |
707 | ## --------------- ## | |
708 | ||
709 | AT_SETUP([%expect right]) | |
710 | ||
711 | AT_DATA([input.y], | |
712 | [[%token NUM OP | |
713 | %expect 1 | |
714 | %% | |
715 | exp: exp OP exp | NUM; | |
716 | ]]) | |
717 | ||
da730230 | 718 | AT_BISON_CHECK([-o input.c input.y]) |
3c31a486 AD |
719 | AT_CLEANUP |
720 | ||
721 | ||
722 | ## ------------------ ## | |
723 | ## %expect too much. ## | |
724 | ## ------------------ ## | |
725 | ||
726 | AT_SETUP([%expect too much]) | |
727 | ||
728 | AT_DATA([input.y], | |
729 | [[%token NUM OP | |
730 | %expect 2 | |
731 | %% | |
732 | exp: exp OP exp | NUM; | |
733 | ]]) | |
734 | ||
da730230 | 735 | AT_BISON_CHECK([-o input.c input.y], 1, [], |
2c8ba4cd | 736 | [input.y: conflicts: 1 shift/reduce |
035aa4a0 | 737 | input.y: expected 2 shift/reduce conflicts |
3c31a486 AD |
738 | ]) |
739 | AT_CLEANUP | |
6876ecd3 PE |
740 | |
741 | ||
41976786 AD |
742 | ## ------------------------------- ## |
743 | ## %expect with reduce conflicts. ## | |
744 | ## ------------------------------- ## | |
6876ecd3 PE |
745 | |
746 | AT_SETUP([%expect with reduce conflicts]) | |
747 | ||
748 | AT_DATA([input.y], | |
749 | [[%expect 0 | |
750 | %% | |
751 | program: a 'a' | a a; | |
752 | a: 'a'; | |
753 | ]]) | |
754 | ||
da730230 | 755 | AT_BISON_CHECK([-o input.c input.y], 1, [], |
2c8ba4cd | 756 | [input.y: conflicts: 1 reduce/reduce |
035aa4a0 | 757 | input.y: expected 0 reduce/reduce conflicts |
6876ecd3 PE |
758 | ]) |
759 | AT_CLEANUP | |
39a06c25 PE |
760 | |
761 | ||
44bb9084 AD |
762 | ## ------------------------- ## |
763 | ## %prec with user strings. ## | |
764 | ## ------------------------- ## | |
765 | ||
766 | AT_SETUP([%prec with user string]) | |
767 | ||
768 | AT_DATA([[input.y]], | |
769 | [[%% | |
770 | exp: | |
771 | "foo" %prec "foo" | |
772 | ; | |
773 | ]]) | |
774 | ||
775 | AT_BISON_CHECK([-o input.c input.y]) | |
776 | AT_CLEANUP | |
777 | ||
778 | ||
779 | ## -------------------------------- ## | |
780 | ## %no-default-prec without %prec. ## | |
781 | ## -------------------------------- ## | |
39a06c25 | 782 | |
22fccf95 | 783 | AT_SETUP([%no-default-prec without %prec]) |
39a06c25 PE |
784 | |
785 | AT_DATA([[input.y]], | |
786 | [[%left '+' | |
787 | %left '*' | |
788 | ||
789 | %% | |
790 | ||
22fccf95 | 791 | %no-default-prec; |
39a06c25 PE |
792 | |
793 | e: e '+' e | |
794 | | e '*' e | |
795 | | '0' | |
796 | ; | |
797 | ]]) | |
798 | ||
da730230 | 799 | AT_BISON_CHECK([-o input.c input.y], 0, [], |
39a06c25 PE |
800 | [[input.y: conflicts: 4 shift/reduce |
801 | ]]) | |
802 | AT_CLEANUP | |
803 | ||
804 | ||
41976786 AD |
805 | ## ----------------------------- ## |
806 | ## %no-default-prec with %prec. ## | |
807 | ## ----------------------------- ## | |
39a06c25 | 808 | |
22fccf95 | 809 | AT_SETUP([%no-default-prec with %prec]) |
39a06c25 PE |
810 | |
811 | AT_DATA([[input.y]], | |
812 | [[%left '+' | |
813 | %left '*' | |
814 | ||
815 | %% | |
816 | ||
22fccf95 | 817 | %no-default-prec; |
39a06c25 PE |
818 | |
819 | e: e '+' e %prec '+' | |
820 | | e '*' e %prec '*' | |
821 | | '0' | |
822 | ; | |
823 | ]]) | |
824 | ||
da730230 | 825 | AT_BISON_CHECK([-o input.c input.y]) |
39a06c25 PE |
826 | AT_CLEANUP |
827 | ||
828 | ||
41976786 AD |
829 | ## --------------- ## |
830 | ## %default-prec. ## | |
831 | ## --------------- ## | |
39a06c25 | 832 | |
22fccf95 | 833 | AT_SETUP([%default-prec]) |
39a06c25 PE |
834 | |
835 | AT_DATA([[input.y]], | |
836 | [[%left '+' | |
837 | %left '*' | |
838 | ||
839 | %% | |
840 | ||
22fccf95 | 841 | %default-prec; |
39a06c25 PE |
842 | |
843 | e: e '+' e | |
844 | | e '*' e | |
845 | | '0' | |
846 | ; | |
847 | ]]) | |
848 | ||
da730230 | 849 | AT_BISON_CHECK([-o input.c input.y]) |
39a06c25 | 850 | AT_CLEANUP |
5967f0cf JD |
851 | |
852 | ||
853 | ## ---------------------------------------------- ## | |
854 | ## Unreachable States After Conflict Resolution. ## | |
855 | ## ---------------------------------------------- ## | |
856 | ||
857 | AT_SETUP([[Unreachable States After Conflict Resolution]]) | |
858 | ||
859 | # If conflict resolution makes states unreachable, remove those states, report | |
860 | # rules that are then unused, and don't report conflicts in those states. Test | |
861 | # what happens when a nonterminal becomes useless as a result of state removal | |
862 | # since that causes lalr.o's goto map to be rewritten. | |
863 | ||
864 | AT_DATA([[input.y]], | |
865 | [[%output "input.c" | |
866 | %left 'a' | |
867 | ||
868 | %% | |
869 | ||
870 | start: resolved_conflict 'a' reported_conflicts 'a' ; | |
871 | ||
31984206 | 872 | /* S/R conflict resolved as reduce, so the state with item |
5967f0cf JD |
873 | * (resolved_conflict: 'a' . unreachable1) and all it transition successors are |
874 | * unreachable, and the associated production is useless. */ | |
875 | resolved_conflict: | |
876 | 'a' unreachable1 | |
877 | | %prec 'a' | |
878 | ; | |
879 | ||
880 | /* S/R conflict that need not be reported since it is unreachable because of | |
881 | * the previous conflict resolution. Nonterminal unreachable1 and all its | |
882 | * productions are useless. */ | |
883 | unreachable1: | |
884 | 'a' unreachable2 | |
885 | | | |
886 | ; | |
887 | ||
888 | /* Likewise for a R/R conflict and nonterminal unreachable2. */ | |
889 | unreachable2: | ; | |
890 | ||
891 | /* Make sure remaining S/R and R/R conflicts are still reported correctly even | |
892 | * when their states are renumbered due to state removal. */ | |
893 | reported_conflicts: | |
894 | 'a' | |
895 | | 'a' | |
896 | | | |
897 | ; | |
898 | ||
899 | ]]) | |
900 | ||
da730230 | 901 | AT_BISON_CHECK([[--report=all input.y]], 0, [], |
5967f0cf | 902 | [[input.y: conflicts: 1 shift/reduce, 1 reduce/reduce |
cff03fb2 JD |
903 | input.y:12.5-20: warning: rule useless in parser due to conflicts: resolved_conflict: 'a' unreachable1 |
904 | input.y:20.5-20: warning: rule useless in parser due to conflicts: unreachable1: 'a' unreachable2 | |
905 | input.y:21.4: warning: rule useless in parser due to conflicts: unreachable1: /* empty */ | |
906 | input.y:25.13: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ | |
907 | input.y:25.16: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ | |
908 | input.y:31.5-7: warning: rule useless in parser due to conflicts: reported_conflicts: 'a' | |
909 | input.y:32.4: warning: rule useless in parser due to conflicts: reported_conflicts: /* empty */ | |
5967f0cf JD |
910 | ]]) |
911 | ||
912 | AT_CHECK([[cat input.output]], 0, | |
cff03fb2 | 913 | [[Rules useless in parser due to conflicts |
5967f0cf JD |
914 | |
915 | 2 resolved_conflict: 'a' unreachable1 | |
916 | ||
917 | 4 unreachable1: 'a' unreachable2 | |
918 | 5 | /* empty */ | |
919 | ||
920 | 6 unreachable2: /* empty */ | |
921 | 7 | /* empty */ | |
922 | ||
923 | 9 reported_conflicts: 'a' | |
924 | 10 | /* empty */ | |
925 | ||
926 | ||
927 | State 4 conflicts: 1 shift/reduce | |
928 | State 5 conflicts: 1 reduce/reduce | |
929 | ||
930 | ||
931 | Grammar | |
932 | ||
933 | 0 $accept: start $end | |
934 | ||
935 | 1 start: resolved_conflict 'a' reported_conflicts 'a' | |
936 | ||
937 | 2 resolved_conflict: 'a' unreachable1 | |
938 | 3 | /* empty */ | |
939 | ||
940 | 4 unreachable1: 'a' unreachable2 | |
941 | 5 | /* empty */ | |
942 | ||
943 | 6 unreachable2: /* empty */ | |
944 | 7 | /* empty */ | |
945 | ||
946 | 8 reported_conflicts: 'a' | |
947 | 9 | 'a' | |
948 | 10 | /* empty */ | |
949 | ||
950 | ||
951 | Terminals, with rules where they appear | |
952 | ||
953 | $end (0) 0 | |
954 | 'a' (97) 1 2 4 8 9 | |
955 | error (256) | |
956 | ||
957 | ||
958 | Nonterminals, with rules where they appear | |
959 | ||
960 | $accept (4) | |
961 | on left: 0 | |
962 | start (5) | |
963 | on left: 1, on right: 0 | |
964 | resolved_conflict (6) | |
965 | on left: 2 3, on right: 1 | |
966 | unreachable1 (7) | |
967 | on left: 4 5, on right: 2 | |
968 | unreachable2 (8) | |
969 | on left: 6 7, on right: 4 | |
970 | reported_conflicts (9) | |
971 | on left: 8 9 10, on right: 1 | |
972 | ||
973 | ||
974 | state 0 | |
975 | ||
976 | 0 $accept: . start $end | |
977 | 1 start: . resolved_conflict 'a' reported_conflicts 'a' | |
978 | 2 resolved_conflict: . 'a' unreachable1 | |
979 | 3 | . ['a'] | |
980 | ||
981 | $default reduce using rule 3 (resolved_conflict) | |
982 | ||
983 | start go to state 1 | |
984 | resolved_conflict go to state 2 | |
985 | ||
986 | Conflict between rule 3 and token 'a' resolved as reduce (%left 'a'). | |
987 | ||
988 | ||
989 | state 1 | |
990 | ||
991 | 0 $accept: start . $end | |
992 | ||
993 | $end shift, and go to state 3 | |
994 | ||
995 | ||
996 | state 2 | |
997 | ||
998 | 1 start: resolved_conflict . 'a' reported_conflicts 'a' | |
999 | ||
1000 | 'a' shift, and go to state 4 | |
1001 | ||
1002 | ||
1003 | state 3 | |
1004 | ||
1005 | 0 $accept: start $end . | |
1006 | ||
1007 | $default accept | |
1008 | ||
1009 | ||
1010 | state 4 | |
1011 | ||
1012 | 1 start: resolved_conflict 'a' . reported_conflicts 'a' | |
1013 | 8 reported_conflicts: . 'a' | |
1014 | 9 | . 'a' | |
1015 | 10 | . ['a'] | |
1016 | ||
1017 | 'a' shift, and go to state 5 | |
1018 | ||
1019 | 'a' [reduce using rule 10 (reported_conflicts)] | |
1020 | ||
1021 | reported_conflicts go to state 6 | |
1022 | ||
1023 | ||
1024 | state 5 | |
1025 | ||
1026 | 8 reported_conflicts: 'a' . ['a'] | |
1027 | 9 | 'a' . ['a'] | |
1028 | ||
1029 | 'a' reduce using rule 8 (reported_conflicts) | |
1030 | 'a' [reduce using rule 9 (reported_conflicts)] | |
1031 | $default reduce using rule 8 (reported_conflicts) | |
1032 | ||
1033 | ||
1034 | state 6 | |
1035 | ||
1036 | 1 start: resolved_conflict 'a' reported_conflicts . 'a' | |
1037 | ||
1038 | 'a' shift, and go to state 7 | |
1039 | ||
1040 | ||
1041 | state 7 | |
1042 | ||
1043 | 1 start: resolved_conflict 'a' reported_conflicts 'a' . | |
9d774aff | 1044 | |
5967f0cf JD |
1045 | $default reduce using rule 1 (start) |
1046 | ]]) | |
1047 | ||
31984206 | 1048 | AT_DATA([[input-keep.y]], |
67212941 | 1049 | [[%define lr.keep-unreachable-states |
31984206 JD |
1050 | ]]) |
1051 | AT_CHECK([[cat input.y >> input-keep.y]]) | |
1052 | ||
da730230 | 1053 | AT_BISON_CHECK([[input-keep.y]], 0, [], |
31984206 | 1054 | [[input-keep.y: conflicts: 2 shift/reduce, 2 reduce/reduce |
cff03fb2 JD |
1055 | input-keep.y:22.4: warning: rule useless in parser due to conflicts: unreachable1: /* empty */ |
1056 | input-keep.y:26.16: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ | |
1057 | input-keep.y:32.5-7: warning: rule useless in parser due to conflicts: reported_conflicts: 'a' | |
1058 | input-keep.y:33.4: warning: rule useless in parser due to conflicts: reported_conflicts: /* empty */ | |
31984206 JD |
1059 | ]]) |
1060 | ||
5967f0cf | 1061 | AT_CLEANUP |
9d774aff JD |
1062 | |
1063 | ||
1064 | ## ------------------------------------------------------------ ## | |
1065 | ## Solved conflicts report for multiple reductions in a state. ## | |
1066 | ## ------------------------------------------------------------ ## | |
1067 | ||
1068 | AT_SETUP([[Solved conflicts report for multiple reductions in a state]]) | |
1069 | ||
1070 | # Used to lose earlier solved conflict messages even within a single S/R/R. | |
1071 | ||
1072 | AT_DATA([[input.y]], | |
1073 | [[%left 'a' | |
1074 | %right 'b' | |
1075 | %right 'c' | |
1076 | %right 'd' | |
1077 | %% | |
1078 | start: | |
1079 | 'a' | |
1080 | | empty_a 'a' | |
1081 | | 'b' | |
1082 | | empty_b 'b' | |
1083 | | 'c' | |
1084 | | empty_c1 'c' | |
1085 | | empty_c2 'c' | |
1086 | | empty_c3 'c' | |
1087 | ; | |
1088 | empty_a: %prec 'a' ; | |
1089 | empty_b: %prec 'b' ; | |
1090 | empty_c1: %prec 'c' ; | |
1091 | empty_c2: %prec 'c' ; | |
1092 | empty_c3: %prec 'd' ; | |
1093 | ]]) | |
da730230 | 1094 | AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore]) |
9d774aff JD |
1095 | AT_CHECK([[cat input.output | sed -n '/^state 0$/,/^state 1$/p']], 0, |
1096 | [[state 0 | |
1097 | ||
1098 | 0 $accept: . start $end | |
1099 | 1 start: . 'a' | |
1100 | 2 | . empty_a 'a' | |
1101 | 3 | . 'b' | |
1102 | 4 | . empty_b 'b' | |
1103 | 5 | . 'c' | |
1104 | 6 | . empty_c1 'c' | |
1105 | 7 | . empty_c2 'c' | |
1106 | 8 | . empty_c3 'c' | |
1107 | 9 empty_a: . ['a'] | |
1108 | 10 empty_b: . [] | |
1109 | 11 empty_c1: . [] | |
1110 | 12 empty_c2: . [] | |
1111 | 13 empty_c3: . ['c'] | |
1112 | ||
1113 | 'b' shift, and go to state 1 | |
d78f0ac9 | 1114 | |
9d774aff JD |
1115 | 'c' reduce using rule 13 (empty_c3) |
1116 | $default reduce using rule 9 (empty_a) | |
1117 | ||
1118 | start go to state 2 | |
1119 | empty_a go to state 3 | |
1120 | empty_b go to state 4 | |
1121 | empty_c1 go to state 5 | |
1122 | empty_c2 go to state 6 | |
1123 | empty_c3 go to state 7 | |
1124 | ||
1125 | Conflict between rule 9 and token 'a' resolved as reduce (%left 'a'). | |
1126 | Conflict between rule 10 and token 'b' resolved as shift (%right 'b'). | |
1127 | Conflict between rule 11 and token 'c' resolved as shift (%right 'c'). | |
1128 | Conflict between rule 12 and token 'c' resolved as shift (%right 'c'). | |
1129 | Conflict between rule 13 and token 'c' resolved as reduce ('c' < 'd'). | |
1130 | ||
1131 | ||
1132 | state 1 | |
1133 | ]]) | |
1134 | ||
1135 | AT_CLEANUP | |
1136 | ||
1137 | ||
1138 | ## ------------------------------------------------------------ ## | |
1139 | ## %nonassoc error actions for multiple reductions in a state. ## | |
1140 | ## ------------------------------------------------------------ ## | |
1141 | ||
1142 | # Used to abort when trying to resolve conflicts as %nonassoc error actions for | |
1143 | # multiple reductions in a state. | |
1144 | ||
1145 | # For a %nonassoc error action token, used to print the first remaining | |
1146 | # reduction on that token without brackets. | |
1147 | ||
1148 | AT_SETUP([[%nonassoc error actions for multiple reductions in a state]]) | |
1149 | ||
1150 | AT_DATA([[input.y]], | |
1151 | [[%nonassoc 'a' 'b' 'c' | |
1152 | %% | |
1153 | start: | |
1154 | 'a' | |
1155 | | empty_a 'a' | |
1156 | | 'b' | |
1157 | | empty_b 'b' | |
1158 | | 'c' | |
1159 | | empty_c1 'c' | |
1160 | | empty_c2 'c' | |
1161 | | empty_c3 'c' | |
1162 | ; | |
1163 | empty_a: %prec 'a' ; | |
1164 | empty_b: %prec 'b' ; | |
1165 | empty_c1: %prec 'c' ; | |
1166 | empty_c2: %prec 'c' ; | |
1167 | empty_c3: %prec 'c' ; | |
1168 | ]]) | |
1169 | ||
da730230 | 1170 | AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore]) |
9d774aff JD |
1171 | AT_CHECK([[cat input.output | sed -n '/^state 0$/,/^state 1$/p']], 0, |
1172 | [[state 0 | |
1173 | ||
1174 | 0 $accept: . start $end | |
1175 | 1 start: . 'a' | |
1176 | 2 | . empty_a 'a' | |
1177 | 3 | . 'b' | |
1178 | 4 | . empty_b 'b' | |
1179 | 5 | . 'c' | |
1180 | 6 | . empty_c1 'c' | |
1181 | 7 | . empty_c2 'c' | |
1182 | 8 | . empty_c3 'c' | |
1183 | 9 empty_a: . [] | |
1184 | 10 empty_b: . [] | |
1185 | 11 empty_c1: . [] | |
1186 | 12 empty_c2: . ['c'] | |
1187 | 13 empty_c3: . ['c'] | |
1188 | ||
1189 | 'a' error (nonassociative) | |
1190 | 'b' error (nonassociative) | |
1191 | 'c' error (nonassociative) | |
1192 | ||
1193 | 'c' [reduce using rule 12 (empty_c2)] | |
1194 | 'c' [reduce using rule 13 (empty_c3)] | |
1195 | ||
1196 | start go to state 1 | |
1197 | empty_a go to state 2 | |
1198 | empty_b go to state 3 | |
1199 | empty_c1 go to state 4 | |
1200 | empty_c2 go to state 5 | |
1201 | empty_c3 go to state 6 | |
1202 | ||
1203 | Conflict between rule 9 and token 'a' resolved as an error (%nonassoc 'a'). | |
1204 | Conflict between rule 10 and token 'b' resolved as an error (%nonassoc 'b'). | |
1205 | Conflict between rule 11 and token 'c' resolved as an error (%nonassoc 'c'). | |
1206 | ||
1207 | ||
1208 | state 1 | |
1209 | ]]) | |
1210 | AT_CLEANUP |