[PATCH 10/17] multistart: equip yacc.c

Akim Demaille <[email protected]>
Newsgroups gmane.comp.parsers.bison.patches
Message-ID <[email protected]>
* data/skeletons/yacc.c: Add support for multiple start symbols.
---
 TODO                  |  4 +++
 data/skeletons/yacc.c | 65 +++++++++++++++++++++++++++++++++++++------
 2 files changed, 60 insertions(+), 9 deletions(-)

diff --git a/TODO b/TODO
index b8641a97..018247c4 100644
--- a/TODO
+++ b/TODO
@@ -675,6 +675,10 @@ input.y:2.8-10: error: start symbol exp does not derive any sentence]])
 We should say "1 nonterminal": the other one is $accept, which should not
 participate in the count.
 
+*** Tokens
+Do we want to disallow terminal start symbols?  The limitation is not
+technical.  Can it be useful to someone to "parse" a token?
+
 ** %include
 This is a popular demand.  We already made many changes in the parser that
 should make this reasonably easy to implement.
diff --git a/data/skeletons/yacc.c b/data/skeletons/yacc.c
index 5e9d7345..5ccd1207 100644
--- a/data/skeletons/yacc.c
+++ b/data/skeletons/yacc.c
@@ -22,6 +22,7 @@ m4_pushdef([b4_copyright_years],
 
 m4_include(b4_skeletonsdir/[c.m4])
 
+
 ## ---------- ##
 ## api.pure.  ##
 ## ---------- ##
@@ -154,13 +155,31 @@ m4_define([b4_rhs_location],
 ## Declarations.  ##
 ## -------------- ##
 
+# _b4_declare_sub_yyparse(START-SYMBOL-NUM)
+# -----------------------------------
+m4_define([_b4_declare_sub_yyparse],
+[[int ]b4_prefix[parse_]_b4_symbol($1, id)[ (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[);]])
+
+
+# _b4_define_sub_yyparse(START-SYMBOL-NUM, SWITCHING-TOKEN-SYMBOL-NUM)
+# --------------------------------------------------------------------
+m4_define([_b4_define_sub_yyparse],
+[[int
+yyparse_]_b4_symbol($1, id)[ (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)
+{
+  return yyparse_impl (]b4_symbol($2, id)[]m4_ifset([b4_parse_param],
+                                                    [[, ]b4_args(b4_parse_param)])[);
+}]])
+
+
 # b4_declare_scanner_communication_variables
 # ------------------------------------------
 # Declare the variables that are global, or local to YYPARSE if
 # pure-parser.
 m4_define([b4_declare_scanner_communication_variables], [[
-/* Lookahead token kind.  */
-int yychar;
+]m4_ifdef([b4_start_symbols], [],
+[[/* Lookahead token kind.  */
+int yychar;]])[
 
 ]b4_pure_if([[
 /* The semantic value of the lookahead symbol.  */
@@ -276,11 +295,14 @@ int ]b4_prefix[push_parse (]b4_prefix[pstate *ps]b4_pure_if([[,
 void ]b4_prefix[pstate_delete (]b4_prefix[pstate *ps);
 ]])
 
+
 # _b4_declare_yyparse
 # -------------------
 # When not the push parser.
 m4_define([_b4_declare_yyparse],
-[[int ]b4_prefix[parse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[);]])
+[[int ]b4_prefix[parse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[);
+]m4_ifdef([b4_start_symbols],
+          [m4_map([_b4_declare_sub_yyparse], m4_defn([b4_start_symbols]))])])
 
 
 # b4_declare_yyparse
@@ -291,6 +313,7 @@ m4_define([b4_declare_yyparse],
 ])
 
 
+
 # b4_shared_declarations
 # ----------------------
 # Declaration that might either go into the header (if --header)
@@ -1534,8 +1557,25 @@ yypush_parse (yypstate *yyps]b4_pure_if([[,
 | yyparse.  |
 `----------*/
 
+]m4_ifdef([b4_start_symbols],
+[[
+static int
+yyparse_impl (int yychar]m4_ifset([b4_parse_param], [, b4_formals(b4_parse_param)])[);
+
+]m4_map([_b4_define_sub_yyparse], m4_defn([b4_start_symbols]))[
+
 int
-yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)]])[
+yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)
+{
+  /* ]b4_symbol(-2, id)[ causes a token to be read.  */
+  return yyparse_impl (]b4_symbol(-2, id)[]m4_ifset([b4_parse_param],
+                                                    [[, ]b4_args(b4_parse_param)])[);
+}
+
+static int
+yyparse_impl (int yychar]m4_ifset([b4_parse_param], [, b4_formals(b4_parse_param)])[)]],
+[[int
+yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)]])])[
 {]b4_pure_if([b4_declare_scanner_communication_variables
 ])b4_push_if([b4_pure_if([], [[
   int yypushed_char = yychar;
@@ -1585,7 +1625,9 @@ yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)]])[
 
   YYDPRINTF ((stderr, "Starting parse\n"));
 
-  yychar = ]b4_symbol(-2, id)[; /* Cause a token to be read.  */
+]m4_ifdef([b4_start_symbols], [],
+[[  yychar = ]b4_symbol(-2, id)[; /* Cause a token to be read.  */
+]])[
 ]m4_ifdef([b4_initial_action], [
 b4_dollar_pushdef([m4_define([b4_dollar_dollar_used])yylval], [], [],
                   [b4_push_if([b4_pure_if([*])yypushed_loc], [yylloc])])dnl
@@ -1686,8 +1728,9 @@ yysetstate:
     }
 #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
 
+]m4_ifdef([b4_start_symbols], [], [[
   if (yystate == YYFINAL)
-    YYACCEPT;
+    YYACCEPT;]])[
 
   goto yybackup;
 
@@ -1768,9 +1811,11 @@ yyread_pushed_token:]])[
   if (yyn <= 0)
     {
       if (yytable_value_is_error (yyn))
-        goto yyerrlab;]b4_lac_if([[
+        goto yyerrlab;
+      yyn = -yyn;]m4_ifdef([b4_start_symbols], [[
+      if (yyr1[yyn] == YYNTOKENS)
+        YYACCEPT;]])[]b4_lac_if([[
       YY_LAC_ESTABLISH;]])[
-      yyn = -yyn;
       goto yyreduce;
     }
 
@@ -1799,7 +1844,9 @@ yyread_pushed_token:]])[
 yydefault:
   yyn = yydefact[yystate];
   if (yyn == 0)
-    goto yyerrlab;
+    goto yyerrlab;]m4_ifdef([b4_start_symbols], [[
+  else if (yyr1[yyn] == YYNTOKENS)
+    YYACCEPT;]])[
   goto yyreduce;
 
 
-- 
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.