2013-01-24 32 views
2

我需要匹配一些输入,构造一个复杂的对象,然后以两种方式匹配其余输入,具体取决于某些道具。的构建对象。 我试过了qi :: eps(/ 条件 /)>> p1 | p2但结果对我来说很明显。 简化代码http://liveworkspace.org/code/1NzThA $ 6助力精神气 - 条件解析

在代码片段,我从输入int_匹配,如果该值== 0尝试匹配“a”或者 - “B” 但我得到了“0B”输入OK!我试图玩大括号,但没有运气。

+0

通过补气可能的解决方法::懒http://liveworkspace.org/code/2B4VCK$8 – user2008982

+0

我已经添加了一个没有语义行为的答案([Boost Spirit:“Semantic actions is evil”?](http://stackoverflow.com/questions/8259440/boost-spirit-semantic-actions-are-evil/8259585#8259585)) – sehe

+0

@sehe:语义行为是邪恶的:你的文章很大一部分是专门讨论基本:)虽然,虽然采取了点,但恕我直言问题与解析器中的上下文敏感性,而不是使其成为一个实际的解析问题,该示例是一个微不足道的表达。我的2c。不过,如果我们中的一个人被接受,这将是一件好事... – FatalFlaw

回答

1

这是你的规则:

qi::rule<char const*> r = 
    qi::int_ [phoenix::ref(p) = qi::_1] 
    >> (qi::eps(phoenix::ref(p) == 0) 
     >> qi::char_('a') | qi::char_('b')) 

那对我说:接受与 'B' 结束 '0A' 或任何东西。这与您在代码段中获得的结果相符。

我承认我并不完全理解你的问题,但是如果你试图获得某种'独占'或'事情发生(如代码片段中的注释所示),那么这个规则是不完整的。您在评论中提出的解决方法(实际上更多的是“修复”而不是“解决方法”)是一种解决方案,但您不需要​​,因为基于凤凰的Qi本地人已经很懒惰,但是您位于右侧跟踪。这是另一种(更具可读性的)解决方案。

qi::rule<char const*> r = 
    qi::int_ [phoenix::ref(p) = qi::_1] 
    >> ((qi::eps(phoenix::ref(p) == 0) >> qi::char_('a')) | 
     (qi::eps(phoenix::ref(p) == 1) >> qi::char_('b'))) 
; 

如果你喜欢使用当地人<>您在您的评论加入,那也没关系,但使用参考p的代码添加较少的开销,只要你记住不要设置p其他地方在你的语法中,你不会最终建立一个递归该规则的语法:)

3

我个人不会轻易使用语义动作(或凤凰)。这不是齐的“精神”(双关半意)。

这是我的看法:

rule<char const*, char()> r = 
    (omit [ int_(0) ] >> char_('a')) | 
    (omit [ int_(1) ] >> char_('b')) 
    ; 

看到了吗?更干净。另外:自动属性传播。看到它住在http://liveworkspace.org/code/1T9h5

输出:

ok: a 
fail 
fail 
ok: b 

完整的示例代码:

//#define BOOST_SPIRIT_DEBUG 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 

namespace qi = boost::spirit::qi; 
namespace phoenix = boost::phoenix; 

template <typename P> 
inline 
void test_parser(char const* input, P const& p, bool full_match = true) 
{ 
    char const* f(input); 
    char const* l(f + strlen(f)); 
    char result; 
    if (qi::parse(f, l, p, result) && (!full_match || (f == l))) 
     std::cout << "ok: " << result << std::endl; 
    else 
     std::cout << "fail" << std::endl; 
} 

int main() 
{ 
    int p; 
    using namespace qi; 
    rule<char const*, char()> r = 
     (omit [ int_(0) ] >> char_('a')) | 
     (omit [ int_(1) ] >> char_('b')) 
     ; 

    BOOST_SPIRIT_DEBUG_NODE(r); 

    test_parser("0a", r); //should match 
    test_parser("0b", r); //should not match 
    test_parser("1a", r); //should not match 
    test_parser("1b", r); //should match 
}