2013-01-24 64 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 
}