From 9babd05a90fc72db1c66bb49e4101a2c665a47b7 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Thu, 9 Sep 2021 06:52:43 +0200 Subject: [PATCH] glr2.cc: move glr_stack and glr_state into the parser class In order to be able to link several glr2.cc parser together, we cannot have glr_stack and glr_state be in no namespace. Putting them in the unnamed namespace is not doable, since we need to fwd declare them in the parser. Putting them in the specified namespace is not enough either, since some users would like to be able to put several parsers in the same name, only differing by the class name. * data/skeletons/glr2.cc (glr_state, glr_stack): Move into yy::parser. --- data/skeletons/glr2.cc | 2594 ++++++++++++++++++++-------------------- 1 file changed, 1300 insertions(+), 1294 deletions(-) diff --git a/data/skeletons/glr2.cc b/data/skeletons/glr2.cc index 573de259..b7d33a14 100644 --- a/data/skeletons/glr2.cc +++ b/data/skeletons/glr2.cc @@ -224,9 +224,6 @@ m4_define([b4_shared_declarations], ]b4_YYDEBUG_define[ -class glr_stack; -class glr_state; - ]b4_namespace_open[ ]b4_bison_locations_if([m4_ifndef([b4_location_file], @@ -239,6 +236,10 @@ class glr_state; ]b4_public_types_declare[ ]b4_symbol_type_define[ + // FIXME: should be private eventually. + class glr_stack; + class glr_state; + /// Build a parser object. ]b4_parser_class[ (]b4_parse_param_decl[); ~]b4_parser_class[ (); @@ -373,10 +374,8 @@ class glr_state; location_type& yyloc]])[); ]b4_parse_param_vars[ - // Needs access to report_syntax_error, etc. + // Needs access to yy_destroy_, report_syntax_error, etc. friend glr_stack; - // Needs access to yy_destroy_. - friend glr_state; }; ]b4_token_ctor_if([b4_yytranslate_define([$1])[ @@ -635,6 +634,9 @@ int yydebug; namespace { + using glr_stack = ]b4_namespace_ref[::]b4_parser_class[::glr_stack; + using glr_state = ]b4_namespace_ref[::]b4_parser_class[::glr_state; + void yypstack (const glr_stack& yystack, size_t yyk) YY_ATTRIBUTE_UNUSED; void yypdumpstack (const glr_stack& yystack) @@ -775,13 +777,11 @@ typedef int state_num; typedef int rule_num; // Forward declarations. -class glr_state; namespace { class semantic_option; } class glr_stack_item; -class glr_stack; /** Accessing symbol of state YYSTATE. */ static inline yysymbol_kind_t @@ -804,216 +804,220 @@ yyrhsLength (rule_num yyrule) return yyr2[yyrule]; } -class glr_state +namespace ]b4_namespace_ref[ { -public: - typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind symbol_kind; - typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind_type symbol_kind_type; - typedef ]b4_namespace_ref[::]b4_parser_class[::value_type value_type;]b4_locations_if([[ - typedef ]b4_namespace_ref[::]b4_parser_class[::location_type location_type;]])[ - - glr_state () - : yyresolved (false) - , yylrState (0) - , yyposn (0) - , yypred (0) - , yyfirstVal (0)]b4_locations_if([[ - , yyloc ()]])[]b4_parse_assert_if([[ - , magic_ (MAGIC)]])[ - {} - - /// Build with a semantic value. - glr_state (state_num lrState, size_t posn, const value_type& val]b4_locations_if([[, const location_type& loc]])[) - : yyresolved (true) - , yylrState (lrState) - , yyposn (posn) - , yypred (0) - , yyval (]b4_variant_if([], [[val]])[)]b4_locations_if([[ - , yyloc (loc)]])[]b4_parse_assert_if([[ - , magic_ (MAGIC)]])[ - {]b4_variant_if([[ - ]b4_symbol_variant([yy_accessing_symbol (lrState)], - [yyval], [copy], [val])])[} - - /// Build with a semantic option. - glr_state (state_num lrState, size_t posn) - : yyresolved (false) - , yylrState (lrState) - , yyposn (posn) - , yypred (0) - , yyfirstVal (0)]b4_locations_if([[ - , yyloc ()]])[]b4_parse_assert_if([[ - , magic_ (MAGIC)]])[ - {} - - glr_state (const glr_state& other) - : yyresolved (other.yyresolved) - , yylrState (other.yylrState) - , yyposn (other.yyposn) - , yypred (0)]b4_locations_if([[ - , yyloc (other.yyloc)]])[]b4_parse_assert_if([[ - , magic_ (MAGIC)]])[ + class ]b4_parser_class[::glr_state { - setPred (other.pred ()); - if (other.yyresolved)]b4_variant_if([[ - { - new (&yyval) value_type (); + public: + typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind symbol_kind; + typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind_type symbol_kind_type; + typedef ]b4_namespace_ref[::]b4_parser_class[::value_type value_type;]b4_locations_if([[ + typedef ]b4_namespace_ref[::]b4_parser_class[::location_type location_type;]])[ + + glr_state () + : yyresolved (false) + , yylrState (0) + , yyposn (0) + , yypred (0) + , yyfirstVal (0)]b4_locations_if([[ + , yyloc ()]])[]b4_parse_assert_if([[ + , magic_ (MAGIC)]])[ + {} + + /// Build with a semantic value. + glr_state (state_num lrState, size_t posn, const value_type& val]b4_locations_if([[, const location_type& loc]])[) + : yyresolved (true) + , yylrState (lrState) + , yyposn (posn) + , yypred (0) + , yyval (]b4_variant_if([], [[val]])[)]b4_locations_if([[ + , yyloc (loc)]])[]b4_parse_assert_if([[ + , magic_ (MAGIC)]])[ + {]b4_variant_if([[ + ]b4_symbol_variant([yy_accessing_symbol (lrState)], + [yyval], [copy], [val])])[} + + /// Build with a semantic option. + glr_state (state_num lrState, size_t posn) + : yyresolved (false) + , yylrState (lrState) + , yyposn (posn) + , yypred (0) + , yyfirstVal (0)]b4_locations_if([[ + , yyloc ()]])[]b4_parse_assert_if([[ + , magic_ (MAGIC)]])[ + {} + + glr_state (const glr_state& other) + : yyresolved (other.yyresolved) + , yylrState (other.yylrState) + , yyposn (other.yyposn) + , yypred (0)]b4_locations_if([[ + , yyloc (other.yyloc)]])[]b4_parse_assert_if([[ + , magic_ (MAGIC)]])[ + { + setPred (other.pred ()); + if (other.yyresolved)]b4_variant_if([[ + { + new (&yyval) value_type (); + ]b4_symbol_variant([yy_accessing_symbol (other.yylrState)], + [yyval], [copy], [other.value ()])[ + }]], [[ + new (&yyval) value_type (other.value ());]])[ + else + { + yyfirstVal = 0; + setFirstVal (other.firstVal ()); + }]b4_parse_assert_if([[ + check_();]])[ + } + + ~glr_state () + {]b4_parse_assert_if([[ + check_ ();]])[ + if (yyresolved) + {]b4_variant_if([[ + yysymbol_kind_t yykind = yy_accessing_symbol (yylrState); + // FIXME: User destructors. + // Value type destructor. + ]b4_symbol_variant([[yykind]], [[yyval]], [[template destroy]])])[ + yyval.~value_type (); + }]b4_parse_assert_if([[ + magic_ = 0;]])[ + } + + glr_state& operator= (const glr_state& other) + {]b4_parse_assert_if([[ + check_ (); + other.check_ ();]])[ + if (!yyresolved && other.yyresolved) + new (&yyval) value_type; + yyresolved = other.yyresolved; + yylrState = other.yylrState; + yyposn = other.yyposn; + setPred (other.pred ()); + if (other.yyresolved)]b4_variant_if([[ ]b4_symbol_variant([yy_accessing_symbol (other.yylrState)], - [yyval], [copy], [other.value ()])[ - }]], [[ - new (&yyval) value_type (other.value ());]])[ - else - { - yyfirstVal = 0; - setFirstVal (other.firstVal ()); - }]b4_parse_assert_if([[ - check_();]])[ - } + [yyval], [copy], [other.value ()])], [[ + value () = other.value ();]])[ + else + setFirstVal (other.firstVal ());]b4_locations_if([[ + yyloc = other.yyloc;]])[ + return *this; + } - ~glr_state () - {]b4_parse_assert_if([[ - check_ ();]])[ - if (yyresolved) - {]b4_variant_if([[ - yysymbol_kind_t yykind = yy_accessing_symbol (yylrState); - // FIXME: User destructors. - // Value type destructor. - ]b4_symbol_variant([[yykind]], [[yyval]], [[template destroy]])])[ - yyval.~value_type (); - }]b4_parse_assert_if([[ - magic_ = 0;]])[ - } + /** Type tag for the semantic value. If true, yyval applies, otherwise + * yyfirstVal applies. */ + bool yyresolved; + /** Number of corresponding LALR(1) machine state. */ + state_num yylrState; + /** Source position of the last token produced by my symbol */ + size_t yyposn; - glr_state& operator= (const glr_state& other) - {]b4_parse_assert_if([[ - check_ (); - other.check_ ();]])[ - if (!yyresolved && other.yyresolved) - new (&yyval) value_type; - yyresolved = other.yyresolved; - yylrState = other.yylrState; - yyposn = other.yyposn; - setPred (other.pred ()); - if (other.yyresolved)]b4_variant_if([[ - ]b4_symbol_variant([yy_accessing_symbol (other.yylrState)], - [yyval], [copy], [other.value ()])], [[ - value () = other.value ();]])[ - else - setFirstVal (other.firstVal ());]b4_locations_if([[ - yyloc = other.yyloc;]])[ - return *this; - } + /// Only call pred() and setPred() on objects in yyitems, not temporaries. + glr_state* pred (); + const glr_state* pred () const; + void setPred (const glr_state* state); - /** Type tag for the semantic value. If true, yyval applies, otherwise - * yyfirstVal applies. */ - bool yyresolved; - /** Number of corresponding LALR(1) machine state. */ - state_num yylrState; - /** Source position of the last token produced by my symbol */ - size_t yyposn; + /// Only call firstVal() and setFirstVal() on objects in yyitems, not + /// temporaries. + semantic_option* firstVal (); + const semantic_option* firstVal () const; + void setFirstVal (const semantic_option* option); - /// Only call pred() and setPred() on objects in yyitems, not temporaries. - glr_state* pred (); - const glr_state* pred () const; - void setPred (const glr_state* state); + value_type& value () + {]b4_parse_assert_if([[ + check_ ();]])[ + return yyval; + } - /// Only call firstVal() and setFirstVal() on objects in yyitems, not - /// temporaries. - semantic_option* firstVal (); - const semantic_option* firstVal () const; - void setFirstVal (const semantic_option* option); + const value_type& value () const + {]b4_parse_assert_if([[ + check_ ();]])[ + return yyval; + } - value_type& value () - {]b4_parse_assert_if([[ - check_ ();]])[ - return yyval; - } + void + destroy (char const *yymsg, ]b4_namespace_ref[::]b4_parser_class[& yyparser]b4_user_formals[); - const value_type& value () const - {]b4_parse_assert_if([[ - check_ ();]])[ - return yyval; - } + /* DEBUGGING ONLY */ + #if ]b4_api_PREFIX[DEBUG + void yy_yypstack () const + {]b4_parse_assert_if([[ + check_ ();]])[ + if (pred () != YY_NULLPTR) + { + pred ()->yy_yypstack (); + std::cerr << " -> "; + } + std::cerr << yylrState << "@@" << yyposn; + } + #endif - void - destroy (char const *yymsg, ]b4_namespace_ref[::]b4_parser_class[& yyparser]b4_user_formals[); + std::ptrdiff_t indexIn (const glr_stack_item* array) const; - /* DEBUGGING ONLY */ -#if ]b4_api_PREFIX[DEBUG - void yy_yypstack () const - {]b4_parse_assert_if([[ - check_ ();]])[ - if (pred () != YY_NULLPTR) - { - pred ()->yy_yypstack (); - std::cerr << " -> "; - } - std::cerr << yylrState << "@@" << yyposn; - } -#endif + glr_stack_item* asItem () + {]b4_parse_assert_if([[ + check_ ();]])[ + return asItem(this); + } - std::ptrdiff_t indexIn (const glr_stack_item* array) const; + const glr_stack_item* asItem () const + {]b4_parse_assert_if([[ + check_ ();]])[ + return asItem (this); + } - glr_stack_item* asItem () - {]b4_parse_assert_if([[ - check_ ();]])[ - return asItem(this); - } + private: + template + static const glr_stack_item* asItem (const T* state) + { + return reinterpret_cast(state); + } + template + static glr_stack_item* asItem (T* state) + { + return reinterpret_cast (state); + } + static const char *as_pointer_ (const glr_state *state) + { + return reinterpret_cast (state); + } + static char *as_pointer_ (glr_state *state) + { + return reinterpret_cast (state); + } + /** Preceding state in this stack */ + std::ptrdiff_t yypred; + union { + /** First in a chain of alternative reductions producing the + * nonterminal corresponding to this state, threaded through + * yyfirstVal. Value "0" means empty. */ + std::ptrdiff_t yyfirstVal; + /** Semantic value for this state. */ + value_type yyval; + };]b4_locations_if([[ + // FIXME: Why public? + public: + /** Source location for this state. */ + location_type yyloc;]])[ - const glr_stack_item* asItem () const - {]b4_parse_assert_if([[ - check_ ();]])[ - return asItem (this); - } + ]b4_parse_assert_if([[ + public: + // Check invariants. + void check_ () const + { + YY_IGNORE_NULL_DEREFERENCE_BEGIN + YYASSERT (this->magic_ == MAGIC); + YY_IGNORE_NULL_DEREFERENCE_END + } -private: - template - static const glr_stack_item* asItem (const T* state) - { - return reinterpret_cast(state); - } - template - static glr_stack_item* asItem (T* state) - { - return reinterpret_cast (state); - } - static const char *as_pointer_ (const glr_state *state) - { - return reinterpret_cast (state); - } - static char *as_pointer_ (glr_state *state) - { - return reinterpret_cast (state); - } - /** Preceding state in this stack */ - std::ptrdiff_t yypred; - union { - /** First in a chain of alternative reductions producing the - * nonterminal corresponding to this state, threaded through - * yyfirstVal. Value "0" means empty. */ - std::ptrdiff_t yyfirstVal; - /** Semantic value for this state. */ - value_type yyval; - };]b4_locations_if([[ - // FIXME: Why public? - public: - /** Source location for this state. */ - location_type yyloc;]])[ + // A magic number to check our pointer arithmetic is sane. + enum { MAGIC = 713705 }; + unsigned int magic_;]])[ + }; +} // namespace ]b4_namespace_ref[ -]b4_parse_assert_if([[ -public: - // Check invariants. - void check_ () const - { - YY_IGNORE_NULL_DEREFERENCE_BEGIN - YYASSERT (this->magic_ == MAGIC); - YY_IGNORE_NULL_DEREFERENCE_END - } - - // A magic number to check our pointer arithmetic is sane. - enum { MAGIC = 713705 }; - unsigned int magic_;]])[ -}; /** A stack of GLRState representing the different heads during * nondeterministic evaluation. */ @@ -2073,1151 +2077,1153 @@ public: #undef YYFILL #define YYFILL(N) yystateStack.yyfill (yyvsp, yylow, (N), yynormal) -class glr_stack +namespace ]b4_namespace_ref[ { -public: - typedef ]b4_namespace_ref[::]b4_parser_class[ parser_type; - typedef parser_type::symbol_kind symbol_kind; - typedef parser_type::symbol_kind_type symbol_kind_type; - typedef parser_type::symbol_type symbol_type; - typedef parser_type::value_type value_type;]b4_locations_if([[ - typedef parser_type::location_type location_type;]])[ - -]b4_parse_error_bmatch([custom\|detailed\|verbose], [[ - typedef parser_type::context context; - // Needs access to yypact_value_is_default, etc. - friend context; -]])[ - - glr_stack (size_t yysize, ]b4_namespace_ref[::]b4_parser_class[& yyparser_yyarg]m4_ifset([b4_parse_param], [, b4_parse_param_decl])[) - : yyerrState (0) - , yystateStack (yysize) - , yyerrcnt (0) - , yyla () - , yyparser (yyparser_yyarg)]m4_ifset([b4_parse_param], [,b4_parse_param_cons])[ - {} - - ~glr_stack () + class ]b4_parser_class[::glr_stack { - if (!this->yyla.empty ()) - yyparser.yy_destroy_ ("Cleanup: discarding lookahead", - this->yyla.kind (), this->yyla.value]b4_locations_if([, this->yyla.location])[); - popall_ (); - } + public: + typedef ]b4_namespace_ref[::]b4_parser_class[ parser_type; + typedef parser_type::symbol_kind symbol_kind; + typedef parser_type::symbol_kind_type symbol_kind_type; + typedef parser_type::symbol_type symbol_type; + typedef parser_type::value_type value_type;]b4_locations_if([[ + typedef parser_type::location_type location_type;]])[ - int yyerrState; -]b4_locations_if([[ /* To compute the location of the error token. */ - glr_stack_item yyerror_range[3];]])[ - state_stack yystateStack; - int yyerrcnt; - symbol_type yyla; - YYJMP_BUF yyexception_buffer; - ]b4_namespace_ref[::]b4_parser_class[& yyparser; + ]b4_parse_error_bmatch([custom\|detailed\|verbose], [[ + typedef parser_type::context context; + // Needs access to yypact_value_is_default, etc. + friend context; + ]])[ -#define YYCHK1(YYE) \ - do { \ - switch (YYE) { \ - case yyok: \ - break; \ - case yyabort: \ - goto yyabortlab; \ - case yyaccept: \ - goto yyacceptlab; \ - case yyerr: \ - goto yyuser_error; \ - default: \ - goto yybuglab; \ - } \ - } while (false) + glr_stack (size_t yysize, ]b4_namespace_ref[::]b4_parser_class[& yyparser_yyarg]m4_ifset([b4_parse_param], [, b4_parse_param_decl])[) + : yyerrState (0) + , yystateStack (yysize) + , yyerrcnt (0) + , yyla () + , yyparser (yyparser_yyarg)]m4_ifset([b4_parse_param], [,b4_parse_param_cons])[ + {} - int - parse () - { - int yyresult; - size_t yyposn; + ~glr_stack () + { + if (!this->yyla.empty ()) + yyparser.yy_destroy_ ("Cleanup: discarding lookahead", + this->yyla.kind (), this->yyla.value]b4_locations_if([, this->yyla.location])[); + popall_ (); + } - YYCDEBUG << "Starting parse\n"; + int yyerrState; + ]b4_locations_if([[ /* To compute the location of the error token. */ + glr_stack_item yyerror_range[3];]])[ + state_stack yystateStack; + int yyerrcnt; + symbol_type yyla; + YYJMP_BUF yyexception_buffer; + ]b4_namespace_ref[::]b4_parser_class[& yyparser; - this->yyla.clear (); -]m4_ifdef([b4_initial_action], [ -b4_dollar_pushdef([yyla.value], [], [], [yyla.location])dnl - b4_user_initial_action -b4_dollar_popdef])[]dnl -[ - switch (YYSETJMP (this->yyexception_buffer)) - { - case 0: break; - case 1: goto yyabortlab; - case 2: goto yyexhaustedlab; - default: goto yybuglab; - } - this->yyglrShift (create_state_set_index(0), 0, 0, this->yyla.value]b4_locations_if([, this->yyla.location])[); - yyposn = 0; + #define YYCHK1(YYE) \ + do { \ + switch (YYE) { \ + case yyok: \ + break; \ + case yyabort: \ + goto yyabortlab; \ + case yyaccept: \ + goto yyacceptlab; \ + case yyerr: \ + goto yyuser_error; \ + default: \ + goto yybuglab; \ + } \ + } while (false) - 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 = this->firstTopState()->yylrState; - YYCDEBUG << "Entering state " << yystate << '\n'; - if (yystate == YYFINAL) - goto yyacceptlab; - if (yy_is_defaulted_state (yystate)) - { - const rule_num yyrule = yy_default_action (yystate); - if (yyrule == 0) - {]b4_locations_if([[ - this->yyerror_range[1].getState().yyloc = this->yyla.location;]])[ - this->yyreportSyntaxError (); - goto yyuser_error; - } - YYCHK1 (this->yyglrReduce (create_state_set_index(0), yyrule, true)); - } - else - { - yyget_token (); - const short* yyconflicts; - const int yyaction = yygetLRActions (yystate, this->yyla.kind (), yyconflicts); - if (*yyconflicts != 0) - break; - if (yy_is_shift_action (yyaction)) - { - YY_SYMBOL_PRINT ("Shifting", this->yyla.kind (), this->yyla.value, this->yyla.location); - yyposn += 1; - // FIXME: we should move yylval. - this->yyglrShift (create_state_set_index(0), yyaction, yyposn, this->yyla.value]b4_locations_if([, this->yyla.location])[); - yyla.clear (); - if (0 < this->yyerrState) - this->yyerrState -= 1; - } - else if (yy_is_error_action (yyaction)) - {]b4_locations_if([[ - this->yyerror_range[1].getState().yyloc = this->yyla.location;]])[ - /* Don't issue an error message again for exceptions - thrown from the scanner. */ - if (this->yyla.kind () != ]b4_symbol(error, kind)[) - this->yyreportSyntaxError (); - goto yyuser_error; - } - else - YYCHK1 (this->yyglrReduce (create_state_set_index(0), -yyaction, true)); - } - } + int + parse () + { + int yyresult; + size_t yyposn; - while (true) - { - for (state_set_index yys = create_state_set_index(0); yys.uget() < this->yystateStack.numTops(); ++yys) - this->yystateStack.yytops.setLookaheadNeeds(yys, !this->yyla.empty ()); + YYCDEBUG << "Starting parse\n"; - /* yyprocessOneStack returns one of three things: + this->yyla.clear (); + ]m4_ifdef([b4_initial_action], [ + b4_dollar_pushdef([yyla.value], [], [], [yyla.location])dnl + b4_user_initial_action + b4_dollar_popdef])[]dnl + [ + switch (YYSETJMP (this->yyexception_buffer)) + { + case 0: break; + case 1: goto yyabortlab; + case 2: goto yyexhaustedlab; + default: goto yybuglab; + } + this->yyglrShift (create_state_set_index(0), 0, 0, this->yyla.value]b4_locations_if([, this->yyla.location])[); + yyposn = 0; - - 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 () < this->yystateStack.numTops (); ++yys) - YYCHK1 (this->yyprocessOneStack (yys, yyposn]b4_locations_if([, &this->yyla.location])[)); - this->yystateStack.yytops.yyremoveDeletes (); - if (this->yystateStack.yytops.size() == 0) - { - this->yystateStack.yytops.yyundeleteLastStack (); - if (this->yystateStack.yytops.size() == 0) - this->yyFail (]b4_locations_if([&this->yyla.location, ])[YY_("syntax error")); - YYCHK1 (this->yyresolveStack ()); - YYCDEBUG << "Returning to deterministic operation.\n";]b4_locations_if([[ - this->yyerror_range[1].getState ().yyloc = this->yyla.location;]])[ - this->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, yyla is emptied - before the loop to make sure the user destructor for yylval isn't - called twice. */ - yysymbol_kind_t yytoken_to_shift = this->yyla.kind (); - this->yyla.kind_ = ]b4_symbol(empty, kind)[; - yyposn += 1; - for (state_set_index yys = create_state_set_index (0); yys.uget () < this->yystateStack.numTops (); ++yys) - { - const state_num yystate = this->topState (yys)->yylrState; - const short* yyconflicts; - const int yyaction = yygetLRActions (yystate, yytoken_to_shift, yyconflicts); - /* Note that yyconflicts were handled by yyprocessOneStack. */ - YYCDEBUG << "On stack " << yys.get() << ", "; - YY_SYMBOL_PRINT ("shifting", yytoken_to_shift, this->yyla.value, this->yyla.location); - this->yyglrShift (yys, yyaction, yyposn, this->yyla.value]b4_locations_if([, this->yyla.location])[); - YYCDEBUG << "Stack " << yys.get() << " now in state " - << this->topState(yys)->yylrState << '\n'; - } -]b4_variant_if([[ - // FIXME: User destructors. - // Value type destructor. - ]b4_symbol_variant([[yytoken_to_shift]], [[this->yyla.value]], [[template destroy]])])[ - - if (this->yystateStack.yytops.size () == 1) - { - YYCHK1 (this->yyresolveStack ()); - YYCDEBUG << "Returning to deterministic operation.\n"; - this->yystateStack.yycompressStack (); - break; - } - } - continue; - yyuser_error: - this->yyrecoverSyntaxError (]b4_locations_if([&this->yyla.location])[); - yyposn = this->firstTopState()->yyposn; - } - - yyacceptlab: - yyresult = 0; - goto yyreturn; - - yybuglab: - YYASSERT (false); - goto yyabortlab; - - yyabortlab: - yyresult = 1; - goto yyreturn; - - yyexhaustedlab: - yyparser.error (]b4_locations_if([this->yyla.location, ])[YY_("memory exhausted")); - yyresult = 2; - goto yyreturn; - - yyreturn: - return yyresult; - } -#undef YYCHK1 - - void yyreserveGlrStack () - { - if (!yystateStack.yyexpandGLRStackIfNeeded ()) - yyMemoryExhausted (); - } - - _Noreturn void - yyMemoryExhausted () - { - YYLONGJMP (yyexception_buffer, 2); - } - - _Noreturn void - yyFail (]b4_locations_if([location_type* yylocp, ])[const char* yymsg) - { - if (yymsg != YY_NULLPTR) - yyparser.error (]b4_locations_if([*yylocp, ])[yymsg); - YYLONGJMP (yyexception_buffer, 1); - } - - /* GLRStates */ - - - /** Add a new semantic action that will execute the action for rule - * YYRULE on the semantic values in YYRHS to the list of - * alternative actions for YYSTATE. Assumes that YYRHS comes from - * stack #YYK of *this. */ - void - yyaddDeferredAction (state_set_index yyk, glr_state* yystate, - glr_state* yyrhs, rule_num yyrule) - { - semantic_option& yynewOption = - yystateStack.yynewSemanticOption(semantic_option(yyrule, ]b4_symbol(empty, kind)[)); - yynewOption.setState(yyrhs); - yynewOption.setNext(yystate->firstVal()); - if (yystateStack.yytops.lookaheadNeeds(yyk)) - { - yynewOption.yytoken = this->yyla.kind ();]b4_variant_if([[ - ]b4_symbol_variant([this->yyla.kind ()], - [yynewOption.yyval], [copy], [this->yyla.value])], [[ - yynewOption.yyval = this->yyla.value;]])[]b4_locations_if([ - yynewOption.yyloc = this->yyla.location;])[ - } - yystate->setFirstVal (&yynewOption); - - yyreserveGlrStack (); - } - -#if ]b4_api_PREFIX[DEBUG - void yypdumpstack () const - { - yystateStack.dumpStack(); - } -#endif - - void - yyreportSyntaxError () - { - if (yyerrState != 0) - return; -]b4_parse_error_case( -[simple], [[ - std::string msg = YY_("syntax error"); - yyparser.error (]b4_join(b4_locations_if([yyla.location]), [[YY_MOVE (msg)]])[);]], -[custom], [[ - context yyctx (*this, yyla); - yyparser.report_syntax_error (yyctx);]], -[[ - context yyctx (*this, yyla); - std::string msg = yyparser.yysyntax_error_ (yyctx); - yyparser.error (]b4_join(b4_locations_if([yyla.location]), [[YY_MOVE (msg)]])[);]])[ - yyerrcnt += 1; - } - - /* Recover from a syntax error on this, assuming that yytoken, - yylval, and yylloc are the syntactic category, semantic value, and location - of the lookahead. */ - void - yyrecoverSyntaxError (]b4_locations_if([location_type* yylocp])[) - { - if (yyerrState == 3) - /* We just shifted the error token and (perhaps) took some - reductions. Skip tokens until we can proceed. */ while (true) { - if (this->yyla.kind () == ]b4_symbol(eof, kind)[) - yyFail (]b4_locations_if([yylocp, ])[YY_NULLPTR); - if (this->yyla.kind () != ]b4_symbol(empty, kind)[) - {]b4_locations_if([[ - /* We throw away the lookahead, but the error range - of the shifted error token must take it into account. */ - glr_state *yys = firstTopState(); - yyerror_range[1].getState().yyloc = yys->yyloc; - yyerror_range[2].getState().yyloc = this->yyla.location; - YYLLOC_DEFAULT ((yys->yyloc), yyerror_range, 2);]])[ - yyparser.yy_destroy_ ("Error: discarding", - this->yyla.kind (), this->yyla.value]b4_locations_if([, this->yyla.location])[);]b4_variant_if([[ - // Value type destructor. - ]b4_symbol_variant([[this->yyla.kind ()]], [[this->yyla.value]], [[template destroy]])])[ - this->yyla.kind_ = ]b4_symbol(empty, kind)[; - } - yyget_token (); - int yyj = yypact[firstTopState()->yylrState]; - if (yypact_value_is_default (yyj)) - return; - yyj += this->yyla.kind (); - if (yyj < 0 || YYLAST < yyj || yycheck[yyj] != this->yyla.kind ()) + /* For efficiency, we have two loops, the first of which is + specialized to deterministic operation (single stack, no + potential ambiguity). */ + /* Standard mode */ + while (true) { - if (yydefact[firstTopState()->yylrState] != 0) - return; - } - else if (! yytable_value_is_error (yytable[yyj])) - return; - } - - if (!yystateStack.reduceToOneStack()) - yyFail (]b4_locations_if([yylocp, ])[YY_NULLPTR); - - /* Now pop stack until we find a state that shifts the error token. */ - yyerrState = 3; - while (firstTopState () != YY_NULLPTR) - { - glr_state *yys = firstTopState (); - int yyj = yypact[yys->yylrState]; - if (! yypact_value_is_default (yyj)) - { - yyj += YYTERROR; - if (0 <= yyj && yyj <= YYLAST && yycheck[yyj] == YYTERROR - && yy_is_shift_action (yytable[yyj])) - { - /* Shift the error token. */]b4_locations_if([[ - /* First adjust its location.*/ - location_type yyerrloc; - yyerror_range[2].getState().yyloc = this->yyla.location; - YYLLOC_DEFAULT (yyerrloc, (yyerror_range), 2);]])[ - YY_SYMBOL_PRINT ("Shifting", yy_accessing_symbol (yytable[yyj]), - this->yyla.value, yyerrloc); - yyglrShift (create_state_set_index(0), yytable[yyj], - yys->yyposn, yyla.value]b4_locations_if([, yyerrloc])[); - yys = firstTopState(); - break; - } - }]b4_locations_if([[ - yyerror_range[1].getState().yyloc = yys->yyloc;]])[ - if (yys->pred() != YY_NULLPTR) - yys->destroy ("Error: popping", yyparser]b4_user_args[); - yystateStack.setFirstTop(yys->pred()); - yystateStack.pop_back(); - } - if (firstTopState() == YY_NULLPTR) - yyFail (]b4_locations_if([yylocp, ])[YY_NULLPTR); - } - - YYRESULTTAG - yyprocessOneStack (state_set_index yyk, - size_t yyposn]b4_locations_if([, location_type* yylocp])[) - { - while (yystateStack.topAt(yyk) != YY_NULLPTR) - { - const state_num yystate = topState(yyk)->yylrState; - YYCDEBUG << "Stack " << yyk.get() - << " Entering state " << yystate << '\n'; - - YYASSERT (yystate != YYFINAL); - - if (yy_is_defaulted_state (yystate)) - { - const rule_num yyrule = yy_default_action (yystate); - if (yyrule == 0) - { - YYCDEBUG << "Stack " << yyk.get() << " dies.\n"; - yystateStack.yytops.yymarkStackDeleted (yyk); - return yyok; - } - const YYRESULTTAG yyflag - = yyglrReduce (yyk, yyrule, yyimmediate[yyrule]); - if (yyflag == yyerr) - { - YYCDEBUG << "Stack " << yyk.get() << " dies" - " (predicate failure or explicit user error).\n"; - yystateStack.yytops.yymarkStackDeleted (yyk); - return yyok; - } - if (yyflag != yyok) - return yyflag; - } - else - { - yystateStack.yytops.setLookaheadNeeds(yyk, true); - yyget_token (); - const short* yyconflicts; - const int yyaction = yygetLRActions (yystate, this->yyla.kind (), yyconflicts); - - for (; *yyconflicts != 0; ++yyconflicts) - { - state_set_index yynewStack = yystateStack.yysplitStack (yyk); - YYCDEBUG << "Splitting off stack " << yynewStack.get() - << " from " << yyk.get() << ".\n"; - YYRESULTTAG yyflag = - yyglrReduce (yynewStack, *yyconflicts, yyimmediate[*yyconflicts]); - if (yyflag == yyok) - YYCHK (yyprocessOneStack (yynewStack, - yyposn]b4_locations_if([, yylocp])[)); - else if (yyflag == yyerr) - { - YYCDEBUG << "Stack " << yynewStack.get() << " dies.\n"; - yystateStack.yytops.yymarkStackDeleted (yynewStack); - } - else - return yyflag; - } - - if (yy_is_shift_action (yyaction)) - break; - else if (yy_is_error_action (yyaction)) - { - YYCDEBUG << "Stack " << yyk.get() << " dies.\n"; - yystateStack.yytops.yymarkStackDeleted (yyk); - break; - } - else - { - YYRESULTTAG yyflag - = yyglrReduce (yyk, -yyaction, yyimmediate[-yyaction]); - if (yyflag == yyerr) - { - YYCDEBUG << "Stack " << yyk.get() << " dies" - " (predicate failure or explicit user error).\n"; - yystateStack.yytops.yymarkStackDeleted (yyk); - break; - } - else if (yyflag != yyok) - return yyflag; - } - } - } - return yyok; - } - - /** Perform user action for rule number YYN, with RHS length YYRHSLEN, - * and top stack item YYVSP. YYVALP points to place to put semantic - * value ($$), and yylocp points to place for location information - * (@@$). Returns yyok for normal return, yyaccept for YYACCEPT, - * yyerr for YYERROR, yyabort for YYABORT. */ - YYRESULTTAG - yyuserAction (rule_num yyrule, int yyrhslen, glr_stack_item* yyvsp, state_set_index yyk, - value_type* yyvalp]b4_locations_if([, location_type* yylocp])[) - { - bool yynormal YY_ATTRIBUTE_UNUSED = !yystateStack.isSplit(); - int yylow = 1; - ]b4_parse_param_use([yyvalp], [yylocp])dnl - [ YY_USE (yyk); - YY_USE (yyrhslen); - # undef yyerrok - # define yyerrok (yyerrState = 0) - # undef YYACCEPT - # define YYACCEPT return yyaccept - # undef YYABORT - # define YYABORT return yyabort - # undef YYERROR - # define YYERROR return yyerrok, yyerr - # undef YYRECOVERING - # define YYRECOVERING() (yyerrState != 0) - # undef yytoken - # define yytoken this->yyla.kind_ - # undef yyclearin - # define yyclearin (yytoken = ]b4_symbol(empty, kind)[) - # undef YYBACKUP - # define YYBACKUP(Token, Value) \ - return yyparser.error (]b4_locations_if([*yylocp, ])[YY_("syntax error: cannot back up")), \ - yyerrok, yyerr - -]b4_variant_if([[ - /* Variants are always initialized to an empty instance of the - correct type. The default '$$ = $1' action is NOT applied - when using variants. */ - // However we really need to prepare yyvsp now if we want to get - // correct locations, so invoke YYFILL for $1 anyway. - (void) YYFILL (1-yyrhslen); - ]b4_symbol_variant([[yylhsNonterm (yyrule)]], [(*yyvalp)], [emplace])], [[ - if (yyrhslen == 0) - *yyvalp = yyval_default; - else - *yyvalp = yyvsp[YYFILL (1-yyrhslen)].getState().value ();]])[]b4_locations_if([[ - /* Default location. */ - YYLLOC_DEFAULT ((*yylocp), (yyvsp - yyrhslen), yyrhslen); - yyerror_range[1].getState().yyloc = *yylocp; -]])[ - /* If yyk == -1, we are running a deferred action on a temporary - stack. In that case, YY_REDUCE_PRINT must not play with YYFILL, - so pretend the stack is "normal". */ - YY_REDUCE_PRINT ((yynormal || yyk == create_state_set_index (-1), yyvsp, yyk, yyrule, yyparser)); - #if YY_EXCEPTIONS - typedef ]b4_namespace_ref[::]b4_parser_class[::syntax_error syntax_error; - try - { - #endif // YY_EXCEPTIONS - switch (yyrule) - { - ]b4_user_actions[ - default: break; - } - #if YY_EXCEPTIONS - } - catch (const syntax_error& yyexc) - { - YYCDEBUG << "Caught exception: " << yyexc.what() << '\n';]b4_locations_if([ - *yylocp = yyexc.location;])[ - yyparser.error (]b4_locations_if([*yylocp, ])[yyexc.what ()); - YYERROR; - } - #endif // YY_EXCEPTIONS - YY_SYMBOL_PRINT ("-> $$ =", yylhsNonterm (yyrule), *yyvalp, *yylocp); - - return yyok; - # undef yyerrok - # undef YYABORT - # undef YYACCEPT - # undef YYERROR - # undef YYBACKUP - # undef yytoken - # undef yyclearin - # undef YYRECOVERING - } - - YYRESULTTAG - yyresolveStack () - { - if (yystateStack.isSplit ()) - { - int yyn = 0; - for (glr_state* yys = firstTopState (); - yys != yystateStack.yysplitPoint; - yys = yys->pred ()) - yyn += 1; - YYCHK (yyresolveStates (*firstTopState (), yyn)); - } - return yyok; - } - - /** Pop the symbols consumed by reduction #YYRULE from the top of stack - * #YYK of *YYSTACKP, and perform the appropriate semantic action on their - * semantic values. Assumes that all ambiguities in semantic values - * have been previously resolved. Set *YYVALP to the resulting value, - * and *YYLOCP to the computed location (if any). Return value is as - * for userAction. */ - YYRESULTTAG - yydoAction (state_set_index yyk, rule_num yyrule, - value_type* yyvalp]b4_locations_if([, location_type* yylocp])[) - { - const int yynrhs = yyrhsLength (yyrule); - - if (!yystateStack.isSplit()) - { - /* Standard special case: single stack. */ - YYASSERT (yyk.get() == 0); - glr_stack_item* yyrhs = yystateStack.firstTop()->asItem(); - const YYRESULTTAG res - = yyuserAction (yyrule, yynrhs, yyrhs, yyk, yyvalp]b4_locations_if([, yylocp])[); - yystateStack.pop_back(static_cast(yynrhs)); - yystateStack.setFirstTop(&yystateStack[yystateStack.size() - 1].getState()); - return res; - } - else - { - glr_stack_item yyrhsVals[YYMAXRHS + YYMAXLEFT + 1]; - glr_state* yys = yystateStack.topAt(yyk); - yyrhsVals[YYMAXRHS + YYMAXLEFT].getState().setPred(yys);]b4_locations_if([[ - if (yynrhs == 0) - /* Set default location. */ - yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].getState().yyloc = yys->yyloc;]])[ - for (int yyi = 0; yyi < yynrhs; yyi += 1) - { - yys = yys->pred(); - YYASSERT (yys != YY_NULLPTR); - } - yystateStack.yyupdateSplit (*yys); - yystateStack.setTopAt(yyk, yys); - return yyuserAction (yyrule, yynrhs, yyrhsVals + YYMAXRHS + YYMAXLEFT - 1, - yyk, - yyvalp]b4_locations_if([, yylocp])[); - } - } - - /** Pop items off stack #YYK of *YYSTACKP according to grammar rule YYRULE, - * and push back on the resulting nonterminal symbol. Perform the - * semantic action associated with YYRULE and store its value with the - * newly pushed state, if YYFORCEEVAL or if *YYSTACKP is currently - * unambiguous. Otherwise, store the deferred semantic action with - * the new state. If the new state would have an identical input - * position, LR state, and predecessor to an existing state on the stack, - * it is identified with that existing state, eliminating stack #YYK from - * *YYSTACKP. In this case, the semantic value is - * added to the options for the existing state's semantic value. - */ - YYRESULTTAG - yyglrReduce (state_set_index yyk, rule_num yyrule, bool yyforceEval) - { - size_t yyposn = topState(yyk)->yyposn; - - if (yyforceEval || !yystateStack.isSplit()) - { - value_type val;]b4_locations_if([[ - location_type loc;]])[ - - YYRESULTTAG yyflag = yydoAction (yyk, yyrule, &val]b4_locations_if([, &loc])[); - if (yyflag == yyerr && yystateStack.isSplit()) - {]b4_parse_trace_if([[ - YYCDEBUG << "Parse on stack " << yyk.get () - << " rejected by rule " << yyrule - 1 - << " (line " << int (yyrline[yyrule]) << ").\n"; - ]])[} - if (yyflag != yyok) - return yyflag; - yyglrShift (yyk, - yyLRgotoState (topState(yyk)->yylrState, - yylhsNonterm (yyrule)), - yyposn, val]b4_locations_if([, loc])[);]b4_variant_if([[ - // FIXME: User destructors. - // Value type destructor. - ]b4_symbol_variant([[yylhsNonterm (yyrule)]], [[val]], [[template destroy]])])[ - } - else - { - glr_state *yys = yystateStack.topAt(yyk); - glr_state *yys0 = yys; - for (int yyn = yyrhsLength (yyrule); 0 < yyn; yyn -= 1) - { - yys = yys->pred(); - YYASSERT (yys != YY_NULLPTR); - } - yystateStack.yyupdateSplit (*yys); - state_num yynewLRState = yyLRgotoState (yys->yylrState, yylhsNonterm (yyrule));]b4_parse_trace_if([[ - YYCDEBUG << "Reduced stack " << yyk.get () - << " by rule " << yyrule - 1 << " (line " << int (yyrline[yyrule]) - << "); action deferred. Now in state " << yynewLRState - << ".\n";]])[ - for (state_set_index yyi = create_state_set_index(0); yyi.uget() < yystateStack.numTops(); ++yyi) - if (yyi != yyk && yystateStack.topAt(yyi) != YY_NULLPTR) - { - const glr_state* yysplit = yystateStack.yysplitPoint; - glr_state* yyp = yystateStack.topAt(yyi); - while (yyp != yys && yyp != yysplit - && yyp->yyposn >= yyposn) + const state_num yystate = this->firstTopState()->yylrState; + YYCDEBUG << "Entering state " << yystate << '\n'; + if (yystate == YYFINAL) + goto yyacceptlab; + if (yy_is_defaulted_state (yystate)) { - if (yyp->yylrState == yynewLRState - && yyp->pred() == yys) - { - yyaddDeferredAction (yyk, yyp, yys0, yyrule); - yystateStack.yytops.yymarkStackDeleted (yyk); - YYCDEBUG << "Merging stack " << yyk.get () - << " into stack " << yyi.get () << ".\n"; - return yyok; + const rule_num yyrule = yy_default_action (yystate); + if (yyrule == 0) + {]b4_locations_if([[ + this->yyerror_range[1].getState().yyloc = this->yyla.location;]])[ + this->yyreportSyntaxError (); + goto yyuser_error; } - yyp = yyp->pred(); + YYCHK1 (this->yyglrReduce (create_state_set_index(0), yyrule, true)); + } + else + { + yyget_token (); + const short* yyconflicts; + const int yyaction = yygetLRActions (yystate, this->yyla.kind (), yyconflicts); + if (*yyconflicts != 0) + break; + if (yy_is_shift_action (yyaction)) + { + YY_SYMBOL_PRINT ("Shifting", this->yyla.kind (), this->yyla.value, this->yyla.location); + yyposn += 1; + // FIXME: we should move yylval. + this->yyglrShift (create_state_set_index(0), yyaction, yyposn, this->yyla.value]b4_locations_if([, this->yyla.location])[); + yyla.clear (); + if (0 < this->yyerrState) + this->yyerrState -= 1; + } + else if (yy_is_error_action (yyaction)) + {]b4_locations_if([[ + this->yyerror_range[1].getState().yyloc = this->yyla.location;]])[ + /* Don't issue an error message again for exceptions + thrown from the scanner. */ + if (this->yyla.kind () != ]b4_symbol(error, kind)[) + this->yyreportSyntaxError (); + goto yyuser_error; + } + else + YYCHK1 (this->yyglrReduce (create_state_set_index(0), -yyaction, true)); } } - yystateStack.setTopAt(yyk, yys); - yyglrShiftDefer (yyk, yynewLRState, yyposn, yys0, yyrule); - } - return yyok; - } - /** Shift stack #YYK of *YYSTACKP, to a new state corresponding to LR - * state YYLRSTATE, at input position YYPOSN, with the (unresolved) - * semantic value of YYRHS under the action for YYRULE. */ - void - yyglrShiftDefer (state_set_index yyk, state_num yylrState, - size_t yyposn, glr_state* yyrhs, rule_num yyrule) - { - glr_state& yynewState = yystateStack.yynewGLRState ( - glr_state (yylrState, yyposn)); - yynewState.setPred (yystateStack.topAt (yyk)); - yystateStack.setTopAt (yyk, &yynewState); - - /* Invokes yyreserveStack. */ - yyaddDeferredAction (yyk, &yynewState, yyrhs, yyrule); - } - - /** Shift to a new state on stack #YYK of *YYSTACKP, corresponding to LR - * state YYLRSTATE, at input position YYPOSN, with (resolved) semantic - * value YYVAL_ARG and source location YYLOC_ARG. */ - void - yyglrShift (state_set_index yyk, state_num yylrState, - size_t yyposn, - const value_type& yyval_arg]b4_locations_if([, const location_type& yyloc_arg])[) - { - glr_state& yynewState = yystateStack.yynewGLRState ( - glr_state (yylrState, yyposn, yyval_arg]b4_locations_if([, yyloc_arg])[)); - yynewState.setPred (yystateStack.topAt(yyk)); - yystateStack.setTopAt (yyk, &yynewState); - yyreserveGlrStack (); - } - -#if ]b4_api_PREFIX[DEBUG - void - yypstack (state_set_index yyk) const - { - yystateStack.yypstates (yystateStack.topAt (yyk)); - } -#endif - - glr_state* topState(state_set_index i) { - return yystateStack.topAt(i); - } - - glr_state* firstTopState() { - return yystateStack.firstTop(); - } - -private: - - void popall_ () - { - /* If the stack is well-formed, pop the stack until it is empty, - destroying its entries as we go. But free the stack regardless - of whether it is well-formed. */ - for (state_set_index k = create_state_set_index(0); k.uget() < yystateStack.numTops(); k += 1) - if (yystateStack.topAt(k) != YY_NULLPTR) - { - while (yystateStack.topAt(k) != YY_NULLPTR) + while (true) { - glr_state* state = topState(k);]b4_locations_if([[ - yyerror_range[1].getState().yyloc = state->yyloc;]])[ - if (state->pred() != YY_NULLPTR) - state->destroy ("Cleanup: popping", yyparser]b4_user_args[); - yystateStack.setTopAt(k, state->pred()); - yystateStack.pop_back(); - } - break; - } - } + for (state_set_index yys = create_state_set_index(0); yys.uget() < this->yystateStack.numTops(); ++yys) + this->yystateStack.yytops.setLookaheadNeeds(yys, !this->yyla.empty ()); - /** Resolve the previous YYN states starting at and including state YYS - * on *YYSTACKP. If result != yyok, some states may have been left - * unresolved possibly with empty semantic option chains. Regardless - * of whether result = yyok, each state has been left with consistent - * data so that destroy can be invoked if necessary. */ - YYRESULTTAG - yyresolveStates (glr_state& yys, int yyn) - { - if (0 < yyn) - { - YYASSERT (yys.pred() != YY_NULLPTR); - YYCHK (yyresolveStates (*yys.pred(), yyn-1)); - if (! yys.yyresolved) - YYCHK (yyresolveValue (yys)); - } - return yyok; - } + /* yyprocessOneStack returns one of three things: - static void - yyuserMerge (int yyn, value_type& yy0, value_type& yy1) - { - YY_USE (yy0); - YY_USE (yy1); + - 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. - switch (yyn) - { -]b4_mergers[ - default: break; - } - } + - 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. - /** Resolve the ambiguity represented in state YYS in *YYSTACKP, - * perform the indicated actions, and set the semantic value of YYS. - * If result != yyok, the chain of semantic options in YYS has been - * cleared instead or it has been left unmodified except that - * redundant options may have been removed. Regardless of whether - * result = yyok, YYS has been left with consistent data so that - * destroy can be invoked if necessary. */ - YYRESULTTAG - yyresolveValue (glr_state& yys) - { - semantic_option* yybest = yys.firstVal(); - YYASSERT(yybest != YY_NULLPTR); - bool yymerge = false; - YYRESULTTAG yyflag;]b4_locations_if([ - location_type *yylocp = &yys.yyloc;])[ + - yyok, when ready to shift a token. - semantic_option* yypPrev = yybest; - for (semantic_option* yyp = yybest->next(); - yyp != YY_NULLPTR; ) - { - if (yybest->isIdenticalTo (*yyp)) - { - yybest->mergeWith (*yyp); - yypPrev->setNext(yyp->next()); - yyp = yypPrev->next(); - } - else - { - switch (yypreference (*yybest, *yyp)) - { - case 0:]b4_locations_if([[ - yyresolveLocations (yys, 1);]])[ - return yystateStack.yyreportAmbiguity (*yybest, *yyp, yyparser]b4_locations_if([, *yylocp])[); - break; - case 1: - yymerge = true; - break; - case 2: - break; - case 3: - yybest = yyp; - yymerge = false; - break; - default: - /* This cannot happen so it is not worth a YYASSERT (false), - but some compilers complain if the default case is - omitted. */ - break; - } - yypPrev = yyp; - yyp = yyp->next(); - } - } + 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. */ - value_type val; - if (yymerge) - { - int yyprec = yydprec[yybest->yyrule]; - yyflag = yyresolveAction (*yybest, &val]b4_locations_if([, yylocp])[); - if (yyflag == yyok) - for (semantic_option* yyp = yybest->next(); - yyp != YY_NULLPTR; - yyp = yyp->next()) - { - if (yyprec == yydprec[yyp->yyrule]) + for (state_set_index yys = create_state_set_index (0); yys.uget () < this->yystateStack.numTops (); ++yys) + YYCHK1 (this->yyprocessOneStack (yys, yyposn]b4_locations_if([, &this->yyla.location])[)); + this->yystateStack.yytops.yyremoveDeletes (); + if (this->yystateStack.yytops.size() == 0) { - value_type yyval_other;]b4_locations_if([ - location_type yydummy;])[ - yyflag = yyresolveAction (*yyp, &yyval_other]b4_locations_if([, &yydummy])[); - if (yyflag != yyok) + this->yystateStack.yytops.yyundeleteLastStack (); + if (this->yystateStack.yytops.size() == 0) + this->yyFail (]b4_locations_if([&this->yyla.location, ])[YY_("syntax error")); + YYCHK1 (this->yyresolveStack ()); + YYCDEBUG << "Returning to deterministic operation.\n";]b4_locations_if([[ + this->yyerror_range[1].getState ().yyloc = this->yyla.location;]])[ + this->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, yyla is emptied + before the loop to make sure the user destructor for yylval isn't + called twice. */ + yysymbol_kind_t yytoken_to_shift = this->yyla.kind (); + this->yyla.kind_ = ]b4_symbol(empty, kind)[; + yyposn += 1; + for (state_set_index yys = create_state_set_index (0); yys.uget () < this->yystateStack.numTops (); ++yys) + { + const state_num yystate = this->topState (yys)->yylrState; + const short* yyconflicts; + const int yyaction = yygetLRActions (yystate, yytoken_to_shift, yyconflicts); + /* Note that yyconflicts were handled by yyprocessOneStack. */ + YYCDEBUG << "On stack " << yys.get() << ", "; + YY_SYMBOL_PRINT ("shifting", yytoken_to_shift, this->yyla.value, this->yyla.location); + this->yyglrShift (yys, yyaction, yyposn, this->yyla.value]b4_locations_if([, this->yyla.location])[); + YYCDEBUG << "Stack " << yys.get() << " now in state " + << this->topState(yys)->yylrState << '\n'; + } + ]b4_variant_if([[ + // FIXME: User destructors. + // Value type destructor. + ]b4_symbol_variant([[yytoken_to_shift]], [[this->yyla.value]], [[template destroy]])])[ + + if (this->yystateStack.yytops.size () == 1) + { + YYCHK1 (this->yyresolveStack ()); + YYCDEBUG << "Returning to deterministic operation.\n"; + this->yystateStack.yycompressStack (); + break; + } + } + continue; + yyuser_error: + this->yyrecoverSyntaxError (]b4_locations_if([&this->yyla.location])[); + yyposn = this->firstTopState()->yyposn; + } + + yyacceptlab: + yyresult = 0; + goto yyreturn; + + yybuglab: + YYASSERT (false); + goto yyabortlab; + + yyabortlab: + yyresult = 1; + goto yyreturn; + + yyexhaustedlab: + yyparser.error (]b4_locations_if([this->yyla.location, ])[YY_("memory exhausted")); + yyresult = 2; + goto yyreturn; + + yyreturn: + return yyresult; + } + #undef YYCHK1 + + void yyreserveGlrStack () + { + if (!yystateStack.yyexpandGLRStackIfNeeded ()) + yyMemoryExhausted (); + } + + _Noreturn void + yyMemoryExhausted () + { + YYLONGJMP (yyexception_buffer, 2); + } + + _Noreturn void + yyFail (]b4_locations_if([location_type* yylocp, ])[const char* yymsg) + { + if (yymsg != YY_NULLPTR) + yyparser.error (]b4_locations_if([*yylocp, ])[yymsg); + YYLONGJMP (yyexception_buffer, 1); + } + + /* GLRStates */ + + + /** Add a new semantic action that will execute the action for rule + * YYRULE on the semantic values in YYRHS to the list of + * alternative actions for YYSTATE. Assumes that YYRHS comes from + * stack #YYK of *this. */ + void + yyaddDeferredAction (state_set_index yyk, glr_state* yystate, + glr_state* yyrhs, rule_num yyrule) + { + semantic_option& yynewOption = + yystateStack.yynewSemanticOption(semantic_option(yyrule, ]b4_symbol(empty, kind)[)); + yynewOption.setState(yyrhs); + yynewOption.setNext(yystate->firstVal()); + if (yystateStack.yytops.lookaheadNeeds(yyk)) + { + yynewOption.yytoken = this->yyla.kind ();]b4_variant_if([[ + ]b4_symbol_variant([this->yyla.kind ()], + [yynewOption.yyval], [copy], [this->yyla.value])], [[ + yynewOption.yyval = this->yyla.value;]])[]b4_locations_if([ + yynewOption.yyloc = this->yyla.location;])[ + } + yystate->setFirstVal (&yynewOption); + + yyreserveGlrStack (); + } + + #if ]b4_api_PREFIX[DEBUG + void yypdumpstack () const + { + yystateStack.dumpStack(); + } + #endif + + void + yyreportSyntaxError () + { + if (yyerrState != 0) + return; + ]b4_parse_error_case( + [simple], [[ + std::string msg = YY_("syntax error"); + yyparser.error (]b4_join(b4_locations_if([yyla.location]), [[YY_MOVE (msg)]])[);]], + [custom], [[ + context yyctx (*this, yyla); + yyparser.report_syntax_error (yyctx);]], + [[ + context yyctx (*this, yyla); + std::string msg = yyparser.yysyntax_error_ (yyctx); + yyparser.error (]b4_join(b4_locations_if([yyla.location]), [[YY_MOVE (msg)]])[);]])[ + yyerrcnt += 1; + } + + /* Recover from a syntax error on this, assuming that yytoken, + yylval, and yylloc are the syntactic category, semantic value, and location + of the lookahead. */ + void + yyrecoverSyntaxError (]b4_locations_if([location_type* yylocp])[) + { + if (yyerrState == 3) + /* We just shifted the error token and (perhaps) took some + reductions. Skip tokens until we can proceed. */ + while (true) + { + if (this->yyla.kind () == ]b4_symbol(eof, kind)[) + yyFail (]b4_locations_if([yylocp, ])[YY_NULLPTR); + if (this->yyla.kind () != ]b4_symbol(empty, kind)[) + {]b4_locations_if([[ + /* We throw away the lookahead, but the error range + of the shifted error token must take it into account. */ + glr_state *yys = firstTopState(); + yyerror_range[1].getState().yyloc = yys->yyloc; + yyerror_range[2].getState().yyloc = this->yyla.location; + YYLLOC_DEFAULT ((yys->yyloc), yyerror_range, 2);]])[ + yyparser.yy_destroy_ ("Error: discarding", + this->yyla.kind (), this->yyla.value]b4_locations_if([, this->yyla.location])[);]b4_variant_if([[ + // Value type destructor. + ]b4_symbol_variant([[this->yyla.kind ()]], [[this->yyla.value]], [[template destroy]])])[ + this->yyla.kind_ = ]b4_symbol(empty, kind)[; + } + yyget_token (); + int yyj = yypact[firstTopState()->yylrState]; + if (yypact_value_is_default (yyj)) + return; + yyj += this->yyla.kind (); + if (yyj < 0 || YYLAST < yyj || yycheck[yyj] != this->yyla.kind ()) + { + if (yydefact[firstTopState()->yylrState] != 0) + return; + } + else if (! yytable_value_is_error (yytable[yyj])) + return; + } + + if (!yystateStack.reduceToOneStack()) + yyFail (]b4_locations_if([yylocp, ])[YY_NULLPTR); + + /* Now pop stack until we find a state that shifts the error token. */ + yyerrState = 3; + while (firstTopState () != YY_NULLPTR) + { + glr_state *yys = firstTopState (); + int yyj = yypact[yys->yylrState]; + if (! yypact_value_is_default (yyj)) + { + yyj += YYTERROR; + if (0 <= yyj && yyj <= YYLAST && yycheck[yyj] == YYTERROR + && yy_is_shift_action (yytable[yyj])) + { + /* Shift the error token. */]b4_locations_if([[ + /* First adjust its location.*/ + location_type yyerrloc; + yyerror_range[2].getState().yyloc = this->yyla.location; + YYLLOC_DEFAULT (yyerrloc, (yyerror_range), 2);]])[ + YY_SYMBOL_PRINT ("Shifting", yy_accessing_symbol (yytable[yyj]), + this->yyla.value, yyerrloc); + yyglrShift (create_state_set_index(0), yytable[yyj], + yys->yyposn, yyla.value]b4_locations_if([, yyerrloc])[); + yys = firstTopState(); + break; + } + }]b4_locations_if([[ + yyerror_range[1].getState().yyloc = yys->yyloc;]])[ + if (yys->pred() != YY_NULLPTR) + yys->destroy ("Error: popping", yyparser]b4_user_args[); + yystateStack.setFirstTop(yys->pred()); + yystateStack.pop_back(); + } + if (firstTopState() == YY_NULLPTR) + yyFail (]b4_locations_if([yylocp, ])[YY_NULLPTR); + } + + YYRESULTTAG + yyprocessOneStack (state_set_index yyk, + size_t yyposn]b4_locations_if([, location_type* yylocp])[) + { + while (yystateStack.topAt(yyk) != YY_NULLPTR) + { + const state_num yystate = topState(yyk)->yylrState; + YYCDEBUG << "Stack " << yyk.get() + << " Entering state " << yystate << '\n'; + + YYASSERT (yystate != YYFINAL); + + if (yy_is_defaulted_state (yystate)) + { + const rule_num yyrule = yy_default_action (yystate); + if (yyrule == 0) + { + YYCDEBUG << "Stack " << yyk.get() << " dies.\n"; + yystateStack.yytops.yymarkStackDeleted (yyk); + return yyok; + } + const YYRESULTTAG yyflag + = yyglrReduce (yyk, yyrule, yyimmediate[yyrule]); + if (yyflag == yyerr) + { + YYCDEBUG << "Stack " << yyk.get() << " dies" + " (predicate failure or explicit user error).\n"; + yystateStack.yytops.yymarkStackDeleted (yyk); + return yyok; + } + if (yyflag != yyok) + return yyflag; + } + else + { + yystateStack.yytops.setLookaheadNeeds(yyk, true); + yyget_token (); + const short* yyconflicts; + const int yyaction = yygetLRActions (yystate, this->yyla.kind (), yyconflicts); + + for (; *yyconflicts != 0; ++yyconflicts) + { + state_set_index yynewStack = yystateStack.yysplitStack (yyk); + YYCDEBUG << "Splitting off stack " << yynewStack.get() + << " from " << yyk.get() << ".\n"; + YYRESULTTAG yyflag = + yyglrReduce (yynewStack, *yyconflicts, yyimmediate[*yyconflicts]); + if (yyflag == yyok) + YYCHK (yyprocessOneStack (yynewStack, + yyposn]b4_locations_if([, yylocp])[)); + else if (yyflag == yyerr) { - yyparser.yy_destroy_ ("Cleanup: discarding incompletely merged value for", - yy_accessing_symbol (yys.yylrState), - this->yyla.value]b4_locations_if([, *yylocp])[); + YYCDEBUG << "Stack " << yynewStack.get() << " dies.\n"; + yystateStack.yytops.yymarkStackDeleted (yynewStack); + } + else + return yyflag; + } + + if (yy_is_shift_action (yyaction)) + break; + else if (yy_is_error_action (yyaction)) + { + YYCDEBUG << "Stack " << yyk.get() << " dies.\n"; + yystateStack.yytops.yymarkStackDeleted (yyk); + break; + } + else + { + YYRESULTTAG yyflag + = yyglrReduce (yyk, -yyaction, yyimmediate[-yyaction]); + if (yyflag == yyerr) + { + YYCDEBUG << "Stack " << yyk.get() << " dies" + " (predicate failure or explicit user error).\n"; + yystateStack.yytops.yymarkStackDeleted (yyk); break; } - yyuserMerge (yymerger[yyp->yyrule], val, yyval_other);]b4_variant_if([[ - // FIXME: User destructors. - // Value type destructor. - ]b4_symbol_variant([[yy_accessing_symbol (yys.yylrState)]], [[yyval_other]], [[template destroy]])])[ + else if (yyflag != yyok) + return yyflag; } } - } - else - yyflag = yyresolveAction (*yybest, &val]b4_locations_if([, yylocp])[); - - if (yyflag == yyok) - { - yys.yyresolved = true; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN]b4_variant_if([[ - new (&yys.value ()) value_type (); - ]b4_symbol_variant([yy_accessing_symbol (yys.yylrState)], - [yys.value ()], [copy], [val])], [[ - new (&yys.value ()) value_type (val);]])[ - - YY_IGNORE_MAYBE_UNINITIALIZED_END - } - else - yys.setFirstVal(YY_NULLPTR); -]b4_variant_if([[ - // FIXME: User destructors. - // Value type destructor. - ]b4_symbol_variant([[yy_accessing_symbol (yys.yylrState)]], [[val]], [[template destroy]])])[ - return yyflag; - } - - /** Resolve the states for the RHS of YYOPT on *YYSTACKP, perform its - * user action, and return the semantic value and location in *YYVALP - * and *YYLOCP. Regardless of whether result = yyok, all RHS states - * have been destroyed (assuming the user action destroys all RHS - * semantic values if invoked). */ - YYRESULTTAG - yyresolveAction (semantic_option& yyopt, value_type* yyvalp]b4_locations_if([, location_type* yylocp])[) - { - glr_state* yyoptState = yyopt.state(); - YYASSERT(yyoptState != YY_NULLPTR); - int yynrhs = yyrhsLength (yyopt.yyrule); - YYRESULTTAG yyflag = yyresolveStates (*yyoptState, yynrhs); - if (yyflag != yyok) - { - for (glr_state *yys = yyoptState; yynrhs > 0; yys = yys->pred(), yynrhs -= 1) - yys->destroy ("Cleanup: popping", yyparser]b4_user_args[); - return yyflag; - } - - glr_stack_item yyrhsVals[YYMAXRHS + YYMAXLEFT + 1]; - yyrhsVals[YYMAXRHS + YYMAXLEFT].getState().setPred(yyopt.state());]b4_locations_if([[ - if (yynrhs == 0) - /* Set default location. */ - yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].getState().yyloc = yyoptState->yyloc;]])[ - { - symbol_type yyla_current = std::move (this->yyla); - this->yyla.kind_ = yyopt.yytoken;]b4_variant_if([[ - ]b4_symbol_variant([this->yyla.kind ()], - [this->yyla.value], [move], [yyopt.yyval])], [[ - this->yyla.value = yyopt.yyval;]])[]b4_locations_if([ - this->yyla.location = yyopt.yyloc;])[ - yyflag = yyuserAction (yyopt.yyrule, yynrhs, - yyrhsVals + YYMAXRHS + YYMAXLEFT - 1, - create_state_set_index (-1), - yyvalp]b4_locations_if([, yylocp])[); - - this->yyla = std::move (yyla_current); + } + return yyok; } - return yyflag; - }]b4_locations_if([[ - /** Resolve the locations for each of the YYN1 states in *YYSTACKP, - * ending at YYS1. Has no effect on previously resolved states. - * The first semantic option of a state is always chosen. */ - void - yyresolveLocations (glr_state &yys1, int yyn1) - { - if (0 < yyn1) + /** Perform user action for rule number YYN, with RHS length YYRHSLEN, + * and top stack item YYVSP. YYVALP points to place to put semantic + * value ($$), and yylocp points to place for location information + * (@@$). Returns yyok for normal return, yyaccept for YYACCEPT, + * yyerr for YYERROR, yyabort for YYABORT. */ + YYRESULTTAG + yyuserAction (rule_num yyrule, int yyrhslen, glr_stack_item* yyvsp, state_set_index yyk, + value_type* yyvalp]b4_locations_if([, location_type* yylocp])[) + { + bool yynormal YY_ATTRIBUTE_UNUSED = !yystateStack.isSplit(); + int yylow = 1; + ]b4_parse_param_use([yyvalp], [yylocp])dnl + [ YY_USE (yyk); + YY_USE (yyrhslen); + # undef yyerrok + # define yyerrok (yyerrState = 0) + # undef YYACCEPT + # define YYACCEPT return yyaccept + # undef YYABORT + # define YYABORT return yyabort + # undef YYERROR + # define YYERROR return yyerrok, yyerr + # undef YYRECOVERING + # define YYRECOVERING() (yyerrState != 0) + # undef yytoken + # define yytoken this->yyla.kind_ + # undef yyclearin + # define yyclearin (yytoken = ]b4_symbol(empty, kind)[) + # undef YYBACKUP + # define YYBACKUP(Token, Value) \ + return yyparser.error (]b4_locations_if([*yylocp, ])[YY_("syntax error: cannot back up")), \ + yyerrok, yyerr + + ]b4_variant_if([[ + /* Variants are always initialized to an empty instance of the + correct type. The default '$$ = $1' action is NOT applied + when using variants. */ + // However we really need to prepare yyvsp now if we want to get + // correct locations, so invoke YYFILL for $1 anyway. + (void) YYFILL (1-yyrhslen); + ]b4_symbol_variant([[yylhsNonterm (yyrule)]], [(*yyvalp)], [emplace])], [[ + if (yyrhslen == 0) + *yyvalp = yyval_default; + else + *yyvalp = yyvsp[YYFILL (1-yyrhslen)].getState().value ();]])[]b4_locations_if([[ + /* Default location. */ + YYLLOC_DEFAULT ((*yylocp), (yyvsp - yyrhslen), yyrhslen); + yyerror_range[1].getState().yyloc = *yylocp; + ]])[ + /* If yyk == -1, we are running a deferred action on a temporary + stack. In that case, YY_REDUCE_PRINT must not play with YYFILL, + so pretend the stack is "normal". */ + YY_REDUCE_PRINT ((yynormal || yyk == create_state_set_index (-1), yyvsp, yyk, yyrule, yyparser)); + #if YY_EXCEPTIONS + typedef ]b4_namespace_ref[::]b4_parser_class[::syntax_error syntax_error; + try { - yyresolveLocations (*yys1.pred(), yyn1 - 1); - if (!yys1.yyresolved) - { - glr_stack_item yyrhsloc[1 + YYMAXRHS]; - YYASSERT (yys1.firstVal() != YY_NULLPTR); - semantic_option& yyoption = *yys1.firstVal(); - const int yynrhs = yyrhsLength (yyoption.yyrule); - if (0 < yynrhs) + #endif // YY_EXCEPTIONS + switch (yyrule) + { + ]b4_user_actions[ + default: break; + } + #if YY_EXCEPTIONS + } + catch (const syntax_error& yyexc) + { + YYCDEBUG << "Caught exception: " << yyexc.what() << '\n';]b4_locations_if([ + *yylocp = yyexc.location;])[ + yyparser.error (]b4_locations_if([*yylocp, ])[yyexc.what ()); + YYERROR; + } + #endif // YY_EXCEPTIONS + YY_SYMBOL_PRINT ("-> $$ =", yylhsNonterm (yyrule), *yyvalp, *yylocp); + + return yyok; + # undef yyerrok + # undef YYABORT + # undef YYACCEPT + # undef YYERROR + # undef YYBACKUP + # undef yytoken + # undef yyclearin + # undef YYRECOVERING + } + + YYRESULTTAG + yyresolveStack () + { + if (yystateStack.isSplit ()) + { + int yyn = 0; + for (glr_state* yys = firstTopState (); + yys != yystateStack.yysplitPoint; + yys = yys->pred ()) + yyn += 1; + YYCHK (yyresolveStates (*firstTopState (), yyn)); + } + return yyok; + } + + /** Pop the symbols consumed by reduction #YYRULE from the top of stack + * #YYK of *YYSTACKP, and perform the appropriate semantic action on their + * semantic values. Assumes that all ambiguities in semantic values + * have been previously resolved. Set *YYVALP to the resulting value, + * and *YYLOCP to the computed location (if any). Return value is as + * for userAction. */ + YYRESULTTAG + yydoAction (state_set_index yyk, rule_num yyrule, + value_type* yyvalp]b4_locations_if([, location_type* yylocp])[) + { + const int yynrhs = yyrhsLength (yyrule); + + if (!yystateStack.isSplit()) + { + /* Standard special case: single stack. */ + YYASSERT (yyk.get() == 0); + glr_stack_item* yyrhs = yystateStack.firstTop()->asItem(); + const YYRESULTTAG res + = yyuserAction (yyrule, yynrhs, yyrhs, yyk, yyvalp]b4_locations_if([, yylocp])[); + yystateStack.pop_back(static_cast(yynrhs)); + yystateStack.setFirstTop(&yystateStack[yystateStack.size() - 1].getState()); + return res; + } + else + { + glr_stack_item yyrhsVals[YYMAXRHS + YYMAXLEFT + 1]; + glr_state* yys = yystateStack.topAt(yyk); + yyrhsVals[YYMAXRHS + YYMAXLEFT].getState().setPred(yys);]b4_locations_if([[ + if (yynrhs == 0) + /* Set default location. */ + yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].getState().yyloc = yys->yyloc;]])[ + for (int yyi = 0; yyi < yynrhs; yyi += 1) + { + yys = yys->pred(); + YYASSERT (yys != YY_NULLPTR); + } + yystateStack.yyupdateSplit (*yys); + yystateStack.setTopAt(yyk, yys); + return yyuserAction (yyrule, yynrhs, yyrhsVals + YYMAXRHS + YYMAXLEFT - 1, + yyk, + yyvalp]b4_locations_if([, yylocp])[); + } + } + + /** Pop items off stack #YYK of *YYSTACKP according to grammar rule YYRULE, + * and push back on the resulting nonterminal symbol. Perform the + * semantic action associated with YYRULE and store its value with the + * newly pushed state, if YYFORCEEVAL or if *YYSTACKP is currently + * unambiguous. Otherwise, store the deferred semantic action with + * the new state. If the new state would have an identical input + * position, LR state, and predecessor to an existing state on the stack, + * it is identified with that existing state, eliminating stack #YYK from + * *YYSTACKP. In this case, the semantic value is + * added to the options for the existing state's semantic value. + */ + YYRESULTTAG + yyglrReduce (state_set_index yyk, rule_num yyrule, bool yyforceEval) + { + size_t yyposn = topState(yyk)->yyposn; + + if (yyforceEval || !yystateStack.isSplit()) + { + value_type val;]b4_locations_if([[ + location_type loc;]])[ + + YYRESULTTAG yyflag = yydoAction (yyk, yyrule, &val]b4_locations_if([, &loc])[); + if (yyflag == yyerr && yystateStack.isSplit()) + {]b4_parse_trace_if([[ + YYCDEBUG << "Parse on stack " << yyk.get () + << " rejected by rule " << yyrule - 1 + << " (line " << int (yyrline[yyrule]) << ").\n"; + ]])[} + if (yyflag != yyok) + return yyflag; + yyglrShift (yyk, + yyLRgotoState (topState(yyk)->yylrState, + yylhsNonterm (yyrule)), + yyposn, val]b4_locations_if([, loc])[);]b4_variant_if([[ + // FIXME: User destructors. + // Value type destructor. + ]b4_symbol_variant([[yylhsNonterm (yyrule)]], [[val]], [[template destroy]])])[ + } + else + { + glr_state *yys = yystateStack.topAt(yyk); + glr_state *yys0 = yys; + for (int yyn = yyrhsLength (yyrule); 0 < yyn; yyn -= 1) + { + yys = yys->pred(); + YYASSERT (yys != YY_NULLPTR); + } + yystateStack.yyupdateSplit (*yys); + state_num yynewLRState = yyLRgotoState (yys->yylrState, yylhsNonterm (yyrule));]b4_parse_trace_if([[ + YYCDEBUG << "Reduced stack " << yyk.get () + << " by rule " << yyrule - 1 << " (line " << int (yyrline[yyrule]) + << "); action deferred. Now in state " << yynewLRState + << ".\n";]])[ + for (state_set_index yyi = create_state_set_index(0); yyi.uget() < yystateStack.numTops(); ++yyi) + if (yyi != yyk && yystateStack.topAt(yyi) != YY_NULLPTR) { - yyresolveLocations (*yyoption.state(), yynrhs); - const glr_state *yys = yyoption.state(); - for (int yyn = yynrhs; yyn > 0; yyn -= 1) + const glr_state* yysplit = yystateStack.yysplitPoint; + glr_state* yyp = yystateStack.topAt(yyi); + while (yyp != yys && yyp != yysplit + && yyp->yyposn >= yyposn) + { + if (yyp->yylrState == yynewLRState + && yyp->pred() == yys) + { + yyaddDeferredAction (yyk, yyp, yys0, yyrule); + yystateStack.yytops.yymarkStackDeleted (yyk); + YYCDEBUG << "Merging stack " << yyk.get () + << " into stack " << yyi.get () << ".\n"; + return yyok; + } + yyp = yyp->pred(); + } + } + yystateStack.setTopAt(yyk, yys); + yyglrShiftDefer (yyk, yynewLRState, yyposn, yys0, yyrule); + } + return yyok; + } + + /** Shift stack #YYK of *YYSTACKP, to a new state corresponding to LR + * state YYLRSTATE, at input position YYPOSN, with the (unresolved) + * semantic value of YYRHS under the action for YYRULE. */ + void + yyglrShiftDefer (state_set_index yyk, state_num yylrState, + size_t yyposn, glr_state* yyrhs, rule_num yyrule) + { + glr_state& yynewState = yystateStack.yynewGLRState ( + glr_state (yylrState, yyposn)); + yynewState.setPred (yystateStack.topAt (yyk)); + yystateStack.setTopAt (yyk, &yynewState); + + /* Invokes yyreserveStack. */ + yyaddDeferredAction (yyk, &yynewState, yyrhs, yyrule); + } + + /** Shift to a new state on stack #YYK of *YYSTACKP, corresponding to LR + * state YYLRSTATE, at input position YYPOSN, with (resolved) semantic + * value YYVAL_ARG and source location YYLOC_ARG. */ + void + yyglrShift (state_set_index yyk, state_num yylrState, + size_t yyposn, + const value_type& yyval_arg]b4_locations_if([, const location_type& yyloc_arg])[) + { + glr_state& yynewState = yystateStack.yynewGLRState ( + glr_state (yylrState, yyposn, yyval_arg]b4_locations_if([, yyloc_arg])[)); + yynewState.setPred (yystateStack.topAt(yyk)); + yystateStack.setTopAt (yyk, &yynewState); + yyreserveGlrStack (); + } + +#if ]b4_api_PREFIX[DEBUG + void + yypstack (state_set_index yyk) const + { + yystateStack.yypstates (yystateStack.topAt (yyk)); + } +#endif + + glr_state* topState(state_set_index i) { + return yystateStack.topAt(i); + } + + glr_state* firstTopState() { + return yystateStack.firstTop(); + } + + private: + + void popall_ () + { + /* If the stack is well-formed, pop the stack until it is empty, + destroying its entries as we go. But free the stack regardless + of whether it is well-formed. */ + for (state_set_index k = create_state_set_index(0); k.uget() < yystateStack.numTops(); k += 1) + if (yystateStack.topAt(k) != YY_NULLPTR) + { + while (yystateStack.topAt(k) != YY_NULLPTR) + { + glr_state* state = topState(k);]b4_locations_if([[ + yyerror_range[1].getState().yyloc = state->yyloc;]])[ + if (state->pred() != YY_NULLPTR) + state->destroy ("Cleanup: popping", yyparser]b4_user_args[); + yystateStack.setTopAt(k, state->pred()); + yystateStack.pop_back(); + } + break; + } + } + + /** Resolve the previous YYN states starting at and including state YYS + * on *YYSTACKP. If result != yyok, some states may have been left + * unresolved possibly with empty semantic option chains. Regardless + * of whether result = yyok, each state has been left with consistent + * data so that destroy can be invoked if necessary. */ + YYRESULTTAG + yyresolveStates (glr_state& yys, int yyn) + { + if (0 < yyn) + { + YYASSERT (yys.pred() != YY_NULLPTR); + YYCHK (yyresolveStates (*yys.pred(), yyn-1)); + if (! yys.yyresolved) + YYCHK (yyresolveValue (yys)); + } + return yyok; + } + + static void + yyuserMerge (int yyn, value_type& yy0, value_type& yy1) + { + YY_USE (yy0); + YY_USE (yy1); + + switch (yyn) + { +]b4_mergers[ + default: break; + } + } + + /** Resolve the ambiguity represented in state YYS in *YYSTACKP, + * perform the indicated actions, and set the semantic value of YYS. + * If result != yyok, the chain of semantic options in YYS has been + * cleared instead or it has been left unmodified except that + * redundant options may have been removed. Regardless of whether + * result = yyok, YYS has been left with consistent data so that + * destroy can be invoked if necessary. */ + YYRESULTTAG + yyresolveValue (glr_state& yys) + { + semantic_option* yybest = yys.firstVal(); + YYASSERT(yybest != YY_NULLPTR); + bool yymerge = false; + YYRESULTTAG yyflag;]b4_locations_if([ + location_type *yylocp = &yys.yyloc;])[ + + semantic_option* yypPrev = yybest; + for (semantic_option* yyp = yybest->next(); + yyp != YY_NULLPTR; ) + { + if (yybest->isIdenticalTo (*yyp)) + { + yybest->mergeWith (*yyp); + yypPrev->setNext(yyp->next()); + yyp = yypPrev->next(); + } + else + { + switch (yypreference (*yybest, *yyp)) { - yyrhsloc[yyn].getState().yyloc = yys->yyloc; - yys = yys->pred(); + case 0:]b4_locations_if([[ + yyresolveLocations (yys, 1);]])[ + return yystateStack.yyreportAmbiguity (*yybest, *yyp, yyparser]b4_locations_if([, *yylocp])[); + break; + case 1: + yymerge = true; + break; + case 2: + break; + case 3: + yybest = yyp; + yymerge = false; + break; + default: + /* This cannot happen so it is not worth a YYASSERT (false), + but some compilers complain if the default case is + omitted. */ + break; } - } - else + yypPrev = yyp; + yyp = yyp->next(); + } + } + + value_type val; + if (yymerge) + { + int yyprec = yydprec[yybest->yyrule]; + yyflag = yyresolveAction (*yybest, &val]b4_locations_if([, yylocp])[); + if (yyflag == yyok) + for (semantic_option* yyp = yybest->next(); + yyp != YY_NULLPTR; + yyp = yyp->next()) { - /* Both yyresolveAction and yyresolveLocations traverse the GSS - in reverse rightmost order. It is only necessary to invoke - yyresolveLocations on a subforest for which yyresolveAction - would have been invoked next had an ambiguity not been - detected. Thus the location of the previous state (but not - necessarily the previous state itself) is guaranteed to be - resolved already. */ - YY_IGNORE_NULL_DEREFERENCE_BEGIN - yyrhsloc[0].getState().yyloc = yyoption.state()->yyloc; - YY_IGNORE_NULL_DEREFERENCE_END + if (yyprec == yydprec[yyp->yyrule]) + { + value_type yyval_other;]b4_locations_if([ + location_type yydummy;])[ + yyflag = yyresolveAction (*yyp, &yyval_other]b4_locations_if([, &yydummy])[); + if (yyflag != yyok) + { + yyparser.yy_destroy_ ("Cleanup: discarding incompletely merged value for", + yy_accessing_symbol (yys.yylrState), + this->yyla.value]b4_locations_if([, *yylocp])[); + break; + } + yyuserMerge (yymerger[yyp->yyrule], val, yyval_other);]b4_variant_if([[ + // FIXME: User destructors. + // Value type destructor. + ]b4_symbol_variant([[yy_accessing_symbol (yys.yylrState)]], [[yyval_other]], [[template destroy]])])[ + } } - YYLLOC_DEFAULT ((yys1.yyloc), yyrhsloc, yynrhs); - } - } - }]])[ + } + else + yyflag = yyresolveAction (*yybest, &val]b4_locations_if([, yylocp])[); - /** If yytoken is empty, fetch the next token. */ - void - yyget_token () - { + if (yyflag == yyok) + { + yys.yyresolved = true; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN]b4_variant_if([[ + new (&yys.value ()) value_type (); + ]b4_symbol_variant([yy_accessing_symbol (yys.yylrState)], + [yys.value ()], [copy], [val])], [[ + new (&yys.value ()) value_type (val);]])[ + + YY_IGNORE_MAYBE_UNINITIALIZED_END + } + else + yys.setFirstVal(YY_NULLPTR); +]b4_variant_if([[ + // FIXME: User destructors. + // Value type destructor. + ]b4_symbol_variant([[yy_accessing_symbol (yys.yylrState)]], [[val]], [[template destroy]])])[ + return yyflag; + } + + /** Resolve the states for the RHS of YYOPT on *YYSTACKP, perform its + * user action, and return the semantic value and location in *YYVALP + * and *YYLOCP. Regardless of whether result = yyok, all RHS states + * have been destroyed (assuming the user action destroys all RHS + * semantic values if invoked). */ + YYRESULTTAG + yyresolveAction (semantic_option& yyopt, value_type* yyvalp]b4_locations_if([, location_type* yylocp])[) + { + glr_state* yyoptState = yyopt.state(); + YYASSERT(yyoptState != YY_NULLPTR); + int yynrhs = yyrhsLength (yyopt.yyrule); + YYRESULTTAG yyflag = yyresolveStates (*yyoptState, yynrhs); + if (yyflag != yyok) + { + for (glr_state *yys = yyoptState; yynrhs > 0; yys = yys->pred(), yynrhs -= 1) + yys->destroy ("Cleanup: popping", yyparser]b4_user_args[); + return yyflag; + } + + glr_stack_item yyrhsVals[YYMAXRHS + YYMAXLEFT + 1]; + yyrhsVals[YYMAXRHS + YYMAXLEFT].getState().setPred(yyopt.state());]b4_locations_if([[ + if (yynrhs == 0) + /* Set default location. */ + yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].getState().yyloc = yyoptState->yyloc;]])[ + { + symbol_type yyla_current = std::move (this->yyla); + this->yyla.kind_ = yyopt.yytoken;]b4_variant_if([[ + ]b4_symbol_variant([this->yyla.kind ()], + [this->yyla.value], [move], [yyopt.yyval])], [[ + this->yyla.value = yyopt.yyval;]])[]b4_locations_if([ + this->yyla.location = yyopt.yyloc;])[ + yyflag = yyuserAction (yyopt.yyrule, yynrhs, + yyrhsVals + YYMAXRHS + YYMAXLEFT - 1, + create_state_set_index (-1), + yyvalp]b4_locations_if([, yylocp])[); + + this->yyla = std::move (yyla_current); + } + return yyflag; + }]b4_locations_if([[ + + /** Resolve the locations for each of the YYN1 states in *YYSTACKP, + * ending at YYS1. Has no effect on previously resolved states. + * The first semantic option of a state is always chosen. */ + void + yyresolveLocations (glr_state &yys1, int yyn1) + { + if (0 < yyn1) + { + yyresolveLocations (*yys1.pred(), yyn1 - 1); + if (!yys1.yyresolved) + { + glr_stack_item yyrhsloc[1 + YYMAXRHS]; + YYASSERT (yys1.firstVal() != YY_NULLPTR); + semantic_option& yyoption = *yys1.firstVal(); + const int yynrhs = yyrhsLength (yyoption.yyrule); + if (0 < yynrhs) + { + yyresolveLocations (*yyoption.state(), yynrhs); + const glr_state *yys = yyoption.state(); + for (int yyn = yynrhs; yyn > 0; yyn -= 1) + { + yyrhsloc[yyn].getState().yyloc = yys->yyloc; + yys = yys->pred(); + } + } + else + { + /* Both yyresolveAction and yyresolveLocations traverse the GSS + in reverse rightmost order. It is only necessary to invoke + yyresolveLocations on a subforest for which yyresolveAction + would have been invoked next had an ambiguity not been + detected. Thus the location of the previous state (but not + necessarily the previous state itself) is guaranteed to be + resolved already. */ + YY_IGNORE_NULL_DEREFERENCE_BEGIN + yyrhsloc[0].getState().yyloc = yyoption.state()->yyloc; + YY_IGNORE_NULL_DEREFERENCE_END + } + YYLLOC_DEFAULT ((yys1.yyloc), yyrhsloc, yynrhs); + } + } + }]])[ + + /** If yytoken is empty, fetch the next token. */ + void + yyget_token () + { ]b4_parse_param_use()dnl -[ if (this->yyla.empty ()) - { - YYCDEBUG << "Reading a token\n"; +[ if (this->yyla.empty ()) + { + YYCDEBUG << "Reading a token\n"; #if YY_EXCEPTIONS - try + try #endif // YY_EXCEPTIONS - {]b4_token_ctor_if([[ - symbol_type yylookahead (]b4_yylex[); - yyla.move (yylookahead);]], [[ - yyla.kind_ = yyparser.yytranslate_ (]b4_yylex[);]])[ - } + {]b4_token_ctor_if([[ + symbol_type yylookahead (]b4_yylex[); + yyla.move (yylookahead);]], [[ + yyla.kind_ = yyparser.yytranslate_ (]b4_yylex[);]])[ + } #if YY_EXCEPTIONS - catch (const ]b4_namespace_ref[::]b4_parser_class[::syntax_error& yyexc) - { - YYCDEBUG << "Caught exception: " << yyexc.what () << '\n';]b4_locations_if([ - this->yyla.location = yyexc.location;])[ - yyparser.error (]b4_locations_if([this->yyla.location, ])[yyexc.what ()); - // Map errors caught in the scanner to the error token, so that error - // handling is started. - this->yyla.kind_ = ]b4_symbol(error, kind)[; - } - } + catch (const ]b4_namespace_ref[::]b4_parser_class[::syntax_error& yyexc) + { + YYCDEBUG << "Caught exception: " << yyexc.what () << '\n';]b4_locations_if([ + this->yyla.location = yyexc.location;])[ + yyparser.error (]b4_locations_if([this->yyla.location, ])[yyexc.what ()); + // Map errors caught in the scanner to the error token, so that error + // handling is started. + this->yyla.kind_ = ]b4_symbol(error, kind)[; + } + } #endif // YY_EXCEPTIONS - if (this->yyla.kind () == ]b4_symbol(eof, kind)[) - YYCDEBUG << "Now at end of input.\n"; - else - YY_SYMBOL_PRINT ("Next token is", this->yyla.kind (), this->yyla.value, this->yyla.location); - } + if (this->yyla.kind () == ]b4_symbol(eof, kind)[) + YYCDEBUG << "Now at end of input.\n"; + else + YY_SYMBOL_PRINT ("Next token is", this->yyla.kind (), this->yyla.value, this->yyla.location); + } - /* Bison grammar-table manipulation. */ + /* Bison grammar-table manipulation. */ - /** The action to take in YYSTATE on seeing YYTOKEN. - * Result R means - * R < 0: Reduce on rule -R. - * R = 0: Error. - * R > 0: Shift to state R. - * Set *YYCONFLICTS to a pointer into yyconfl to a 0-terminated list - * of conflicting reductions. - */ - static int - yygetLRActions (state_num yystate, yysymbol_kind_t yytoken, const short*& yyconflicts) - { - int yyindex = yypact[yystate] + yytoken; - if (yytoken == ]b4_symbol(error, kind)[) - { - // This is the error token. - yyconflicts = yyconfl; - return 0; - } - else if (yy_is_defaulted_state (yystate) - || yyindex < 0 || YYLAST < yyindex || yycheck[yyindex] != yytoken) - { - yyconflicts = yyconfl; - return -yydefact[yystate]; - } - else if (! yytable_value_is_error (yytable[yyindex])) - { - yyconflicts = yyconfl + yyconflp[yyindex]; - return yytable[yyindex]; - } - else - { - yyconflicts = yyconfl + yyconflp[yyindex]; - return 0; - } - } - - /** Compute post-reduction state. - * \param yystate the current state - * \param yysym the nonterminal to push on the stack - */ - static state_num - yyLRgotoState (state_num yystate, yysymbol_kind_t yysym) - { - const int yyr = yypgoto[yysym - YYNTOKENS] + yystate; - if (0 <= yyr && yyr <= YYLAST && yycheck[yyr] == yystate) - return yytable[yyr]; - else - return yydefgoto[yysym - YYNTOKENS]; - } - - static bool - yypact_value_is_default (state_num yystate) - { - return ]b4_table_value_equals([[pact]], [[yystate]], [b4_pact_ninf], [YYPACT_NINF])[; - } - - static bool - yytable_value_is_error (int yytable_value YY_ATTRIBUTE_UNUSED) - { - return ]b4_table_value_equals([[table]], [[yytable_value]], [b4_table_ninf], [YYTABLE_NINF])[; - } - - static bool - yy_is_shift_action (int yyaction) - { - return 0 < yyaction; - } - - static bool - yy_is_error_action (int yyaction) - { - return yyaction == 0; - } - - /** Whether LR state YYSTATE has only a default reduction - * (regardless of token). */ - static bool - yy_is_defaulted_state (state_num yystate) - { - return yypact_value_is_default (yypact[yystate]); - } - - /** The default reduction for YYSTATE, assuming it has one. */ - static rule_num - yy_default_action (state_num yystate) - { - return yydefact[yystate]; - } - - /* GLRStacks */ - - /** Y0 and Y1 represent two possible actions to take in a given - * parsing state; return 0 if no combination is possible, - * 1 if user-mergeable, 2 if Y0 is preferred, 3 if Y1 is preferred. */ - static int - yypreference (const semantic_option& y0, const semantic_option& y1) - { - rule_num r0 = y0.yyrule, r1 = y1.yyrule; - int p0 = yydprec[r0], p1 = yydprec[r1]; - - if (p0 == p1) - { - if (yymerger[r0] == 0 || yymerger[r0] != yymerger[r1]) + /** The action to take in YYSTATE on seeing YYTOKEN. + * Result R means + * R < 0: Reduce on rule -R. + * R = 0: Error. + * R > 0: Shift to state R. + * Set *YYCONFLICTS to a pointer into yyconfl to a 0-terminated list + * of conflicting reductions. + */ + static int + yygetLRActions (state_num yystate, yysymbol_kind_t yytoken, const short*& yyconflicts) + { + int yyindex = yypact[yystate] + yytoken; + if (yytoken == ]b4_symbol(error, kind)[) + { + // This is the error token. + yyconflicts = yyconfl; return 0; - else - return 1; - } - if (p0 == 0 || p1 == 0) + } + else if (yy_is_defaulted_state (yystate) + || yyindex < 0 || YYLAST < yyindex || yycheck[yyindex] != yytoken) + { + yyconflicts = yyconfl; + return -yydefact[yystate]; + } + else if (! yytable_value_is_error (yytable[yyindex])) + { + yyconflicts = yyconfl + yyconflp[yyindex]; + return yytable[yyindex]; + } + else + { + yyconflicts = yyconfl + yyconflp[yyindex]; + return 0; + } + } + + /** Compute post-reduction state. + * \param yystate the current state + * \param yysym the nonterminal to push on the stack + */ + static state_num + yyLRgotoState (state_num yystate, yysymbol_kind_t yysym) + { + const int yyr = yypgoto[yysym - YYNTOKENS] + yystate; + if (0 <= yyr && yyr <= YYLAST && yycheck[yyr] == yystate) + return yytable[yyr]; + else + return yydefgoto[yysym - YYNTOKENS]; + } + + static bool + yypact_value_is_default (state_num yystate) + { + return ]b4_table_value_equals([[pact]], [[yystate]], [b4_pact_ninf], [YYPACT_NINF])[; + } + + static bool + yytable_value_is_error (int yytable_value YY_ATTRIBUTE_UNUSED) + { + return ]b4_table_value_equals([[table]], [[yytable_value]], [b4_table_ninf], [YYTABLE_NINF])[; + } + + static bool + yy_is_shift_action (int yyaction) + { + return 0 < yyaction; + } + + static bool + yy_is_error_action (int yyaction) + { + return yyaction == 0; + } + + /** Whether LR state YYSTATE has only a default reduction + * (regardless of token). */ + static bool + yy_is_defaulted_state (state_num yystate) + { + return yypact_value_is_default (yypact[yystate]); + } + + /** The default reduction for YYSTATE, assuming it has one. */ + static rule_num + yy_default_action (state_num yystate) + { + return yydefact[yystate]; + } + + /* GLRStacks */ + + /** Y0 and Y1 represent two possible actions to take in a given + * parsing state; return 0 if no combination is possible, + * 1 if user-mergeable, 2 if Y0 is preferred, 3 if Y1 is preferred. */ + static int + yypreference (const semantic_option& y0, const semantic_option& y1) + { + rule_num r0 = y0.yyrule, r1 = y1.yyrule; + int p0 = yydprec[r0], p1 = yydprec[r1]; + + if (p0 == p1) + { + if (yymerger[r0] == 0 || yymerger[r0] != yymerger[r1]) + return 0; + else + return 1; + } + if (p0 == 0 || p1 == 0) + return 0; + if (p0 < p1) + return 3; + if (p1 < p0) + return 2; return 0; - if (p0 < p1) - return 3; - if (p1 < p0) - return 2; - return 0; - } + } -]b4_parse_param_vars[ - -}; + ]b4_parse_param_vars[ + }; // class ]b4_parser_class[::glr_stack +} // namespace ]b4_namespace_ref[ /* DEBUGGING ONLY */