[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 7/9] glr2.cc: make yyparse a member function
From: |
Akim Demaille |
Subject: |
[PATCH 7/9] glr2.cc: make yyparse a member function |
Date: |
Sun, 13 Dec 2020 08:49:25 +0100 |
Amusingly enough, glr2.cc still had its core function, yyparse, being
a free function instead of a member function.
* data/skeletons/glr2.cc (yyparse): Remove this free function called
from yyparser::parse. Inline its body into...
(yyparser::parse): this member function.
This requires moving a bit the yychar, etc. macros.
Access to token can be simplified (the
b4_namespace_ref::b4_parser_class prefix is no longer needed).
---
data/skeletons/glr2.cc | 382 +++++++++++++++++++----------------------
1 file changed, 180 insertions(+), 202 deletions(-)
diff --git a/data/skeletons/glr2.cc b/data/skeletons/glr2.cc
index 6fce8445..78fdf45a 100644
--- a/data/skeletons/glr2.cc
+++ b/data/skeletons/glr2.cc
@@ -2849,189 +2849,6 @@ yypreference (const semantic_option& y0, const
semantic_option& y1)
} while (0)
-/*----------.
-| yyparse. |
-`----------*/
-
-int
-yyparse (]b4_namespace_ref[::]b4_parser_class[& yyparser]b4_user_formals[)
-{
- int yyresult;
- glr_stack yystack(YYINITDEPTH, yyparser]b4_user_args[);
- glr_stack* const yystackp = &yystack;
- size_t yyposn;
-
- YY_DEBUG_STREAM << "Starting parse\n";
-
- yychar = ]b4_namespace_ref::b4_parser_class::token::b4_symbol(empty, id)[;
- yylval = yyval_default;]b4_locations_if([
- yylloc = yyloc_default;])[
-]m4_ifdef([b4_initial_action], [
-b4_dollar_pushdef([yylval], [], [], [yylloc])dnl
- b4_user_initial_action
-b4_dollar_popdef])[]dnl
-[
- switch (YYSETJMP (yystack.yyexception_buffer))
- {
- case 0: break;
- case 1: goto yyabortlab;
- case 2: goto yyexhaustedlab;
- default: goto yybuglab;
- }
- yystack.yyglrShift (create_state_set_index(0), 0, 0,
yylval]b4_locations_if([, &yylloc])[);
- yyposn = 0;
-
- while (true)
- {
- /* For efficiency, we have two loops, the first of which is
- specialized to deterministic operation (single stack, no
- potential ambiguity). */
- /* Standard mode */
- while (true)
- {
- const state_num yystate = yystack.firstTopState()->yylrState;
- YY_DEBUG_STREAM << "Entering state " << yystate << "\n";
- if (yystate == YYFINAL)
- goto yyacceptlab;
- if (yyisDefaultedState (yystate))
- {
- const rule_num yyrule = yydefaultAction (yystate);
- if (yyrule == 0)
- {]b4_locations_if([[
- yystack.yyerror_range[1].getState().yyloc = yylloc;]])[
- yystack.yyreportSyntaxError ();
- goto yyuser_error;
- }
- YYCHK1 (yystack.yyglrReduce (create_state_set_index(0), yyrule,
true));
- }
- else
- {
- const yysymbol_kind_t yytoken = ]b4_yygetToken_call[;
- const short* yyconflicts;
- const int yyaction = yygetLRActions (yystate, yytoken,
yyconflicts);
- if (*yyconflicts != 0)
- break;
- if (yyisShiftAction (yyaction))
- {
- YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
- yychar =
]b4_namespace_ref::b4_parser_class::token::b4_symbol(empty, id)[;
- yyposn += 1;
- yystack.yyglrShift (create_state_set_index(0), yyaction,
yyposn, yylval]b4_locations_if([, &yylloc])[);
- if (0 < yystack.yyerrState)
- yystack.yyerrState -= 1;
- }
- else if (yyisErrorAction (yyaction))
- {]b4_locations_if([[
- yystack.yyerror_range[1].getState().yyloc = yylloc;]])[
- /* Don't issue an error message again for exceptions
- thrown from the scanner. */
- if (yychar !=
]b4_namespace_ref::b4_parser_class::token::b4_symbol(error, id)[)
- yystack.yyreportSyntaxError ();
- goto yyuser_error;
- }
- else
- YYCHK1 (yystack.yyglrReduce (create_state_set_index(0),
-yyaction, true));
- }
- }
-
- while (true)
- {
- for (state_set_index yys = create_state_set_index(0); yys.uget() <
yystack.yystateStack.numTops(); ++yys)
- yystackp->yystateStack.yytops.setLookaheadNeeds(yys, yychar !=
]b4_namespace_ref::b4_parser_class::token::b4_symbol(empty, id)[);
-
- /* yyprocessOneStack returns one of three things:
-
- - An error flag. If the caller is yyprocessOneStack, it
- immediately returns as well. When the caller is finally
- yyparse, it jumps to an error label via YYCHK1.
-
- - yyok, but yyprocessOneStack has invoked yymarkStackDeleted
- (yys), which sets the top state of yys to NULL. Thus,
- yyparse's following invocation of yyremoveDeletes will remove
- the stack.
-
- - yyok, when ready to shift a token.
-
- Except in the first case, yyparse will invoke yyremoveDeletes and
- then shift the next token onto all remaining stacks. This
- synchronization of the shift (that is, after all preceding
- reductions on all stacks) helps prevent double destructor calls
- on yylval in the event of memory exhaustion. */
-
- for (state_set_index yys = create_state_set_index(0); yys.uget() <
yystack.yystateStack.numTops(); ++yys)
- YYCHK1 (yystack.yyprocessOneStack (yys, yyposn]b4_locations_if([,
&yylloc])[));
- yystack.yystateStack.yytops.yyremoveDeletes ();
- if (yystack.yystateStack.yytops.size() == 0)
- {
- yystack.yystateStack.yytops.yyundeleteLastStack ();
- if (yystack.yystateStack.yytops.size() == 0)
- yystack.yyFail (]b4_locations_if([&yylloc, ])[YY_("syntax
error"));
- YYCHK1 (yystack.yyresolveStack ());
- YY_DEBUG_STREAM << "Returning to deterministic
operation.\n";]b4_locations_if([[
- yystack.yyerror_range[1].getState().yyloc = yylloc;]])[
- yystack.yyreportSyntaxError ();
- goto yyuser_error;
- }
-
- /* If any yyglrShift call fails, it will fail after shifting. Thus,
- a copy of yylval will already be on stack 0 in the event of a
- failure in the following loop. Thus, yychar is set to
]b4_symbol(empty, id)[
- before the loop to make sure the user destructor for yylval isn't
- called twice. */
- yysymbol_kind_t yytoken_to_shift = YYTRANSLATE (yychar);
- yychar = ]b4_namespace_ref::b4_parser_class::token::b4_symbol(empty,
id)[;
- yyposn += 1;
- for (state_set_index yys = create_state_set_index(0); yys.uget() <
yystack.yystateStack.numTops(); ++yys)
- {
- const state_num yystate = yystack.topState(yys)->yylrState;
- const short* yyconflicts;
- const int yyaction = yygetLRActions (yystate, yytoken_to_shift,
- yyconflicts);
- /* Note that yyconflicts were handled by yyprocessOneStack. */
- YY_DEBUG_STREAM << "On stack " << yys.get() << ", ";
- YY_SYMBOL_PRINT ("shifting", yytoken_to_shift, &yylval, &yylloc);
- yystack.yyglrShift (yys, yyaction, yyposn,
- yylval]b4_locations_if([, &yylloc])[);
- YY_DEBUG_STREAM << "Stack " << yys.get() << " now in state #"
- << yystack.topState(yys)->yylrState << '\n';
- }
-
- if (yystack.yystateStack.yytops.size() == 1)
- {
- YYCHK1 (yystack.yyresolveStack ());
- YY_DEBUG_STREAM << "Returning to deterministic operation.\n";
- yystack.yystateStack.yycompressStack ();
- break;
- }
- }
- continue;
- yyuser_error:
- yystack.yyrecoverSyntaxError (]b4_locations_if([&yylloc])[);
- yyposn = yystack.firstTopState()->yyposn;
- }
-
- yyacceptlab:
- yyresult = 0;
- goto yyreturn;
-
- yybuglab:
- YYASSERT (false);
- goto yyabortlab;
-
- yyabortlab:
- yyresult = 1;
- goto yyreturn;
-
- yyexhaustedlab:
- yyparser.error (]b4_locations_if([yylloc, ])[YY_("memory exhausted"));
- yyresult = 2;
- goto yyreturn;
-
- yyreturn:
- return yyresult;
-}
-
-
/* DEBUGGING ONLY */
#if ]b4_api_PREFIX[DEBUG
static void
@@ -3045,23 +2862,6 @@ static void yypdumpstack (glr_stack* yystackp) {
#endif
-#undef yylval
-#undef yychar
-#undef yynerrs]b4_locations_if([
-#undef yylloc])
-
-m4_if(b4_prefix, [yy], [],
-[[/* Substitute the variable and function names. */
-#define yyparse ]b4_prefix[parse
-#define yylex ]b4_prefix[lex
-#define yyerror ]b4_prefix[error
-#define yylval ]b4_prefix[lval
-#define yychar ]b4_prefix[char
-#define yydebug ]b4_prefix[debug
-#define yynerrs ]b4_prefix[nerrs]b4_locations_if([[
-#define yylloc ]b4_prefix[lloc]])])[
-
-
]b4_namespace_open[
]dnl In this section, the parse params are the original parse_params.
m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
@@ -3088,8 +2888,186 @@ m4_pushdef([b4_parse_param],
m4_defn([b4_parse_param_orig]))dnl
int
]b4_parser_class[::parse ()
{
- return ::yyparse (*this]b4_user_args[);
- }
+ ]b4_parser_class[ &yyparser = *this;
+ int yyresult;
+ glr_stack yystack(YYINITDEPTH, *this]b4_user_args[);
+ glr_stack* const yystackp = &yystack;
+ size_t yyposn;
+
+ YY_DEBUG_STREAM << "Starting parse\n";
+
+ yychar = ]b4_namespace_ref::b4_parser_class::token::b4_symbol(empty, id)[;
+ yylval = yyval_default;]b4_locations_if([
+ yylloc = yyloc_default;])[
+]m4_ifdef([b4_initial_action], [
+b4_dollar_pushdef([yylval], [], [], [yylloc])dnl
+ b4_user_initial_action
+b4_dollar_popdef])[]dnl
+[
+ switch (YYSETJMP (yystack.yyexception_buffer))
+ {
+ case 0: break;
+ case 1: goto yyabortlab;
+ case 2: goto yyexhaustedlab;
+ default: goto yybuglab;
+ }
+ yystack.yyglrShift (create_state_set_index(0), 0, 0,
yylval]b4_locations_if([, &yylloc])[);
+ yyposn = 0;
+
+ while (true)
+ {
+ /* For efficiency, we have two loops, the first of which is
+ specialized to deterministic operation (single stack, no
+ potential ambiguity). */
+ /* Standard mode */
+ while (true)
+ {
+ const state_num yystate = yystack.firstTopState()->yylrState;
+ YY_DEBUG_STREAM << "Entering state " << yystate << "\n";
+ if (yystate == YYFINAL)
+ goto yyacceptlab;
+ if (yyisDefaultedState (yystate))
+ {
+ const rule_num yyrule = yydefaultAction (yystate);
+ if (yyrule == 0)
+ {]b4_locations_if([[
+ yystack.yyerror_range[1].getState().yyloc = yylloc;]])[
+ yystack.yyreportSyntaxError ();
+ goto yyuser_error;
+ }
+ YYCHK1 (yystack.yyglrReduce (create_state_set_index(0),
yyrule, true));
+ }
+ else
+ {
+ const yysymbol_kind_t yytoken = ]b4_yygetToken_call[;
+ const short* yyconflicts;
+ const int yyaction = yygetLRActions (yystate, yytoken,
yyconflicts);
+ if (*yyconflicts != 0)
+ break;
+ if (yyisShiftAction (yyaction))
+ {
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+ yychar = token::]b4_symbol(empty, id)[;
+ yyposn += 1;
+ yystack.yyglrShift (create_state_set_index(0), yyaction,
yyposn, yylval]b4_locations_if([, &yylloc])[);
+ if (0 < yystack.yyerrState)
+ yystack.yyerrState -= 1;
+ }
+ else if (yyisErrorAction (yyaction))
+ {]b4_locations_if([[
+ yystack.yyerror_range[1].getState().yyloc = yylloc;]])[
+ /* Don't issue an error message again for exceptions
+ thrown from the scanner. */
+ if (yychar != token::]b4_symbol(error, id)[)
+ yystack.yyreportSyntaxError ();
+ goto yyuser_error;
+ }
+ else
+ YYCHK1 (yystack.yyglrReduce (create_state_set_index(0),
-yyaction, true));
+ }
+ }
+
+ while (true)
+ {
+ for (state_set_index yys = create_state_set_index(0); yys.uget() <
yystack.yystateStack.numTops(); ++yys)
+ yystackp->yystateStack.yytops.setLookaheadNeeds(yys, yychar !=
token::]b4_symbol(empty, id)[);
+
+ /* yyprocessOneStack returns one of three things:
+
+ - An error flag. If the caller is yyprocessOneStack, it
+ immediately returns as well. When the caller is finally
+ yyparse, it jumps to an error label via YYCHK1.
+
+ - yyok, but yyprocessOneStack has invoked yymarkStackDeleted
+ (yys), which sets the top state of yys to NULL. Thus,
+ yyparse's following invocation of yyremoveDeletes will remove
+ the stack.
+
+ - yyok, when ready to shift a token.
+
+ Except in the first case, yyparse will invoke yyremoveDeletes
and
+ then shift the next token onto all remaining stacks. This
+ synchronization of the shift (that is, after all preceding
+ reductions on all stacks) helps prevent double destructor calls
+ on yylval in the event of memory exhaustion. */
+
+ for (state_set_index yys = create_state_set_index(0); yys.uget() <
yystack.yystateStack.numTops(); ++yys)
+ YYCHK1 (yystack.yyprocessOneStack (yys,
yyposn]b4_locations_if([, &yylloc])[));
+ yystack.yystateStack.yytops.yyremoveDeletes ();
+ if (yystack.yystateStack.yytops.size() == 0)
+ {
+ yystack.yystateStack.yytops.yyundeleteLastStack ();
+ if (yystack.yystateStack.yytops.size() == 0)
+ yystack.yyFail (]b4_locations_if([&yylloc, ])[YY_("syntax
error"));
+ YYCHK1 (yystack.yyresolveStack ());
+ YY_DEBUG_STREAM << "Returning to deterministic
operation.\n";]b4_locations_if([[
+ yystack.yyerror_range[1].getState().yyloc = yylloc;]])[
+ yystack.yyreportSyntaxError ();
+ goto yyuser_error;
+ }
+
+ /* If any yyglrShift call fails, it will fail after shifting.
Thus,
+ a copy of yylval will already be on stack 0 in the event of a
+ failure in the following loop. Thus, yychar is set to
]b4_symbol(empty, id)[
+ before the loop to make sure the user destructor for yylval
isn't
+ called twice. */
+ yysymbol_kind_t yytoken_to_shift = YYTRANSLATE (yychar);
+ yychar = token::]b4_symbol(empty, id)[;
+ yyposn += 1;
+ for (state_set_index yys = create_state_set_index(0); yys.uget() <
yystack.yystateStack.numTops(); ++yys)
+ {
+ const state_num yystate = yystack.topState(yys)->yylrState;
+ const short* yyconflicts;
+ const int yyaction = yygetLRActions (yystate, yytoken_to_shift,
+ yyconflicts);
+ /* Note that yyconflicts were handled by yyprocessOneStack. */
+ YY_DEBUG_STREAM << "On stack " << yys.get() << ", ";
+ YY_SYMBOL_PRINT ("shifting", yytoken_to_shift, &yylval,
&yylloc);
+ yystack.yyglrShift (yys, yyaction, yyposn,
+ yylval]b4_locations_if([, &yylloc])[);
+ YY_DEBUG_STREAM << "Stack " << yys.get() << " now in state #"
+ << yystack.topState(yys)->yylrState << '\n';
+ }
+
+ if (yystack.yystateStack.yytops.size() == 1)
+ {
+ YYCHK1 (yystack.yyresolveStack ());
+ YY_DEBUG_STREAM << "Returning to deterministic operation.\n";
+ yystack.yystateStack.yycompressStack ();
+ break;
+ }
+ }
+ continue;
+ yyuser_error:
+ yystack.yyrecoverSyntaxError (]b4_locations_if([&yylloc])[);
+ yyposn = yystack.firstTopState()->yyposn;
+ }
+
+ yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+ yybuglab:
+ YYASSERT (false);
+ goto yyabortlab;
+
+ yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+ yyexhaustedlab:
+ error (]b4_locations_if([yylloc, ])[YY_("memory exhausted"));
+ yyresult = 2;
+ goto yyreturn;
+
+ yyreturn:
+ return yyresult;
+}
+
+#undef yylval
+#undef yychar
+#undef yynerrs]b4_locations_if([
+#undef yylloc])[
]b4_parse_error_bmatch([custom\|detailed],
[[ const char *
--
2.29.2
- [PATCH 0/9] glr2.cc: fixes, Akim Demaille, 2020/12/13
- [PATCH 1/9] glr2.cc: add sanity checks in glr_stack_item, Akim Demaille, 2020/12/13
- [PATCH 3/9] glr2.cc: style fixes, Akim Demaille, 2020/12/13
- [PATCH 2/9] glr2.cc: add sanity check in glr_state, Akim Demaille, 2020/12/13
- [PATCH 4/9] glr2.cc: fix pointer arithmethics, Akim Demaille, 2020/12/13
- [PATCH 5/9] glr2.cc: fix yycompressStack, Akim Demaille, 2020/12/13
- [PATCH 6/9] glr2.cc: being pure is not an option, Akim Demaille, 2020/12/13
- [PATCH 7/9] glr2.cc: make yyparse a member function,
Akim Demaille <=
- [PATCH 8/9] glr2.cc: make the example more C++, Akim Demaille, 2020/12/13
- [PATCH 9/9] glr.c: comment changes, Akim Demaille, 2020/12/13