mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-11 21:33: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:
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. */
|
||||
|
||||
Reference in New Issue
Block a user