]> git.saurik.com Git - bison.git/blob - src/conflicts.c
* src/conflicts.c (print_reductions): Formatting changes.
[bison.git] / src / conflicts.c
1 /* Find and resolve or report look-ahead conflicts for bison,
2 Copyright 1984, 1989, 1992, 2000, 2001 Free Software Foundation, Inc.
3
4 This file is part of Bison, the GNU Compiler Compiler.
5
6 Bison is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 Bison is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Bison; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21 #include "system.h"
22 #include "complain.h"
23 #include "getargs.h"
24 #include "files.h"
25 #include "gram.h"
26 #include "state.h"
27 #include "lalr.h"
28 #include "conflicts.h"
29 #include "reader.h"
30 #include "LR0.h"
31
32 /* -1 stands for not specified. */
33 int expected_conflicts = -1;
34 static char *conflicts = NULL;
35
36 static unsigned *shiftset = NULL;
37 static unsigned *lookaheadset = NULL;
38 \f
39
40 static inline void
41 log_resolution (int state, int LAno, int token, char *resolution)
42 {
43 if (verbose_flag)
44 obstack_fgrow4 (&output_obstack,
45 _("\
46 Conflict in state %d between rule %d and token %s resolved as %s.\n"),
47 state, LAruleno[LAno], tags[token], resolution);
48 }
49
50
51 /*------------------------------------------------------------------.
52 | Turn off the shift recorded for the specified token in the |
53 | specified state. Used when we resolve a shift-reduce conflict in |
54 | favor of the reduction. |
55 `------------------------------------------------------------------*/
56
57 static void
58 flush_shift (int state, int token)
59 {
60 shifts *shiftp = state_table[state]->shifts;
61 int i;
62
63 RESETBIT (lookaheadset, token);
64 for (i = 0; i < shiftp->nshifts; i++)
65 if (!SHIFT_IS_DISABLED (shiftp, i) && SHIFT_SYMBOL (shiftp, i) == token)
66 SHIFT_DISABLE (shiftp, i);
67 }
68
69
70 /*-------------------------------------------------------------------.
71 | Turn off the reduce recorded for the specified token for the |
72 | specified lookahead. Used when we resolve a shift-reduce conflict |
73 | in favor of the shift. |
74 `-------------------------------------------------------------------*/
75
76 static void
77 flush_reduce (int lookahead, int token)
78 {
79 RESETBIT (LA (lookahead), token);
80 }
81
82
83 /*------------------------------------------------------------------.
84 | Attempt to resolve shift-reduce conflict for one rule by means of |
85 | precedence declarations. It has already been checked that the |
86 | rule has a precedence. A conflict is resolved by modifying the |
87 | shift or reduce tables so that there is no longer a conflict. |
88 `------------------------------------------------------------------*/
89
90 static void
91 resolve_sr_conflict (int state, int lookahead)
92 {
93 int i;
94 /* find the rule to reduce by to get precedence of reduction */
95 int redprec = rule_table[LAruleno[lookahead]].prec;
96 errs *errp = ERRS_ALLOC (ntokens + 1);
97 short *errtokens = errp->errs;
98
99 for (i = 0; i < ntokens; i++)
100 if (BITISSET (LA (lookahead), i)
101 && BITISSET (lookaheadset, i)
102 && sprec[i])
103 {
104 /* Shift-reduce conflict occurs for token number i
105 and it has a precedence.
106 The precedence of shifting is that of token i. */
107 if (sprec[i] < redprec)
108 {
109 log_resolution (state, lookahead, i, _("reduce"));
110 flush_shift (state, i);
111 }
112 else if (sprec[i] > redprec)
113 {
114 log_resolution (state, lookahead, i, _("shift"));
115 flush_reduce (lookahead, i);
116 }
117 else
118 /* Matching precedence levels.
119 For left association, keep only the reduction.
120 For right association, keep only the shift.
121 For nonassociation, keep neither. */
122
123 switch (sassoc[i])
124 {
125 case right_assoc:
126 log_resolution (state, lookahead, i, _("shift"));
127 flush_reduce (lookahead, i);
128 break;
129
130 case left_assoc:
131 log_resolution (state, lookahead, i, _("reduce"));
132 flush_shift (state, i);
133 break;
134
135 case non_assoc:
136 log_resolution (state, lookahead, i, _("an error"));
137 flush_shift (state, i);
138 flush_reduce (lookahead, i);
139 /* Record an explicit error for this token. */
140 *errtokens++ = i;
141 break;
142 }
143 }
144
145 errp->nerrs = errtokens - errp->errs;
146 /* Some tokens have been explicitly made errors. Allocate a
147 permanent errs structure for this state, to record them. */
148 i = (char *) errtokens - (char *) errp;
149 state_table[state]->errs = ERRS_ALLOC (i + 1);
150 memcpy (state_table[state]->errs, errp, i);
151 free (errp);
152 }
153
154
155 static void
156 set_conflicts (int state)
157 {
158 int i, j;
159 shifts *shiftp;
160
161 if (state_table[state]->consistent)
162 return;
163
164 for (i = 0; i < tokensetsize; i++)
165 lookaheadset[i] = 0;
166
167 shiftp = state_table[state]->shifts;
168 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
169 if (!SHIFT_IS_DISABLED (shiftp, i))
170 SETBIT (lookaheadset, SHIFT_SYMBOL (shiftp, i));
171
172 /* Loop over all rules which require lookahead in this state. First
173 check for shift-reduce conflict, and try to resolve using
174 precedence */
175 for (i = state_table[state]->lookaheads;
176 i < state_table[state + 1]->lookaheads;
177 ++i)
178 if (rule_table[LAruleno[i]].prec)
179 for (j = 0; j < tokensetsize; ++j)
180 if (LA (i)[j] & lookaheadset[j])
181 {
182 resolve_sr_conflict (state, i);
183 break;
184 }
185
186
187 /* Loop over all rules which require lookahead in this state. Check
188 for conflicts not resolved above. */
189 for (i = state_table[state]->lookaheads;
190 i < state_table[state + 1]->lookaheads;
191 ++i)
192 {
193 for (j = 0; j < tokensetsize; ++j)
194 if (LA (i)[j] & lookaheadset[j])
195 conflicts[state] = 1;
196
197 for (j = 0; j < tokensetsize; ++j)
198 lookaheadset[j] |= LA (i)[j];
199 }
200 }
201
202 void
203 solve_conflicts (void)
204 {
205 int i;
206
207 conflicts = XCALLOC (char, nstates);
208 shiftset = XCALLOC (unsigned, tokensetsize);
209 lookaheadset = XCALLOC (unsigned, tokensetsize);
210
211 for (i = 0; i < nstates; i++)
212 set_conflicts (i);
213 }
214
215
216 /*---------------------------------------------.
217 | Count the number of shift/reduce conflicts. |
218 `---------------------------------------------*/
219
220 static int
221 count_sr_conflicts (int state)
222 {
223 int i, k;
224 int src_count = 0;
225 shifts *shiftp = state_table[state]->shifts;
226
227 if (!shiftp)
228 return 0;
229
230 for (i = 0; i < tokensetsize; i++)
231 {
232 shiftset[i] = 0;
233 lookaheadset[i] = 0;
234 }
235
236 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
237 if (!SHIFT_IS_DISABLED (shiftp, i))
238 SETBIT (shiftset, SHIFT_SYMBOL (shiftp, i));
239
240 for (i = state_table[state]->lookaheads;
241 i < state_table[state + 1]->lookaheads;
242 ++i)
243 for (k = 0; k < tokensetsize; ++k)
244 lookaheadset[k] |= LA (i)[k];
245
246 for (k = 0; k < tokensetsize; ++k)
247 lookaheadset[k] &= shiftset[k];
248
249 for (i = 0; i < ntokens; i++)
250 if (BITISSET (lookaheadset, i))
251 src_count++;
252
253 return src_count;
254 }
255
256
257 /*----------------------------------------------.
258 | Count the number of reduce/reduce conflicts. |
259 `----------------------------------------------*/
260
261 static int
262 count_rr_conflicts (int state)
263 {
264 int i;
265 int rrc_count = 0;
266
267 int m = state_table[state]->lookaheads;
268 int n = state_table[state + 1]->lookaheads;
269
270 if (n - m < 2)
271 return 0;
272
273 for (i = 0; i < ntokens; i++)
274 {
275 int count = 0;
276 int j;
277 for (j = m; j < n; j++)
278 if (BITISSET (LA (m), j))
279 count++;
280
281 if (count >= 2)
282 rrc_count++;
283 }
284
285 return rrc_count;
286 }
287
288 /*--------------------------------------------------------------.
289 | Return a human readable string which reports shift/reduce and |
290 | reduce/reduce conflict numbers (SRC_NUM, RRC_NUM). |
291 `--------------------------------------------------------------*/
292
293 static const char *
294 conflict_report (int src_num, int rrc_num)
295 {
296 static char res[4096];
297 char *cp = res;
298
299 if (src_num >= 1)
300 {
301 sprintf (cp, ngettext ("%d shift/reduce conflict",
302 "%d shift/reduce conflicts", src_num), src_num);
303 cp += strlen (cp);
304 }
305
306 if (src_num > 0 && rrc_num > 0)
307 {
308 sprintf (cp, " %s ", _("and"));
309 cp += strlen (cp);
310 }
311
312 if (rrc_num >= 1)
313 {
314 sprintf (cp, ngettext ("%d reduce/reduce conflict",
315 "%d reduce/reduce conflicts", rrc_num), rrc_num);
316 cp += strlen (cp);
317 }
318
319 *cp++ = '.';
320 *cp++ = '\n';
321 *cp++ = '\0';
322
323 return res;
324 }
325
326
327 /*-----------------------------------------------------------.
328 | Output the detailed description of states with conflicts. |
329 `-----------------------------------------------------------*/
330
331 void
332 conflicts_output (FILE *out)
333 {
334 bool printed_sth = FALSE;
335 int i;
336 for (i = 0; i < nstates; i++)
337 if (conflicts[i])
338 {
339 fprintf (out, _("State %d contains "), i);
340 fputs (conflict_report (count_sr_conflicts (i),
341 count_rr_conflicts (i)), out);
342 printed_sth = TRUE;
343 }
344 if (printed_sth)
345 fputs ("\n\n", out);
346 }
347
348
349 /*------------------------------------------.
350 | Reporting the total number of conflicts. |
351 `------------------------------------------*/
352
353 void
354 conflicts_print (void)
355 {
356 int i;
357
358 /* Is the number of SR conflicts OK? Either EXPECTED_CONFLICTS is
359 not set, and then we want 0 SR, or else it is specified, in which
360 case we want equality. */
361 int src_ok = 0;
362
363 int src_total = 0;
364 int rrc_total = 0;
365
366 /* Conflicts by state. */
367 for (i = 0; i < nstates; i++)
368 if (conflicts[i])
369 {
370 src_total += count_sr_conflicts (i);
371 rrc_total += count_rr_conflicts (i);
372 }
373
374 src_ok = src_total == (expected_conflicts == -1 ? 0 : expected_conflicts);
375
376 /* If there are no RR conflicts, and as many SR conflicts as
377 expected, then there is nothing to report. */
378 if (!rrc_total && src_ok)
379 return;
380
381 /* Report the total number of conflicts on STDERR. */
382 if (yacc_flag)
383 {
384 /* If invoked with `--yacc', use the output format specified by
385 POSIX. */
386 fprintf (stderr, _("conflicts: "));
387 if (src_total > 0)
388 fprintf (stderr, _(" %d shift/reduce"), src_total);
389 if (src_total > 0 && rrc_total > 0)
390 fprintf (stderr, ",");
391 if (rrc_total > 0)
392 fprintf (stderr, _(" %d reduce/reduce"), rrc_total);
393 putc ('\n', stderr);
394 }
395 else
396 {
397 fprintf (stderr, _("%s contains "), infile);
398 fputs (conflict_report (src_total, rrc_total), stderr);
399 }
400
401 if (expected_conflicts != -1 && !src_ok)
402 {
403 complain_message_count++;
404 fprintf (stderr, ngettext ("expected %d shift/reduce conflict\n",
405 "expected %d shift/reduce conflicts\n",
406 expected_conflicts),
407 expected_conflicts);
408 }
409 }
410
411
412 void
413 print_reductions (FILE *out, int state)
414 {
415 int i;
416 int j;
417 int m = state_table[state]->lookaheads;
418 int n = state_table[state + 1]->lookaheads;
419 shifts *shiftp = state_table[state]->shifts;
420 errs *errp = state_table[state]->errs;
421 int nodefault = 0;
422
423 for (i = 0; i < tokensetsize; i++)
424 shiftset[i] = 0;
425
426 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
427 if (!SHIFT_IS_DISABLED (shiftp, i))
428 {
429 /* if this state has a shift for the error token, don't use a
430 default rule. */
431 if (SHIFT_IS_ERROR (shiftp, i))
432 nodefault = 1;
433 SETBIT (shiftset, SHIFT_SYMBOL (shiftp, i));
434 }
435
436 if (errp)
437 for (i = 0; i < errp->nerrs; i++)
438 if (errp->errs[i])
439 SETBIT (shiftset, errp->errs[i]);
440
441 if (n - m == 1 && !nodefault)
442 {
443 int k;
444 int default_rule = LAruleno[m];
445
446 for (k = 0; k < tokensetsize; ++k)
447 lookaheadset[k] = LA (m)[k] & shiftset[k];
448
449 for (i = 0; i < ntokens; i++)
450 if (BITISSET (lookaheadset, i))
451 fprintf (out, _(" %-4s\t[reduce using rule %d (%s)]\n"),
452 tags[i], default_rule,
453 tags[rule_table[default_rule].lhs]);
454
455 fprintf (out, _(" $default\treduce using rule %d (%s)\n\n"),
456 default_rule, tags[rule_table[default_rule].lhs]);
457 }
458 else if (n - m >= 1)
459 {
460 int k;
461
462 int cmax = 0;
463 int default_LA = -1;
464 int default_rule = 0;
465
466 if (!nodefault)
467 for (i = m; i < n; i++)
468 {
469 int count = 0;
470
471 for (k = 0; k < tokensetsize; ++k)
472 lookaheadset[k] = LA (i)[k] & ~shiftset[k];
473
474 for (j = 0; j < ntokens; j++)
475 if (BITISSET (lookaheadset, j))
476 count++;
477
478 if (count > cmax)
479 {
480 cmax = count;
481 default_LA = i;
482 default_rule = LAruleno[i];
483 }
484
485 for (k = 0; k < tokensetsize; ++k)
486 shiftset[k] |= lookaheadset[k];
487 }
488
489 for (i = 0; i < tokensetsize; i++)
490 shiftset[i] = 0;
491
492 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
493 if (!SHIFT_IS_DISABLED (shiftp, i))
494 SETBIT (shiftset, SHIFT_SYMBOL (shiftp, i));
495
496 for (i = 0; i < ntokens; i++)
497 {
498 int defaulted = 0;
499 int count = BITISSET (shiftset, i);
500
501 for (j = m; j < n; j++)
502 {
503 if (BITISSET (LA (m), j))
504 {
505 if (count == 0)
506 {
507 if (j != default_LA)
508 fprintf (out,
509 _(" %-4s\treduce using rule %d (%s)\n"),
510 tags[i],
511 LAruleno[j],
512 tags[rule_table[LAruleno[j]].lhs]);
513 else
514 defaulted = 1;
515
516 count++;
517 }
518 else
519 {
520 if (defaulted)
521 fprintf (out,
522 _(" %-4s\treduce using rule %d (%s)\n"),
523 tags[i],
524 LAruleno[default_LA],
525 tags[rule_table[LAruleno[default_LA]].lhs]);
526 defaulted = 0;
527 fprintf (out,
528 _(" %-4s\t[reduce using rule %d (%s)]\n"),
529 tags[i],
530 LAruleno[j],
531 tags[rule_table[LAruleno[j]].lhs]);
532 }
533 }
534 }
535 }
536
537 if (default_LA >= 0)
538 fprintf (out, _(" $default\treduce using rule %d (%s)\n"),
539 default_rule, tags[rule_table[default_rule].lhs]);
540 }
541 }
542
543
544 void
545 free_conflicts (void)
546 {
547 XFREE (conflicts);
548 XFREE (shiftset);
549 XFREE (lookaheadset);
550 }