multistart: turn start symbols into rules on $accept

Now that the parser can read several start symbols, let's process
them, and create the corresponding rules.

* src/parse-gram.y (grammar_declaration): Accept a list of start symbols.
* src/reader.h, src/reader.c (grammar_start_symbol_set): Rename as...
(grammar_start_symbols_set): this.

* src/reader.h, src/reader.c (start_flag): Replace with...
(start_symbols): this.
* src/reader.c (grammar_start_symbols_set): Build a list of start
symbols.
(switching_token, create_start_rules): New.
(check_and_convert_grammar): Use them to turn the list of start
symbols into a set of rules.
* src/reduce.c (nonterminals_reduce): Don't complain about $accept,
it's an internal detail.
(reduce_grammar): Complain about all the start symbols that don't
derive sentences.

* src/symtab.c (startsymbol, startsymbol_loc): Remove, replaced by
start_symbols.
symbols_pack): Move the check about the start symbols
to...
* src/symlist.c (check_start_symbols): here.
Adjust to multiple start symbols.
* tests/reduce.at (Empty Language): Generalize into...
(Bad start symbols): this.
This commit is contained in:
Akim Demaille
2020-02-20 18:11:29 +01:00
parent db68f61595
commit 8eaddf326b
8 changed files with 194 additions and 54 deletions

View File

@@ -275,7 +275,8 @@ nonterminals_reduce (void)
if (!bitset_test (V, i))
{
nterm_map[i - ntokens] = n++;
if (symbols[i]->content->status != used)
if (symbols[i]->content->status != used
&& symbols[i] != acceptsymbol)
complain (&symbols[i]->location, Wother,
_("nonterminal useless in grammar: %s"),
symbols[i]->tag);
@@ -381,10 +382,18 @@ reduce_grammar (void)
{
reduce_print ();
if (!bitset_test (N, acceptsymbol->content->number - ntokens))
complain (&startsymbol_loc, fatal,
_("start symbol %s does not derive any sentence"),
startsymbol->tag);
// Check that start symbols have non-empty languages.
bool failure = false;
for (symbol_list *list = start_symbols; list; list = list->next)
if (!bitset_test (N, list->content.sym->content->number - ntokens))
{
failure = true;
complain (&list->sym_loc, complaint,
_("start symbol %s does not derive any sentence"),
list->content.sym->tag);
}
if (failure)
exit (EXIT_FAILURE);
/* First reduce the nonterminals, as they renumber themselves in the
whole grammar. If you change the order, nonterms would be