1 /* Find and resolve or report look-ahead conflicts for bison,
2 Copyright (C) 1984, 1989, 1992, 2000, 2001, 2002
3 Free Software Foundation, Inc.
5 This file is part of Bison, the GNU Compiler Compiler.
7 Bison is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 Bison is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bison; see the file COPYING. If not, write to the Free
19 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
31 #include "conflicts.h"
35 /* -1 stands for not specified. */
36 int expected_conflicts
= -1;
37 static char *conflicts
= NULL
;
38 struct obstack solved_conflicts_obstack
;
40 static bitset shiftset
;
41 static bitset lookaheadset
;
45 enum conflict_resolution_e
55 /*----------------------------------------------------------------.
56 | Explain how an SR conflict between TOKEN and RULE was resolved: |
58 `----------------------------------------------------------------*/
61 log_resolution (rule_t
*rule
, symbol_number_t token
,
62 enum conflict_resolution_e resolution
)
64 if (report_flag
& report_solved_conflicts
)
66 /* The description of the resolution. */
69 case shift_resolution
:
71 obstack_fgrow2 (&solved_conflicts_obstack
,
73 Conflict between rule %d and token %s resolved as shift"),
77 case reduce_resolution
:
78 case right_resolution
:
79 obstack_fgrow2 (&solved_conflicts_obstack
,
81 Conflict between rule %d and token %s resolved as reduce"),
85 case nonassoc_resolution
:
86 obstack_fgrow2 (&solved_conflicts_obstack
,
88 Conflict between rule %d and token %s resolved as an error"),
97 case shift_resolution
:
98 obstack_fgrow2 (&solved_conflicts_obstack
,
101 symbols
[token
]->tag
);
104 case reduce_resolution
:
105 obstack_fgrow2 (&solved_conflicts_obstack
,
111 case left_resolution
:
112 obstack_fgrow1 (&solved_conflicts_obstack
,
114 symbols
[token
]->tag
);
117 case right_resolution
:
118 obstack_fgrow1 (&solved_conflicts_obstack
,
120 symbols
[token
]->tag
);
122 case nonassoc_resolution
:
123 obstack_fgrow1 (&solved_conflicts_obstack
,
125 symbols
[token
]->tag
);
128 obstack_sgrow (&solved_conflicts_obstack
, ".\n");
133 /*------------------------------------------------------------------.
134 | Turn off the shift recorded for the specified token in the |
135 | specified state. Used when we resolve a shift-reduce conflict in |
136 | favor of the reduction. |
137 `------------------------------------------------------------------*/
140 flush_shift (state_t
*state
, int token
)
142 transitions_t
*transitions
= state
->shifts
;
145 bitset_reset (lookaheadset
, token
);
146 for (i
= 0; i
< transitions
->num
; i
++)
147 if (!TRANSITION_IS_DISABLED (transitions
, i
)
148 && TRANSITION_SYMBOL (transitions
, i
) == token
)
149 TRANSITION_DISABLE (transitions
, i
);
153 /*-------------------------------------------------------------------.
154 | Turn off the reduce recorded for the specified token for the |
155 | specified lookahead. Used when we resolve a shift-reduce conflict |
156 | in favor of the shift. |
157 `-------------------------------------------------------------------*/
160 flush_reduce (bitset lookaheads
, int token
)
162 bitset_reset (lookaheads
, token
);
166 /*------------------------------------------------------------------.
167 | Attempt to resolve shift-reduce conflict for one rule by means of |
168 | precedence declarations. It has already been checked that the |
169 | rule has a precedence. A conflict is resolved by modifying the |
170 | shift or reduce tables so that there is no longer a conflict. |
172 | LOOKAHEAD is the number of the lookahead bitset to consider. |
173 `------------------------------------------------------------------*/
176 resolve_sr_conflict (state_t
*state
, int lookahead
)
179 /* Find the rule to reduce by to get precedence of reduction. */
180 rule_t
*redrule
= state
->lookaheads_rule
[lookahead
];
181 int redprec
= redrule
->prec
->prec
;
182 bitset lookaheads
= state
->lookaheads
[lookahead
];
183 errs_t
*errp
= errs_new (ntokens
+ 1);
186 for (i
= 0; i
< ntokens
; i
++)
187 if (bitset_test (lookaheads
, i
)
188 && bitset_test (lookaheadset
, i
)
191 /* Shift-reduce conflict occurs for token number i
192 and it has a precedence.
193 The precedence of shifting is that of token i. */
194 if (symbols
[i
]->prec
< redprec
)
196 log_resolution (redrule
, i
, reduce_resolution
);
197 flush_shift (state
, i
);
199 else if (symbols
[i
]->prec
> redprec
)
201 log_resolution (redrule
, i
, shift_resolution
);
202 flush_reduce (lookaheads
, i
);
205 /* Matching precedence levels.
206 For left association, keep only the reduction.
207 For right association, keep only the shift.
208 For nonassociation, keep neither. */
210 switch (symbols
[i
]->assoc
)
213 log_resolution (redrule
, i
, right_resolution
);
214 flush_reduce (lookaheads
, i
);
218 log_resolution (redrule
, i
, left_resolution
);
219 flush_shift (state
, i
);
223 log_resolution (redrule
, i
, nonassoc_resolution
);
224 flush_shift (state
, i
);
225 flush_reduce (lookaheads
, i
);
226 /* Record an explicit error for this token. */
227 errp
->symbols
[errp
->num
++] = i
;
231 assert (symbols
[i
]->assoc
!= undef_assoc
);
236 /* Some tokens have been explicitly made errors. Allocate a
237 permanent errs structure for this state, to record them. */
238 state
->errs
= errs_dup (errp
);
241 if (obstack_object_size (&solved_conflicts_obstack
))
243 obstack_1grow (&solved_conflicts_obstack
, '\0');
244 state
->solved_conflicts
= obstack_finish (&solved_conflicts_obstack
);
250 set_conflicts (state_t
*state
)
253 transitions_t
*transitions
;
255 if (state
->consistent
)
258 bitset_zero (lookaheadset
);
260 transitions
= state
->shifts
;
261 for (i
= 0; i
< transitions
->num
&& TRANSITION_IS_SHIFT (transitions
, i
); i
++)
262 if (!TRANSITION_IS_DISABLED (transitions
, i
))
263 bitset_set (lookaheadset
, TRANSITION_SYMBOL (transitions
, i
));
265 /* Loop over all rules which require lookahead in this state. First
266 check for shift-reduce conflict, and try to resolve using
268 for (i
= 0; i
< state
->nlookaheads
; ++i
)
269 if (state
->lookaheads_rule
[i
]->prec
270 && state
->lookaheads_rule
[i
]->prec
->prec
271 && !bitset_disjoint_p (state
->lookaheads
[i
], lookaheadset
))
273 resolve_sr_conflict (state
, i
);
277 /* Loop over all rules which require lookahead in this state. Check
278 for conflicts not resolved above. */
279 for (i
= 0; i
< state
->nlookaheads
; ++i
)
281 if (!bitset_disjoint_p (state
->lookaheads
[i
], lookaheadset
))
282 conflicts
[state
->number
] = 1;
284 bitset_or (lookaheadset
, lookaheadset
, state
->lookaheads
[i
]);
289 conflicts_solve (void)
293 conflicts
= XCALLOC (char, nstates
);
294 shiftset
= bitset_create (ntokens
, BITSET_FIXED
);
295 lookaheadset
= bitset_create (ntokens
, BITSET_FIXED
);
296 obstack_init (&solved_conflicts_obstack
);
298 for (i
= 0; i
< nstates
; i
++)
299 set_conflicts (states
[i
]);
303 /*---------------------------------------------.
304 | Count the number of shift/reduce conflicts. |
305 `---------------------------------------------*/
308 count_sr_conflicts (state_t
*state
)
312 transitions_t
*transitions
= state
->shifts
;
317 bitset_zero (lookaheadset
);
318 bitset_zero (shiftset
);
320 for (i
= 0; i
< transitions
->num
&& TRANSITION_IS_SHIFT (transitions
, i
); i
++)
321 if (!TRANSITION_IS_DISABLED (transitions
, i
))
322 bitset_set (shiftset
, TRANSITION_SYMBOL (transitions
, i
));
324 for (i
= 0; i
< state
->nlookaheads
; ++i
)
325 bitset_or (lookaheadset
, lookaheadset
, state
->lookaheads
[i
]);
327 bitset_and (lookaheadset
, lookaheadset
, shiftset
);
329 src_count
= bitset_count (lookaheadset
);
335 /*----------------------------------------------------------------.
336 | Count the number of reduce/reduce conflicts. If ONE_PER_TOKEN, |
337 | count one conflict for each token that has any reduce/reduce |
338 | conflicts. Otherwise, count one conflict for each pair of |
339 | conflicting reductions. |
340 +`----------------------------------------------------------------*/
343 count_rr_conflicts (state_t
*state
, int one_per_token
)
348 if (state
->nlookaheads
< 2)
351 for (i
= 0; i
< ntokens
; i
++)
355 for (j
= 0; j
< state
->nlookaheads
; ++j
)
356 if (bitset_test (state
->lookaheads
[j
], i
))
360 rrc_count
+= one_per_token
? 1 : count
-1;
366 /*--------------------------------------------------------------.
367 | Return a human readable string which reports shift/reduce and |
368 | reduce/reduce conflict numbers (SRC_NUM, RRC_NUM). |
369 `--------------------------------------------------------------*/
372 conflict_report (int src_num
, int rrc_num
)
374 static char res
[4096];
379 sprintf (cp
, ngettext ("%d shift/reduce conflict",
380 "%d shift/reduce conflicts", src_num
), src_num
);
384 if (src_num
> 0 && rrc_num
> 0)
386 sprintf (cp
, " %s ", _("and"));
392 sprintf (cp
, ngettext ("%d reduce/reduce conflict",
393 "%d reduce/reduce conflicts", rrc_num
), rrc_num
);
405 /*-----------------------------------------------------------.
406 | Output the detailed description of states with conflicts. |
407 `-----------------------------------------------------------*/
410 conflicts_output (FILE *out
)
412 bool printed_sth
= FALSE
;
414 for (i
= 0; i
< nstates
; i
++)
417 fprintf (out
, _("State %d contains "), i
);
418 fputs (conflict_report (count_sr_conflicts (states
[i
]),
419 count_rr_conflicts (states
[i
], TRUE
)), out
);
426 /*--------------------------------------------------------.
427 | Total the number of S/R and R/R conflicts. Unlike the |
428 | code in conflicts_output, however, count EACH pair of |
429 | reductions for the same state and lookahead as one |
431 `--------------------------------------------------------*/
434 conflicts_total_count (void)
439 /* Conflicts by state. */
441 for (i
= 0; i
< nstates
; i
++)
444 count
+= count_sr_conflicts (states
[i
]);
445 count
+= count_rr_conflicts (states
[i
], FALSE
);
451 /*------------------------------------------.
452 | Reporting the total number of conflicts. |
453 `------------------------------------------*/
456 conflicts_print (void)
458 /* Is the number of SR conflicts OK? Either EXPECTED_CONFLICTS is
459 not set, and then we want 0 SR, or else it is specified, in which
460 case we want equality. */
466 /* Conflicts by state. */
470 for (i
= 0; i
< nstates
; i
++)
473 src_total
+= count_sr_conflicts (states
[i
]);
474 rrc_total
+= count_rr_conflicts (states
[i
], TRUE
);
478 src_ok
= src_total
== (expected_conflicts
== -1 ? 0 : expected_conflicts
);
480 /* If there are no RR conflicts, and as many SR conflicts as
481 expected, then there is nothing to report. */
482 if (!rrc_total
&& src_ok
)
485 /* Report the total number of conflicts on STDERR. */
488 /* If invoked with `--yacc', use the output format specified by
490 fprintf (stderr
, _("conflicts: "));
492 fprintf (stderr
, _(" %d shift/reduce"), src_total
);
493 if (src_total
> 0 && rrc_total
> 0)
494 fprintf (stderr
, ",");
496 fprintf (stderr
, _(" %d reduce/reduce"), rrc_total
);
501 fprintf (stderr
, _("%s contains "), infile
);
502 fputs (conflict_report (src_total
, rrc_total
), stderr
);
505 if (expected_conflicts
!= -1 && !src_ok
)
507 complain_message_count
++;
508 fprintf (stderr
, ngettext ("expected %d shift/reduce conflict\n",
509 "expected %d shift/reduce conflicts\n",
517 conflicts_free (void)
520 bitset_free (shiftset
);
521 bitset_free (lookaheadset
);
522 obstack_free (&solved_conflicts_obstack
, NULL
);