summaryrefslogtreecommitdiff
path: root/src/symlist.c
diff options
context:
space:
mode:
authorAkim Demaille <akim.demaille@gmail.com>2020-11-22 11:19:48 +0100
committerAkim Demaille <akim.demaille@gmail.com>2020-11-30 16:48:03 +0100
commit5b19f91ccf5f80e30729fec4b0f8b48b566fdc86 (patch)
tree4251ff9ec45b15df950389ab1d2d0730ba61e0de /src/symlist.c
parent7fe9205b9f58a7235721ba63c0f80ad009eba2b5 (diff)
downloadbison-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.c30
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. |
`-----------------------------------------------*/