[PATCH 15/17] multistart: allow tokens as start symbols

Akim Demaille <[email protected]>
Newsgroups gmane.comp.parsers.bison.patches
Message-ID <[email protected]>
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.
---
 examples/c/lexcalc/parse.y |  2 +-
 src/reader.c               | 11 ++++++-----
 src/symtab.c               | 11 ++++++++---
 3 files changed, 15 insertions(+), 9 deletions(-)

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 <int> exp expression line
 %printer { fprintf (yyo, "%d", $$); } <int>
 
-%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 1daccc22..4b6575d4 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,
@@ -828,9 +829,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.
@@ -871,6 +870,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)
     {
@@ -885,7 +885,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;
 }
 
 
-- 
2.28.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.