Factoring out common parts of Spirit rules

后端 未结 2 1674
失恋的感觉
失恋的感觉 2020-12-21 16:55

I have a lot of rules that have common prefix and suffix:

rule = begin_stuff >> some >> other >> stuff >> end_stuff.
<
相关标签:
2条回答
  • 2020-12-21 17:34

    I think you are looking for 'subrules' (that Spirit V1/classical used to have). These are obsolete now.

    Have a look at

    • c++11 auto and BOOST_AUTO

      auto subexpression = int_ >> ',' >> double_;
      qi::rule<It> rule  = "A:" >> subexpression >> "Rest:" >> (subexpression % eol);
      

      There used to be issues with using auto on Spirit rules (notably with MSVC) (see Zero to 60 MPH in 2 seconds! and comments) but I have been informed this (soon) is no longer an issue:

      Yep. Anyway,FYI, it's fixed in Spirit-3. You can 
      use auto all you want. 
      
      Regards, 
      -- 
      Joel de Guzman
      
    • qi::lazy

    • inherited arguments - introduced in the Mini XML - ASTs tutorial

    Here is a proof of concept that passes a common subrule to different 'compound' rules to allow for wrapping in (), [] or {}:

    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    
    namespace qi = boost::spirit::qi;
    namespace phx = boost::phoenix;
    
    typedef std::string::const_iterator It;
    
    template <typename R>
        void test(const std::string& input, R const& rule)
    {
        It f(input.begin()), l(input.end());
        bool ok = qi::phrase_parse(f,l,rule,qi::space);
        std::cout << "'" << input << "'\tparse " << (ok?"success":"failure") << "\n";
    }
    
    int main()
    {
        typedef qi::rule<It,                    qi::space_type> common_rule;
        typedef qi::rule<It, void(common_rule), qi::space_type> compound_rule;
    
        common_rule common = qi::int_;
    
        compound_rule 
            in_parens   = qi::lit('(') >> qi::_r1 >> ')',
            in_brackets = qi::lit('[') >> qi::_r1 >> ']',
            in_braces   = qi::lit('{') >> qi::_r1 >> '}';
    
        test("{ 231 }"  , in_braces  (phx::ref(common )) );
        test("{ hello }", in_braces  (phx::val("hello")) );
    
        test("( 231 )"  , in_parens  (phx::ref(common )) );
        test("( hello )", in_parens  (phx::val("hello")) );
    
        test("[ 231 ]"  , in_brackets(phx::ref(common )) );
        test("[ hello ]", in_brackets(phx::val("hello")) );
    }
    

    Output:

    '{ 231 }'   parse success
    '{ hello }' parse success
    '( 231 )'   parse success
    '( hello )' parse success
    '[ 231 ]'   parse success
    '[ hello ]' parse success
    

    PS. Note the above is not a typical Spirit grammar. This way doesn't play too well when the 'common' rule would expose different attributes.

    0 讨论(0)
  • 2020-12-21 17:42

    I think you need to use the Qi Confix Parser Derective from Spirit Repository. It is exactly what you need.

    0 讨论(0)
提交回复
热议问题