mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 04:13:03 +00:00
glr2.cc: make yyparse a member function
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).
This commit is contained in:
@@ -2849,189 +2849,6 @@ yypreference (const semantic_option& y0, const semantic_option& y1)
|
|||||||
} while (0)
|
} 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 */
|
/* DEBUGGING ONLY */
|
||||||
#if ]b4_api_PREFIX[DEBUG
|
#if ]b4_api_PREFIX[DEBUG
|
||||||
static void
|
static void
|
||||||
@@ -3045,23 +2862,6 @@ static void yypdumpstack (glr_stack* yystackp) {
|
|||||||
|
|
||||||
#endif
|
#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[
|
]b4_namespace_open[
|
||||||
]dnl In this section, the parse params are the original parse_params.
|
]dnl In this section, the parse params are the original parse_params.
|
||||||
m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
|
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
|
int
|
||||||
]b4_parser_class[::parse ()
|
]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],
|
]b4_parse_error_bmatch([custom\|detailed],
|
||||||
[[ const char *
|
[[ const char *
|
||||||
|
|||||||
Reference in New Issue
Block a user