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:
Akim Demaille
2020-11-22 11:19:48 +01:00
parent 7fe9205b9f
commit 5b19f91ccf
6 changed files with 137 additions and 15 deletions

View File

@@ -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. |
`-----------------------------------------------*/