2014-02-22 54 views
6

如何防止Boost Spirit Symbol解析器在以有效關鍵字(符號)開始時接受關鍵字(符號)。我希望構造失敗解析'ONEMORE'作爲一個整體,並不能成功解析'ONE',因爲這是一個有效的關鍵字,然後在'更多'上失敗。防止Boost Spirit Symbol解析器太早接受關鍵字

這裏是下面的代碼的實際輸出:

Keyword as a number: 1 
Keyword as a number: 2 
Keyword as a number: 1 
Invalid keyword: MORETHREE 

而這也是我喜歡它是:

Keyword as a number: 1 
Keyword as a number: 2 
Invalid keyword: ONEMORE 
Keyword as a number: 3 

的代碼只是一個樣本,以傳達出點。

#include <boost/config/warning_disable.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <iostream> 
#include <string> 

using namespace std; 
namespace qi = boost::spirit::qi; 
namespace ascii = boost::spirit::ascii; 

void printNumber(unsigned u) 
{ 
    cout << "Keyword as a number: " << u << endl; 
} 

void printInvalidKeyword(const string &s) 
{ 
    cout << "Invalid keyword: " << s << endl; 
} 

template <typename Iterator> 
struct keyword_parser : qi::grammar<Iterator, ascii::space_type> 
{ 
    struct mySymbols_ : qi::symbols<char, unsigned> 
    { 
     mySymbols_() 
     { 
      add 
      ("ONE" , 1) 
      ("TWO" , 2) 
      ("THREE" , 2) 
      ; 
     } 

    } mySymbols; 

    keyword_parser() : keyword_parser::base_type(start) 
    { 
     using qi::_1; 
     using qi::raw; 
     using ascii::char_; 

     start %= *(
        mySymbols[&printNumber] 
        | 
        invalid[&printInvalidKeyword] 
        ); 

     invalid = +char_; 

    } 

    qi::rule<Iterator, ascii::space_type> start; 
    qi::rule<Iterator, std::string(), ascii::space_type> invalid; 
}; 

int main() 
{ 
    using boost::spirit::ascii::space; 
    typedef std::string::const_iterator iterator_type; 
    typedef keyword_parser<iterator_type> keyword_parser; 

    std::string s = "ONE TWO ONEMORE THREE"; 
    iterator_type b = s.begin(); 
    iterator_type e = s.end(); 
    phrase_parse(b, e, keyword_parser(), space); 

    return 0; 
} 

回答

6

qi::repository::distinct外觀或採取一些措施,你自己:正在申報

start %= *(
      keyword [cout << val("Keyword as a number: ") << _1 << endl] 
     | invalid [cout << val("Invalid keyword: ")  << _1 << endl] 
     ); 

keyword = mySymbols >> !(char_("a-zA-Z0-9_")); 

invalid = +ascii::graph; 

的規則

qi::rule<Iterator, ascii::space_type> start; 

// lexemes do not ignore embedded skippables 
qi::rule<Iterator, int()> keyword; 
qi::rule<Iterator, std::string()> invalid; 

看到它Live On Coliru

打印:

Keyword as a number: 1 
Keyword as a number: 2 
Invalid keyword: ONEMORE 
Keyword as a number: 2 

完整的源:

#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 
#include <iostream> 
#include <string> 

using namespace std; 
namespace qi = boost::spirit::qi; 
namespace phx = boost::phoenix; 
namespace ascii = boost::spirit::ascii; 

template <typename Iterator> 
struct keyword_parser : qi::grammar<Iterator, ascii::space_type> 
{ 
    struct mySymbols_ : qi::symbols<char, unsigned> 
    { 
     mySymbols_() 
     { 
      add 
      ("ONE" , 1) 
      ("TWO" , 2) 
      ("THREE" , 2) 
      ; 
     } 

    } mySymbols; 

    keyword_parser() : keyword_parser::base_type(start) 
    { 
     using qi::_1; 
     using ascii::char_; 
     using phx::val; 

     start %= *(
        keyword [cout << val("Keyword as a number: ") << _1 << endl] 
       | invalid [cout << val("Invalid keyword: ")  << _1 << endl] 
       ); 

     keyword = mySymbols >> !(char_("a-zA-Z0-9_")); 

     invalid = +ascii::graph; 

    } 

    qi::rule<Iterator, ascii::space_type> start; 
    // lexemes do not ignore embedded skippables 
    qi::rule<Iterator, int()> keyword; 
    qi::rule<Iterator, std::string()/*IMPLICIT LEXEME:, ascii::space_type*/> invalid; 
}; 

int main() 
{ 
    using boost::spirit::ascii::space; 
    typedef std::string::const_iterator iterator_type; 
    typedef keyword_parser<iterator_type> keyword_parser; 

    std::string s = "ONE TWO ONEMORE THREE"; 
    iterator_type b = s.begin(); 
    iterator_type e = s.end(); 
    phrase_parse(b, e, keyword_parser(), space); 

    return 0; 
} 
+0

有些東西是簡單的,除非你不看它:-) THX。 – Halt

相關問題