1 /* Find and resolve or report look-ahead conflicts for bison,
3 Copyright (C) 1984, 1989, 1992, 2000, 2001, 2002
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., 59 Temple Place - Suite 330, Boston, MA
29 #include "conflicts.h"
38 /* -1 stands for not specified. */
39 int expected_conflicts
= -1;
40 static char *conflicts
= NULL
;
41 struct obstack solved_conflicts_obstack
;
43 static bitset shiftset
;
44 static bitset lookaheadset
;
48 enum conflict_resolution
58 /*----------------------------------------------------------------.
59 | Explain how an SR conflict between TOKEN and RULE was resolved: |
61 `----------------------------------------------------------------*/
64 log_resolution (rule
*r
, symbol_number token
,
65 enum conflict_resolution resolution
)
67 if (report_flag
& report_solved_conflicts
)
69 /* The description of the resolution. */
72 case shift_resolution
:
73 case right_resolution
:
74 obstack_fgrow2 (&solved_conflicts_obstack
,
76 Conflict between rule %d and token %s resolved as shift"),
80 case reduce_resolution
:
82 obstack_fgrow2 (&solved_conflicts_obstack
,
84 Conflict between rule %d and token %s resolved as reduce"),
88 case nonassoc_resolution
:
89 obstack_fgrow2 (&solved_conflicts_obstack
,
91 Conflict between rule %d and token %s resolved as an error"),
100 case shift_resolution
:
101 obstack_fgrow2 (&solved_conflicts_obstack
,
104 symbols
[token
]->tag
);
107 case reduce_resolution
:
108 obstack_fgrow2 (&solved_conflicts_obstack
,
114 case left_resolution
:
115 obstack_fgrow1 (&solved_conflicts_obstack
,
117 symbols
[token
]->tag
);
120 case right_resolution
:
121 obstack_fgrow1 (&solved_conflicts_obstack
,
123 symbols
[token
]->tag
);
125 case nonassoc_resolution
:
126 obstack_fgrow1 (&solved_conflicts_obstack
,
128 symbols
[token
]->tag
);
131 obstack_sgrow (&solved_conflicts_obstack
, ".\n");
136 /*------------------------------------------------------------------.
137 | Turn off the shift recorded for the specified token in the |
138 | specified state. Used when we resolve a shift-reduce conflict in |
139 | favor of the reduction. |
140 `------------------------------------------------------------------*/
143 flush_shift (state
*s
, int token
)
145 transitions
*trans
= s
->transitions
;
148 bitset_reset (lookaheadset
, token
);
149 for (i
= 0; i
< trans
->num
; i
++)
150 if (!TRANSITION_IS_DISABLED (trans
, i
)
151 && TRANSITION_SYMBOL (trans
, i
) == token
)
152 TRANSITION_DISABLE (trans
, i
);
156 /*-------------------------------------------------------------------.
157 | Turn off the reduce recorded for the specified token for the |
158 | specified lookahead. Used when we resolve a shift-reduce conflict |
159 | in favor of the shift. |
160 `-------------------------------------------------------------------*/
163 flush_reduce (bitset lookaheads
, int token
)
165 bitset_reset (lookaheads
, token
);
169 /*------------------------------------------------------------------.
170 | Attempt to resolve shift-reduce conflict for one rule by means of |
171 | precedence declarations. It has already been checked that the |
172 | rule has a precedence. A conflict is resolved by modifying the |
173 | shift or reduce tables so that there is no longer a conflict. |
175 | LOOKAHEAD is the number of the lookahead bitset to consider. |
177 | ERRORS can be used to store discovered explicit errors. |
178 `------------------------------------------------------------------*/
181 resolve_sr_conflict (state
*s
, int ruleno
, symbol
**errors
)
184 reductions
*reds
= s
->reductions
;
185 /* Find the rule to reduce by to get precedence of reduction. */
186 rule
*redrule
= reds
->rules
[ruleno
];
187 int redprec
= redrule
->prec
->prec
;
188 bitset lookaheads
= reds
->lookaheads
[ruleno
];
191 for (i
= 0; i
< ntokens
; i
++)
192 if (bitset_test (lookaheads
, i
)
193 && bitset_test (lookaheadset
, i
)
196 /* Shift-reduce conflict occurs for token number i
197 and it has a precedence.
198 The precedence of shifting is that of token i. */
199 if (symbols
[i
]->prec
< redprec
)
201 log_resolution (redrule
, i
, reduce_resolution
);
204 else if (symbols
[i
]->prec
> redprec
)
206 log_resolution (redrule
, i
, shift_resolution
);
207 flush_reduce (lookaheads
, i
);
210 /* Matching precedence levels.
211 For left association, keep only the reduction.
212 For right association, keep only the shift.
213 For nonassociation, keep neither. */
215 switch (symbols
[i
]->assoc
)
218 log_resolution (redrule
, i
, right_resolution
);
219 flush_reduce (lookaheads
, i
);
223 log_resolution (redrule
, i
, left_resolution
);
228 log_resolution (redrule
, i
, nonassoc_resolution
);
230 flush_reduce (lookaheads
, i
);
231 /* Record an explicit error for this token. */
232 errors
[nerrs
++] = symbols
[i
];
240 /* Some tokens have been explicitly made errors. Allocate a
241 permanent errs structure for this state, to record them. */
242 state_errs_set (s
, nerrs
, errors
);
244 if (obstack_object_size (&solved_conflicts_obstack
))
246 obstack_1grow (&solved_conflicts_obstack
, '\0');
247 s
->solved_conflicts
= obstack_finish (&solved_conflicts_obstack
);
252 /*-------------------------------------------------------------------.
253 | Solve the S/R conflicts of state S using the |
254 | precedence/associativity, and flag it inconsistent if it still has |
255 | conflicts. ERRORS can be used as storage to compute the list of |
256 | lookaheads on which S raises a syntax error (%nonassoc). |
257 `-------------------------------------------------------------------*/
260 set_conflicts (state
*s
, symbol
**errors
)
263 transitions
*trans
= s
->transitions
;
264 reductions
*reds
= s
->reductions
;
269 bitset_zero (lookaheadset
);
271 FOR_EACH_SHIFT (trans
, i
)
272 bitset_set (lookaheadset
, TRANSITION_SYMBOL (trans
, i
));
274 /* Loop over all rules which require lookahead in this state. First
275 check for shift-reduce conflict, and try to resolve using
277 for (i
= 0; i
< reds
->num
; ++i
)
278 if (reds
->rules
[i
]->prec
&& reds
->rules
[i
]->prec
->prec
279 && !bitset_disjoint_p (reds
->lookaheads
[i
], lookaheadset
))
281 resolve_sr_conflict (s
, i
, errors
);
285 /* Loop over all rules which require lookahead in this state. Check
286 for conflicts not resolved above. */
287 for (i
= 0; i
< reds
->num
; ++i
)
289 if (!bitset_disjoint_p (reds
->lookaheads
[i
], lookaheadset
))
290 conflicts
[s
->number
] = 1;
292 bitset_or (lookaheadset
, lookaheadset
, reds
->lookaheads
[i
]);
297 /*----------------------------------------------------------------.
298 | Solve all the S/R conflicts using the precedence/associativity, |
299 | and flag as inconsistent the states that still have conflicts. |
300 `----------------------------------------------------------------*/
303 conflicts_solve (void)
306 /* List of lookaheads on which we explicitly raise a syntax error. */
307 symbol
**errors
= XMALLOC (symbol
*, ntokens
+ 1);
309 conflicts
= XCALLOC (char, nstates
);
310 shiftset
= bitset_create (ntokens
, BITSET_FIXED
);
311 lookaheadset
= bitset_create (ntokens
, BITSET_FIXED
);
312 obstack_init (&solved_conflicts_obstack
);
314 for (i
= 0; i
< nstates
; i
++)
316 set_conflicts (states
[i
], errors
);
318 /* For uniformity of the code, make sure all the states have a valid
320 if (!states
[i
]->errs
)
321 states
[i
]->errs
= errs_new (0, 0);
328 /*---------------------------------------------.
329 | Count the number of shift/reduce conflicts. |
330 `---------------------------------------------*/
333 count_sr_conflicts (state
*s
)
337 transitions
*trans
= s
->transitions
;
338 reductions
*reds
= s
->reductions
;
343 bitset_zero (lookaheadset
);
344 bitset_zero (shiftset
);
346 FOR_EACH_SHIFT (trans
, i
)
347 bitset_set (shiftset
, TRANSITION_SYMBOL (trans
, i
));
349 for (i
= 0; i
< reds
->num
; ++i
)
350 bitset_or (lookaheadset
, lookaheadset
, reds
->lookaheads
[i
]);
352 bitset_and (lookaheadset
, lookaheadset
, shiftset
);
354 src_count
= bitset_count (lookaheadset
);
360 /*----------------------------------------------------------------.
361 | Count the number of reduce/reduce conflicts. If ONE_PER_TOKEN, |
362 | count one conflict for each token that has any reduce/reduce |
363 | conflicts. Otherwise, count one conflict for each pair of |
364 | conflicting reductions. |
365 +`----------------------------------------------------------------*/
368 count_rr_conflicts (state
*s
, int one_per_token
)
371 reductions
*reds
= s
->reductions
;
374 for (i
= 0; i
< ntokens
; i
++)
378 for (j
= 0; j
< reds
->num
; ++j
)
379 if (bitset_test (reds
->lookaheads
[j
], i
))
383 rrc_count
+= one_per_token
? 1 : count
-1;
390 /*--------------------------------------------------------------.
391 | Return a human readable string which reports shift/reduce and |
392 | reduce/reduce conflict numbers (SRC_NUM, RRC_NUM). |
393 `--------------------------------------------------------------*/
396 conflict_report (int src_num
, int rrc_num
)
398 static char res
[4096];
403 sprintf (cp
, ngettext ("%d shift/reduce conflict",
404 "%d shift/reduce conflicts", src_num
), src_num
);
408 if (src_num
> 0 && rrc_num
> 0)
410 sprintf (cp
, " %s ", _("and"));
416 sprintf (cp
, ngettext ("%d reduce/reduce conflict",
417 "%d reduce/reduce conflicts", rrc_num
), rrc_num
);
427 /*----------------------------------------------------------------.
428 | Same as above, but report the number of conflicts a` la POSIX. |
429 `----------------------------------------------------------------*/
432 conflict_report_yacc (int src_num
, int rrc_num
)
434 /* If invoked with `--yacc', use the output format specified by
436 fprintf (stderr
, _("conflicts: "));
438 fprintf (stderr
, _(" %d shift/reduce"), src_num
);
439 if (src_num
> 0 && rrc_num
> 0)
440 fprintf (stderr
, ",");
442 fprintf (stderr
, _(" %d reduce/reduce"), rrc_num
);
447 /*-----------------------------------------------------------.
448 | Output the detailed description of states with conflicts. |
449 `-----------------------------------------------------------*/
452 conflicts_output (FILE *out
)
454 bool printed_sth
= false;
456 for (i
= 0; i
< nstates
; i
++)
458 state
*s
= states
[i
];
461 fprintf (out
, _("State %d contains "), i
);
462 fprintf (out
, "%s.\n",
463 conflict_report (count_sr_conflicts (s
),
464 count_rr_conflicts (s
, true)));
472 /*--------------------------------------------------------.
473 | Total the number of S/R and R/R conflicts. Unlike the |
474 | code in conflicts_output, however, count EACH pair of |
475 | reductions for the same state and lookahead as one |
477 `--------------------------------------------------------*/
480 conflicts_total_count (void)
485 /* Conflicts by state. */
487 for (i
= 0; i
< nstates
; i
++)
490 count
+= count_sr_conflicts (states
[i
]);
491 count
+= count_rr_conflicts (states
[i
], false);
497 /*------------------------------------------.
498 | Reporting the total number of conflicts. |
499 `------------------------------------------*/
502 conflicts_print (void)
504 /* Is the number of SR conflicts OK? Either EXPECTED_CONFLICTS is
505 not set, and then we want 0 SR, or else it is specified, in which
506 case we want equality. */
512 /* Conflicts by state. */
516 for (i
= 0; i
< nstates
; i
++)
519 src_total
+= count_sr_conflicts (states
[i
]);
520 rrc_total
+= count_rr_conflicts (states
[i
], true);
524 src_ok
= src_total
== (expected_conflicts
== -1 ? 0 : expected_conflicts
);
526 /* If there are no RR conflicts, and as many SR conflicts as
527 expected, then there is nothing to report. */
528 if (!rrc_total
&& src_ok
)
531 /* Report the total number of conflicts on STDERR. */
533 conflict_report_yacc (src_total
, rrc_total
);
535 warn ("%s", conflict_report (src_total
, rrc_total
));
537 if (expected_conflicts
!= -1 && !src_ok
)
538 complain (ngettext ("expected %d shift/reduce conflict",
539 "expected %d shift/reduce conflicts",
546 conflicts_free (void)
549 bitset_free (shiftset
);
550 bitset_free (lookaheadset
);
551 obstack_free (&solved_conflicts_obstack
, NULL
);