1 # Exercising Bison Grammar Reduction. -*- Autotest -*-
3 # Copyright (C) 2001-2002, 2007-2011 Free Software Foundation, Inc.
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 AT_BANNER([[Grammar Reduction.]])
21 ## ------------------- ##
22 ## Useless Terminals. ##
23 ## ------------------- ##
25 AT_SETUP([Useless Terminals])
46 AT_BISON_CHECK([[input.y]])
48 AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
49 [[Terminals unused in grammar
65 ## ---------------------- ##
66 ## Useless Nonterminals. ##
67 ## ---------------------- ##
69 AT_SETUP([Useless Nonterminals])
90 AT_BISON_CHECK([[input.y]], 0, [],
91 [[input.y: warning: 9 nonterminals useless in grammar
92 input.y:4.8-15: warning: nonterminal useless in grammar: useless1
93 input.y:5.8-15: warning: nonterminal useless in grammar: useless2
94 input.y:6.8-15: warning: nonterminal useless in grammar: useless3
95 input.y:7.8-15: warning: nonterminal useless in grammar: useless4
96 input.y:8.8-15: warning: nonterminal useless in grammar: useless5
97 input.y:9.8-15: warning: nonterminal useless in grammar: useless6
98 input.y:10.8-15: warning: nonterminal useless in grammar: useless7
99 input.y:11.8-15: warning: nonterminal useless in grammar: useless8
100 input.y:12.8-15: warning: nonterminal useless in grammar: useless9
103 AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
104 [[Nonterminals useless in grammar
120 ## --------------- ##
122 ## --------------- ##
124 AT_SETUP([Useless Rules])
126 AT_KEYWORDS([report])
145 AT_BISON_CHECK([[input.y]], 0, [],
146 [[input.y: warning: 9 nonterminals useless in grammar
147 input.y: warning: 9 rules useless in grammar
148 input.y:6.1-8: warning: nonterminal useless in grammar: useless1
149 input.y:7.1-8: warning: nonterminal useless in grammar: useless2
150 input.y:8.1-8: warning: nonterminal useless in grammar: useless3
151 input.y:9.1-8: warning: nonterminal useless in grammar: useless4
152 input.y:10.1-8: warning: nonterminal useless in grammar: useless5
153 input.y:11.1-8: warning: nonterminal useless in grammar: useless6
154 input.y:12.1-8: warning: nonterminal useless in grammar: useless7
155 input.y:13.1-8: warning: nonterminal useless in grammar: useless8
156 input.y:14.1-8: warning: nonterminal useless in grammar: useless9
157 input.y:6.11-13: warning: rule useless in grammar: useless1: '1'
158 input.y:7.11-13: warning: rule useless in grammar: useless2: '2'
159 input.y:8.11-13: warning: rule useless in grammar: useless3: '3'
160 input.y:9.11-13: warning: rule useless in grammar: useless4: '4'
161 input.y:10.11-13: warning: rule useless in grammar: useless5: '5'
162 input.y:11.11-13: warning: rule useless in grammar: useless6: '6'
163 input.y:12.11-13: warning: rule useless in grammar: useless7: '7'
164 input.y:13.11-13: warning: rule useless in grammar: useless8: '8'
165 input.y:14.11-13: warning: rule useless in grammar: useless9: '9'
168 AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
169 [[Nonterminals useless in grammar
179 Terminals unused in grammar
189 Rules useless in grammar
205 ## ------------------- ##
206 ## Reduced Automaton. ##
207 ## ------------------- ##
209 # Check that the automaton is that as the for the grammar reduced by
212 AT_SETUP([Reduced Automaton])
214 AT_KEYWORDS([report])
216 # The non reduced grammar.
217 # ------------------------
218 AT_DATA([[not-reduced.y]],
219 [[/* A useless token. */
224 %output "not-reduced.c"
228 exp: useful { /* A useful action. */ }
229 | non_productive { /* A non productive action. */ }
232 not_reachable: useful { /* A not reachable action. */ }
235 non_productive: non_productive useless_token
236 { /* Another non productive action. */ }
241 AT_BISON_CHECK([[not-reduced.y]], 0, [],
242 [[not-reduced.y: warning: 2 nonterminals useless in grammar
243 not-reduced.y: warning: 3 rules useless in grammar
244 not-reduced.y:14.1-13: warning: nonterminal useless in grammar: not_reachable
245 not-reduced.y:11.6-19: warning: nonterminal useless in grammar: non_productive
246 not-reduced.y:11.6-57: warning: rule useless in grammar: exp: non_productive
247 not-reduced.y:14.16-56: warning: rule useless in grammar: not_reachable: useful
248 not-reduced.y:17.17-18.63: warning: rule useless in grammar: non_productive: non_productive useless_token
251 AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' not-reduced.output]], 0,
252 [[Nonterminals useless in grammar
255 Terminals unused in grammar
257 Rules useless in grammar
258 2 exp: non_productive
259 3 not_reachable: useful
260 4 non_productive: non_productive useless_token
263 # The reduced grammar.
264 # --------------------
265 AT_DATA([[reduced.y]],
266 [[/* A useless token. */
275 exp: useful { /* A useful action. */ }
276 // | non_productive { /* A non productive action. */ } */
279 //not_reachable: useful { /* A not reachable action. */ }
282 //non_productive: non_productive useless_token
283 // { /* Another non productive action. */ }
288 AT_BISON_CHECK([[reduced.y]])
290 # Comparing the parsers.
292 AT_CHECK([sed 's/not-reduced/reduced/g' not-reduced.c], 0, [expout])
298 ## ------------------- ##
299 ## Underivable Rules. ##
300 ## ------------------- ##
302 AT_SETUP([Underivable Rules])
304 AT_KEYWORDS([report])
311 exp: useful | underivable;
312 underivable: indirection;
313 indirection: underivable;
316 AT_BISON_CHECK([[input.y]], 0, [],
317 [[input.y: warning: 2 nonterminals useless in grammar
318 input.y: warning: 3 rules useless in grammar
319 input.y:5.15-25: warning: nonterminal useless in grammar: underivable
320 input.y:6.14-24: warning: nonterminal useless in grammar: indirection
321 input.y:5.15-25: warning: rule useless in grammar: exp: underivable
322 input.y:6.14-24: warning: rule useless in grammar: underivable: indirection
323 input.y:7.14-24: warning: rule useless in grammar: indirection: underivable
326 AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
327 [[Nonterminals useless in grammar
330 Rules useless in grammar
332 3 underivable: indirection
333 4 indirection: underivable
340 ## ---------------- ##
341 ## Empty Language. ##
342 ## ---------------- ##
344 AT_SETUP([Empty Language])
352 AT_BISON_CHECK([[input.y]], 1, [],
353 [[input.y: warning: 2 nonterminals useless in grammar
354 input.y: warning: 2 rules useless in grammar
355 input.y:3.1-3: fatal error: start symbol exp does not derive any sentence
362 ## ----------------- ##
363 ## %define lr.type. ##
364 ## ----------------- ##
366 # AT_TEST_LR_TYPE(DESCRIPTION,
367 # DECLS, GRAMMAR, INPUT,
368 # BISON-STDERR, TABLES,
370 # [PARSER-EXIT-VALUE],
371 # [PARSER-STDOUT], [PARSER-STDERR])
372 # -------------------------------------------------
373 m4_define([AT_TEST_LR_TYPE],
375 AT_TEST_TABLES_AND_PARSE([[no %define lr.type: ]$1],
377 [$2], m4_shiftn(2, $@))
378 AT_TEST_TABLES_AND_PARSE([[%define lr.type lalr: ]$1],
380 [[%define lr.type lalr
383 AT_TEST_TABLES_AND_PARSE([[%define lr.type ielr: ]$1],
385 [[%define lr.type ielr
388 AT_TEST_TABLES_AND_PARSE([[%define lr.type canonical-lr: ]$1],
389 [[canonical LR]], [[]],
390 [[%define lr.type canonical-lr
395 AT_TEST_LR_TYPE([[Single State Split]],
397 // Conflict resolution renders state 12 unreachable for canonical LR(1). We
398 // keep it so that the paser table diff is easier to code.
399 %define lr.keep-unreachable-states]],
401 S: 'a' A 'a' /* rule 1 */
402 | 'b' A 'b' /* rule 2 */
406 /* A conflict should appear after the first 'a' in rules 4 and 5 but only after
407 having shifted the first 'a' in rule 1. However, when LALR(1) merging is
408 chosen, the state containing that conflict is reused after having seen the
409 first 'b' in rule 2 and then the first 'a' in rules 4 and 5. In both cases,
410 because of the merged state, if the next token is an 'a', the %left forces a
411 reduction action with rule 5. In the latter case, only a shift is actually
412 grammatically correct. Thus, the parser would report a syntax error for the
413 grammatically correct sentence "baab" because it would encounter a syntax
414 error after that incorrect reduction.
416 Despite not being LALR(1), Menhir version 20070322 suffers from this problem
417 as well. It uses David Pager's weak compatibility test for merging states.
418 Bison and Menhir accept non-LR(1) grammars with conflict resolution. Pager
419 designed his algorithm only for LR(1) grammars. */
420 A: 'a' 'a' /* rule 4 */
424 /* Rule 3, rule 6, and rule 7 ensure that Bison does not report rule 4 as
425 useless after conflict resolution. This proves that, even though LALR(1)
426 generates incorrect parser tables sometimes, Bison will not necessarily
427 produce any warning to help the user realize it. */
428 c: 'a' 'b' /* rule 6 */
434 [['b', 'a', 'a', 'b']],
447 'a' shift, and go to state 1
448 'b' shift, and go to state 2
449 'c' shift, and go to state 3
460 'a' shift, and go to state 5
471 'a' shift, and go to state ]AT_COND_CASE([[LALR]], [[5]], [[16]])[
484 'a' shift, and go to state 8
494 $end shift, and go to state 11
500 5 | 'a' . ]AT_COND_CASE([[LALR]], [[['a', 'b']]], [[['a']]])[
502 ]AT_COND_CASE([[canonical LR]], [['a']],
503 [[$default]])[ reduce using rule 5 (A)
505 Conflict between rule 5 and token 'a' resolved as reduce (%left 'a').
512 'a' shift, and go to state 13
519 'b' shift, and go to state 14
528 'a' shift, and go to state ]AT_COND_CASE([[canonical LR]], [[17]],
530 'b' shift, and go to state 15
532 ]AT_COND_CASE([[canonical LR]], [[$end]],
533 [[$default]])[ reduce using rule 5 (A)
538 7 c: A .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
540 ]AT_COND_CASE([[canonical LR]], [[$end]],
541 [[$default]])[ reduce using rule 7 (c)
546 3 S: 'c' c .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
548 ]AT_COND_CASE([[canonical LR]], [[$end]],
549 [[$default]])[ reduce using rule 3 (S)
561 4 A: 'a' 'a' .]AT_COND_CASE([[canonical LR]], [[ ['a']]])[
563 ]AT_COND_CASE([[canonical LR]], [['a']],
564 [[$default]])[ reduce using rule 4 (A)
569 1 S: 'a' A 'a' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
571 ]AT_COND_CASE([[canonical LR]], [[$end]],
572 [[$default]])[ reduce using rule 1 (S)
577 2 S: 'b' A 'b' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
579 ]AT_COND_CASE([[canonical LR]], [[$end]],
580 [[$default]])[ reduce using rule 2 (S)
585 6 c: 'a' 'b' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
587 ]AT_COND_CASE([[canonical LR]], [[$end]],
588 [[$default]])[ reduce using rule 6 (c)]AT_COND_CASE([[LALR]],
597 'a' shift, and go to state ]AT_COND_CASE([[canonical LR]], [[18]],
600 ]AT_COND_CASE([[canonical LR]], [['b']],
601 [[$default]])[ reduce using rule 5 (A)]AT_COND_CASE([[canonical LR]], [[
606 4 A: 'a' 'a' . [$end]
608 $end reduce using rule 4 (A)
615 'b' reduce using rule 4 (A)]])])[
621 dnl PARSER-EXIT-VALUE, PARSER-STDOUT, PARSER-STDERR
622 [AT_COND_CASE([[LALR]], [[1]], [[0]])],
624 [AT_COND_CASE([[LALR]],
628 AT_TEST_LR_TYPE([[Lane Split]],
630 // Conflict resolution renders state 16 unreachable for canonical LR(1). We
631 // keep it so that the paser table diff is easier to code.
632 %define lr.keep-unreachable-states]],
634 /* Similar to the last test case set but two states must be split. */
635 S: 'a' A 'a' /* rule 1 */
636 | 'b' A 'b' /* rule 2 */
640 A: 'a' 'a' 'a' /* rule 4 */
641 | 'a' 'a' /* rule 5 */
644 c: 'a' 'a' 'b' /* rule 6 */
650 [['b', 'a', 'a', 'a', 'b']],
663 'a' shift, and go to state 1
664 'b' shift, and go to state 2
665 'c' shift, and go to state 3
676 'a' shift, and go to state 5
687 'a' shift, and go to state ]AT_COND_CASE([[LALR]], [[5]], [[18]])[
700 'a' shift, and go to state 8
710 $end shift, and go to state 11
718 'a' shift, and go to state 12
725 'a' shift, and go to state 13
732 'b' shift, and go to state 14
741 'a' shift, and go to state 15
746 7 c: A .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
748 ]AT_COND_CASE([[canonical LR]], [[$end]],
749 [[$default]])[ reduce using rule 7 (c)
754 3 S: 'c' c .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
756 ]AT_COND_CASE([[canonical LR]], [[$end]],
757 [[$default]])[ reduce using rule 3 (S)
770 5 | 'a' 'a' . ]AT_COND_CASE([[LALR]], [[['a', 'b']]], [[['a']]])[
772 ]AT_COND_CASE([[canonical LR]], [['a']],
773 [[$default]])[ reduce using rule 5 (A)
775 Conflict between rule 5 and token 'a' resolved as reduce (%left 'a').
780 1 S: 'a' A 'a' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
782 ]AT_COND_CASE([[canonical LR]], [[$end]],
783 [[$default]])[ reduce using rule 1 (S)
788 2 S: 'b' A 'b' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
790 ]AT_COND_CASE([[canonical LR]], [[$end]],
791 [[$default]])[ reduce using rule 2 (S)
800 'a' shift, and go to state ]AT_COND_CASE([[canonical LR]], [[19]],
802 'b' shift, and go to state 17
804 ]AT_COND_CASE([[canonical LR]], [[$end]],
805 [[$default]])[ reduce using rule 5 (A)
810 4 A: 'a' 'a' 'a' .]AT_COND_CASE([[canonical LR]], [[ ['a']]])[
812 ]AT_COND_CASE([[canonical LR]], [['a']],
813 [[$default]])[ reduce using rule 4 (A)
818 6 c: 'a' 'a' 'b' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
820 ]AT_COND_CASE([[canonical LR]], [[$end]],
821 [[$default]])[ reduce using rule 6 (c)]AT_COND_CASE([[LALR]],
830 'a' shift, and go to state ]AT_COND_CASE([[canonical LR]], [[20]],
834 state 19]AT_COND_CASE([[canonical LR]], [[
836 4 A: 'a' 'a' 'a' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
838 ]AT_COND_CASE([[canonical LR]], [[$end]],
839 [[$default]])[ reduce using rule 4 (A)
847 'a' shift, and go to state ]AT_COND_CASE([[canonical LR]], [[21]],
850 ]AT_COND_CASE([[canonical LR]], [['b']],
851 [[$default]])[ reduce using rule 5 (A)]AT_COND_CASE([[canonical LR]], [[
856 4 A: 'a' 'a' 'a' .]AT_COND_CASE([[canonical LR]], [[ ['b']]])[
858 ]AT_COND_CASE([[canonical LR]], [['b']],
859 [[$default]])[ reduce using rule 4 (A)]])])[
865 dnl PARSER-EXIT-VALUE, PARSER-STDOUT, PARSER-STDERR
866 [AT_COND_CASE([[LALR]], [[1]], [[0]])],
868 [AT_COND_CASE([[LALR]],
872 AT_TEST_LR_TYPE([[Complex Lane Split]],
874 // Conflict resolution renders state 16 unreachable for canonical LR(1). We
875 // keep it so that the paser table diff is easier to code.
876 %define lr.keep-unreachable-states]],
878 /* Similar to the last test case set but forseeing the S/R conflict from the
879 first state that must be split is becoming difficult. Imagine if B were
880 even more complex. Imagine if A had other RHS's ending in other
897 [['b', 'a', 'a', 'a', 'b']],
910 'a' shift, and go to state 1
911 'b' shift, and go to state 2
912 'c' shift, and go to state 3
922 'a' shift, and go to state 5
932 'a' shift, and go to state ]AT_COND_CASE([[LALR]], [[5]], [[19]])[
944 'a' shift, and go to state 8
954 $end shift, and go to state 11
961 'a' shift, and go to state 12
968 'a' shift, and go to state 13
975 'b' shift, and go to state 14
983 'a' shift, and go to state 15
988 8 c: A .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
990 ]AT_COND_CASE([[canonical LR]], [[$end]],
991 [[$default]])[ reduce using rule 8 (c)
996 3 S: 'c' c .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
998 ]AT_COND_CASE([[canonical LR]], [[$end]],
999 [[$default]])[ reduce using rule 3 (S)
1013 6 | . ]AT_COND_CASE([[LALR]], [[['a', 'b']]], [[['a']]])[
1015 ]AT_COND_CASE([[canonical LR]], [['a']],
1016 [[$default]])[ reduce using rule 6 (B)
1020 Conflict between rule 6 and token 'a' resolved as reduce (%left 'a').
1025 1 S: 'a' A 'a' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
1027 ]AT_COND_CASE([[canonical LR]], [[$end]],
1028 [[$default]])[ reduce using rule 1 (S)
1033 2 S: 'b' A 'b' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
1035 ]AT_COND_CASE([[canonical LR]], [[$end]],
1036 [[$default]])[ reduce using rule 2 (S)
1046 'a' shift, and go to state ]AT_COND_CASE([[canonical LR]], [[20]],
1048 'b' shift, and go to state 18
1050 ]AT_COND_CASE([[canonical LR]], [[$end]],
1051 [[$default]])[ reduce using rule 6 (B)
1053 B go to state ]AT_COND_CASE([[canonical LR]], [[21]], [[17]])[
1058 5 B: 'a' .]AT_COND_CASE([[canonical LR]], [[ ['a']]])[
1060 ]AT_COND_CASE([[canonical LR]], [['a']],
1061 [[$default]])[ reduce using rule 5 (B)
1066 4 A: 'a' 'a' B .]AT_COND_CASE([[canonical LR]], [[ ['a']]])[
1068 ]AT_COND_CASE([[canonical LR]], [['a']],
1069 [[$default]])[ reduce using rule 4 (A)
1074 7 c: 'a' 'a' 'b' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
1076 ]AT_COND_CASE([[canonical LR]], [[$end]],
1077 [[$default]])[ reduce using rule 7 (c)]AT_COND_CASE([[LALR]], [], [[
1084 'a' shift, and go to state ]AT_COND_CASE([[canonical LR]], [[22]],
1088 state 20]AT_COND_CASE([[canonical LR]], [[
1092 $end reduce using rule 5 (B)
1097 4 A: 'a' 'a' B . [$end]
1099 $end reduce using rule 4 (A)
1108 'a' shift, and go to state ]AT_COND_CASE([[canonical LR]], [[23]],
1111 ]AT_COND_CASE([[canonical LR]], [['b']],
1112 [[$default]])[ reduce using rule 6 (B)
1114 B go to state ]AT_COND_CASE([[canonical LR]], [[24
1121 'b' reduce using rule 5 (B)
1126 4 A: 'a' 'a' B . ['b']
1128 'b' reduce using rule 4 (A)]], [[17]])])[
1134 dnl PARSER-EXIT-VALUE, PARSER-STDOUT, PARSER-STDERR
1135 [AT_COND_CASE([[LALR]], [[1]], [[0]])],
1137 [AT_COND_CASE([[LALR]],
1141 AT_TEST_LR_TYPE([[Split During Added Lookahead Propagation]],
1142 [[%define lr.keep-unreachable-states]],
1144 /* The partial state chart diagram below is for LALR(1). State 0 is the start
1145 state. States are iterated for successor construction in numerical order.
1146 Transitions are downwards.
1148 State 13 has a R/R conflict that cannot be predicted by Bison's LR(1)
1149 algorithm using annotations alone. That is, when state 11's successor on
1150 'd' is merged with state 5 (which is originally just state 1's successor on
1151 'd'), state 5's successor on 'e' must then be changed because the resulting
1152 lookaheads that propagate to it now make it incompatible with state 8's
1153 successor on 'e'. In other words, state 13 must be split to avoid the
1171 This grammar is designed carefully to make sure that, despite Bison's LR(1)
1172 algorithm's bread-first iteration of transitions to reconstruct states,
1173 state 11's successors are constructed after state 5's and state 8's.
1174 Otherwise (for example, if you remove the first 'c' in each of rules 6 and
1175 7), state 5's successor on 'e' would never be merged with state 8's, so the
1176 split of the resulting state 13 would never need to be performed. */
1190 [['b', 'd', 'e', 'g']],
1193 [AT_COND_CASE([[LALR]],
1194 [[input.y: conflicts: 1 reduce/reduce
1209 'a' shift, and go to state 1
1210 'b' shift, and go to state 2
1211 'c' shift, and go to state 3
1223 'd' shift, and go to state 5
1237 'd' shift, and go to state 8
1245 6 S: 'c' . 'c' A 'g'
1248 'c' shift, and go to state 11
1255 $end shift, and go to state 12
1263 'e' shift, and go to state ]AT_COND_CASE([[LALR]], [[13]],
1264 [[canonical LR]], [[13]],
1272 'f' shift, and go to state 14
1277 2 S: 'a' B .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
1279 ]AT_COND_CASE([[canonical LR]], [[$end]],
1280 [[$default]])[ reduce using rule 2 (S)
1285 5 S: 'b' 'd' . [$end]
1289 'e' shift, and go to state ]AT_COND_CASE([[canonical LR]], [[20]],
1292 ]AT_COND_CASE([[canonical LR]], [[$end]],
1293 [[$default]])[ reduce using rule 5 (S)
1300 'f' shift, and go to state 15
1307 'g' shift, and go to state 16
1312 6 S: 'c' 'c' . A 'g'
1317 'd' shift, and go to state ]AT_COND_CASE([[canonical LR]], [[21]],
1328 $default accept]AT_COND_CASE([[LALR]], [[
1333 8 A: 'd' 'e' . ['f', 'g']
1334 9 B: 'd' 'e' . [$end, 'g']
1336 $end reduce using rule 9 (B)
1337 'g' reduce using rule 8 (A)
1338 'g' [reduce using rule 9 (B)]
1339 $default reduce using rule 8 (A)]], [[
1344 8 A: 'd' 'e' . ['f']
1345 9 B: 'd' 'e' . ]AT_COND_CASE([[canonical LR]], [[[$end]]], [[['g']]])[
1347 ]AT_COND_CASE([[canonical LR]], [[$end]],
1348 [['g' ]])[ reduce using rule 9 (B)
1349 ]AT_COND_CASE([[canonical LR]], [['f' ]],
1350 [[$default]])[ reduce using rule 8 (A)]])[
1355 1 S: 'a' A 'f' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
1357 ]AT_COND_CASE([[canonical LR]], [[$end]],
1358 [[$default]])[ reduce using rule 1 (S)
1363 3 S: 'b' A 'f' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
1365 ]AT_COND_CASE([[canonical LR]], [[$end]],
1366 [[$default]])[ reduce using rule 3 (S)
1371 4 S: 'b' B 'g' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
1373 ]AT_COND_CASE([[canonical LR]], [[$end]],
1374 [[$default]])[ reduce using rule 4 (S)
1379 6 S: 'c' 'c' A . 'g'
1381 'g' shift, and go to state 19
1386 7 S: 'c' 'c' B .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
1388 ]AT_COND_CASE([[canonical LR]], [[$end]],
1389 [[$default]])[ reduce using rule 7 (S)
1394 6 S: 'c' 'c' A 'g' .]AT_COND_CASE([[canonical LR]], [[ [$end]]])[
1396 ]AT_COND_CASE([[canonical LR]], [[$end]],
1397 [[$default]])[ reduce using rule 6 (S)]AT_COND_CASE([[LALR]],
1401 state 20]AT_COND_CASE([[canonical LR]], [[
1403 8 A: 'd' 'e' . ['f']
1404 9 B: 'd' 'e' . ['g']
1406 'f' reduce using rule 8 (A)
1407 'g' reduce using rule 9 (B)
1415 'e' shift, and go to state 22
1420 8 A: 'd' 'e' . ['g']
1421 9 B: 'd' 'e' . [$end]
1423 $end reduce using rule 9 (B)
1424 'g' reduce using rule 8 (A)]], [[
1426 8 A: 'd' 'e' . ['f', 'g']
1427 9 B: 'd' 'e' . [$end]
1429 $end reduce using rule 9 (B)
1430 $default reduce using rule 8 (A)]])])[
1436 dnl PARSER-EXIT-VALUE, PARSER-STDOUT, PARSER-STDERR
1437 [AT_COND_CASE([[LALR]], [[1]], [[0]])],
1439 [AT_COND_CASE([[LALR]],
1445 ## ------------------------------- ##
1446 ## %define lr.default-reductions. ##
1447 ## ------------------------------- ##
1449 # AT_TEST_LR_DEFAULT_REDUCTIONS(GRAMMAR, INPUT, TABLES)
1450 # -----------------------------------------------------
1451 m4_define([AT_TEST_LR_DEFAULT_REDUCTIONS],
1453 AT_TEST_TABLES_AND_PARSE([[no %define lr.default-reductions]],
1456 [$1], [$2], [[]], [$3])
1457 AT_TEST_TABLES_AND_PARSE([[%define lr.default-reductions full]],
1459 [[%define lr.default-reductions full]],
1460 [$1], [$2], [[]], [$3])
1461 AT_TEST_TABLES_AND_PARSE([[%define lr.default-reductions consistent]],
1462 [[consistent]], [[]],
1463 [[%define lr.default-reductions consistent]],
1464 [$1], [$2], [[]], [$3])
1465 AT_TEST_TABLES_AND_PARSE([[%define lr.default-reductions accepting]],
1466 [[accepting]], [[]],
1467 [[%define lr.default-reductions accepting]],
1468 [$1], [$2], [[]], [$3])
1471 AT_TEST_LR_DEFAULT_REDUCTIONS([[
1472 /* The start state is consistent and has a shift on 'a' and no reductions.
1473 After pushing the b below, enter an inconsistent state that has a shift and
1474 one reduction with one lookahead. */
1481 /* After shifting this 'a', enter a consistent state that has no shift and 1
1482 reduction with multiple lookaheads. */
1485 /* After the previous reduction, enter an inconsistent state that has no shift
1486 and multiple reductions. The first reduction has more lookaheads than the
1487 second, so the first should always be preferred as the default reduction if
1488 enabled. The second reduction has one lookahead. */
1492 dnl Visit each state mentioned above.
1496 0 $accept: . start $end
1502 'a' shift, and go to state 1
1510 4 a: 'a' .]AT_COND_CASE([[accepting]], [[ [$end, 'a', 'b']
1512 $end reduce using rule 4 (a)
1513 'a' reduce using rule 4 (a)
1514 'b' reduce using rule 4 (a)]], [[
1516 $default reduce using rule 4 (a)]])[
1521 0 $accept: start . $end
1523 $end shift, and go to state 4
1532 6 c: . ['b']]AT_COND_CASE([[full]], [[
1534 'b' reduce using rule 6 (c)
1535 $default reduce using rule 5 (b)]], [[
1537 $end reduce using rule 5 (b)
1538 'a' reduce using rule 5 (b)
1539 'b' reduce using rule 6 (c)]])[
1547 0 $accept: start $end .
1554 1 start: a b . [$end]
1557 'a' shift, and go to state 7
1559 ]AT_COND_CASE([[full]], [[$default]],
1560 [[$end]])[ reduce using rule 1 (start)
1567 'b' shift, and go to state 8
1572 2 start: a b 'a' .]AT_COND_CASE([[accepting]], [[ [$end]
1574 $end reduce using rule 2 (start)]], [[
1576 $default reduce using rule 2 (start)]])[
1581 3 start: a c 'b' .]AT_COND_CASE([[accepting]], [[ [$end]
1583 $end reduce using rule 3 (start)]], [[
1585 $default reduce using rule 3 (start)]])[