* src/state.h (state_t): `solved_conflicts' is a new member.

* src/LR0.c (new_state): Set it to 0.
* src/conflicts.h, src/conflicts.c (print_conflicts)
(free_conflicts, solve_conflicts): Rename as...
(conflicts_print, conflicts_free, conflicts_solve): these.
Adjust callers.
* src/conflicts.c (enum conflict_resolution_e)
(solved_conflicts_obstack): New, used by...
(log_resolution): this.
Adjust to attach the conflict resolution to each state.
Complete the description with the precedence/associativity
information.
(resolve_sr_conflict): Adjust.
* src/print.c (print_state): Output its solved_conflicts.
* tests/conflicts.at (Unresolved SR Conflicts)
(Solved SR Conflicts): Exercise --report=all.
This commit is contained in:
Akim Demaille
2002-05-26 20:25:52 +00:00
parent a49aecd528
commit b408954b40
12 changed files with 159 additions and 53 deletions

View File

@@ -200,8 +200,9 @@ new_state (symbol_number_t symbol, size_t core_size, item_number_t *core)
p = STATE_ALLOC (core_size);
p->accessing_symbol = symbol;
p->number = nstates;
p->nitems = core_size;
p->solved_conflicts = NULL;
p->nitems = core_size;
memcpy (p->items, core, core_size * sizeof (core[0]));
/* If this is the eoftoken, and this is not the initial state, then

View File

@@ -35,22 +35,93 @@
/* -1 stands for not specified. */
int expected_conflicts = -1;
static char *conflicts = NULL;
struct obstack solved_conflicts_obstack;
static bitset shiftset;
static bitset lookaheadset;
enum conflict_resolution_e
{
shift_resolution,
reduce_resolution,
left_resolution,
right_resolution,
nonassoc_resolution,
};
static inline void
log_resolution (state_t *state, int LAno, int token, const char *resolution)
log_resolution (int lookahead, int token,
enum conflict_resolution_e resolution)
{
if (report_flag & report_states)
obstack_fgrow4 (&output_obstack,
_("\
Conflict in state %d between rule %d and token %s resolved as %s.\n"),
state->number,
LArule[LAno]->number,
symbols[token]->tag,
resolution);
if (report_flag & report_solved_conflicts)
{
/* The description of the resolution. */
switch (resolution)
{
case shift_resolution:
case left_resolution:
obstack_fgrow2 (&solved_conflicts_obstack,
_("\
Conflict between rule %d and token %s resolved as shift"),
LArule[lookahead]->number,
symbols[token]->tag);
break;
case reduce_resolution:
case right_resolution:
obstack_fgrow2 (&solved_conflicts_obstack,
_("\
Conflict between rule %d and token %s resolved as reduce"),
LArule[lookahead]->number,
symbols[token]->tag);
break;
case nonassoc_resolution:
obstack_fgrow2 (&solved_conflicts_obstack,
_("\
Conflict between rule %d and token %s resolved as an error"),
LArule[lookahead]->number,
symbols[token]->tag);
break;
}
/* The reason. */
switch (resolution)
{
case shift_resolution:
obstack_fgrow2 (&solved_conflicts_obstack,
" (%s < %s)",
LArule[lookahead]->prec->tag,
symbols[token]->tag);
break;
case reduce_resolution:
obstack_fgrow2 (&solved_conflicts_obstack,
" (%s < %s)",
symbols[token]->tag,
LArule[lookahead]->prec->tag);
break;
case left_resolution:
obstack_printf (&solved_conflicts_obstack,
" (%%left %s)",
symbols[token]->tag);
break;
case right_resolution:
obstack_fgrow1 (&solved_conflicts_obstack,
" (%%right %s)",
symbols[token]->tag);
break;
case nonassoc_resolution:
obstack_fgrow1 (&solved_conflicts_obstack,
" (%%nonassoc %s)",
symbols[token]->tag);
break;
}
obstack_sgrow (&solved_conflicts_obstack, ".\n");
}
}
@@ -112,12 +183,12 @@ resolve_sr_conflict (state_t *state, int lookahead)
The precedence of shifting is that of token i. */
if (symbols[i]->prec < redprec)
{
log_resolution (state, lookahead, i, _("reduce"));
log_resolution (lookahead, i, reduce_resolution);
flush_shift (state, i);
}
else if (symbols[i]->prec > redprec)
{
log_resolution (state, lookahead, i, _("shift"));
log_resolution (lookahead, i, shift_resolution);
flush_reduce (lookahead, i);
}
else
@@ -129,17 +200,17 @@ resolve_sr_conflict (state_t *state, int lookahead)
switch (symbols[i]->assoc)
{
case right_assoc:
log_resolution (state, lookahead, i, _("shift"));
log_resolution (lookahead, i, right_resolution);
flush_reduce (lookahead, i);
break;
case left_assoc:
log_resolution (state, lookahead, i, _("reduce"));
log_resolution (lookahead, i, left_resolution);
flush_shift (state, i);
break;
case non_assoc:
log_resolution (state, lookahead, i, _("an error"));
log_resolution (lookahead, i, nonassoc_resolution);
flush_shift (state, i);
flush_reduce (lookahead, i);
/* Record an explicit error for this token. */
@@ -152,6 +223,12 @@ resolve_sr_conflict (state_t *state, int lookahead)
permanent errs structure for this state, to record them. */
state->errs = errs_dup (errp);
free (errp);
if (obstack_object_size (&solved_conflicts_obstack))
{
obstack_1grow (&solved_conflicts_obstack, '\0');
state->solved_conflicts = obstack_finish (&solved_conflicts_obstack);
}
}
@@ -195,13 +272,14 @@ set_conflicts (state_t *state)
}
void
solve_conflicts (void)
conflicts_solve (void)
{
size_t i;
conflicts = XCALLOC (char, nstates);
shiftset = bitset_create (ntokens, BITSET_FIXED);
lookaheadset = bitset_create (ntokens, BITSET_FIXED);
obstack_init (&solved_conflicts_obstack);
for (i = 0; i < nstates; i++)
set_conflicts (states[i]);
@@ -393,9 +471,10 @@ conflicts_print (void)
void
free_conflicts (void)
conflicts_free (void)
{
XFREE (conflicts);
bitset_free (shiftset);
bitset_free (lookaheadset);
obstack_free (&solved_conflicts_obstack, NULL);
}

View File

@@ -1,5 +1,5 @@
/* Find and resolve or report look-ahead conflicts for bison,
Copyright 2000, 2001 Free Software Foundation, Inc.
Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
@@ -22,10 +22,10 @@
# define CONFLICTS_H_
# include "state.h"
void solve_conflicts PARAMS ((void));
void conflicts_solve PARAMS ((void));
void conflicts_print PARAMS ((void));
void conflicts_output PARAMS ((FILE *out));
void free_conflicts PARAMS ((void));
void conflicts_free PARAMS ((void));
/* Were there conflicts? */
extern int expected_conflicts;

View File

@@ -55,6 +55,7 @@ static const char * const report_args[] =
"state", "states",
"itemset", "itemsets",
"lookahead", "lookaheads",
"solved",
"all",
0
};
@@ -65,6 +66,7 @@ static const int report_types[] =
report_states, report_states,
report_states | report_itemsets, report_states | report_itemsets,
report_states | report_lookaheads, report_states | report_lookaheads,
report_states | report_solved_conflicts,
report_all
};
@@ -140,6 +142,7 @@ THINGS is a list of comma separated words that can include:\n\
`state' describe the states\n\
`itemset' complete the core item sets with their closure\n\
`lookahead' explicitly associate lookaheads to items\n\
`solved' describe shift/reduce conflicts solving\n\
`all' include all the above information\n\
`none' disable the report\n\
"), stream);

View File

@@ -43,6 +43,7 @@ enum
report_states = 1 << 0,
report_itemsets = 1 << 1,
report_lookaheads = 1 << 2,
report_solved_conflicts = 1 << 3,
report_all = ~0
};

View File

@@ -84,7 +84,7 @@ main (int argc, char *argv[])
lookahead is not enough to disambiguate the parsing. In file
conflicts. Also resolve s/r conflicts based on precedence
declarations. */
solve_conflicts ();
conflicts_solve ();
conflicts_print ();
/* Output file names. */
@@ -107,7 +107,7 @@ main (int argc, char *argv[])
output ();
reduce_free ();
free_conflicts ();
conflicts_free ();
free_nullable ();
free_derives ();
grammar_free ();

View File

@@ -364,6 +364,9 @@ print_state (FILE *out, state_t *state)
fputs ("\n\n", out);
print_core (out, state);
print_actions (out, state);
if ((report_flag & report_solved_conflicts)
&& state->solved_conflicts)
fputs (state->solved_conflicts, out);
fputs ("\n\n", out);
}

View File

@@ -184,7 +184,12 @@ typedef struct state_s
short lookaheadsp;
int nlookaheads;
/* Its items. */
/* If some conflicts were solved thanks to precedence/associativity,
a human readable description of the resolution. */
const char *solved_conflicts;
/* Its items. Must be last, since ITEMS can be arbitrarily large.
*/
unsigned short nitems;
item_number_t items[1];
} state_t;