1 |
/* Find and resolve or report look-ahead conflicts for bison, |
/* Find and resolve or report look-ahead conflicts for bison, |
2 |
|
|
3 |
Copyright (C) 1984, 1989, 1992, 2000, 2001, 2002 |
Copyright (C) 1984, 1989, 1992, 2000, 2001, 2002 |
4 |
Free Software Foundation, Inc. |
Free Software Foundation, Inc. |
5 |
|
|
21 |
02111-1307, USA. */ |
02111-1307, USA. */ |
22 |
|
|
23 |
#include "system.h" |
#include "system.h" |
24 |
#include "bitset.h" |
|
25 |
|
#include <bitset.h> |
26 |
|
|
27 |
|
#include "LR0.h" |
28 |
#include "complain.h" |
#include "complain.h" |
29 |
#include "getargs.h" |
#include "conflicts.h" |
|
#include "symtab.h" |
|
30 |
#include "files.h" |
#include "files.h" |
31 |
|
#include "getargs.h" |
32 |
#include "gram.h" |
#include "gram.h" |
|
#include "state.h" |
|
33 |
#include "lalr.h" |
#include "lalr.h" |
|
#include "conflicts.h" |
|
34 |
#include "reader.h" |
#include "reader.h" |
35 |
#include "LR0.h" |
#include "state.h" |
36 |
|
#include "symtab.h" |
37 |
|
|
38 |
/* -1 stands for not specified. */ |
/* -1 stands for not specified. */ |
39 |
int expected_conflicts = -1; |
int expected_conflicts = -1; |
45 |
|
|
46 |
|
|
47 |
|
|
48 |
enum conflict_resolution_e |
enum conflict_resolution |
49 |
{ |
{ |
50 |
shift_resolution, |
shift_resolution, |
51 |
reduce_resolution, |
reduce_resolution, |
61 |
`----------------------------------------------------------------*/ |
`----------------------------------------------------------------*/ |
62 |
|
|
63 |
static inline void |
static inline void |
64 |
log_resolution (rule_t *rule, symbol_number_t token, |
log_resolution (rule *r, symbol_number token, |
65 |
enum conflict_resolution_e resolution) |
enum conflict_resolution resolution) |
66 |
{ |
{ |
67 |
if (report_flag & report_solved_conflicts) |
if (report_flag & report_solved_conflicts) |
68 |
{ |
{ |
74 |
obstack_fgrow2 (&solved_conflicts_obstack, |
obstack_fgrow2 (&solved_conflicts_obstack, |
75 |
_("\ |
_("\ |
76 |
Conflict between rule %d and token %s resolved as shift"), |
Conflict between rule %d and token %s resolved as shift"), |
77 |
rule->number, |
r->number, |
78 |
symbols[token]->tag); |
symbols[token]->tag); |
79 |
break; |
break; |
80 |
case reduce_resolution: |
case reduce_resolution: |
82 |
obstack_fgrow2 (&solved_conflicts_obstack, |
obstack_fgrow2 (&solved_conflicts_obstack, |
83 |
_("\ |
_("\ |
84 |
Conflict between rule %d and token %s resolved as reduce"), |
Conflict between rule %d and token %s resolved as reduce"), |
85 |
rule->number, |
r->number, |
86 |
symbols[token]->tag); |
symbols[token]->tag); |
87 |
break; |
break; |
88 |
case nonassoc_resolution: |
case nonassoc_resolution: |
89 |
obstack_fgrow2 (&solved_conflicts_obstack, |
obstack_fgrow2 (&solved_conflicts_obstack, |
90 |
_("\ |
_("\ |
91 |
Conflict between rule %d and token %s resolved as an error"), |
Conflict between rule %d and token %s resolved as an error"), |
92 |
rule->number, |
r->number, |
93 |
symbols[token]->tag); |
symbols[token]->tag); |
94 |
break; |
break; |
95 |
} |
} |
100 |
case shift_resolution: |
case shift_resolution: |
101 |
obstack_fgrow2 (&solved_conflicts_obstack, |
obstack_fgrow2 (&solved_conflicts_obstack, |
102 |
" (%s < %s)", |
" (%s < %s)", |
103 |
rule->prec->tag, |
r->prec->tag, |
104 |
symbols[token]->tag); |
symbols[token]->tag); |
105 |
break; |
break; |
106 |
|
|
108 |
obstack_fgrow2 (&solved_conflicts_obstack, |
obstack_fgrow2 (&solved_conflicts_obstack, |
109 |
" (%s < %s)", |
" (%s < %s)", |
110 |
symbols[token]->tag, |
symbols[token]->tag, |
111 |
rule->prec->tag); |
r->prec->tag); |
112 |
break; |
break; |
113 |
|
|
114 |
case left_resolution: |
case left_resolution: |
140 |
`------------------------------------------------------------------*/ |
`------------------------------------------------------------------*/ |
141 |
|
|
142 |
static void |
static void |
143 |
flush_shift (state_t *state, int token) |
flush_shift (state *s, int token) |
144 |
{ |
{ |
145 |
transitions_t *transitions = state->transitions; |
transitions *trans = s->transitions; |
146 |
int i; |
int i; |
147 |
|
|
148 |
bitset_reset (lookaheadset, token); |
bitset_reset (lookaheadset, token); |
149 |
for (i = 0; i < transitions->num; i++) |
for (i = 0; i < trans->num; i++) |
150 |
if (!TRANSITION_IS_DISABLED (transitions, i) |
if (!TRANSITION_IS_DISABLED (trans, i) |
151 |
&& TRANSITION_SYMBOL (transitions, i) == token) |
&& TRANSITION_SYMBOL (trans, i) == token) |
152 |
TRANSITION_DISABLE (transitions, i); |
TRANSITION_DISABLE (trans, i); |
153 |
} |
} |
154 |
|
|
155 |
|
|
174 |
| | |
| | |
175 |
| LOOKAHEAD is the number of the lookahead bitset to consider. | |
| LOOKAHEAD is the number of the lookahead bitset to consider. | |
176 |
| | |
| | |
177 |
| ERRS can be used to store discovered explicit errors. | |
| ERRORS can be used to store discovered explicit errors. | |
178 |
`------------------------------------------------------------------*/ |
`------------------------------------------------------------------*/ |
179 |
|
|
180 |
static void |
static void |
181 |
resolve_sr_conflict (state_t *state, int ruleno, |
resolve_sr_conflict (state *s, int ruleno, symbol **errors) |
|
symbol_t **errs) |
|
182 |
{ |
{ |
183 |
symbol_number_t i; |
symbol_number i; |
184 |
reductions_t *reds = state->reductions; |
reductions *reds = s->reductions; |
185 |
/* Find the rule to reduce by to get precedence of reduction. */ |
/* Find the rule to reduce by to get precedence of reduction. */ |
186 |
rule_t *redrule = reds->rules[ruleno]; |
rule *redrule = reds->rules[ruleno]; |
187 |
int redprec = redrule->prec->prec; |
int redprec = redrule->prec->prec; |
188 |
bitset lookaheads = reds->lookaheads[ruleno]; |
bitset lookaheads = reds->lookaheads[ruleno]; |
189 |
int nerrs = 0; |
int nerrs = 0; |
199 |
if (symbols[i]->prec < redprec) |
if (symbols[i]->prec < redprec) |
200 |
{ |
{ |
201 |
log_resolution (redrule, i, reduce_resolution); |
log_resolution (redrule, i, reduce_resolution); |
202 |
flush_shift (state, i); |
flush_shift (s, i); |
203 |
} |
} |
204 |
else if (symbols[i]->prec > redprec) |
else if (symbols[i]->prec > redprec) |
205 |
{ |
{ |
221 |
|
|
222 |
case left_assoc: |
case left_assoc: |
223 |
log_resolution (redrule, i, left_resolution); |
log_resolution (redrule, i, left_resolution); |
224 |
flush_shift (state, i); |
flush_shift (s, i); |
225 |
break; |
break; |
226 |
|
|
227 |
case non_assoc: |
case non_assoc: |
228 |
log_resolution (redrule, i, nonassoc_resolution); |
log_resolution (redrule, i, nonassoc_resolution); |
229 |
flush_shift (state, i); |
flush_shift (s, i); |
230 |
flush_reduce (lookaheads, i); |
flush_reduce (lookaheads, i); |
231 |
/* Record an explicit error for this token. */ |
/* Record an explicit error for this token. */ |
232 |
errs[nerrs++] = symbols[i]; |
errors[nerrs++] = symbols[i]; |
233 |
break; |
break; |
234 |
|
|
235 |
case undef_assoc: |
case undef_assoc: |
239 |
|
|
240 |
/* Some tokens have been explicitly made errors. Allocate a |
/* Some tokens have been explicitly made errors. Allocate a |
241 |
permanent errs structure for this state, to record them. */ |
permanent errs structure for this state, to record them. */ |
242 |
state_errs_set (state, nerrs, errs); |
state_errs_set (s, nerrs, errors); |
243 |
|
|
244 |
if (obstack_object_size (&solved_conflicts_obstack)) |
if (obstack_object_size (&solved_conflicts_obstack)) |
245 |
{ |
{ |
246 |
obstack_1grow (&solved_conflicts_obstack, '\0'); |
obstack_1grow (&solved_conflicts_obstack, '\0'); |
247 |
state->solved_conflicts = obstack_finish (&solved_conflicts_obstack); |
s->solved_conflicts = obstack_finish (&solved_conflicts_obstack); |
248 |
} |
} |
249 |
} |
} |
250 |
|
|
251 |
|
|
252 |
/*-------------------------------------------------------------------. |
/*-------------------------------------------------------------------. |
253 |
| Solve the S/R conflicts of STATE using the | |
| Solve the S/R conflicts of state S using the | |
254 |
| precedence/associativity, and flag it inconsistent if it still has | |
| precedence/associativity, and flag it inconsistent if it still has | |
255 |
| conflicts. ERRS can be used as storage to compute the list of | |
| conflicts. ERRORS can be used as storage to compute the list of | |
256 |
| lookaheads on which this STATE raises a syntax error (%nonassoc). | |
| lookaheads on which S raises a syntax error (%nonassoc). | |
257 |
`-------------------------------------------------------------------*/ |
`-------------------------------------------------------------------*/ |
258 |
|
|
259 |
static void |
static void |
260 |
set_conflicts (state_t *state, symbol_t **errs) |
set_conflicts (state *s, symbol **errors) |
261 |
{ |
{ |
262 |
int i; |
int i; |
263 |
transitions_t *transitions = state->transitions; |
transitions *trans = s->transitions; |
264 |
reductions_t *reds = state->reductions; |
reductions *reds = s->reductions; |
265 |
|
|
266 |
if (state->consistent) |
if (s->consistent) |
267 |
return; |
return; |
268 |
|
|
269 |
bitset_zero (lookaheadset); |
bitset_zero (lookaheadset); |
270 |
|
|
271 |
FOR_EACH_SHIFT (transitions, i) |
FOR_EACH_SHIFT (trans, i) |
272 |
bitset_set (lookaheadset, TRANSITION_SYMBOL (transitions, i)); |
bitset_set (lookaheadset, TRANSITION_SYMBOL (trans, i)); |
273 |
|
|
274 |
/* Loop over all rules which require lookahead in this state. First |
/* Loop over all rules which require lookahead in this state. First |
275 |
check for shift-reduce conflict, and try to resolve using |
check for shift-reduce conflict, and try to resolve using |
278 |
if (reds->rules[i]->prec && reds->rules[i]->prec->prec |
if (reds->rules[i]->prec && reds->rules[i]->prec->prec |
279 |
&& !bitset_disjoint_p (reds->lookaheads[i], lookaheadset)) |
&& !bitset_disjoint_p (reds->lookaheads[i], lookaheadset)) |
280 |
{ |
{ |
281 |
resolve_sr_conflict (state, i, errs); |
resolve_sr_conflict (s, i, errors); |
282 |
break; |
break; |
283 |
} |
} |
284 |
|
|
287 |
for (i = 0; i < reds->num; ++i) |
for (i = 0; i < reds->num; ++i) |
288 |
{ |
{ |
289 |
if (!bitset_disjoint_p (reds->lookaheads[i], lookaheadset)) |
if (!bitset_disjoint_p (reds->lookaheads[i], lookaheadset)) |
290 |
conflicts[state->number] = 1; |
conflicts[s->number] = 1; |
291 |
|
|
292 |
bitset_or (lookaheadset, lookaheadset, reds->lookaheads[i]); |
bitset_or (lookaheadset, lookaheadset, reds->lookaheads[i]); |
293 |
} |
} |
302 |
void |
void |
303 |
conflicts_solve (void) |
conflicts_solve (void) |
304 |
{ |
{ |
305 |
state_number_t i; |
state_number i; |
306 |
/* List of lookaheads on which we explicitly raise a syntax error. */ |
/* List of lookaheads on which we explicitly raise a syntax error. */ |
307 |
symbol_t **errs = XMALLOC (symbol_t *, ntokens + 1); |
symbol **errors = XMALLOC (symbol *, ntokens + 1); |
308 |
|
|
309 |
conflicts = XCALLOC (char, nstates); |
conflicts = XCALLOC (char, nstates); |
310 |
shiftset = bitset_create (ntokens, BITSET_FIXED); |
shiftset = bitset_create (ntokens, BITSET_FIXED); |
313 |
|
|
314 |
for (i = 0; i < nstates; i++) |
for (i = 0; i < nstates; i++) |
315 |
{ |
{ |
316 |
set_conflicts (states[i], errs); |
set_conflicts (states[i], errors); |
317 |
|
|
318 |
/* For uniformity of the code, make sure all the states have a valid |
/* For uniformity of the code, make sure all the states have a valid |
319 |
`errs' member. */ |
`errs' member. */ |
321 |
states[i]->errs = errs_new (0, 0); |
states[i]->errs = errs_new (0, 0); |
322 |
} |
} |
323 |
|
|
324 |
free (errs); |
free (errors); |
325 |
} |
} |
326 |
|
|
327 |
|
|
330 |
`---------------------------------------------*/ |
`---------------------------------------------*/ |
331 |
|
|
332 |
static int |
static int |
333 |
count_sr_conflicts (state_t *state) |
count_sr_conflicts (state *s) |
334 |
{ |
{ |
335 |
int i; |
int i; |
336 |
int src_count = 0; |
int src_count = 0; |
337 |
transitions_t *transitions = state->transitions; |
transitions *trans = s->transitions; |
338 |
reductions_t *reds = state->reductions; |
reductions *reds = s->reductions; |
339 |
|
|
340 |
if (!transitions) |
if (!trans) |
341 |
return 0; |
return 0; |
342 |
|
|
343 |
bitset_zero (lookaheadset); |
bitset_zero (lookaheadset); |
344 |
bitset_zero (shiftset); |
bitset_zero (shiftset); |
345 |
|
|
346 |
FOR_EACH_SHIFT (transitions, i) |
FOR_EACH_SHIFT (trans, i) |
347 |
bitset_set (shiftset, TRANSITION_SYMBOL (transitions, i)); |
bitset_set (shiftset, TRANSITION_SYMBOL (trans, i)); |
348 |
|
|
349 |
for (i = 0; i < reds->num; ++i) |
for (i = 0; i < reds->num; ++i) |
350 |
bitset_or (lookaheadset, lookaheadset, reds->lookaheads[i]); |
bitset_or (lookaheadset, lookaheadset, reds->lookaheads[i]); |
365 |
+`----------------------------------------------------------------*/ |
+`----------------------------------------------------------------*/ |
366 |
|
|
367 |
static int |
static int |
368 |
count_rr_conflicts (state_t *state, int one_per_token) |
count_rr_conflicts (state *s, int one_per_token) |
369 |
{ |
{ |
370 |
int i; |
int i; |
371 |
reductions_t *reds = state->reductions; |
reductions *reds = s->reductions; |
372 |
int rrc_count = 0; |
int rrc_count = 0; |
373 |
|
|
374 |
for (i = 0; i < ntokens; i++) |
for (i = 0; i < ntokens; i++) |
452 |
conflicts_output (FILE *out) |
conflicts_output (FILE *out) |
453 |
{ |
{ |
454 |
bool printed_sth = false; |
bool printed_sth = false; |
455 |
state_number_t i; |
state_number i; |
456 |
for (i = 0; i < nstates; i++) |
for (i = 0; i < nstates; i++) |
457 |
{ |
{ |
458 |
state_t *s = states[i]; |
state *s = states[i]; |
459 |
if (conflicts[i]) |
if (conflicts[i]) |
460 |
{ |
{ |
461 |
fprintf (out, _("State %d contains "), i); |
fprintf (out, _("State %d contains "), i); |
479 |
int |
int |
480 |
conflicts_total_count (void) |
conflicts_total_count (void) |
481 |
{ |
{ |
482 |
state_number_t i; |
state_number i; |
483 |
int count; |
int count; |
484 |
|
|
485 |
/* Conflicts by state. */ |
/* Conflicts by state. */ |
511 |
|
|
512 |
/* Conflicts by state. */ |
/* Conflicts by state. */ |
513 |
{ |
{ |
514 |
state_number_t i; |
state_number i; |
515 |
|
|
516 |
for (i = 0; i < nstates; i++) |
for (i = 0; i < nstates; i++) |
517 |
if (conflicts[i]) |
if (conflicts[i]) |