1 /* Find and resolve or report lookahead conflicts for bison,
3 Copyright (C) 1984, 1989, 1992, 2000-2012 Free Software Foundation,
6 This file is part of Bison, the GNU Compiler Compiler.
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
28 #include "conflicts.h"
33 #include "print-xml.h"
38 /* -1 stands for not specified. */
39 int expected_sr_conflicts
= -1;
40 int expected_rr_conflicts
= -1;
41 static char *conflicts
;
42 static struct obstack solved_conflicts_obstack
;
43 static struct obstack solved_conflicts_xml_obstack
;
45 static bitset shift_set
;
46 static bitset lookahead_set
;
50 enum conflict_resolution
60 /*----------------------------------------------------------------.
61 | Explain how an SR conflict between TOKEN and RULE was resolved: |
63 `----------------------------------------------------------------*/
66 log_resolution (rule
*r
, symbol_number token
,
67 enum conflict_resolution resolution
)
69 if (report_flag
& report_solved_conflicts
)
71 /* The description of the resolution. */
74 case shift_resolution
:
75 case right_resolution
:
76 obstack_fgrow2 (&solved_conflicts_obstack
,
77 _(" Conflict between rule %d and token %s"
78 " resolved as shift"),
83 case reduce_resolution
:
85 obstack_fgrow2 (&solved_conflicts_obstack
,
86 _(" Conflict between rule %d and token %s"
87 " resolved as reduce"),
92 case nonassoc_resolution
:
93 obstack_fgrow2 (&solved_conflicts_obstack
,
94 _(" Conflict between rule %d and token %s"
95 " resolved as an error"),
104 case shift_resolution
:
105 obstack_fgrow2 (&solved_conflicts_obstack
,
108 symbols
[token
]->tag
);
111 case reduce_resolution
:
112 obstack_fgrow2 (&solved_conflicts_obstack
,
118 case left_resolution
:
119 obstack_fgrow1 (&solved_conflicts_obstack
,
121 symbols
[token
]->tag
);
124 case right_resolution
:
125 obstack_fgrow1 (&solved_conflicts_obstack
,
127 symbols
[token
]->tag
);
130 case nonassoc_resolution
:
131 obstack_fgrow1 (&solved_conflicts_obstack
,
133 symbols
[token
]->tag
);
137 obstack_sgrow (&solved_conflicts_obstack
, ".\n");
143 /* The description of the resolution. */
146 case shift_resolution
:
147 case right_resolution
:
148 obstack_fgrow2 (&solved_conflicts_xml_obstack
,
149 " <resolution rule=\"%d\" symbol=\"%s\""
152 xml_escape (symbols
[token
]->tag
));
155 case reduce_resolution
:
156 case left_resolution
:
157 obstack_fgrow2 (&solved_conflicts_xml_obstack
,
158 " <resolution rule=\"%d\" symbol=\"%s\""
161 xml_escape (symbols
[token
]->tag
));
164 case nonassoc_resolution
:
165 obstack_fgrow2 (&solved_conflicts_xml_obstack
,
166 " <resolution rule=\"%d\" symbol=\"%s\""
169 xml_escape (symbols
[token
]->tag
));
176 case shift_resolution
:
177 obstack_fgrow2 (&solved_conflicts_xml_obstack
,
179 xml_escape_n (0, r
->prec
->tag
),
180 xml_escape_n (1, symbols
[token
]->tag
));
183 case reduce_resolution
:
184 obstack_fgrow2 (&solved_conflicts_xml_obstack
,
186 xml_escape_n (0, symbols
[token
]->tag
),
187 xml_escape_n (1, r
->prec
->tag
));
190 case left_resolution
:
191 obstack_fgrow1 (&solved_conflicts_xml_obstack
,
193 xml_escape (symbols
[token
]->tag
));
196 case right_resolution
:
197 obstack_fgrow1 (&solved_conflicts_xml_obstack
,
199 xml_escape (symbols
[token
]->tag
));
202 case nonassoc_resolution
:
203 obstack_fgrow1 (&solved_conflicts_xml_obstack
,
205 xml_escape (symbols
[token
]->tag
));
209 obstack_sgrow (&solved_conflicts_xml_obstack
, "</resolution>\n");
214 /*------------------------------------------------------------------.
215 | Turn off the shift recorded for the specified token in the |
216 | specified state. Used when we resolve a shift-reduce conflict in |
217 | favor of the reduction or as an error (%nonassoc). |
218 `------------------------------------------------------------------*/
221 flush_shift (state
*s
, int token
)
223 transitions
*trans
= s
->transitions
;
226 bitset_reset (lookahead_set
, token
);
227 for (i
= 0; i
< trans
->num
; i
++)
228 if (!TRANSITION_IS_DISABLED (trans
, i
)
229 && TRANSITION_SYMBOL (trans
, i
) == token
)
230 TRANSITION_DISABLE (trans
, i
);
234 /*--------------------------------------------------------------------.
235 | Turn off the reduce recorded for the specified token in the |
236 | specified lookahead set. Used when we resolve a shift-reduce |
237 | conflict in favor of the shift or as an error (%nonassoc). |
238 `--------------------------------------------------------------------*/
241 flush_reduce (bitset lookahead_tokens
, int token
)
243 bitset_reset (lookahead_tokens
, token
);
247 /*------------------------------------------------------------------.
248 | Attempt to resolve shift-reduce conflict for one rule by means of |
249 | precedence declarations. It has already been checked that the |
250 | rule has a precedence. A conflict is resolved by modifying the |
251 | shift or reduce tables so that there is no longer a conflict. |
253 | RULENO is the number of the lookahead bitset to consider. |
255 | ERRORS and NERRS can be used to store discovered explicit |
257 `------------------------------------------------------------------*/
260 resolve_sr_conflict (state
*s
, int ruleno
, symbol
**errors
, int *nerrs
)
263 reductions
*reds
= s
->reductions
;
264 /* Find the rule to reduce by to get precedence of reduction. */
265 rule
*redrule
= reds
->rules
[ruleno
];
266 int redprec
= redrule
->prec
->prec
;
267 bitset lookahead_tokens
= reds
->lookahead_tokens
[ruleno
];
269 for (i
= 0; i
< ntokens
; i
++)
270 if (bitset_test (lookahead_tokens
, i
)
271 && bitset_test (lookahead_set
, i
)
274 /* Shift-reduce conflict occurs for token number i
275 and it has a precedence.
276 The precedence of shifting is that of token i. */
277 if (symbols
[i
]->prec
< redprec
)
279 log_resolution (redrule
, i
, reduce_resolution
);
282 else if (symbols
[i
]->prec
> redprec
)
284 log_resolution (redrule
, i
, shift_resolution
);
285 flush_reduce (lookahead_tokens
, i
);
288 /* Matching precedence levels.
289 For non-defined associativity, keep both: unexpected
290 associativity conflict.
291 For left associativity, keep only the reduction.
292 For right associativity, keep only the shift.
293 For nonassociativity, keep neither. */
295 switch (symbols
[i
]->assoc
)
300 case precedence_assoc
:
304 log_resolution (redrule
, i
, right_resolution
);
305 flush_reduce (lookahead_tokens
, i
);
309 log_resolution (redrule
, i
, left_resolution
);
314 log_resolution (redrule
, i
, nonassoc_resolution
);
316 flush_reduce (lookahead_tokens
, i
);
317 /* Record an explicit error for this token. */
318 errors
[(*nerrs
)++] = symbols
[i
];
325 /*-------------------------------------------------------------------.
326 | Solve the S/R conflicts of state S using the |
327 | precedence/associativity, and flag it inconsistent if it still has |
328 | conflicts. ERRORS can be used as storage to compute the list of |
329 | lookahead tokens on which S raises a syntax error (%nonassoc). |
330 `-------------------------------------------------------------------*/
333 set_conflicts (state
*s
, symbol
**errors
)
336 transitions
*trans
= s
->transitions
;
337 reductions
*reds
= s
->reductions
;
343 bitset_zero (lookahead_set
);
345 FOR_EACH_SHIFT (trans
, i
)
346 bitset_set (lookahead_set
, TRANSITION_SYMBOL (trans
, i
));
348 /* Loop over all rules which require lookahead in this state. First
349 check for shift-reduce conflict, and try to resolve using
351 for (i
= 0; i
< reds
->num
; ++i
)
352 if (reds
->rules
[i
]->prec
&& reds
->rules
[i
]->prec
->prec
353 && !bitset_disjoint_p (reds
->lookahead_tokens
[i
], lookahead_set
))
354 resolve_sr_conflict (s
, i
, errors
, &nerrs
);
358 /* Some tokens have been explicitly made errors. Allocate a
359 permanent errs structure for this state, to record them. */
360 state_errs_set (s
, nerrs
, errors
);
362 if (obstack_object_size (&solved_conflicts_obstack
))
364 obstack_1grow (&solved_conflicts_obstack
, '\0');
365 s
->solved_conflicts
= obstack_finish (&solved_conflicts_obstack
);
367 if (obstack_object_size (&solved_conflicts_xml_obstack
))
369 obstack_1grow (&solved_conflicts_xml_obstack
, '\0');
370 s
->solved_conflicts_xml
= obstack_finish (&solved_conflicts_xml_obstack
);
373 /* Loop over all rules which require lookahead in this state. Check
374 for conflicts not resolved above. */
375 for (i
= 0; i
< reds
->num
; ++i
)
377 if (!bitset_disjoint_p (reds
->lookahead_tokens
[i
], lookahead_set
))
378 conflicts
[s
->number
] = 1;
379 bitset_or (lookahead_set
, lookahead_set
, reds
->lookahead_tokens
[i
]);
384 /*----------------------------------------------------------------.
385 | Solve all the S/R conflicts using the precedence/associativity, |
386 | and flag as inconsistent the states that still have conflicts. |
387 `----------------------------------------------------------------*/
390 conflicts_solve (void)
393 /* List of lookahead tokens on which we explicitly raise a syntax error. */
394 symbol
**errors
= xnmalloc (ntokens
+ 1, sizeof *errors
);
396 conflicts
= xcalloc (nstates
, sizeof *conflicts
);
397 shift_set
= bitset_create (ntokens
, BITSET_FIXED
);
398 lookahead_set
= bitset_create (ntokens
, BITSET_FIXED
);
399 obstack_init (&solved_conflicts_obstack
);
400 obstack_init (&solved_conflicts_xml_obstack
);
402 for (i
= 0; i
< nstates
; i
++)
404 set_conflicts (states
[i
], errors
);
406 /* For uniformity of the code, make sure all the states have a valid
408 if (!states
[i
]->errs
)
409 states
[i
]->errs
= errs_new (0, 0);
417 conflicts_update_state_numbers (state_number old_to_new
[],
418 state_number nstates_old
)
421 for (i
= 0; i
< nstates_old
; ++i
)
422 if (old_to_new
[i
] != nstates_old
)
423 conflicts
[old_to_new
[i
]] = conflicts
[i
];
427 /*---------------------------------------------.
428 | Count the number of shift/reduce conflicts. |
429 `---------------------------------------------*/
432 count_sr_conflicts (state
*s
)
436 transitions
*trans
= s
->transitions
;
437 reductions
*reds
= s
->reductions
;
442 bitset_zero (lookahead_set
);
443 bitset_zero (shift_set
);
445 FOR_EACH_SHIFT (trans
, i
)
446 bitset_set (shift_set
, TRANSITION_SYMBOL (trans
, i
));
448 for (i
= 0; i
< reds
->num
; ++i
)
449 bitset_or (lookahead_set
, lookahead_set
, reds
->lookahead_tokens
[i
]);
451 bitset_and (lookahead_set
, lookahead_set
, shift_set
);
453 src_count
= bitset_count (lookahead_set
);
459 /*----------------------------------------------------------------.
460 | Count the number of reduce/reduce conflicts. If ONE_PER_TOKEN, |
461 | count one conflict for each token that has any reduce/reduce |
462 | conflicts. Otherwise, count one conflict for each pair of |
463 | conflicting reductions. |
464 +`----------------------------------------------------------------*/
467 count_rr_conflicts (state
*s
, bool one_per_token
)
470 reductions
*reds
= s
->reductions
;
473 for (i
= 0; i
< ntokens
; i
++)
477 for (j
= 0; j
< reds
->num
; ++j
)
478 if (bitset_test (reds
->lookahead_tokens
[j
], i
))
482 rrc_count
+= one_per_token
? 1 : count
-1;
489 /*--------------------------------------------------------.
490 | Report the number of conflicts, using the Yacc format. |
491 `--------------------------------------------------------*/
494 conflict_report (FILE *out
, int src_num
, int rrc_num
)
496 if (src_num
&& rrc_num
)
497 fprintf (out
, _("conflicts: %d shift/reduce, %d reduce/reduce\n"),
500 fprintf (out
, _("conflicts: %d shift/reduce\n"), src_num
);
502 fprintf (out
, _("conflicts: %d reduce/reduce\n"), rrc_num
);
506 /*-----------------------------------------------------------.
507 | Output the detailed description of states with conflicts. |
508 `-----------------------------------------------------------*/
511 conflicts_output (FILE *out
)
513 bool printed_sth
= false;
515 for (i
= 0; i
< nstates
; i
++)
517 state
*s
= states
[i
];
520 fprintf (out
, _("State %d "), i
);
521 conflict_report (out
, count_sr_conflicts (s
),
522 count_rr_conflicts (s
, true));
530 /*--------------------------------------------------------.
531 | Total the number of S/R and R/R conflicts. Unlike the |
532 | code in conflicts_output, however, count EACH pair of |
533 | reductions for the same state and lookahead as one |
535 `--------------------------------------------------------*/
538 conflicts_total_count (void)
543 /* Conflicts by state. */
545 for (i
= 0; i
< nstates
; i
++)
548 count
+= count_sr_conflicts (states
[i
]);
549 count
+= count_rr_conflicts (states
[i
], false);
555 /*------------------------------------------.
556 | Reporting the total number of conflicts. |
557 `------------------------------------------*/
560 conflicts_print (void)
562 /* Is the number of SR conflicts OK? Either EXPECTED_CONFLICTS is
563 not set, and then we want 0 SR, or else it is specified, in which
564 case we want equality. */
573 /* Conflicts by state. */
577 for (i
= 0; i
< nstates
; i
++)
580 src_total
+= count_sr_conflicts (states
[i
]);
581 rrc_total
+= count_rr_conflicts (states
[i
], true);
585 if (! glr_parser
&& rrc_total
> 0 && expected_rr_conflicts
!= -1)
587 complain (Wother
, _("%%expect-rr applies only to GLR parsers"));
588 expected_rr_conflicts
= -1;
591 src_expected
= expected_sr_conflicts
== -1 ? 0 : expected_sr_conflicts
;
592 rrc_expected
= expected_rr_conflicts
== -1 ? 0 : expected_rr_conflicts
;
593 src_ok
= src_total
== src_expected
;
594 rrc_ok
= rrc_total
== rrc_expected
;
596 /* If there are as many RR conflicts and SR conflicts as
597 expected, then there is nothing to report. */
601 /* Report the total number of conflicts on STDERR. */
602 if (expected_sr_conflicts
== -1 && expected_rr_conflicts
== -1)
604 if (!(warnings_flag
& Wconflicts_sr
))
606 if (!(warnings_flag
& Wconflicts_rr
))
609 if (src_total
| rrc_total
)
611 if (expected_sr_conflicts
== -1 && expected_rr_conflicts
== -1)
612 set_warning_issued ();
614 fprintf (stderr
, "%s: ", current_file
);
615 conflict_report (stderr
, src_total
, rrc_total
);
618 if (expected_sr_conflicts
!= -1 || expected_rr_conflicts
!= -1)
621 complain (complaint
, ngettext ("expected %d shift/reduce conflict",
622 "expected %d shift/reduce conflicts",
626 complain (complaint
, ngettext ("expected %d reduce/reduce conflict",
627 "expected %d reduce/reduce conflicts",
635 conflicts_free (void)
638 bitset_free (shift_set
);
639 bitset_free (lookahead_set
);
640 obstack_free (&solved_conflicts_obstack
, NULL
);
641 obstack_free (&solved_conflicts_xml_obstack
, NULL
);