glr2.cc: add support for variants

(Bison) Variants are extremely picky, which makes them both
annoying (lots of micro-details must be taken care of) and
precious (all the micro-details must be taken care of, in particular
object lifetime).

So (i) each time a semantic value is stored, it must be stored in a
place that exists, and (ii) each time a semantic value is discarded,
its place must have been emptied.

Example of (i)

    - new (&yys.value ()) value_type (s->value ());
    + {]b4_variant_if([[
    +   new (&yys.value ()) value_type ();
    +   ]b4_symbol_variant([yy_accessing_symbol (s->yylrState)],
    +                      [yys.value ()], [copy], [s->value ()])], [[
    +   new (&yys.value ()) value_type (s->value ());]])[
    + }

Example of (ii)

      yyparser.yy_destroy_ ("Error: discarding",
    -                       yytoken, &yylval]b4_locations_if([, &yylloc])[);
    +                       yytoken, &yylval]b4_locations_if([, &yylloc])[);]b4_variant_if([[
    + // Value type destructor.
    + ]b4_symbol_variant([[YYTRANSLATE (this->yychar)]], [[yylval]], [[template destroy]])])[
      this->yychar = ]b4_namespace_ref[::]b4_parser_class[::token::]b4_symbol(empty, id)[;

However, in some places we must not be "pure".  In particular:

    glr_stack_item (const glr_stack_item& other) YY_NOEXCEPT YY_NOTHROW
      : is_state_ (other.is_state_)
    {
      std::memcpy (raw_, other.raw_, union_size);
    }

still must use memcpy, because the constructor would change pred, and
it must not.  This constructor is used only when resizing the stack,
in which case pred (which is relative) must not be "adjusted".

The result works, but is messy.  Its verbosity comes from at least two
factors:

- we don't have support for complete symbols (binding kind, value and
  location), and we should at least try to have it.  That simplified
  lalr1.cc a lot.

- I have not tried to be smart and use 'move' when possible.  As a
  consequence many places have 'copy' and then 'destroy'.  That kind
  of clean up can be done once everything appears to be solid.

* data/skeletons/glr2.cc: Be more rigorous in object lifetime.
In particular, don't forget to discard the lookahead when we're done
with it.
Call variant routines where needed.
Deal with plenty of details.
(b4_call_merger): Add support for variants.
Use references in mergers, rather than pointers.

* examples/c++/glr/c++-types.yy: Exercise variants.
This commit is contained in:
Akim Demaille
2020-12-27 09:37:26 +01:00
parent c2a06bf791
commit e51e89856a
2 changed files with 171 additions and 52 deletions

View File

@@ -17,6 +17,9 @@
m4_include(b4_skeletonsdir/[c++.m4]) m4_include(b4_skeletonsdir/[c++.m4])
# api.value.type=variant is valid.
m4_define([b4_value_type_setup_variant])
# b4_tname_if(TNAME-NEEDED, TNAME-NOT-NEEDED) # b4_tname_if(TNAME-NEEDED, TNAME-NOT-NEEDED)
# ------------------------------------------- # -------------------------------------------
m4_define([b4_tname_if], m4_define([b4_tname_if],
@@ -28,6 +31,7 @@ m4_define([b4_tname_if],
b4_bison_locations_if([ b4_bison_locations_if([
m4_define([b4_location_constructors]) m4_define([b4_location_constructors])
m4_include(b4_skeletonsdir/[location.cc])]) m4_include(b4_skeletonsdir/[location.cc])])
b4_variant_if([m4_include(b4_skeletonsdir/[variant.hh])])
m4_define([b4_parser_class], m4_define([b4_parser_class],
[b4_percent_define_get([[api.parser.class]])]) [b4_percent_define_get([[api.parser.class]])])
@@ -127,8 +131,9 @@ m4_define([b4_rhs_location],
m4_define([b4_call_merger], m4_define([b4_call_merger],
[b4_case([$1], [b4_case([$1],
[ b4_symbol_if([$3], [has_type], [ b4_symbol_if([$3], [has_type],
[yy0->b4_symbol($3, slot) = $2 (*yy0, *yy1);], [b4_variant_if([yy0.as<b4_symbol($3, type)> () = $2 (yy0.as<b4_symbol($3, type)>(), yy1.as<b4_symbol($3, type)>());],
[*yy0 = $2 (*yy0, *yy1);])])]) [yy0.b4_symbol($3, slot) = $2 (yy0, yy1);])],
[yy0 = $2 (yy0, yy1);])])])
# b4_lex # b4_lex
# ------ # ------
@@ -734,6 +739,7 @@ yyrhsLength (rule_num yyrule);
class glr_state class glr_state
{ {
public: public:
typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind symbol_kind;
typedef ]b4_namespace_ref[::]b4_parser_class[::value_type value_type;]b4_locations_if([[ 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;]])[ typedef ]b4_namespace_ref[::]b4_parser_class[::location_type location_type;]])[
@@ -741,21 +747,24 @@ public:
: yyresolved (false) : yyresolved (false)
, yylrState (0) , yylrState (0)
, yyposn (0) , yyposn (0)
, yypred (0)]b4_locations_if([[ , yypred (0)
, yyfirstVal (0)]b4_locations_if([[
, yyloc ()]])[]b4_parse_assert_if([[ , yyloc ()]])[]b4_parse_assert_if([[
, magic_ (MAGIC)]])[ , magic_ (MAGIC)]])[
{} {}
/// Build with a semantic value. /// Build with a semantic value.
glr_state (state_num lrState, size_t posn, value_type sval]b4_locations_if([[, location_type loc]])[) glr_state (state_num lrState, size_t posn, const value_type& val]b4_locations_if([[, const location_type& loc]])[)
: yyresolved (true) : yyresolved (true)
, yylrState (lrState) , yylrState (lrState)
, yyposn (posn) , yyposn (posn)
, yypred (0) , yypred (0)
, yyval (sval)]b4_locations_if([[ , yyval (]b4_variant_if([], [[val]])[)]b4_locations_if([[
, yyloc (loc)]])[]b4_parse_assert_if([[ , yyloc (loc)]])[]b4_parse_assert_if([[
, magic_ (MAGIC)]])[ , magic_ (MAGIC)]])[
{} {]b4_variant_if([[
]b4_symbol_variant([yy_accessing_symbol (lrState)],
[yyval], [copy], [val])])[}
/// Build with a semantic option. /// Build with a semantic option.
glr_state (state_num lrState, size_t posn) glr_state (state_num lrState, size_t posn)
@@ -777,19 +786,33 @@ public:
, magic_ (MAGIC)]])[ , magic_ (MAGIC)]])[
{ {
setPred (other.pred ()); setPred (other.pred ());
if (other.yyresolved) if (other.yyresolved)]b4_variant_if([[
new (&yyval) value_type (other.value ()); {
new (&yyval) value_type ();
]b4_symbol_variant([yy_accessing_symbol (other.yylrState)],
[yyval], [copy], [other.value ()])[
}]], [[
new (&yyval) value_type (other.value ());]])[
else else
setFirstVal (other.firstVal ());]b4_parse_assert_if([[ {
yyfirstVal = 0;
setFirstVal (other.firstVal ());
}]b4_parse_assert_if([[
check_();]])[ check_();]])[
} }
~glr_state () ~glr_state ()
{]b4_parse_assert_if([[ {]b4_parse_assert_if([[
check_ (); check_ ();]])[
magic_ = 0;]])[
if (yyresolved) if (yyresolved)
yyval.~value_type (); {]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) glr_state& operator= (const glr_state& other)
@@ -802,8 +825,10 @@ public:
yylrState = other.yylrState; yylrState = other.yylrState;
yyposn = other.yyposn; yyposn = other.yyposn;
setPred (other.pred ()); setPred (other.pred ());
if (other.yyresolved) if (other.yyresolved)]b4_variant_if([[
value () = other.value (); ]b4_symbol_variant([yy_accessing_symbol (other.yylrState)],
[yyval], [copy], [other.value ()])], [[
value () = other.value ();]])[
else else
setFirstVal (other.firstVal ());]b4_locations_if([[ setFirstVal (other.firstVal ());]b4_locations_if([[
yyloc = other.yyloc;]])[ yyloc = other.yyloc;]])[
@@ -1061,6 +1086,7 @@ private:
class semantic_option class semantic_option
{ {
public: public:
typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind symbol_kind;
typedef ]b4_namespace_ref[::]b4_parser_class[::value_type value_type;]b4_locations_if([[ 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;]])[ typedef ]b4_namespace_ref[::]b4_parser_class[::location_type location_type;]])[
@@ -1068,7 +1094,9 @@ public:
: yyrule (0) : yyrule (0)
, yystate (0) , yystate (0)
, yynext (0) , yynext (0)
, yychar (0)]b4_parse_assert_if([[ , yychar (0)
, yyval ()]b4_locations_if([[
, yyloc ()]])[]b4_parse_assert_if([[
, magic_ (MAGIC)]])[ , magic_ (MAGIC)]])[
{} {}
@@ -1076,10 +1104,42 @@ public:
: yyrule (rule) : yyrule (rule)
, yystate (0) , yystate (0)
, yynext (0) , yynext (0)
, yychar (rawChar)]b4_parse_assert_if([[ , yychar (rawChar)
, yyval ()]b4_locations_if([[
, yyloc ()]])[]b4_parse_assert_if([[
, magic_ (MAGIC)]])[ , magic_ (MAGIC)]])[
{} {}
semantic_option (const semantic_option& that)
: yyrule (that.yyrule)
, yystate (that.yystate)
, yynext (that.yynext)
, yychar (that.yychar)
, yyval (]b4_variant_if([], [[that.yyval]])[)]b4_locations_if([[
, yyloc (that.yyloc)]])[]b4_parse_assert_if([[
, magic_ (MAGIC)]])[
{]b4_parse_assert_if([[
that.check_ ();]])[]b4_variant_if([[
]b4_symbol_variant([YYTRANSLATE (yychar)],
[yyval], [copy], [that.yyval])])[
}
// Needed for the assignment in yynewSemanticOption.
semantic_option& operator= (const semantic_option& that)
{]b4_parse_assert_if([[
check_ ();
that.check_ ();]])[
yyrule = that.yyrule;
yystate = that.yystate;
yynext = that.yynext;
yychar = that.yychar;]b4_variant_if([[
]b4_symbol_variant([YYTRANSLATE (yychar)],
[yyval], [copy], [that.yyval])], [[
yyval = that.yyval;]])[]b4_locations_if([[
yyloc = that.yyloc;]])[
return *this;
}
/// Only call state() and setState() on objects in yyitems, not temporaries. /// Only call state() and setState() on objects in yyitems, not temporaries.
glr_state* state(); glr_state* state();
const glr_state* state() const; const glr_state* state() const;
@@ -1134,13 +1194,19 @@ public:
break; break;
else if (yys0->yyresolved) else if (yys0->yyresolved)
{ {
yys1->yyresolved = true; yys1->yyresolved = true;]b4_variant_if([[
yys1->value () = yys0->value (); YYASSERT (yys1->yylrState == yys0->yylrState);
]b4_symbol_variant([yy_accessing_symbol (yys0->yylrState)],
[yys1->value ()], [copy], [yys0->value ()])], [[
yys1->value () = yys0->value ();]])[
} }
else if (yys1->yyresolved) else if (yys1->yyresolved)
{ {
yys0->yyresolved = true; yys0->yyresolved = true;]b4_variant_if([[
yys0->value () = yys1->value (); YYASSERT (yys0->yylrState == yys1->yylrState);
]b4_symbol_variant([yy_accessing_symbol (yys1->yylrState)],
[yys0->value ()], [copy], [yys1->value ()])], [[
yys0->value () = yys1->value ();]])[
} }
else else
{ {
@@ -1300,6 +1366,7 @@ public:
check_ (); check_ ();
other.check_ ();]])[ other.check_ ();]])[
std::swap (is_state_, other.is_state_); std::swap (is_state_, other.is_state_);
// NB: swap on arrays is C++11.
std::swap (raw_, other.raw_); std::swap (raw_, other.raw_);
return *this; return *this;
} }
@@ -1520,6 +1587,7 @@ yyLRgotoState (state_num yystate, yysymbol_kind_t yysym);
class state_stack class state_stack
{ {
public: public:
typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind symbol_kind;
typedef ]b4_namespace_ref[::]b4_parser_class[::value_type value_type;]b4_locations_if([[ 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;]])[ typedef ]b4_namespace_ref[::]b4_parser_class[::location_type location_type;]])[
@@ -1721,10 +1789,11 @@ public:
/** Return a fresh GLRState. /** Return a fresh GLRState.
* Callers should call yyreserveStack afterwards to make sure there is * Callers should call yyreserveStack afterwards to make sure there is
* sufficient headroom. */ * sufficient headroom. */
glr_state& yynewGLRState(glr_state newState) { glr_state& yynewGLRState (const glr_state& newState)
glr_state& state = yyitems[yynewGLRStackItem(true)].getState(); {
#if 201103L <= YY_CPLUSPLUS glr_state& state = yyitems[yynewGLRStackItem (true)].getState ();
state = std::move(newState); #if false && 201103L <= YY_CPLUSPLUS
state = std::move (newState);
#else #else
state = newState; state = newState;
#endif #endif
@@ -1775,7 +1844,12 @@ public:
#endif #endif
yys.yyresolved = s->yyresolved; yys.yyresolved = s->yyresolved;
if (s->yyresolved) if (s->yyresolved)
new (&yys.value ()) value_type (s->value ()); {]b4_variant_if([[
new (&yys.value ()) value_type ();
]b4_symbol_variant([yy_accessing_symbol (s->yylrState)],
[yys.value ()], [copy], [s->value ()])], [[
new (&yys.value ()) value_type (s->value ());]])[
}
else else
/* The effect of using yyval or yyloc (in an immediate /* The effect of using yyval or yyloc (in an immediate
* rule) is undefined. */ * rule) is undefined. */
@@ -1922,6 +1996,7 @@ public:
class glr_stack class glr_stack
{ {
public: public:
typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind symbol_kind;
typedef ]b4_namespace_ref[::]b4_parser_class[::value_type value_type;]b4_locations_if([[ 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;]])[ typedef ]b4_namespace_ref[::]b4_parser_class[::location_type location_type;]])[
@@ -1988,8 +2063,10 @@ public:
yynewOption.setNext(yystate->firstVal()); yynewOption.setNext(yystate->firstVal());
if (yystateStack.yytops.lookaheadNeeds(yyk)) if (yystateStack.yytops.lookaheadNeeds(yyk))
{ {
yynewOption.yychar = this->yychar; yynewOption.yychar = this->yychar;]b4_variant_if([[
yynewOption.yyval = this->yylval;]b4_locations_if([ ]b4_symbol_variant([YYTRANSLATE (this->yychar)],
[yynewOption.yyval], [copy], [this->yylval])], [[
yynewOption.yyval = this->yylval;]])[]b4_locations_if([
yynewOption.yyloc = this->yylloc;])[ yynewOption.yyloc = this->yylloc;])[
} }
yystate->setFirstVal(&yynewOption); yystate->setFirstVal(&yynewOption);
@@ -2133,7 +2210,9 @@ public:
YYLLOC_DEFAULT ((yys->yyloc), yyerror_range, 2);]])[ YYLLOC_DEFAULT ((yys->yyloc), yyerror_range, 2);]])[
yysymbol_kind_t yytoken = YYTRANSLATE (this->yychar); yysymbol_kind_t yytoken = YYTRANSLATE (this->yychar);
yyparser.yy_destroy_ ("Error: discarding", yyparser.yy_destroy_ ("Error: discarding",
yytoken, &yylval]b4_locations_if([, &yylloc])[); yytoken, &yylval]b4_locations_if([, &yylloc])[);]b4_variant_if([[
// Value type destructor.
]b4_symbol_variant([[YYTRANSLATE (this->yychar)]], [[yylval]], [[template destroy]])])[
this->yychar = ]b4_namespace_ref[::]b4_parser_class[::token::]b4_symbol(empty, id)[; this->yychar = ]b4_namespace_ref[::]b4_parser_class[::token::]b4_symbol(empty, id)[;
} }
yysymbol_kind_t yytoken = yygetToken (this->yychar, yyparser, *this]b4_user_args[); yysymbol_kind_t yytoken = yygetToken (this->yychar, yyparser, *this]b4_user_args[);
@@ -2307,10 +2386,18 @@ public:
return yyparser.error (]b4_locations_if([*yylocp, ])[YY_("syntax error: cannot back up")), \ return yyparser.error (]b4_locations_if([*yylocp, ])[YY_("syntax error: cannot back up")), \
yyerrok, yyerr 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) if (yyrhslen == 0)
*yyvalp = yyval_default; *yyvalp = yyval_default;
else else
*yyvalp = yyvsp[YYFILL (1-yyrhslen)].getState().value ();]b4_locations_if([[ *yyvalp = yyvsp[YYFILL (1-yyrhslen)].getState().value ();]])[]b4_locations_if([[
/* Default location. */ /* Default location. */
YYLLOC_DEFAULT ((*yylocp), (yyvsp - yyrhslen), yyrhslen); YYLLOC_DEFAULT ((*yylocp), (yyvsp - yyrhslen), yyrhslen);
yyerror_range[1].getState().yyloc = *yylocp; yyerror_range[1].getState().yyloc = *yylocp;
@@ -2444,7 +2531,10 @@ public:
yyglrShift (yyk, yyglrShift (yyk,
yyLRgotoState (topState(yyk)->yylrState, yyLRgotoState (topState(yyk)->yylrState,
yylhsNonterm (yyrule)), yylhsNonterm (yyrule)),
yyposn, val]b4_locations_if([, loc])[); yyposn, val]b4_locations_if([, loc])[);]b4_variant_if([[
// FIXME: User destructors.
// Value type destructor.
]b4_symbol_variant([[yylhsNonterm (yyrule)]], [[val]], [[template destroy]])])[
} }
else else
{ {
@@ -2509,7 +2599,7 @@ public:
void void
yyglrShift (state_set_index yyk, state_num yylrState, yyglrShift (state_set_index yyk, state_num yylrState,
size_t yyposn, size_t yyposn,
value_type& yyval_arg]b4_locations_if([, const location_type& yyloc_arg])[) const value_type& yyval_arg]b4_locations_if([, const location_type& yyloc_arg])[)
{ {
glr_state& yynewState = yystateStack.yynewGLRState ( glr_state& yynewState = yystateStack.yynewGLRState (
glr_state (yylrState, yyposn, yyval_arg]b4_locations_if([, yyloc_arg])[)); glr_state (yylrState, yyposn, yyval_arg]b4_locations_if([, yyloc_arg])[));
@@ -2576,7 +2666,7 @@ private:
} }
static void static void
yyuserMerge (int yyn, value_type* yy0, value_type* yy1) yyuserMerge (int yyn, value_type& yy0, value_type& yy1)
{ {
YY_USE (yy0); YY_USE (yy0);
YY_USE (yy1); YY_USE (yy1);
@@ -2664,7 +2754,10 @@ private:
&this->yylval]b4_locations_if([, yylocp])[); &this->yylval]b4_locations_if([, yylocp])[);
break; break;
} }
yyuserMerge (yymerger[yyp->yyrule], &val, &yyval_other); 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]])])[
} }
} }
} }
@@ -2674,12 +2767,20 @@ private:
if (yyflag == yyok) if (yyflag == yyok)
{ {
yys.yyresolved = true; yys.yyresolved = true;
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN]b4_variant_if([[
new (&yys.value ()) value_type (val); 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 YY_IGNORE_MAYBE_UNINITIALIZED_END
} }
else else
yys.setFirstVal(YY_NULLPTR); 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; return yyflag;
} }
@@ -2708,18 +2809,27 @@ private:
/* Set default location. */ /* Set default location. */
yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].getState().yyloc = yyoptState->yyloc;]])[ yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].getState().yyloc = yyoptState->yyloc;]])[
{ {
int yychar_current = this->yychar; int yychar_current = this->yychar;]b4_variant_if([[
value_type yylval_current = this->yylval;]b4_locations_if([ value_type yylval_current;
]b4_symbol_variant([YYTRANSLATE (this->yychar)],
[yylval_current], [move], [this->yylval])], [[
value_type yylval_current = this->yylval;]])[]b4_locations_if([
location_type yylloc_current = this->yylloc;])[ location_type yylloc_current = this->yylloc;])[
this->yychar = yyopt.yychar;
this->yylval = yyopt.yyval;]b4_locations_if([ this->yychar = yyopt.yychar;]b4_variant_if([[
]b4_symbol_variant([YYTRANSLATE (this->yychar)],
[this->yylval], [move], [yyopt.yyval])], [[
this->yylval = yyopt.yyval;]])[]b4_locations_if([
this->yylloc = yyopt.yyloc;])[ this->yylloc = yyopt.yyloc;])[
yyflag = yyuserAction (yyopt.yyrule, yynrhs, yyflag = yyuserAction (yyopt.yyrule, yynrhs,
yyrhsVals + YYMAXRHS + YYMAXLEFT - 1, yyrhsVals + YYMAXRHS + YYMAXLEFT - 1,
create_state_set_index (-1), create_state_set_index (-1),
yyvalp]b4_locations_if([, yylocp])[); yyvalp]b4_locations_if([, yylocp])[);
this->yychar = yychar_current;
this->yylval = yylval_current;]b4_locations_if([ this->yychar = yychar_current;]b4_variant_if([[
]b4_symbol_variant([YYTRANSLATE (this->yychar)],
[this->yylval], [move], [yylval_current])], [[
this->yylval = yylval_current;]])[]b4_locations_if([
this->yylloc = yylloc_current;])[ this->yylloc = yylloc_current;])[
} }
return yyflag; return yyflag;
@@ -2967,8 +3077,8 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
YYCDEBUG << "Starting parse\n"; YYCDEBUG << "Starting parse\n";
yystack.yychar = ]b4_namespace_ref::b4_parser_class[::token::]b4_symbol(empty, id)[; yystack.yychar = token::]b4_symbol(empty, id)[;]b4_variant_if([], [[
yystack.yylval = yyval_default;]b4_locations_if([ yystack.yylval = yyval_default;]])[]b4_locations_if([
yystack.yylloc = yyloc_default;])[ yystack.yylloc = yyloc_default;])[
]m4_ifdef([b4_initial_action], [ ]m4_ifdef([b4_initial_action], [
b4_dollar_pushdef([yystack.yylval], [], [], [yystack.yylloc])dnl b4_dollar_pushdef([yystack.yylval], [], [], [yystack.yylloc])dnl
@@ -3020,7 +3130,11 @@ b4_dollar_popdef])[]dnl
YY_SYMBOL_PRINT ("Shifting", yytoken, &yystack.yylval, &yystack.yylloc); YY_SYMBOL_PRINT ("Shifting", yytoken, &yystack.yylval, &yystack.yylloc);
yystack.yychar = token::]b4_symbol(empty, id)[; yystack.yychar = token::]b4_symbol(empty, id)[;
yyposn += 1; yyposn += 1;
yystack.yyglrShift (create_state_set_index(0), yyaction, yyposn, yystack.yylval]b4_locations_if([, yystack.yylloc])[); // FIXME: we should move yylval.
yystack.yyglrShift (create_state_set_index(0), yyaction, yyposn, yystack.yylval]b4_locations_if([, yystack.yylloc])[);]b4_variant_if([[
// FIXME: User destructors.
// Value type destructor.
]b4_symbol_variant([[yytoken]], [[yystack.yylval]], [[template destroy]])])[
if (0 < yystack.yyerrState) if (0 < yystack.yyerrState)
yystack.yyerrState -= 1; yystack.yyerrState -= 1;
} }
@@ -3098,6 +3212,10 @@ b4_dollar_popdef])[]dnl
YYCDEBUG << "Stack " << yys.get() << " now in state " YYCDEBUG << "Stack " << yys.get() << " now in state "
<< yystack.topState(yys)->yylrState << '\n'; << yystack.topState(yys)->yylrState << '\n';
} }
]b4_variant_if([[
// FIXME: User destructors.
// Value type destructor.
]b4_symbol_variant([[yytoken_to_shift]], [[yystack.yylval]], [[template destroy]])])[
if (yystack.yystateStack.yytops.size() == 1) if (yystack.yystateStack.yytops.size() == 1)
{ {

View File

@@ -34,7 +34,7 @@
#include "ast.hh" #include "ast.hh"
} }
%define api.value.type {Node} %define api.value.type variant
%code %code
{ {
@@ -47,8 +47,8 @@
# define nullptr 0 # define nullptr 0
#endif #endif
static yy::parser::value_type static Node
stmtMerge (const yy::parser::value_type& x0, const yy::parser::value_type& x1); stmtMerge (const Node& x0, const Node& x1);
static int static int
yylex (yy::parser::value_type* val, yy::parser::location_type* loc); yylex (yy::parser::value_type* val, yy::parser::location_type* loc);
@@ -56,12 +56,13 @@
%expect-rr 1 %expect-rr 1
%type <Node> TYPENAME ID stmt expr decl declarator
%printer { yyo << $$; } <Node>
%token %token
TYPENAME "typename" TYPENAME "typename"
ID "identifier" ID "identifier"
%printer { yyo << $$; } TYPENAME ID stmt expr decl declarator
%right '=' %right '='
%left '+' %left '+'
@@ -148,7 +149,7 @@ yylex (yy::parser::value_type* lvalp, yy::parser::location_type* llocp)
= isupper (static_cast <unsigned char> (form[0])) = isupper (static_cast <unsigned char> (form[0]))
? yy::parser::token::TYPENAME ? yy::parser::token::TYPENAME
: yy::parser::token::ID; : yy::parser::token::ID;
*lvalp = Term (form); lvalp->emplace<Node> (Term (form));
} }
else else
{ {
@@ -163,8 +164,8 @@ yylex (yy::parser::value_type* lvalp, yy::parser::location_type* llocp)
} }
} }
static yy::parser::value_type static Node
stmtMerge (const yy::parser::value_type& x0, const yy::parser::value_type& x1) stmtMerge (const Node& x0, const Node& x1)
{ {
return Nterm ("<OR>", x0, x1); return Nterm ("<OR>", x0, x1);
} }