mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
multistart: check duplicates
* src/symlist.h, src/symlist.c (symbol_list_find_symbol) (symbol_list_last): New. (symbol_list_append): Use symbol_list_last. * src/reader.c (grammar_start_symbols_add): Check and discard duplicates. * tests/input.at (Duplicate %start symbol): New. * tests/reduce.at (Bad start symbols): Add the multistart keyword.
This commit is contained in:
2
gnulib
2
gnulib
Submodule gnulib updated: 9351b4033b...b141afaf9b
32
src/reader.c
32
src/reader.c
@@ -55,7 +55,37 @@ bool default_prec = true;
|
||||
void
|
||||
grammar_start_symbols_add (symbol_list *syms)
|
||||
{
|
||||
start_symbols = symbol_list_append (start_symbols, syms);
|
||||
/* Report and ignore duplicates. Append the others to START_SYMBOLS. */
|
||||
symbol_list *last = symbol_list_last (start_symbols);
|
||||
for (symbol_list *l = syms; l && l->content.sym; /* nothing */)
|
||||
{
|
||||
/* Is there a previous definition? */
|
||||
symbol_list *first = symbol_list_find_symbol (start_symbols, l->content.sym);
|
||||
if (first)
|
||||
{
|
||||
duplicate_directive ("%start", first->sym_loc, l->sym_loc);
|
||||
symbol_list *dup = l;
|
||||
l = l->next;
|
||||
dup->next = NULL;
|
||||
symbol_list_free (dup);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (last)
|
||||
{
|
||||
last->next = l;
|
||||
last = l;
|
||||
}
|
||||
else
|
||||
{
|
||||
last = l;
|
||||
start_symbols = last;
|
||||
}
|
||||
symbol_list *next = l->next;
|
||||
l->next = NULL;
|
||||
l = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -91,6 +91,16 @@ symbol_list_type_set (symbol_list *syms, uniqstr type_name)
|
||||
}
|
||||
|
||||
|
||||
symbol_list *
|
||||
symbol_list_find_symbol (symbol_list *l, const symbol *sym)
|
||||
{
|
||||
for (/* Nothing. */; l && l->content.sym; l = l->next)
|
||||
if (l->content.sym == sym)
|
||||
return l;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------.
|
||||
| Print this list, for which every content_type must be SYMLIST_SYMBOL. |
|
||||
`-----------------------------------------------------------------------*/
|
||||
@@ -129,23 +139,29 @@ symbol_list_prepend (symbol_list *list, symbol_list *node)
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------.
|
||||
| Append NODE to the LIST. |
|
||||
`-------------------------*/
|
||||
symbol_list *
|
||||
symbol_list_last (symbol_list *list)
|
||||
{
|
||||
if (!list)
|
||||
return NULL;
|
||||
symbol_list *next = list;
|
||||
while (next->next)
|
||||
next = next->next;
|
||||
return next;
|
||||
}
|
||||
|
||||
symbol_list *
|
||||
symbol_list_append (symbol_list *list, symbol_list *node)
|
||||
{
|
||||
if (!list)
|
||||
return node;
|
||||
symbol_list *next = list;
|
||||
while (next->next)
|
||||
next = next->next;
|
||||
next->next = node;
|
||||
if (list)
|
||||
symbol_list_last (list)->next = node;
|
||||
else
|
||||
list = node;
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------.
|
||||
| Free the LIST, but not the items it contains. |
|
||||
`-----------------------------------------------*/
|
||||
|
||||
@@ -112,6 +112,9 @@ symbol_list *symbol_list_type_new (uniqstr type_name, location loc);
|
||||
** \returns \c syms */
|
||||
symbol_list *symbol_list_type_set (symbol_list *syms, uniqstr type_name);
|
||||
|
||||
/** Find a symbol with the same content as \c sym within \c syms. */
|
||||
symbol_list *symbol_list_find_symbol (symbol_list *syms, const symbol *sym);
|
||||
|
||||
/** Print this list.
|
||||
|
||||
\pre For every node \c n in the list, <tt>n->content_type =
|
||||
@@ -121,6 +124,9 @@ void symbol_list_syms_print (const symbol_list *l, FILE *f);
|
||||
/** Prepend \c node to \c list. */
|
||||
symbol_list *symbol_list_prepend (symbol_list *list, symbol_list *node);
|
||||
|
||||
/** The last node of this list. */
|
||||
symbol_list *symbol_list_last (symbol_list *list);
|
||||
|
||||
/** Append \c node to \c list. */
|
||||
symbol_list *symbol_list_append (symbol_list *list, symbol_list *node);
|
||||
|
||||
@@ -136,11 +142,11 @@ int symbol_list_length (symbol_list const *l);
|
||||
**/
|
||||
symbol_list *symbol_list_n_get (symbol_list *l, int n);
|
||||
|
||||
/* Get the data type (alternative in the union) of the value for
|
||||
symbol N in rule RULE. */
|
||||
/** Get the data type (alternative in the union) of the value for
|
||||
symbol N in rule RULE. */
|
||||
uniqstr symbol_list_n_type_name_get (symbol_list *l, int n);
|
||||
|
||||
/* Check whether the node is a border element of a rule. */
|
||||
/** Check whether the node is a border element of a rule. */
|
||||
bool symbol_list_null (symbol_list *node);
|
||||
|
||||
/** Set the \c \%destructor or \c \%printer for \c node as \c cprops. */
|
||||
|
||||
@@ -1814,6 +1814,75 @@ AT_BISON_CHECK([-o input.c input.y])
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
## ------------------------- ##
|
||||
## Duplicate %start symbol. ##
|
||||
## ------------------------- ##
|
||||
|
||||
AT_SETUP([Duplicate %start symbol])
|
||||
|
||||
AT_KEYWORDS([multistart])
|
||||
|
||||
AT_DATA([input.y],
|
||||
[[%start exp exp exp
|
||||
%%
|
||||
exp: %empty;
|
||||
]])
|
||||
|
||||
AT_BISON_CHECK([-fcaret input.y], [0], [],
|
||||
[[input.y:1.12-14: warning: duplicate directive [-Wother]
|
||||
1 | %start exp exp exp
|
||||
| ^~~
|
||||
input.y:1.8-10: note: previous declaration
|
||||
1 | %start exp exp exp
|
||||
| ^~~
|
||||
input.y:1.16-18: warning: duplicate directive [-Wother]
|
||||
1 | %start exp exp exp
|
||||
| ^~~
|
||||
input.y:1.8-10: note: previous declaration
|
||||
1 | %start exp exp exp
|
||||
| ^~~
|
||||
input.y: warning: fix-its can be applied. Rerun with option '--update'. [-Wother]
|
||||
]])
|
||||
|
||||
AT_DATA([input.y],
|
||||
[[%start exp foo exp
|
||||
%%
|
||||
exp: foo;
|
||||
foo: %empty;
|
||||
]])
|
||||
|
||||
AT_BISON_CHECK([-fcaret input.y], [0], [],
|
||||
[[input.y:1.16-18: warning: duplicate directive [-Wother]
|
||||
1 | %start exp foo exp
|
||||
| ^~~
|
||||
input.y:1.8-10: note: previous declaration
|
||||
1 | %start exp foo exp
|
||||
| ^~~
|
||||
input.y: warning: fix-its can be applied. Rerun with option '--update'. [-Wother]
|
||||
]])
|
||||
|
||||
AT_DATA([input.y],
|
||||
[[%start exp foo
|
||||
%start exp
|
||||
%%
|
||||
exp: foo;
|
||||
foo: %empty;
|
||||
]])
|
||||
|
||||
AT_BISON_CHECK([-fcaret input.y], [0], [],
|
||||
[[input.y:2.8-10: warning: duplicate directive [-Wother]
|
||||
2 | %start exp
|
||||
| ^~~
|
||||
input.y:1.8-10: note: previous declaration
|
||||
1 | %start exp foo
|
||||
| ^~~
|
||||
input.y: warning: fix-its can be applied. Rerun with option '--update'. [-Wother]
|
||||
]])
|
||||
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
## --------------------- ##
|
||||
## %prec takes a token. ##
|
||||
## --------------------- ##
|
||||
|
||||
@@ -452,7 +452,7 @@ AT_CLEANUP
|
||||
AT_SETUP([Bad start symbols])
|
||||
|
||||
m4_pushdef([AT_TEST],
|
||||
[
|
||||
[AT_BISON_OPTION_PUSHDEFS([$1])
|
||||
AT_DATA([[input.y]],
|
||||
[%%
|
||||
$1
|
||||
@@ -461,6 +461,7 @@ $1
|
||||
AT_BISON_CHECK([[input.y]], 1, [],
|
||||
[$2
|
||||
])
|
||||
AT_BISON_OPTION_POPDEFS([$1])
|
||||
])
|
||||
|
||||
AT_TEST(
|
||||
|
||||
Reference in New Issue
Block a user