symbols: properly fuse the properties of two symbol aliases

This completes and fixes a728075710.
Reported by Valentin Tolmer.

Before it Bison used to put the properties of the symbols
(associativity, printer, etc.) in the 'symbol' structure.  An
identifier-named token (FOO) and its string-named alias ("foo")
duplicated these properties, and symbol_check_alias_consistency()
checked that both had compatible properties and fused them, at the end
of the parsing of the grammar.

The commit a728075710 introduces a
sym_content structure that keeps all these properties, and ensures
that both aliases point to the same sym_content (instead of
duplicating).  However, it removed symbol_check_alias_consistency,
which resulted in the non-fusion of *existing* properties:

  %token FOO "foo"
  %left FOO %left "foo"

was properly diagnosed as a redeclaration, but

  %left FOO %left "foo"
  %token FOO "foo"

was not, as the properties of FOO and "foo" were not checked before
fusion.  It certainly also means that

  %left "foo"
  %token FOO "foo"

did not transfer properly the associativity to FOO.

The fix is simple: reintroduce symbol_check_alias_consistency (under a
better name, symbol_merge_properties) and call it where appropriate.

Also, that commit made USER_NUMBER_HAS_STRING_ALIAS useless, but left
it.

* src/symtab.h (USER_NUMBER_HAS_STRING_ALIAS): Remove, unused.
Adjust dependencies.
* src/symtab.c (symbol_merge_properties): New, based on the former
symbol_check_alias_consistency.
* tests/input.at: Re-enable tests that we now pass.
This commit is contained in:
Akim Demaille
2013-12-10 09:24:20 +01:00
parent b7d4c48e55
commit 8044fda634
3 changed files with 81 additions and 50 deletions

View File

@@ -269,7 +269,6 @@ is_identifier (uniqstr s)
uniqstr
symbol_id_get (symbol const *sym)
{
aver (sym->content->user_token_number != USER_NUMBER_HAS_STRING_ALIAS);
if (sym->alias)
sym = sym->alias;
return is_identifier (sym->tag) ? sym->tag : 0;
@@ -559,6 +558,45 @@ semantic_type_check_defined_processor (void *sem_type,
}
/*-------------------------------------------------------------------.
| Merge the properties (precedence, associativity, etc.) of SYM, and |
| its string-named alias STR; check consistency. |
`-------------------------------------------------------------------*/
static void
symbol_merge_properties (symbol *sym, symbol *str)
{
if (str->content->type_name != sym->content->type_name)
{
if (str->content->type_name)
symbol_type_set (sym,
str->content->type_name, str->content->type_location);
else
symbol_type_set (str,
sym->content->type_name, sym->content->type_location);
}
{
int i;
for (i = 0; i < CODE_PROPS_SIZE; ++i)
if (str->content->props[i].code)
symbol_code_props_set (sym, i, &str->content->props[i]);
else if (sym->content->props[i].code)
symbol_code_props_set (str, i, &sym->content->props[i]);
}
if (sym->content->prec || str->content->prec)
{
if (str->content->prec)
symbol_precedence_set (sym, str->content->prec, str->content->assoc,
str->content->prec_location);
else
symbol_precedence_set (str, sym->content->prec, sym->content->assoc,
sym->content->prec_location);
}
}
void
symbol_make_alias (symbol *sym, symbol *str, location loc)
{
@@ -570,6 +608,7 @@ symbol_make_alias (symbol *sym, symbol *str, location loc)
_("symbol %s given more than one literal string"), sym->tag);
else
{
symbol_merge_properties (sym, str);
sym_content_free (str->content);
str->content = sym->content;
str->content->symbol = str;
@@ -591,8 +630,6 @@ symbol_pack (symbol *this)
aver (this->content->number != NUMBER_UNDEFINED);
if (this->content->class == nterm_sym)
this->content->number += ntokens;
else if (this->content->user_token_number == USER_NUMBER_HAS_STRING_ALIAS)
return true;
symbols[this->content->number] = this->content->symbol;
return true;

View File

@@ -137,12 +137,6 @@ struct sym_content
/** Undefined user number. */
# define USER_NUMBER_UNDEFINED -1
/* 'symbol->user_token_number == USER_NUMBER_HAS_STRING_ALIAS' means
this symbol has a literal string alias. For instance, '%token foo
"foo"' has '"foo"' numbered regularly, and 'foo' numbered as
USER_NUMBER_HAS_STRING_ALIAS. */
# define USER_NUMBER_HAS_STRING_ALIAS -9991
/* Undefined internal token number. */
# define NUMBER_UNDEFINED (-1)