diff --git a/examples/c/lexcalc/parse.y b/examples/c/lexcalc/parse.y index b3aaf476..59708115 100644 --- a/examples/c/lexcalc/parse.y +++ b/examples/c/lexcalc/parse.y @@ -79,7 +79,7 @@ %type exp expression line %printer { fprintf (yyo, "%d", $$); } -%start input expression +%start input expression NUM // Precedence (from lowest to highest) and associativity. %left "+" "-" diff --git a/src/reader.c b/src/reader.c index 3125213e..7aabd835 100644 --- a/src/reader.c +++ b/src/reader.c @@ -322,7 +322,8 @@ grammar_rule_check_and_complete (symbol_list *r) const symbol *start = r->next->next->content.sym; if (start->content->type_name) obstack_printf (obstack_for_actions, - "{ ]b4_accept([orig %d])[; }", + "{ ]b4_accept([%s%d])[; }", + start->content->class == nterm_sym ? "orig " : "", start->content->number); else obstack_printf (obstack_for_actions, @@ -827,9 +828,7 @@ switching_token (const symbol *start) { char buf[100]; size_t len = sizeof buf; - char *name - = asnprintf (buf, &len, - "YY_PARSE_%s", start->alias ? start->alias->tag : start->tag); + char *name = asnprintf (buf, &len, "YY_PARSE_%s", symbol_id_get (start)); if (!name) xalloc_die (); // Setting the location ensures deterministic symbol numbers. @@ -881,6 +880,7 @@ create_start_rules (void) static void check_start_symbols (void) { + const bool multistart = start_symbols && start_symbols->next; // Sanity checks on the start symbols. 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". 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, _("the start symbol %s is a token"), start->tag); diff --git a/src/symtab.c b/src/symtab.c index 31a3c048..d0ec50a9 100644 --- a/src/symtab.c +++ b/src/symtab.c @@ -305,9 +305,14 @@ is_identifier (uniqstr s) uniqstr symbol_id_get (symbol const *sym) { - if (sym->alias) - sym = sym->alias; - return is_identifier (sym->tag) ? sym->tag : 0; + // There's one weird case: YYerror is the alias, and error is the + // base symbol. Return YYerror in that case. + if (sym->alias && is_identifier (sym->alias->tag)) + return sym->alias->tag; + else if (is_identifier (sym->tag)) + return sym->tag; + else + return NULL; }