2013-10-04 47 views
2

編輯:我已經撕掉了詞法分析器,因爲它不能與Qi完全整合,只是混淆了語法(請參閱here)。助力精神lex和qi。集成一個跳過語法分析器


我想在精神lex框架之上增長一個語法。當我嘗試將一個跳過解析器移入語法時,我開始出現錯誤。

因此,將qi::grammar<>qi::rule<> event簽名從<Iterator>更改爲<Iterator,void(),ascii::space_type>。在語法結構中。我需要做什麼?

此外,我已設置token_def以省略其屬性optional令牌和其他一些。爲什麼它仍然爲詞法分析器中的可選語義動作提供有效的_val?我想問的原因是因爲我認爲問題必須與qi中的事件規則的rhs上的可選標記的字符串屬性無關,而與規則的屬性簽名不一致。

#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/spirit/include/lex_lexertl.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/cstdint.hpp> 
#include <string> 
#include<exception> 

namespace lex = boost::spirit::lex; 
namespace px = boost::phoenix; 
namespace qi = boost::spirit::qi; 
namespace ascii = boost::spirit::ascii; 

template <typename Lexer> 
struct tokens : lex::lexer<Lexer> 
{ 
    tokens() 
     : left_paranthesis("\"{\""), 
     right_paranthesis("\"}\""), 
     colon(":"), 
     namespace_("(?i:namespace)"), 
     event("(?i:event)"), 
     optional("(?i:optional)"), 
     required("(?i:required)"), 
     ordinal("\\d+"), 
     identifier("\\w+") 

    { 
     using boost::spirit::lex::_val; 

     this->self 
      = " " 
      | left_paranthesis [ std::cout << px::val("lpar") << std::endl] 
      | right_paranthesis [ std::cout << px::val("rpar") << std::endl] 
      | colon    [ std::cout << px::val("colon") << std::endl] 
      | namespace_   [ std::cout << px::val("kw namesapce") << std::endl] 
      | event    [ std::cout << px::val("kw event") << std::endl] 
      | optional   [ std::cout << px::val("optional ") << "-->" << _val << "<--" << std::endl] 
      | required   [ std::cout << px::val("required") << std::endl] 
      | ordinal    [ std::cout << px::val("val ordinal (") << _val << ")" << std::endl] 
      | identifier   [std::cout << px::val("val identifier(") << _val << ")" << std::endl]; 
    } 

    lex::token_def<> left_paranthesis, right_paranthesis, colon; 
    lex::token_def<lex::omit> namespace_, event, optional, required; 
    lex::token_def<boost::uint32_t> ordinal; 
    lex::token_def<> identifier; 
}; 

template <typename Iterator> 
struct grammar : qi::grammar<Iterator> 
{ 
    template <typename TokenDef> 
    grammar(TokenDef const& tok) 
     : grammar::base_type(event) 
    { 
     //start = event; 
     event = tok.optional [ std::cout << px::val("== OPTIONAL") << std::endl]; 
    } 

    qi::rule<Iterator> start; 
    qi::rule<Iterator> event; 
}; 

// std::string test = "namespace{ event { OPtiONAL 124:hello_world RequireD} } "; 

std::string test = "OPTIONAL"; 

int main() 
{ 
    typedef lex::lexertl::token<std::string::iterator, boost::mpl::vector<boost::uint32_t, std::string> > token_type; 
    typedef lex::lexertl::actor_lexer<token_type> lexer_type; 
    typedef tokens<lexer_type>::iterator_type iterator_type; 

    tokens<lexer_type> token_lexer; 
    grammar<iterator_type> grammar(token_lexer); 

    std::string::iterator first = test.begin(); 
    std::string::iterator last = test.end(); 
    bool r; 

    r = lex::tokenize_and_parse(first, last, token_lexer, grammar); 

    if(r) 
     ; 
    else 
    { 
     std::cout << "parsing failed" << std::endl; 
    } 
    /* 
    lexer_type::iterator_type iter; 

    try 
    { 
     iter = token_lexer.begin(first,last); 
    } 
    catch(std::exception & e) 
    { 
     std::cout << e.what() << std::endl; 
    } 

    lexer_type::iterator_type end = token_lexer.end(); 

    while (iter != end && token_is_valid(*iter)) 
     ++iter; 
    */ 
} 

此語法失敗:

template <typename Iterator> 
struct grammar : qi::grammar<Iterator,void(),ascii::space_type> 
{ 
    template <typename TokenDef> 
    grammar(TokenDef const& tok) 
     : grammar::base_type(event) 
    { 
     //start = event; 
     event = tok.optional [ std::cout << px::val("== OPTIONAL") << std::endl]; 
    } 

    qi::rule<Iterator> start; 
    qi::rule<Iterator,void(),ascii::space_type> event; 
}; 

回答

2

與大多數的精神。如果你想要做一些真實的事情,你必須花費數小時的時間尋找一個沒有記錄的解決方案,但它被埋在了示例和郵件列表中。認真考慮搬到ragel或flex/bison。問題不在於機器不可用,而在於它沒有證件。

在這種情況下,當查看lex文檔時,通過查看具有tokenize_and_phrase_parse函數的lex分析器api調用,會引起大量誤解。當你試圖使用qi::phrase_parse這個文件時,這個文件不會解釋如何使用這個函數連接船長。

通過修改詞法分析器,然後使用一些未公開的qi-s​​kipper構造體初始化語法和規則,完成將空間跳躍器放入解析器的連線。你可以在lex例子目錄中看到這個動作(例5)。代碼編譯和工作:

#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/spirit/include/lex_lexertl.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/cstdint.hpp> 
#include <string> 
#include<exception> 

namespace lex = boost::spirit::lex; 
namespace px = boost::phoenix; 
namespace qi = boost::spirit::qi; 
namespace ascii = boost::spirit::ascii; 

template <typename Lexer> 
struct tokens : lex::lexer<Lexer> 
{ 
    tokens() 
     : left_paranthesis("\"{\""), 
     right_paranthesis("\"}\""), 
     colon(":"), 
     namespace_("(?i:namespace)"), 
     event("(?i:event)"), 
     optional("(?i:optional)"), 
     required("(?i:required)"), 
     ordinal("\\d+"), 
     identifier("\\w+") 

    { 
     using boost::spirit::lex::_val; 

     this->self 
      = 
       left_paranthesis [ std::cout << px::val("lpar") << std::endl] 
      | right_paranthesis [ std::cout << px::val("rpar") << std::endl] 
      | colon    [ std::cout << px::val("colon") << std::endl] 
      | namespace_   [ std::cout << px::val("kw namesapce") << std::endl] 
      | event    [ std::cout << px::val("kw event") << std::endl] 
      | optional   [ std::cout << px::val("optional ") << "-->" << _val << "<--" << std::endl] 
      | required   [ std::cout << px::val("required") << std::endl] 
      | ordinal    [ std::cout << px::val("val ordinal (") << _val << ")" << std::endl] 
      | identifier   [std::cout << px::val("val identifier(") << _val << ")" << std::endl]; 


     this->self("WS") = lex::token_def<>("[ \\t\\n]+"); 
    } 


    lex::token_def<> left_paranthesis, right_paranthesis, colon; 
    lex::token_def<lex::omit> namespace_, event, optional, required; 
    lex::token_def<boost::uint32_t> ordinal; 
    lex::token_def<> identifier; 
}; 

template <typename Iterator, typename Lexer> 
struct grammar : qi::grammar<Iterator,qi::in_state_skipper<Lexer> > 
{ 
    template <typename TokenDef> 
    grammar(TokenDef const& tok) 
     : grammar::base_type(event) 
    { 
     //start = event; 
     event = tok.optional [ std::cout << px::val("== OPTIONAL") << std::endl]; 
    } 

    qi::rule<Iterator> start; 
    qi::rule<Iterator, qi::in_state_skipper<Lexer> > event; 
}; 

// std::string test = "namespace{ event { OPtiONAL 124:hello_world RequireD} } "; 

std::string test = " OPTIONAL "; 

int main() 
{ 
    typedef lex::lexertl::token<std::string::iterator, boost::mpl::vector<boost::uint32_t, std::string> > token_type; 
    typedef lex::lexertl::actor_lexer<token_type> lexer_type; 
    typedef tokens<lexer_type>::iterator_type iterator_type; 

    tokens<lexer_type> token_lexer; 
    grammar<iterator_type,tokens<lexer_type>::lexer_def> grammar(token_lexer); 

    std::string::iterator it = test.begin(); 
    iterator_type first = token_lexer.begin(it, test.end()); 
    iterator_type last = token_lexer.end(); 

    bool r; 

    r = qi::phrase_parse(first, last, grammar, qi::in_state("WS")[token_lexer.self]); 

    if(r) 
     ; 
    else 
    { 
     std::cout << "parsing failed" << std::endl; 
    } 
    /* 
    lexer_type::iterator_type iter; 

    try 
    { 
     iter = token_lexer.begin(first,last); 
    } 
    catch(std::exception & e) 
    { 
     std::cout << e.what() << std::endl; 
    } 

    lexer_type::iterator_type end = token_lexer.end(); 

    while (iter != end && token_is_valid(*iter)) 
     ++iter; 
    */ 
} 
+0

但是,'lex :: pass_flags :: pass_ignore'完全記錄符合法案。問題是,你不需要傳統的船長。 – sehe

+0

是的,說實話,這種做事方式讓語法比以前更乾淨。如果我使用'pass_ignore',我想我甚至不必跳過語法中的'qi :: in_state_skipper <>'圈,詞法分析器會默默地跳過WS令牌? –

+0

尋找[由sehe](http://stackoverflow.com/search?q=user:85371+ [boost-spirit])提供的大量優秀(和可悲的低估)精神相關答案總是一個好主意。這個網站。 [這個特別](http://stackoverflow.com/search?q=user%3A85371+ [boost-spirit] + lex +隊長)似乎是合適的。 – llonesmiz