]>
git.saurik.com Git - bison.git/blob - 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. 
   4    This file is part of Bison, the GNU Compiler Compiler. 
   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) 
  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. 
  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 
  27 #include "conflicts.h" 
  31 int any_conflicts 
= 0; 
  32 errs 
**err_table 
= NULL
; 
  33 int expected_conflicts
; 
  34 static char *conflicts 
= NULL
; 
  36 static unsigned *shiftset 
= NULL
; 
  37 static unsigned *lookaheadset 
= NULL
; 
  43 log_resolution (int state
, int LAno
, int token
, char *resolution
) 
  45   obstack_fgrow4 (&output_obstack
, 
  47 Conflict in state %d between rule %d and token %s resolved as %s.\n"), 
  48                   state
, LAruleno
[LAno
], tags
[token
], resolution
); 
  52 /*------------------------------------------------------------------. 
  53 | Turn off the shift recorded for the specified token in the        | 
  54 | specified state.  Used when we resolve a shift-reduce conflict in | 
  55 | favor of the reduction.                                           | 
  56 `------------------------------------------------------------------*/ 
  59 flush_shift (int state
, int token
) 
  64   shiftp 
= shift_table
[state
]; 
  69       for (i 
= 0; i 
< k
; i
++) 
  72               && token 
== accessing_symbol
[shiftp
->shifts
[i
]]) 
  73             (shiftp
->shifts
[i
]) = 0; 
  79 /*------------------------------------------------------------------. 
  80 | Attempt to resolve shift-reduce conflict for one rule by means of | 
  81 | precedence declarations.  It has already been checked that the    | 
  82 | rule has a precedence.  A conflict is resolved by modifying the   | 
  83 | shift or reduce tables so that there is no longer a conflict.     | 
  84 `------------------------------------------------------------------*/ 
  87 resolve_sr_conflict (int state
, int lookaheadnum
) 
  94   errs 
*errp 
= (errs 
*) xcalloc (sizeof (errs
) + ntokens 
* sizeof (short), 1); 
  95   short *errtokens 
= errp
->errs
; 
  97   /* find the rule to reduce by to get precedence of reduction  */ 
  98   redprec 
= rprec
[LAruleno
[lookaheadnum
]]; 
 101   fp1 
= LA 
+ lookaheadnum 
* tokensetsize
; 
 103   for (i 
= 0; i 
< ntokens
; i
++) 
 105       if ((mask 
& *fp2 
& *fp1
) && sprec
[i
]) 
 106         /* Shift-reduce conflict occurs for token number i 
 107            and it has a precedence. 
 108            The precedence of shifting is that of token i.  */ 
 110           if (sprec
[i
] < redprec
) 
 112               log_resolution (state
, lookaheadnum
, i
, _("reduce")); 
 113               *fp2 
&= ~mask
;    /* flush the shift for this token */ 
 114               flush_shift (state
, i
); 
 116           else if (sprec
[i
] > redprec
) 
 118               log_resolution (state
, lookaheadnum
, i
, _("shift")); 
 119               *fp1 
&= ~mask
;    /* flush the reduce for this token */ 
 123               /* Matching precedence levels. 
 124                  For left association, keep only the reduction. 
 125                  For right association, keep only the shift. 
 126                  For nonassociation, keep neither.  */ 
 131                   log_resolution (state
, lookaheadnum
, i
, _("shift")); 
 135                   log_resolution (state
, lookaheadnum
, i
, _("reduce")); 
 139                   log_resolution (state
, lookaheadnum
, i
, _("an error")); 
 143               if (sassoc
[i
] != right_assoc
) 
 145                   *fp2 
&= ~mask
;        /* flush the shift for this token */ 
 146                   flush_shift (state
, i
); 
 148               if (sassoc
[i
] != left_assoc
) 
 150                   *fp1 
&= ~mask
;        /* flush the reduce for this token */ 
 152               if (sassoc
[i
] == non_assoc
) 
 154                   /* Record an explicit error for this token.  */ 
 168   errp
->nerrs 
= errtokens 
- errp
->errs
; 
 171       /* Some tokens have been explicitly made errors.  Allocate 
 172          a permanent errs structure for this state, to record them.  */ 
 173       i 
= (char *) errtokens 
- (char *) errp
; 
 174       err_table
[state
] = (errs 
*) xcalloc ((unsigned int) i
, 1); 
 175       bcopy (errp
, err_table
[state
], i
); 
 178     err_table
[state
] = 0; 
 184 set_conflicts (int state
) 
 195   if (consistent
[state
]) 
 198   for (i 
= 0; i 
< tokensetsize
; i
++) 
 201   shiftp 
= shift_table
[state
]; 
 205       for (i 
= 0; i 
< k
; i
++) 
 207           symbol 
= accessing_symbol
[shiftp
->shifts
[i
]]; 
 210           SETBIT (lookaheadset
, symbol
); 
 214   k 
= lookaheads
[state 
+ 1]; 
 215   fp4 
= lookaheadset 
+ tokensetsize
; 
 217   /* Loop over all rules which require lookahead in this state.  First 
 218      check for shift-reduce conflict, and try to resolve using 
 220   for (i 
= lookaheads
[state
]; i 
< k
; i
++) 
 221     if (rprec
[LAruleno
[i
]]) 
 223         fp1 
= LA 
+ i 
* tokensetsize
; 
 231                 resolve_sr_conflict (state
, i
); 
 238   /* Loop over all rules which require lookahead in this state.  Check 
 239      for conflicts not resolved above.  */ 
 240   for (i 
= lookaheads
[state
]; i 
< k
; i
++) 
 242       fp1 
= LA 
+ i 
* tokensetsize
; 
 250               conflicts
[state
] = 1; 
 264 solve_conflicts (void) 
 268   conflicts 
= XCALLOC (char, nstates
); 
 269   shiftset 
= XCALLOC (unsigned, tokensetsize
); 
 270   lookaheadset 
= XCALLOC (unsigned, tokensetsize
); 
 272   err_table 
= XCALLOC (errs 
*, nstates
); 
 276   for (i 
= 0; i 
< nstates
; i
++) 
 281 /*---------------------------------------------. 
 282 | Count the number of shift/reduce conflicts.  | 
 283 `---------------------------------------------*/ 
 286 count_sr_conflicts (int state
) 
 299   shiftp 
= shift_table
[state
]; 
 303   for (i 
= 0; i 
< tokensetsize
; i
++) 
 310   for (i 
= 0; i 
< k
; i
++) 
 312       if (!shiftp
->shifts
[i
]) 
 314       symbol 
= accessing_symbol
[shiftp
->shifts
[i
]]; 
 317       SETBIT (shiftset
, symbol
); 
 320   k 
= lookaheads
[state 
+ 1]; 
 321   fp3 
= lookaheadset 
+ tokensetsize
; 
 323   for (i 
= lookaheads
[state
]; i 
< k
; i
++) 
 325       fp1 
= LA 
+ i 
* tokensetsize
; 
 340   for (i 
= 0; i 
< ntokens
; i
++) 
 355 /*----------------------------------------------. 
 356 | Count the number of reduce/reduce conflicts.  | 
 357 `----------------------------------------------*/ 
 360 count_rr_conflicts (int state
) 
 373   m 
= lookaheads
[state
]; 
 374   n 
= lookaheads
[state 
+ 1]; 
 380   baseword 
= LA 
+ m 
* tokensetsize
; 
 381   for (i 
= 0; i 
< ntokens
; i
++) 
 386       for (j 
= m
; j 
< n
; j
++) 
 391           wordp 
+= tokensetsize
; 
 406 /*--------------------------------------------------------------. 
 407 | Return a human readable string which reports shift/reduce and | 
 408 | reduce/reduce conflict numbers (SRC_NUM, RRC_NUM).            | 
 409 `--------------------------------------------------------------*/ 
 412 conflict_report (int src_num
, int rrc_num
) 
 414   static char res
[4096]; 
 419       sprintf (cp
, _(" 1 shift/reduce conflict")); 
 422   else if (src_num 
> 1) 
 424       sprintf (cp
, _(" %d shift/reduce conflicts"), src_num
); 
 428   if (src_num 
> 0 && rrc_num 
> 0) 
 430       sprintf (cp
, _(" and")); 
 436       sprintf (cp
, _(" 1 reduce/reduce conflict")); 
 439   else if (rrc_num 
> 1) 
 441       sprintf (cp
, _(" %d reduce/reduce conflicts"), rrc_num
); 
 453 /*---------------------------------------------. 
 454 | Compute and give a report on the conflicts.  | 
 455 `---------------------------------------------*/ 
 458 print_conflicts (FILE *out
) 
 467   /* Count the total number of conflicts, and if wanted, give a 
 468      detailed report in FOUTPUT.  */ 
 469   for (i 
= 0; i 
< nstates
; i
++) 
 473           count_sr_conflicts (i
); 
 474           count_rr_conflicts (i
); 
 475           src_total 
+= src_count
; 
 476           rrc_total 
+= rrc_count
; 
 480               fprintf (out
, _("State %d contains"), i
); 
 481               fputs (conflict_report (src_count
, rrc_count
), out
); 
 486   /* Report the total number of conflicts on STDERR.  */ 
 489       /* If invoked with `--yacc', use the output format specified by 
 491       fprintf (stderr
, _("conflicts: ")); 
 493         fprintf (stderr
, _(" %d shift/reduce"), src_total
); 
 494       if (src_total 
> 0 && rrc_total 
> 0) 
 495         fprintf (stderr
, ","); 
 497         fprintf (stderr
, _(" %d reduce/reduce"), rrc_total
); 
 502       fprintf (stderr
, _("%s contains"), infile
); 
 503       fputs (conflict_report (src_total
, rrc_total
), stderr
); 
 509 print_reductions (int state
) 
 524   int default_rule 
= 0; 
 531   for (i 
= 0; i 
< tokensetsize
; i
++) 
 534   shiftp 
= shift_table
[state
]; 
 538       for (i 
= 0; i 
< k
; i
++) 
 540           if (!shiftp
->shifts
[i
]) 
 542           symbol 
= accessing_symbol
[shiftp
->shifts
[i
]]; 
 545           /* if this state has a shift for the error token, 
 546              don't use a default rule.  */ 
 547           if (symbol 
== error_token_number
) 
 549           SETBIT (shiftset
, symbol
); 
 553   errp 
= err_table
[state
]; 
 557       for (i 
= 0; i 
< k
; i
++) 
 561           symbol 
= errp
->errs
[i
]; 
 562           SETBIT (shiftset
, symbol
); 
 566   m 
= lookaheads
[state
]; 
 567   n 
= lookaheads
[state 
+ 1]; 
 569   if (n 
- m 
== 1 && !nodefault
) 
 571       default_rule 
= LAruleno
[m
]; 
 573       fp1 
= LA 
+ m 
* tokensetsize
; 
 576       fp4 
= lookaheadset 
+ tokensetsize
; 
 579         *fp3
++ = *fp1
++ & *fp2
++; 
 584       for (i 
= 0; i 
< ntokens
; i
++) 
 587             obstack_fgrow3 (&output_obstack
, 
 588                             _("    %-4s\t[reduce using rule %d (%s)]\n"), 
 589                             tags
[i
], default_rule
, tags
[rlhs
[default_rule
]]); 
 599       obstack_fgrow2 (&output_obstack
, 
 600                       _("    $default\treduce using rule %d (%s)\n\n"), 
 601                       default_rule
, tags
[rlhs
[default_rule
]]); 
 607       fp4 
= lookaheadset 
+ tokensetsize
; 
 610         for (i 
= m
; i 
< n
; i
++) 
 612             fp1 
= LA 
+ i 
* tokensetsize
; 
 617               *fp3
++ = *fp1
++ & (~(*fp2
++)); 
 622             for (j 
= 0; j 
< ntokens
; j
++) 
 639                 default_rule 
= LAruleno
[i
]; 
 649       for (i 
= 0; i 
< tokensetsize
; i
++) 
 655           for (i 
= 0; i 
< k
; i
++) 
 657               if (!shiftp
->shifts
[i
]) 
 659               symbol 
= accessing_symbol
[shiftp
->shifts
[i
]]; 
 662               SETBIT (shiftset
, symbol
); 
 667       fp1 
= LA 
+ m 
* tokensetsize
; 
 669       for (i 
= 0; i 
< ntokens
; i
++) 
 679           for (j 
= m
; j 
< n
; j
++) 
 688                           obstack_fgrow3 (&output_obstack
, 
 689                                    _("    %-4s\treduce using rule %d (%s)\n"), 
 690                                    tags
[i
], rule
, tags
[rlhs
[rule
]]); 
 701                           rule 
= LAruleno
[default_LA
]; 
 702                           obstack_fgrow3 (&output_obstack
, 
 703                                    _("    %-4s\treduce using rule %d (%s)\n"), 
 704                                    tags
[i
], rule
, tags
[rlhs
[rule
]]); 
 708                       obstack_fgrow3 (&output_obstack
, 
 709                                _("    %-4s\t[reduce using rule %d (%s)]\n"), 
 710                                tags
[i
], rule
, tags
[rlhs
[rule
]]); 
 721               /* We tried incrementing just fp1, and just fp2; both seem wrong. 
 722                  It seems necessary to increment both in sync.  */ 
 729         obstack_fgrow2 (&output_obstack
, 
 730                         _("    $default\treduce using rule %d (%s)\n"), 
 731                         default_rule
, tags
[rlhs
[default_rule
]]); 
 733       obstack_1grow (&output_obstack
, '\n'); 
 739 free_conflicts (void) 
 743   XFREE (lookaheadset
);