diff options
author | Akim Demaille <akim.demaille@gmail.com> | 2020-11-22 11:19:48 +0100 |
---|---|---|
committer | Akim Demaille <akim.demaille@gmail.com> | 2020-11-30 16:48:03 +0100 |
commit | 5b19f91ccf5f80e30729fec4b0f8b48b566fdc86 (patch) | |
tree | 4251ff9ec45b15df950389ab1d2d0730ba61e0de /src/symlist.c | |
parent | 7fe9205b9f58a7235721ba63c0f80ad009eba2b5 (diff) | |
download | bison-5b19f91ccf5f80e30729fec4b0f8b48b566fdc86.tar.gz |
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.
Diffstat (limited to 'src/symlist.c')
-rw-r--r-- | src/symlist.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/src/symlist.c b/src/symlist.c index f3bc12bc..1e899646 100644 --- a/src/symlist.c +++ b/src/symlist.c @@ -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_append (symbol_list *list, symbol_list *node) +symbol_list_last (symbol_list *list) { if (!list) - return node; + return NULL; symbol_list *next = list; while (next->next) next = next->next; - next->next = node; + return next; +} + +symbol_list * +symbol_list_append (symbol_list *list, symbol_list *node) +{ + if (list) + symbol_list_last (list)->next = node; + else + list = node; return list; } + /*-----------------------------------------------. | Free the LIST, but not the items it contains. | `-----------------------------------------------*/ |