* src/print.c (state_default_rule_compute): New, extracted from...

(print_reductions): here.
Pessimize, but clarify the code.
* tests/conflicts.at (Defaulted Conflicted Reduction): New.
This commit is contained in:
Akim Demaille
2002-06-30 17:32:47 +00:00
parent 53d4308dbb
commit bc933ef16d
4 changed files with 301 additions and 126 deletions

View File

@@ -1,3 +1,10 @@
2002-06-30 Akim Demaille <akim@epita.fr>
* src/print.c (state_default_rule_compute): New, extracted from...
(print_reductions): here.
Pessimize, but clarify the code.
* tests/conflicts.at (Defaulted Conflicted Reduction): New.
2002-06-30 Akim Demaille <akim@epita.fr>
* src/output.c (action_row): Let default_rule be always a rule

24
TODO
View File

@@ -3,6 +3,16 @@
* URGENT: Documenting C++ output
Write a first documentation for C++ output.
* Report and GLR
How would Paul like to display the conflicted actions? In particular,
what when two reductions are possible on a given lookahead, but one is
part of $default. Should we make the two reductions explicit, or just
keep $default? See the following point.
* Report and Disabled Reductions
See `tests/conflicts.at (Defaulted Conflicted Reduction)', and decide
what we want to do.
* value_components_used
Was defined but not used: where was it coming from? It can't be to
check if %union is used, since the user is free to $<foo>n on her
@@ -16,7 +26,9 @@ to #define yyerror and yyprint to steal internal variables...
* documentation
Explain $axiom (and maybe change its name: BTYacc names it `goal',
byacc `$accept' probably based on AT&T Yacc, Meta `Start'...).
Complete the glossary (item, axiom, ?).
Complete the glossary (item, axiom, ?). Should we also rename `$'?
BYacc uses `$end'. `$eof' is attracting, but after all we may be
parsing a string, a stream etc.
* Error messages
Some are really funky. For instance
@@ -26,11 +38,11 @@ Some are really funky. For instance
is really weird. Revisit them all.
* Report documentation
Extend with error. The hard part will probably be finding the right
rule so that a single state does not exhibit to many yet undocumented
``features''. Maybe an empty action ought to be presented too. Shall
we try to make a single grammar with all these features, or should we
have several very small grammars?
Extend with error productions. The hard part will probably be finding
the right rule so that a single state does not exhibit too many yet
undocumented ``features''. Maybe an empty action ought to be
presented too. Shall we try to make a single grammar with all these
features, or should we have several very small grammars?
* Documentation
Some history of Bison and some bibliography would be most welcome.

View File

@@ -165,86 +165,92 @@ print_gotos (FILE *out, state_t *state)
}
}
static void
print_reductions (FILE *out, state_t *state)
/*----------------------------------------------------------.
| Return the default rule of this STATE if it has one, NULL |
| otherwise. |
`----------------------------------------------------------*/
static rule_t *
state_default_rule_compute (state_t *state)
{
int i;
shifts_t *shiftp = state->shifts;
reductions_t *redp = state->reductions;
errs_t *errp = state->errs;
int nodefault = 0;
if (redp->nreds == 0)
return;
rule_t *default_rule = NULL;
int cmax = 0;
int i;
/* No need for a lookahead. */
if (state->consistent)
{
int rule = redp->rules[0];
symbol_number_t symbol = rules[rule].lhs->number;
fprintf (out, _(" $default\treduce using rule %d (%s)\n\n"),
rule - 1, symbol_tag_get (symbols[symbol]));
return;
}
return &rules[redp->rules[0]];
/* 1. Each reduction is possibly masked by the lookaheads on which
we shift (S/R conflicts)... */
bitset_zero (shiftset);
{
shifts_t *shiftp = state->shifts;
for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
if (!SHIFT_IS_DISABLED (shiftp, i))
{
/* if this state has a shift for the error token, don't use a
/* If this state has a shift for the error token, don't use a
default rule. */
if (SHIFT_IS_ERROR (shiftp, i))
nodefault = 1;
return NULL;
bitset_set (shiftset, SHIFT_SYMBOL (shiftp, i));
}
}
/* 2. Each reduction is possibly masked by the lookaheads on which
we raise an error (due to %nonassoc). */
{
errs_t *errp = state->errs;
for (i = 0; i < errp->nerrs; i++)
if (errp->errs[i])
bitset_set (shiftset, errp->errs[i]);
if (state->nlookaheads == 1 && !nodefault)
{
rule_t *default_rule = state->lookaheads_rule[0];
bitset_and (lookaheadset, state->lookaheads[0], shiftset);
BITSET_EXECUTE (lookaheadset, 0, i,
{
fprintf (out, _(" %-4s\t[reduce using rule %d (%s)]\n"),
symbol_tag_get (symbols[i]),
default_rule->number - 1,
symbol_tag_get_n (default_rule->lhs, 1));
});
fprintf (out, _(" $default\treduce using rule %d (%s)\n\n"),
default_rule->number - 1,
symbol_tag_get (default_rule->lhs));
}
else if (state->nlookaheads >= 1)
{
int cmax = 0;
int default_LA = -1;
rule_t *default_rule = NULL;
if (!nodefault)
for (i = 0; i < state->nlookaheads; ++i)
{
int count = 0;
/* How many non-masked lookaheads are there for this reduction?
*/
bitset_andn (lookaheadset, state->lookaheads[i], shiftset);
count = bitset_count (lookaheadset);
if (count > cmax)
{
cmax = count;
default_LA = i;
default_rule = state->lookaheads_rule[i];
}
bitset_or (shiftset, shiftset, lookaheadset);
/* 3. And finally, each reduction is possibly masked by previous
reductions (in R/R conflicts, we keep the first reductions).
*/
bitset_or (shiftset, shiftset, state->lookaheads[i]);
}
bitset_zero (shiftset);
return default_rule;
}
/*----------------------------------------------------.
| Report on OUT the reduction actions of this STATE. |
`----------------------------------------------------*/
static void
print_reductions (FILE *out, state_t *state)
{
int i;
shifts_t *shiftp = state->shifts;
reductions_t *redp = state->reductions;
rule_t *default_rule = NULL;
if (redp->nreds == 0)
return;
default_rule = state_default_rule_compute (state);
bitset_zero (shiftset);
for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
if (!SHIFT_IS_DISABLED (shiftp, i))
bitset_set (shiftset, SHIFT_SYMBOL (shiftp, i));
@@ -260,7 +266,7 @@ print_reductions (FILE *out, state_t *state)
{
if (count == 0)
{
if (j != default_LA)
if (state->lookaheads_rule[j] != default_rule)
fprintf (out,
_(" %-4s\treduce using rule %d (%s)\n"),
symbol_tag_get (symbols[i]),
@@ -268,7 +274,6 @@ print_reductions (FILE *out, state_t *state)
symbol_tag_get_n (state->lookaheads_rule[j]->lhs, 1));
else
defaulted = 1;
count++;
}
else
@@ -277,8 +282,8 @@ print_reductions (FILE *out, state_t *state)
fprintf (out,
_(" %-4s\treduce using rule %d (%s)\n"),
symbol_tag_get (symbols[i]),
state->lookaheads_rule[default_LA]->number - 1,
symbol_tag_get_n (state->lookaheads_rule[default_LA]->lhs, 1));
default_rule->number - 1,
symbol_tag_get_n (default_rule->lhs, 1));
defaulted = 0;
fprintf (out,
_(" %-4s\t[reduce using rule %d (%s)]\n"),
@@ -289,14 +294,19 @@ print_reductions (FILE *out, state_t *state)
}
}
if (default_LA >= 0)
if (default_rule)
fprintf (out, _(" $default\treduce using rule %d (%s)\n"),
default_rule->number - 1,
symbol_tag_get (default_rule->lhs));
}
fputc ('\n', out);
}
/*--------------------------------------------------------------.
| Report on OUT all the actions (shifts, gotos, reductions, and |
| explicit erros from %nonassoc) of STATE. |
`--------------------------------------------------------------*/
static void
print_actions (FILE *out, state_t *state)
{
@@ -318,6 +328,7 @@ print_actions (FILE *out, state_t *state)
print_gotos (out, state);
}
static void
print_state (FILE *out, state_t *state)
{

View File

@@ -41,6 +41,7 @@ AT_CHECK([bison input.y -o input.c])
AT_CLEANUP
## ------------------- ##
## %nonassoc and eof. ##
## ------------------- ##
@@ -237,26 +238,30 @@ state 5
AT_CLEANUP
## --------------------- ##
## Solved SR Conflicts. ##
## --------------------- ##
## ------------------------- ##
## Unresolved SR Conflicts. ##
## ------------------------- ##
AT_SETUP([Solved SR Conflicts])
AT_SETUP([Unresolved SR Conflicts])
AT_KEYWORDS([report])
AT_DATA([input.y],
[[%token NUM OP
%right OP
%%
exp: exp OP exp | NUM;
]])
AT_CHECK([bison input.y -o input.c --report=all], 0, [], [])
AT_CHECK([bison input.y -o input.c --report=all], 0, [],
[input.y contains 1 shift/reduce conflict.
])
# Check the contents of the report.
AT_CHECK([cat input.output], [],
[[Grammar
[[State 5 contains 1 shift/reduce conflict.
Grammar
0 $axiom: exp $
@@ -331,14 +336,154 @@ 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
OP [reduce using rule 1 (exp)]
$default reduce using rule 1 (exp)
Conflict between rule 2 and token OP resolved as reduce (%right OP).
]])
AT_CLEANUP
## -------------------------------- ##
## Defaulted Conflicted Reduction. ##
## -------------------------------- ##
# When there are RR conflicts, some rules are disabled. Usually it is
# simply displayed as:
#
# $ reduce using rule 3 (num)
# $ [reduce using rule 4 (id)]
#
# But when `reduce 3' is the default action, we'd produce:
#
# $ [reduce using rule 4 (id)]
# $default reduce using rule 3 (num)
#
# In this precise case (a reduction is masked by the default
# reduction), we make the `reduce 3' explicit:
#
# $ reduce using rule 3 (num)
# $ [reduce using rule 4 (id)]
# $default reduce using rule 3 (num)
#
# Maybe that's not the best display, but then, please propose something
# else.
AT_SETUP([Defaulted Conflicted Reduction])
AT_KEYWORDS([report])
AT_DATA([input.y],
[[%%
exp: num | id;
num: '0';
id : '0';
%%
]])
AT_CHECK([bison input.y -o input.c --report=all], 1, [],
[input.y contains 1 reduce/reduce conflict.
])
# Check the contents of the report.
AT_CHECK([cat input.output], [],
[[State 1 contains 1 reduce/reduce conflict.
Grammar
0 $axiom: exp $
1 exp: num
2 | id
3 num: '0'
4 id: '0'
Terminals, with rules where they appear
$ (0) 0
'0' (48) 3 4
error (256)
Nonterminals, with rules where they appear
$axiom (4)
on left: 0
exp (5)
on left: 1 2, on right: 0
num (6)
on left: 3, on right: 1
id (7)
on left: 4, on right: 2
state 0
$axiom -> . exp $ (rule 0)
exp -> . num (rule 1)
exp -> . id (rule 2)
num -> . '0' (rule 3)
id -> . '0' (rule 4)
'0' shift, and go to state 1
exp go to state 2
num go to state 3
id go to state 4
state 1
num -> '0' . [$] (rule 3)
id -> '0' . [$] (rule 4)
$ reduce using rule 3 (num)
$ [reduce using rule 4 (id)]
$default reduce using rule 3 (num)
state 2
$axiom -> exp . $ (rule 0)
$ shift, and go to state 5
state 3
exp -> num . (rule 1)
$default reduce using rule 1 (exp)
state 4
exp -> id . (rule 2)
$default reduce using rule 2 (exp)
state 5
$axiom -> exp $ . (rule 0)
$default accept
]])
@@ -381,7 +526,7 @@ AT_DATA([input.y],
exp: exp OP exp | NUM;
]])
AT_CHECK([bison input.y -o input.c], 0)
AT_CHECK([bison input.y -o input.c])
AT_CLEANUP