]> git.saurik.com Git - bison.git/blame - src/conflicts.c
(strsuffix, stringappend): Remove; unused.
[bison.git] / src / conflicts.c
CommitLineData
08089d5d 1/* Find and resolve or report look-ahead conflicts for bison,
f041e30b 2
03b31c0c
AD
3 Copyright (C) 1984, 1989, 1992, 2000, 2001, 2002
4 Free Software Foundation, Inc.
08089d5d 5
ceed8467 6 This file is part of Bison, the GNU Compiler Compiler.
08089d5d 7
ceed8467
AD
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)
11 any later version.
08089d5d 12
ceed8467
AD
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.
08089d5d 17
ceed8467
AD
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
21 02111-1307, USA. */
08089d5d 22
08089d5d 23#include "system.h"
f041e30b
PE
24
25#include <bitset.h>
26
27#include "LR0.h"
7da99ede 28#include "complain.h"
f041e30b 29#include "conflicts.h"
08089d5d 30#include "files.h"
f041e30b 31#include "getargs.h"
08089d5d 32#include "gram.h"
720d742f 33#include "lalr.h"
b2ca4022 34#include "reader.h"
f041e30b
PE
35#include "state.h"
36#include "symtab.h"
d2729d44 37
7da99ede
AD
38/* -1 stands for not specified. */
39int expected_conflicts = -1;
342b8b6e 40static char *conflicts = NULL;
b408954b 41struct obstack solved_conflicts_obstack;
08089d5d 42
b86796bf
AD
43static bitset shiftset;
44static bitset lookaheadset;
b408954b 45
c29240e7 46\f
08089d5d 47
f041e30b 48enum conflict_resolution
b408954b
AD
49 {
50 shift_resolution,
51 reduce_resolution,
52 left_resolution,
53 right_resolution,
86eff183 54 nonassoc_resolution
b408954b
AD
55 };
56
57
9801d40c
AD
58/*----------------------------------------------------------------.
59| Explain how an SR conflict between TOKEN and RULE was resolved: |
60| RESOLUTION. |
61`----------------------------------------------------------------*/
62
c29240e7 63static inline void
f041e30b
PE
64log_resolution (rule *r, symbol_number token,
65 enum conflict_resolution resolution)
08089d5d 66{
b408954b
AD
67 if (report_flag & report_solved_conflicts)
68 {
69 /* The description of the resolution. */
70 switch (resolution)
71 {
72 case shift_resolution:
4b3d3a8e 73 case right_resolution:
b408954b
AD
74 obstack_fgrow2 (&solved_conflicts_obstack,
75 _("\
76 Conflict between rule %d and token %s resolved as shift"),
f041e30b 77 r->number,
b408954b
AD
78 symbols[token]->tag);
79 break;
80 case reduce_resolution:
4b3d3a8e 81 case left_resolution:
b408954b
AD
82 obstack_fgrow2 (&solved_conflicts_obstack,
83 _("\
84 Conflict between rule %d and token %s resolved as reduce"),
f041e30b 85 r->number,
b408954b
AD
86 symbols[token]->tag);
87 break;
88 case nonassoc_resolution:
89 obstack_fgrow2 (&solved_conflicts_obstack,
90 _("\
91 Conflict between rule %d and token %s resolved as an error"),
f041e30b 92 r->number,
b408954b
AD
93 symbols[token]->tag);
94 break;
95 }
96
97 /* The reason. */
98 switch (resolution)
99 {
100 case shift_resolution:
101 obstack_fgrow2 (&solved_conflicts_obstack,
102 " (%s < %s)",
f041e30b 103 r->prec->tag,
b408954b
AD
104 symbols[token]->tag);
105 break;
106
107 case reduce_resolution:
108 obstack_fgrow2 (&solved_conflicts_obstack,
109 " (%s < %s)",
110 symbols[token]->tag,
f041e30b 111 r->prec->tag);
b408954b
AD
112 break;
113
114 case left_resolution:
4a713ec2 115 obstack_fgrow1 (&solved_conflicts_obstack,
b408954b
AD
116 " (%%left %s)",
117 symbols[token]->tag);
118 break;
119
120 case right_resolution:
121 obstack_fgrow1 (&solved_conflicts_obstack,
122 " (%%right %s)",
123 symbols[token]->tag);
124 break;
125 case nonassoc_resolution:
126 obstack_fgrow1 (&solved_conflicts_obstack,
127 " (%%nonassoc %s)",
128 symbols[token]->tag);
129 break;
130 }
131 obstack_sgrow (&solved_conflicts_obstack, ".\n");
132 }
08089d5d
DM
133}
134
135
c29240e7
AD
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`------------------------------------------------------------------*/
141
4a120d45 142static void
f041e30b 143flush_shift (state *s, int token)
08089d5d 144{
f041e30b 145 transitions *trans = s->transitions;
9f136c07 146 int i;
c29240e7 147
b86796bf 148 bitset_reset (lookaheadset, token);
f041e30b
PE
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);
08089d5d
DM
153}
154
155
709ae8c6
AD
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`-------------------------------------------------------------------*/
161
162static void
9801d40c 163flush_reduce (bitset lookaheads, int token)
709ae8c6 164{
9801d40c 165 bitset_reset (lookaheads, token);
709ae8c6
AD
166}
167
168
c29240e7
AD
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. |
9801d40c
AD
174| |
175| LOOKAHEAD is the number of the lookahead bitset to consider. |
8b752b00 176| |
f041e30b 177| ERRORS can be used to store discovered explicit errors. |
c29240e7 178`------------------------------------------------------------------*/
08089d5d 179
4a120d45 180static void
f041e30b 181resolve_sr_conflict (state *s, int ruleno, symbol **errors)
08089d5d 182{
f041e30b
PE
183 symbol_number i;
184 reductions *reds = s->reductions;
9801d40c 185 /* Find the rule to reduce by to get precedence of reduction. */
f041e30b 186 rule *redrule = reds->rules[ruleno];
9801d40c 187 int redprec = redrule->prec->prec;
cd08e51e 188 bitset lookaheads = reds->lookaheads[ruleno];
8b752b00 189 int nerrs = 0;
08089d5d 190
08089d5d 191 for (i = 0; i < ntokens; i++)
9801d40c 192 if (bitset_test (lookaheads, i)
b86796bf 193 && bitset_test (lookaheadset, i)
0e78e603 194 && symbols[i]->prec)
92b16366 195 {
709ae8c6
AD
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. */
0e78e603 199 if (symbols[i]->prec < redprec)
92b16366 200 {
9801d40c 201 log_resolution (redrule, i, reduce_resolution);
f041e30b 202 flush_shift (s, i);
92b16366 203 }
0e78e603 204 else if (symbols[i]->prec > redprec)
92b16366 205 {
9801d40c
AD
206 log_resolution (redrule, i, shift_resolution);
207 flush_reduce (lookaheads, i);
92b16366
AD
208 }
209 else
709ae8c6
AD
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. */
214
5a670b1e 215 switch (symbols[i]->assoc)
709ae8c6
AD
216 {
217 case right_assoc:
9801d40c
AD
218 log_resolution (redrule, i, right_resolution);
219 flush_reduce (lookaheads, i);
709ae8c6
AD
220 break;
221
222 case left_assoc:
9801d40c 223 log_resolution (redrule, i, left_resolution);
f041e30b 224 flush_shift (s, i);
709ae8c6
AD
225 break;
226
227 case non_assoc:
9801d40c 228 log_resolution (redrule, i, nonassoc_resolution);
f041e30b 229 flush_shift (s, i);
9801d40c 230 flush_reduce (lookaheads, i);
709ae8c6 231 /* Record an explicit error for this token. */
f041e30b 232 errors[nerrs++] = symbols[i];
709ae8c6 233 break;
e9955c83
AD
234
235 case undef_assoc:
b9a01048 236 abort ();
709ae8c6 237 }
92b16366
AD
238 }
239
92b16366
AD
240 /* Some tokens have been explicitly made errors. Allocate a
241 permanent errs structure for this state, to record them. */
f041e30b 242 state_errs_set (s, nerrs, errors);
b408954b
AD
243
244 if (obstack_object_size (&solved_conflicts_obstack))
245 {
246 obstack_1grow (&solved_conflicts_obstack, '\0');
f041e30b 247 s->solved_conflicts = obstack_finish (&solved_conflicts_obstack);
b408954b 248 }
08089d5d
DM
249}
250
251
8b752b00 252/*-------------------------------------------------------------------.
f041e30b 253| Solve the S/R conflicts of state S using the |
8b752b00 254| precedence/associativity, and flag it inconsistent if it still has |
f041e30b
PE
255| conflicts. ERRORS can be used as storage to compute the list of |
256| lookaheads on which S raises a syntax error (%nonassoc). |
8b752b00
AD
257`-------------------------------------------------------------------*/
258
4a120d45 259static void
f041e30b 260set_conflicts (state *s, symbol **errors)
08089d5d 261{
914feea9 262 int i;
f041e30b
PE
263 transitions *trans = s->transitions;
264 reductions *reds = s->reductions;
c29240e7 265
f041e30b 266 if (s->consistent)
c29240e7 267 return;
08089d5d 268
b86796bf 269 bitset_zero (lookaheadset);
08089d5d 270
f041e30b
PE
271 FOR_EACH_SHIFT (trans, i)
272 bitset_set (lookaheadset, TRANSITION_SYMBOL (trans, i));
08089d5d 273
c29240e7
AD
274 /* Loop over all rules which require lookahead in this state. First
275 check for shift-reduce conflict, and try to resolve using
9801d40c 276 precedence. */
cd08e51e
AD
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))
914feea9 280 {
f041e30b 281 resolve_sr_conflict (s, i, errors);
914feea9
AD
282 break;
283 }
08089d5d 284
c29240e7
AD
285 /* Loop over all rules which require lookahead in this state. Check
286 for conflicts not resolved above. */
cd08e51e 287 for (i = 0; i < reds->num; ++i)
08089d5d 288 {
cd08e51e 289 if (!bitset_disjoint_p (reds->lookaheads[i], lookaheadset))
f041e30b 290 conflicts[s->number] = 1;
08089d5d 291
cd08e51e 292 bitset_or (lookaheadset, lookaheadset, reds->lookaheads[i]);
c29240e7
AD
293 }
294}
08089d5d 295
8b752b00
AD
296
297/*----------------------------------------------------------------.
298| Solve all the S/R conflicts using the precedence/associativity, |
299| and flag as inconsistent the states that still have conflicts. |
300`----------------------------------------------------------------*/
301
08089d5d 302void
b408954b 303conflicts_solve (void)
08089d5d 304{
f041e30b 305 state_number i;
6e649e65 306 /* List of lookaheads on which we explicitly raise a syntax error. */
f041e30b 307 symbol **errors = XMALLOC (symbol *, ntokens + 1);
08089d5d 308
d7913476 309 conflicts = XCALLOC (char, nstates);
b86796bf 310 shiftset = bitset_create (ntokens, BITSET_FIXED);
b86796bf 311 lookaheadset = bitset_create (ntokens, BITSET_FIXED);
b408954b 312 obstack_init (&solved_conflicts_obstack);
08089d5d 313
c29240e7 314 for (i = 0; i < nstates; i++)
8b752b00 315 {
f041e30b 316 set_conflicts (states[i], errors);
8b752b00
AD
317
318 /* For uniformity of the code, make sure all the states have a valid
319 `errs' member. */
320 if (!states[i]->errs)
321 states[i]->errs = errs_new (0, 0);
322 }
323
f041e30b 324 free (errors);
08089d5d
DM
325}
326
327
c29240e7
AD
328/*---------------------------------------------.
329| Count the number of shift/reduce conflicts. |
330`---------------------------------------------*/
331
0df87bb6 332static int
f041e30b 333count_sr_conflicts (state *s)
08089d5d 334{
f9abaa2c 335 int i;
0df87bb6 336 int src_count = 0;
f041e30b
PE
337 transitions *trans = s->transitions;
338 reductions *reds = s->reductions;
08089d5d 339
f041e30b 340 if (!trans)
0df87bb6 341 return 0;
08089d5d 342
b86796bf
AD
343 bitset_zero (lookaheadset);
344 bitset_zero (shiftset);
08089d5d 345
f041e30b
PE
346 FOR_EACH_SHIFT (trans, i)
347 bitset_set (shiftset, TRANSITION_SYMBOL (trans, i));
08089d5d 348
cd08e51e
AD
349 for (i = 0; i < reds->num; ++i)
350 bitset_or (lookaheadset, lookaheadset, reds->lookaheads[i]);
08089d5d 351
b86796bf 352 bitset_and (lookaheadset, lookaheadset, shiftset);
08089d5d 353
914feea9 354 src_count = bitset_count (lookaheadset);
0df87bb6
AD
355
356 return src_count;
08089d5d
DM
357}
358
359
676385e2
PH
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+`----------------------------------------------------------------*/
c29240e7 366
0df87bb6 367static int
f041e30b 368count_rr_conflicts (state *s, int one_per_token)
08089d5d 369{
c29240e7 370 int i;
f041e30b 371 reductions *reds = s->reductions;
0df87bb6 372 int rrc_count = 0;
08089d5d 373
08089d5d
DM
374 for (i = 0; i < ntokens; i++)
375 {
0df87bb6
AD
376 int count = 0;
377 int j;
cd08e51e
AD
378 for (j = 0; j < reds->num; ++j)
379 if (bitset_test (reds->lookaheads[j], i))
52afa962 380 count++;
08089d5d 381
c29240e7 382 if (count >= 2)
676385e2 383 rrc_count += one_per_token ? 1 : count-1;
08089d5d 384 }
0df87bb6
AD
385
386 return rrc_count;
08089d5d
DM
387}
388
52489d44 389
ff4423cc
AD
390/*--------------------------------------------------------------.
391| Return a human readable string which reports shift/reduce and |
392| reduce/reduce conflict numbers (SRC_NUM, RRC_NUM). |
393`--------------------------------------------------------------*/
c29240e7 394
ff4423cc
AD
395static const char *
396conflict_report (int src_num, int rrc_num)
c29240e7 397{
ff4423cc
AD
398 static char res[4096];
399 char *cp = res;
400
7da99ede 401 if (src_num >= 1)
22c821f3 402 {
7da99ede
AD
403 sprintf (cp, ngettext ("%d shift/reduce conflict",
404 "%d shift/reduce conflicts", src_num), src_num);
22c821f3
AD
405 cp += strlen (cp);
406 }
c29240e7 407
0619caf0 408 if (src_num > 0 && rrc_num > 0)
22c821f3 409 {
7da99ede 410 sprintf (cp, " %s ", _("and"));
22c821f3
AD
411 cp += strlen (cp);
412 }
c29240e7 413
7da99ede 414 if (rrc_num >= 1)
22c821f3 415 {
7da99ede
AD
416 sprintf (cp, ngettext ("%d reduce/reduce conflict",
417 "%d reduce/reduce conflicts", rrc_num), rrc_num);
22c821f3
AD
418 cp += strlen (cp);
419 }
ff4423cc 420
ff4423cc 421 *cp++ = '\0';
c29240e7 422
ff4423cc 423 return res;
c29240e7
AD
424}
425
426
52489d44
AD
427/*----------------------------------------------------------------.
428| Same as above, but report the number of conflicts a` la POSIX. |
429`----------------------------------------------------------------*/
430
431static void
432conflict_report_yacc (int src_num, int rrc_num)
433{
434 /* If invoked with `--yacc', use the output format specified by
435 POSIX. */
436 fprintf (stderr, _("conflicts: "));
437 if (src_num > 0)
438 fprintf (stderr, _(" %d shift/reduce"), src_num);
439 if (src_num > 0 && rrc_num > 0)
440 fprintf (stderr, ",");
441 if (rrc_num > 0)
442 fprintf (stderr, _(" %d reduce/reduce"), rrc_num);
443 putc ('\n', stderr);
444}
445
446
0df87bb6
AD
447/*-----------------------------------------------------------.
448| Output the detailed description of states with conflicts. |
449`-----------------------------------------------------------*/
c29240e7
AD
450
451void
0df87bb6 452conflicts_output (FILE *out)
c29240e7 453{
8307162d 454 bool printed_sth = false;
f041e30b 455 state_number i;
0df87bb6 456 for (i = 0; i < nstates; i++)
640748ee 457 {
f041e30b 458 state *s = states[i];
640748ee
AD
459 if (conflicts[i])
460 {
461 fprintf (out, _("State %d contains "), i);
52489d44
AD
462 fprintf (out, "%s.\n",
463 conflict_report (count_sr_conflicts (s),
8307162d
PE
464 count_rr_conflicts (s, true)));
465 printed_sth = true;
640748ee
AD
466 }
467 }
d2d1b42b
AD
468 if (printed_sth)
469 fputs ("\n\n", out);
0df87bb6 470}
c29240e7 471
676385e2
PH
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 |
476| conflict. |
477`--------------------------------------------------------*/
478
479int
480conflicts_total_count (void)
481{
f041e30b 482 state_number i;
676385e2
PH
483 int count;
484
485 /* Conflicts by state. */
486 count = 0;
487 for (i = 0; i < nstates; i++)
488 if (conflicts[i])
489 {
490 count += count_sr_conflicts (states[i]);
8307162d 491 count += count_rr_conflicts (states[i], false);
676385e2
PH
492 }
493 return count;
494}
e0e5bf84 495
c29240e7 496
0df87bb6
AD
497/*------------------------------------------.
498| Reporting the total number of conflicts. |
499`------------------------------------------*/
0619caf0 500
0df87bb6
AD
501void
502conflicts_print (void)
503{
a034c8b8
AD
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. */
507 int src_ok = 0;
508
0df87bb6
AD
509 int src_total = 0;
510 int rrc_total = 0;
511
512 /* Conflicts by state. */
d57650a5 513 {
f041e30b 514 state_number i;
d57650a5
AD
515
516 for (i = 0; i < nstates; i++)
517 if (conflicts[i])
518 {
519 src_total += count_sr_conflicts (states[i]);
8307162d 520 rrc_total += count_rr_conflicts (states[i], true);
d57650a5
AD
521 }
522 }
c29240e7 523
a034c8b8
AD
524 src_ok = src_total == (expected_conflicts == -1 ? 0 : expected_conflicts);
525
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)
529 return;
530
0619caf0 531 /* Report the total number of conflicts on STDERR. */
a034c8b8 532 if (yacc_flag)
52489d44 533 conflict_report_yacc (src_total, rrc_total);
a034c8b8 534 else
52489d44 535 warn ("%s", conflict_report (src_total, rrc_total));
7da99ede 536
a034c8b8 537 if (expected_conflicts != -1 && !src_ok)
52489d44
AD
538 complain (ngettext ("expected %d shift/reduce conflict",
539 "expected %d shift/reduce conflicts",
540 expected_conflicts),
541 expected_conflicts);
c29240e7
AD
542}
543
544
08089d5d 545void
b408954b 546conflicts_free (void)
08089d5d 547{
d7913476 548 XFREE (conflicts);
b86796bf
AD
549 bitset_free (shiftset);
550 bitset_free (lookaheadset);
b408954b 551 obstack_free (&solved_conflicts_obstack, NULL);
08089d5d 552}