1 /* Find and resolve or report look-ahead conflicts for bison,
3 Copyright (C) 1984, 1989, 1992, 2000, 2001, 2002, 2003, 2004
4 Free Software Foundation, Inc.
6 This file is part of Bison, the GNU Compiler Compiler.
8 Bison is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 Bison is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Bison; see the file COPYING. If not, write to the Free
20 Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
29 #include "conflicts.h"
38 /* -1 stands for not specified. */
39 int expected_sr_conflicts
= -1;
40 int expected_rr_conflicts
= -1;
41 static char *conflicts
;
42 struct obstack solved_conflicts_obstack
;
44 static bitset shift_set
;
45 static bitset look_ahead_set
;
49 enum conflict_resolution
59 /*----------------------------------------------------------------.
60 | Explain how an SR conflict between TOKEN and RULE was resolved: |
62 `----------------------------------------------------------------*/
65 log_resolution (rule
*r
, symbol_number token
,
66 enum conflict_resolution resolution
)
68 if (report_flag
& report_solved_conflicts
)
70 /* The description of the resolution. */
73 case shift_resolution
:
74 case right_resolution
:
75 obstack_fgrow2 (&solved_conflicts_obstack
,
77 Conflict between rule %d and token %s resolved as shift"),
81 case reduce_resolution
:
83 obstack_fgrow2 (&solved_conflicts_obstack
,
85 Conflict between rule %d and token %s resolved as reduce"),
89 case nonassoc_resolution
:
90 obstack_fgrow2 (&solved_conflicts_obstack
,
92 Conflict between rule %d and token %s resolved as an error"),
101 case shift_resolution
:
102 obstack_fgrow2 (&solved_conflicts_obstack
,
105 symbols
[token
]->tag
);
108 case reduce_resolution
:
109 obstack_fgrow2 (&solved_conflicts_obstack
,
115 case left_resolution
:
116 obstack_fgrow1 (&solved_conflicts_obstack
,
118 symbols
[token
]->tag
);
121 case right_resolution
:
122 obstack_fgrow1 (&solved_conflicts_obstack
,
124 symbols
[token
]->tag
);
126 case nonassoc_resolution
:
127 obstack_fgrow1 (&solved_conflicts_obstack
,
129 symbols
[token
]->tag
);
132 obstack_sgrow (&solved_conflicts_obstack
, ".\n");
137 /*------------------------------------------------------------------.
138 | Turn off the shift recorded for the specified token in the |
139 | specified state. Used when we resolve a shift-reduce conflict in |
140 | favor of the reduction. |
141 `------------------------------------------------------------------*/
144 flush_shift (state
*s
, int token
)
146 transitions
*trans
= s
->transitions
;
149 bitset_reset (look_ahead_set
, token
);
150 for (i
= 0; i
< trans
->num
; i
++)
151 if (!TRANSITION_IS_DISABLED (trans
, i
)
152 && TRANSITION_SYMBOL (trans
, i
) == token
)
153 TRANSITION_DISABLE (trans
, i
);
157 /*--------------------------------------------------------------------.
158 | Turn off the reduce recorded for the specified token for the |
159 | specified look-ahead. Used when we resolve a shift-reduce conflict |
160 | in favor of the shift. |
161 `--------------------------------------------------------------------*/
164 flush_reduce (bitset look_ahead_tokens
, int token
)
166 bitset_reset (look_ahead_tokens
, token
);
170 /*------------------------------------------------------------------.
171 | Attempt to resolve shift-reduce conflict for one rule by means of |
172 | precedence declarations. It has already been checked that the |
173 | rule has a precedence. A conflict is resolved by modifying the |
174 | shift or reduce tables so that there is no longer a conflict. |
176 | RULENO is the number of the look-ahead bitset to consider. |
178 | ERRORS can be used to store discovered explicit errors. |
179 `------------------------------------------------------------------*/
182 resolve_sr_conflict (state
*s
, int ruleno
, symbol
**errors
)
185 reductions
*reds
= s
->reductions
;
186 /* Find the rule to reduce by to get precedence of reduction. */
187 rule
*redrule
= reds
->rules
[ruleno
];
188 int redprec
= redrule
->prec
->prec
;
189 bitset look_ahead_tokens
= reds
->look_ahead_tokens
[ruleno
];
192 for (i
= 0; i
< ntokens
; i
++)
193 if (bitset_test (look_ahead_tokens
, i
)
194 && bitset_test (look_ahead_set
, i
)
197 /* Shift-reduce conflict occurs for token number i
198 and it has a precedence.
199 The precedence of shifting is that of token i. */
200 if (symbols
[i
]->prec
< redprec
)
202 log_resolution (redrule
, i
, reduce_resolution
);
205 else if (symbols
[i
]->prec
> redprec
)
207 log_resolution (redrule
, i
, shift_resolution
);
208 flush_reduce (look_ahead_tokens
, i
);
211 /* Matching precedence levels.
212 For left association, keep only the reduction.
213 For right association, keep only the shift.
214 For nonassociation, keep neither. */
216 switch (symbols
[i
]->assoc
)
219 log_resolution (redrule
, i
, right_resolution
);
220 flush_reduce (look_ahead_tokens
, i
);
224 log_resolution (redrule
, i
, left_resolution
);
229 log_resolution (redrule
, i
, nonassoc_resolution
);
231 flush_reduce (look_ahead_tokens
, i
);
232 /* Record an explicit error for this token. */
233 errors
[nerrs
++] = symbols
[i
];
243 /* Some tokens have been explicitly made errors. Allocate a
244 permanent errs structure for this state, to record them. */
245 state_errs_set (s
, nerrs
, errors
);
248 if (obstack_object_size (&solved_conflicts_obstack
))
250 obstack_1grow (&solved_conflicts_obstack
, '\0');
251 s
->solved_conflicts
= obstack_finish (&solved_conflicts_obstack
);
256 /*-------------------------------------------------------------------.
257 | Solve the S/R conflicts of state S using the |
258 | precedence/associativity, and flag it inconsistent if it still has |
259 | conflicts. ERRORS can be used as storage to compute the list of |
260 | look-ahead tokens on which S raises a syntax error (%nonassoc). |
261 `-------------------------------------------------------------------*/
264 set_conflicts (state
*s
, symbol
**errors
)
267 transitions
*trans
= s
->transitions
;
268 reductions
*reds
= s
->reductions
;
273 bitset_zero (look_ahead_set
);
275 FOR_EACH_SHIFT (trans
, i
)
276 bitset_set (look_ahead_set
, TRANSITION_SYMBOL (trans
, i
));
278 /* Loop over all rules which require look-ahead in this state. First
279 check for shift-reduce conflict, and try to resolve using
281 for (i
= 0; i
< reds
->num
; ++i
)
282 if (reds
->rules
[i
]->prec
&& reds
->rules
[i
]->prec
->prec
283 && !bitset_disjoint_p (reds
->look_ahead_tokens
[i
], look_ahead_set
))
284 resolve_sr_conflict (s
, i
, errors
);
286 /* Loop over all rules which require look-ahead in this state. Check
287 for conflicts not resolved above. */
288 for (i
= 0; i
< reds
->num
; ++i
)
290 if (!bitset_disjoint_p (reds
->look_ahead_tokens
[i
], look_ahead_set
))
291 conflicts
[s
->number
] = 1;
293 bitset_or (look_ahead_set
, look_ahead_set
, reds
->look_ahead_tokens
[i
]);
298 /*----------------------------------------------------------------.
299 | Solve all the S/R conflicts using the precedence/associativity, |
300 | and flag as inconsistent the states that still have conflicts. |
301 `----------------------------------------------------------------*/
304 conflicts_solve (void)
307 /* List of look-ahead tokens on which we explicitly raise a syntax error. */
308 symbol
**errors
= xnmalloc (ntokens
+ 1, sizeof *errors
);
310 conflicts
= xcalloc (nstates
, sizeof *conflicts
);
311 shift_set
= bitset_create (ntokens
, BITSET_FIXED
);
312 look_ahead_set
= bitset_create (ntokens
, BITSET_FIXED
);
313 obstack_init (&solved_conflicts_obstack
);
315 for (i
= 0; i
< nstates
; i
++)
317 set_conflicts (states
[i
], errors
);
319 /* For uniformity of the code, make sure all the states have a valid
321 if (!states
[i
]->errs
)
322 states
[i
]->errs
= errs_new (0, 0);
329 /*---------------------------------------------.
330 | Count the number of shift/reduce conflicts. |
331 `---------------------------------------------*/
334 count_sr_conflicts (state
*s
)
338 transitions
*trans
= s
->transitions
;
339 reductions
*reds
= s
->reductions
;
344 bitset_zero (look_ahead_set
);
345 bitset_zero (shift_set
);
347 FOR_EACH_SHIFT (trans
, i
)
348 bitset_set (shift_set
, TRANSITION_SYMBOL (trans
, i
));
350 for (i
= 0; i
< reds
->num
; ++i
)
351 bitset_or (look_ahead_set
, look_ahead_set
, reds
->look_ahead_tokens
[i
]);
353 bitset_and (look_ahead_set
, look_ahead_set
, shift_set
);
355 src_count
= bitset_count (look_ahead_set
);
361 /*----------------------------------------------------------------.
362 | Count the number of reduce/reduce conflicts. If ONE_PER_TOKEN, |
363 | count one conflict for each token that has any reduce/reduce |
364 | conflicts. Otherwise, count one conflict for each pair of |
365 | conflicting reductions. |
366 +`----------------------------------------------------------------*/
369 count_rr_conflicts (state
*s
, bool one_per_token
)
372 reductions
*reds
= s
->reductions
;
375 for (i
= 0; i
< ntokens
; i
++)
379 for (j
= 0; j
< reds
->num
; ++j
)
380 if (bitset_test (reds
->look_ahead_tokens
[j
], i
))
384 rrc_count
+= one_per_token
? 1 : count
-1;
391 /*--------------------------------------------------------.
392 | Report the number of conflicts, using the Yacc format. |
393 `--------------------------------------------------------*/
396 conflict_report (FILE *out
, int src_num
, int rrc_num
)
398 if (src_num
&& rrc_num
)
399 fprintf (out
, _("conflicts: %d shift/reduce, %d reduce/reduce\n"),
402 fprintf (out
, _("conflicts: %d shift/reduce\n"), src_num
);
404 fprintf (out
, _("conflicts: %d reduce/reduce\n"), rrc_num
);
408 /*-----------------------------------------------------------.
409 | Output the detailed description of states with conflicts. |
410 `-----------------------------------------------------------*/
413 conflicts_output (FILE *out
)
415 bool printed_sth
= false;
417 for (i
= 0; i
< nstates
; i
++)
419 state
*s
= states
[i
];
422 fprintf (out
, _("State %d "), i
);
423 conflict_report (out
, count_sr_conflicts (s
),
424 count_rr_conflicts (s
, true));
432 /*--------------------------------------------------------.
433 | Total the number of S/R and R/R conflicts. Unlike the |
434 | code in conflicts_output, however, count EACH pair of |
435 | reductions for the same state and look-ahead as one |
437 `--------------------------------------------------------*/
440 conflicts_total_count (void)
445 /* Conflicts by state. */
447 for (i
= 0; i
< nstates
; i
++)
450 count
+= count_sr_conflicts (states
[i
]);
451 count
+= count_rr_conflicts (states
[i
], false);
457 /*------------------------------------------.
458 | Reporting the total number of conflicts. |
459 `------------------------------------------*/
462 conflicts_print (void)
464 /* Is the number of SR conflicts OK? Either EXPECTED_CONFLICTS is
465 not set, and then we want 0 SR, or else it is specified, in which
466 case we want equality. */
473 /* Conflicts by state. */
477 for (i
= 0; i
< nstates
; i
++)
480 src_total
+= count_sr_conflicts (states
[i
]);
481 rrc_total
+= count_rr_conflicts (states
[i
], true);
485 if (! glr_parser
&& rrc_total
> 0 && expected_rr_conflicts
!= -1)
487 warn (_("%%expect-rr applies only to GLR parsers"));
488 expected_rr_conflicts
= -1;
492 src_total
== (expected_sr_conflicts
== -1 ? 0 : expected_sr_conflicts
);
494 rrc_total
== (expected_rr_conflicts
== -1 ? 0 : expected_rr_conflicts
);
496 /* If there are as many RR conflicts and SR conflicts as
497 expected, then there is nothing to report. */
498 if (rrc_ok
&& src_ok
)
501 /* Report the total number of conflicts on STDERR. */
503 fprintf (stderr
, "%s: ", current_file
);
504 conflict_report (stderr
, src_total
, rrc_total
);
506 if (expected_sr_conflicts
!= -1 || expected_rr_conflicts
!= -1)
508 int sr
= expected_sr_conflicts
== -1 ? 0 : expected_sr_conflicts
;
509 int rr
= expected_rr_conflicts
== -1 ? 0 : expected_rr_conflicts
;
511 warn (ngettext ("expected %d shift/reduce conflict",
512 "expected %d shift/reduce conflicts",
515 warn (ngettext ("expected %d reduce/reduce conflict",
516 "expected %d reduce/reduce conflicts",
523 conflicts_free (void)
526 bitset_free (shift_set
);
527 bitset_free (look_ahead_set
);
528 obstack_free (&solved_conflicts_obstack
, NULL
);