c++ - 分解出精神规则的共同部分

标签 c++ boost-spirit

我有很多具有共同前缀和后缀的规则:

rule = begin_stuff >> some >> other >> stuff >> end_stuff.

(其中 begin_stuffend_stuff 由文字组成)

我想说

 rule = wrapped(some >> other >> stuff);

我尝试了一些类似的事情

  template<typename Rule> Rule wrapped(Rule inside) 
  {
    Rule result;
    result = begin_stuff >> inside >> end_stuff;
    return result;
  }

但我得到的只是来自 Qi 的大量编译时断言。

如何以这种方式重构 Spirit 规则?

最佳答案

我认为您正在寻找“子规则”(Spirit V1/classical 曾经有)。这些现在已经过时了。

看看

  • c++11 autoBOOST_AUTO

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

    过去在 Spirit 规则(尤其是 MSVC)上使用 auto 时会出现问题(请参阅 Zero to 60 MPH in 2 seconds! 和评论),但我很快就被告知了这一点 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 - 在 Mini XML - ASTs 中介绍教程

这是一个概念证明,它将公共(public)子规则传递给不同的“复合”规则,以允许包装在 ()[]{} :

#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")) );
}

输出:

'{ 231 }'   parse success
'{ hello }' parse success
'( 231 )'   parse success
'( hello )' parse success
'[ 231 ]'   parse success
'[ hello ]' parse success
PS。请注意,上面不是典型的 Spirit 语法。当“通用”规则会公开不同的属性时,这种方式效果不太好。

关于c++ - 分解出精神规则的共同部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13388227/

相关文章:

c++ - 我可以在循环 vector<shared_ptr<BaseClass>> 时以某种方式调用派生类方法吗?

c++ - VS2015 中的 std::thread 错误 C2893

c++ - 如何从循环中构建 boost::spirit 规则?

c++ - spirit X3怎么加条件期望值

c++ - 使用 boost::spirit 在 C++ 中读取二维数组

c++ - 如何使用字符串名称而不是变量?

c++ - 注入(inject) C++ DLL

c++ - 有没有办法让模板匹配所有指针类型?

c++ - 使用 Spirit 将 std::vector<std::vector<double> 解析为结构体属性

c++ - 我如何更改此示例中的语法以解析“AND ( (OR (a b c)) (NOT (d)))