Skip to content

Instantly share code, notes, and snippets.

@cppljevans
Created March 6, 2019 05:53

Revisions

  1. cppljevans created this gist Mar 6, 2019.
    124 changes: 124 additions & 0 deletions x3-only_1_xform-double_int.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,124 @@
    //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;
    }