multistart: allow tokens as start symbols

After all, why not?

* src/reader.c (switching_token): Use symbol_id_get.
(check_start_symbols): Require that the start symbol is a token only
if it's the only one.
* examples/c/lexcalc/parse.y: Let NUM be a start symbol.
This commit is contained in:
Akim Demaille
2020-08-04 16:47:19 +02:00
parent d9cf99b6a5
commit 683040b324
3 changed files with 15 additions and 9 deletions

View File

@@ -79,7 +79,7 @@
%type <int> exp expression line %type <int> exp expression line
%printer { fprintf (yyo, "%d", $$); } <int> %printer { fprintf (yyo, "%d", $$); } <int>
%start input expression %start input expression NUM
// Precedence (from lowest to highest) and associativity. // Precedence (from lowest to highest) and associativity.
%left "+" "-" %left "+" "-"

View File

@@ -322,7 +322,8 @@ grammar_rule_check_and_complete (symbol_list *r)
const symbol *start = r->next->next->content.sym; const symbol *start = r->next->next->content.sym;
if (start->content->type_name) if (start->content->type_name)
obstack_printf (obstack_for_actions, obstack_printf (obstack_for_actions,
"{ ]b4_accept([orig %d])[; }", "{ ]b4_accept([%s%d])[; }",
start->content->class == nterm_sym ? "orig " : "",
start->content->number); start->content->number);
else else
obstack_printf (obstack_for_actions, obstack_printf (obstack_for_actions,
@@ -827,9 +828,7 @@ switching_token (const symbol *start)
{ {
char buf[100]; char buf[100];
size_t len = sizeof buf; size_t len = sizeof buf;
char *name char *name = asnprintf (buf, &len, "YY_PARSE_%s", symbol_id_get (start));
= asnprintf (buf, &len,
"YY_PARSE_%s", start->alias ? start->alias->tag : start->tag);
if (!name) if (!name)
xalloc_die (); xalloc_die ();
// Setting the location ensures deterministic symbol numbers. // Setting the location ensures deterministic symbol numbers.
@@ -881,6 +880,7 @@ create_start_rules (void)
static void static void
check_start_symbols (void) check_start_symbols (void)
{ {
const bool multistart = start_symbols && start_symbols->next;
// Sanity checks on the start symbols. // Sanity checks on the start symbols.
for (symbol_list *list = start_symbols; list; list = list->next) for (symbol_list *list = start_symbols; list; list = list->next)
{ {
@@ -895,7 +895,8 @@ check_start_symbols (void)
// defined as a token and has no rules". // defined as a token and has no rules".
abort (); abort ();
} }
if (start->content->class == token_sym) // If your only start symbol is a token, you're weird.
if (!multistart && start->content->class == token_sym)
complain (&start->location, complaint, complain (&start->location, complaint,
_("the start symbol %s is a token"), _("the start symbol %s is a token"),
start->tag); start->tag);

View File

@@ -305,9 +305,14 @@ is_identifier (uniqstr s)
uniqstr uniqstr
symbol_id_get (symbol const *sym) symbol_id_get (symbol const *sym)
{ {
if (sym->alias) // There's one weird case: YYerror is the alias, and error is the
sym = sym->alias; // base symbol. Return YYerror in that case.
return is_identifier (sym->tag) ? sym->tag : 0; if (sym->alias && is_identifier (sym->alias->tag))
return sym->alias->tag;
else if (is_identifier (sym->tag))
return sym->tag;
else
return NULL;
} }