Skip to content

Instantly share code, notes, and snippets.

@cppljevans
Created March 6, 2019 05:53
Show Gist options
  • Save cppljevans/e1fa1f6a0ebfda6bea8ae0ec1c823e41 to your computer and use it in GitHub Desktop.
Save cppljevans/e1fa1f6a0ebfda6bea8ae0ec1c823e41 to your computer and use it in GitHub Desktop.
Joel's suggested changes (and a little more)
//Purpose:
// Follow Joel's suggestion about changing the
// xform_rule attribute to double expressed here:
// https://github.com/boostorg/spirit/issues/459#issuecomment-469476231
//Result:
// **SAME** result when defined(CALL_RULE_DEFINITION_SPECIALIZATION).
// IOW, the wrong value for `attr_rule`. Without this define,
// the results are as expected, i.e. `attr_rule` == 1235.
// However, that's because, **behind the scenes**, spirit is
// making a redundant (i.e. useless) call to the default
// transform which is a no-op. The key word here is **useless**.
// If something is useless, it should be removed. Of course there is
// a use-case where the transform is needed, i.e. when a rule_definition
// is the argument to x3::parse; however, that case is handled
// by moving the transform from call_rule_definition to rule_definition::parse.
// IOW, the same place it occurs in rule::parse. Is there a problem with that move
// as implmeneted in PR#479?
//========
#include <iostream>
#include <boost/spirit/home/x3.hpp>
namespace x3=boost::spirit::x3;
using xform_attr=double;
using parse_attr=int;
namespace boost { namespace spirit { namespace x3
{
//The end-user **does** expect this to be used
//because the call to x3::parse **does** use
//Exposed (i.e. parse_attr) as the type of the attr argument.
template <>
struct transform_attribute
< parse_attr//Exposed
, xform_attr//Transformed
>
{
typedef parse_attr Exposed;
typedef xform_attr Transformed;
typedef Transformed type;
static type pre(Exposed&exposed)
{
return 3000;
}
static void post(Exposed& val, type&& transformed)
{
val=transformed+1;//non-default transform
std::cout<<"<parse_attr,xform_attr>::val="<<val<<"\n";
}
};
#define CALL_RULE_DEFINITION_SPECIALIZATION
#ifdef CALL_RULE_DEFINITION_SPECIALIZATION
//The end-user does **not** expect this to be used
//because the call to x3::parse does **not** use
//Exposed(i.e. xform_attr) as the type of the attr argument.
//
//**Yet, with the current develop branch, it **is** used
//in call_rule_definition **when** it's called from
//rule::parse.
//
//Let's call this an "ill-use" of transform_attribute.
//
template <>
struct transform_attribute
< xform_attr//Exposed
, xform_attr//Transformed
>
{
typedef xform_attr Exposed;
typedef xform_attr Transformed;
typedef xform_attr& type;
static type pre(Exposed&exposed)
{
return exposed;
}
static void post(Exposed& val, Transformed const& transformed)
{
val=transformed+1;//non-default transform
std::cout<<"<xform_attr,xform_attr>::val="<<val<<"\n";
}
};
#endif//CALL_RULE_DEFINITION_SPECIALIZATION
}}}
auto xform_rule_def=x3::int_;
x3::rule<class xform_rule_id,xform_attr> xform_rule="xform_rule";
BOOST_SPIRIT_DEFINE(xform_rule)
int main()
{
std::string input_str="1234";
using iter_t=std::string::iterator;
iter_t const first=input_str.begin();
iter_t const last=input_str.end();
//#define USE_DEFN
#ifdef USE_DEFN
parse_attr attr_defn=1000;
bool result_defn=
x3::parse
( first
, last
, xform_rule = xform_rule_def //only 1 transform
, attr_defn
);
std::cout<<"result_defn="<<result_defn<<":attr_defn="<<attr_defn<<"\n";
#endif
#define USE_RULE
#ifdef USE_RULE
parse_attr attr_rule=2000;
bool result_rule=
x3::parse
( first
, last
, xform_rule //2 transforms with develop branch
, attr_rule
);
//attr_defn should be same as attr_rule:
std::cout<<"result_rule="<<result_rule<<":attr_rule="<<attr_rule<<"\n";
#endif
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment