* 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

@@ -1,3 +1,22 @@
2002-05-26 Akim Demaille <akim@epita.fr>
* 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.
2002-05-26 Akim Demaille <akim@epita.fr>
* src/LR0.c, src/derives.c, src/gram.c, src/gram.h, src/lalr.c,

13
NEWS
View File

@@ -73,7 +73,7 @@ Changes in version 1.49b:
* Semantic parser
This old option, which has been broken for ages, is removed.
* New translations
* New translation
Croatian, thanks to Denis Lackovic.
* Incorrect token definitions
@@ -87,9 +87,14 @@ Changes in version 1.49b:
* Reports
In addition to --verbose, bison supports --report=THINGS, which
produces additional information:
`itemset' complete the core item sets with their closure
`lookahead' explicitly associate lookaheads to items
- itemset
complete the core item sets with their closure
- lookahead
explicitly associate lookaheads to items
- solved
describe shift/reduce conflicts solving.
Bison used to systematically output this information on top of
the report. Solved conflicts are now attached to their states.
Changes in version 1.35, 2002-03-25:

16
TODO
View File

@@ -40,22 +40,6 @@ When implementing multiple-%union support, bare the following in mind:
Provide better assistance for understanding the conflicts by providing
a sample text exhibiting the (LALR) ambiguity.
* report
Solved conflicts should not be reported in the beginning of the file.
Rather they should be reported within each state description. Also,
now that the symbol providing the precedence of a rule is kept, it is
possible to explain why a conflict was solved this way. E.g., instead
of
Conflict in state 8 between rule 2 and token '+' resolved as reduce.
we can (in state 8) report something like
Conflict between rule 2 and token '+' resolved as reduce
because '*' < '+'.
or something like that.
* Coding system independence
Paul notes:

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;

View File

@@ -136,7 +136,7 @@ AT_DATA([input.y],
exp: exp OP exp | NUM;
]])
AT_CHECK([bison input.y -o input.c -v], 0, [],
AT_CHECK([bison input.y -o input.c --report=all], 0, [],
[input.y contains 1 shift/reduce conflict.
])
@@ -172,6 +172,8 @@ exp (6)
state 0
$axiom -> . exp $ (rule 0)
exp -> . exp OP exp (rule 1)
exp -> . NUM (rule 2)
NUM shift, and go to state 1
@@ -206,7 +208,9 @@ state 3
state 4
exp -> . exp OP exp (rule 1)
exp -> exp OP . exp (rule 1)
exp -> . NUM (rule 2)
NUM shift, and go to state 1
@@ -216,8 +220,8 @@ state 4
state 5
exp -> exp . OP exp (rule 1)
exp -> exp OP exp . (rule 1)
exp -> exp . OP exp [$, OP] (rule 1)
exp -> exp OP exp . [$, OP] (rule 1)
OP shift, and go to state 4
@@ -244,14 +248,11 @@ AT_DATA([input.y],
exp: exp OP exp | NUM;
]])
AT_CHECK([bison input.y -o input.c -v], 0, [], [])
AT_CHECK([bison input.y -o input.c --report=all], 0, [], [])
# Check the contents of the report.
AT_CHECK([cat input.output], [],
[[Conflict in state 5 between rule 2 and token OP resolved as shift.
Grammar
[[Grammar
Number, Line, Rule
0 4 $axiom -> exp $
@@ -278,6 +279,8 @@ exp (6)
state 0
$axiom -> . exp $ (rule 0)
exp -> . exp OP exp (rule 1)
exp -> . NUM (rule 2)
NUM shift, and go to state 1
@@ -312,7 +315,9 @@ state 3
state 4
exp -> . exp OP exp (rule 1)
exp -> exp OP . exp (rule 1)
exp -> . NUM (rule 2)
NUM shift, and go to state 1
@@ -322,13 +327,14 @@ state 4
state 5
exp -> exp . OP exp (rule 1)
exp -> exp OP exp . (rule 1)
exp -> exp . OP exp [$] (rule 1)
exp -> exp OP exp . [$] (rule 1)
OP shift, and go to state 4
$default reduce using rule 1 (exp)
Conflict between rule 2 and token OP resolved as reduce (%right OP).
]])