2013-10-21 114 views
1

我如何追溯精神屬性的位置?跟蹤boost :: spirit的位置

一個簡單的例子

template <typename Iterator> 
bool trace_numbers(Iterator first, Iterator last) 
{ 
    using boost::spirit::qi::double_; 
    using boost::spirit::qi::phrase_parse; 
    using boost::spirit::ascii::space; 

    bool r = phrase_parse(first, last, 

          // Begin grammar 
          (
           double_ % ',' 
         ) 
      , 
      // End grammar 
      space); 

    if (first != last) // fail if we did not get a full match 
     return false; 
    return r; 
} 

我想跟蹤的「double_」的位置(行和列),我發現line_pos_iterator但不知道如何使用它。我也發現multi-pass,但不要」是否知道它可以用來追蹤這些倉位(如果可以的話,如何?)。

+0

標記你的問題[標籤:助推精神]將最大限度地提高它將達到圖書館專家的機會。一個簡單的搜索引導我到這個網站[這個答案](http://stackoverflow.com/a/8365427/2417774),可能會有所幫助。 – llonesmiz

+0

@cv_and_he謝謝,我研究過這個例子,但它太難閱讀了,很難說這是一個很好的例子來展示如何使用「line_pos_iterator」。無論如何,如果我能理解如何使用它,我會發布答案。 – StereoMatching

+3

使用'on_success'進行調查,最近的問題和答案顯示瞭如何使用它。創建一個'double_ast'結構和規則,並且對於規則(只是由'double_'組成)添加一個'on_success'處理函數,將解析信息綁定到'double_ast'值。這就是我爲我的項目所做的(儘管它是一個基本的'ast_node'類和一個廣義的'on_success'處理程序)。 – GManNickG

回答

1

經過一番研究,我發現單獨使用spirit :: lex或將它與spirit :: qi結合是一個解決方案。

#include <boost/config/warning_disable.hpp> 
//[wcp_includes 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/lex_lexertl.hpp> 
#include <boost/spirit/include/phoenix_operator.hpp> 
#include <boost/spirit/include/phoenix_statement.hpp> 
#include <boost/spirit/include/phoenix_container.hpp> 
//] 

#include <iostream> 
#include <string> 
#include <vector> 

namespace spiritParser 
{ 

//[wcp_namespaces 
using namespace boost::spirit; 
using namespace boost::spirit::ascii; 

//[wcp_token_ids 
enum tokenids 
{ 
    IDANY = lex::min_token_id + 10 
}; 
//] 

//[wcp_token_definition 
template <typename Lexer> 
struct number_position_track_tokens : lex::lexer<Lexer> 
{ 
    number_position_track_tokens() 
    { 
     // define patterns (lexer macros) to be used during token definition 
     // below 
     this->self.add_pattern 
      ("NUM", "[0-9]+") 
     ; 

     number = "{NUM}"; // reference the pattern 'NUM' as defined above 

     this->self.add 
      (number)   // no token id is needed here 
      (".", IDANY)  // characters are usable as tokens as well 
     ; 
    } 

    lex::token_def<std::string> number; 
}; 
//] 

template<typename Iterator> 
struct numberGrammar : qi::grammar<Iterator> 
{ 
    template <typename TokenDef> 
    numberGrammar(TokenDef const &tok) 
     : numberGrammar::base_type(start) 
     , num(0), position(0) 
    { 
     using boost::phoenix::ref; 
     using boost::phoenix::push_back; 
     using boost::phoenix::size; 
     //"34, 44, 55, 66, 77, 88" 
     start = *( tok.number  [++ref(num), 
             boost::phoenix::push_back(boost::phoenix::ref(numPosition), boost::phoenix::ref(position)), 
             ref(position) += size(_1) 
             ] 
        | qi::token(IDANY) [++ref(position)] 
       ) 
       ; 
    } 

    std::size_t num, position; 
    std::vector<size_t> numPosition; 
    qi::rule<Iterator> start; 
}; 

void lex_word_count_1() 
{ 
    using token_type = lex::lexertl::token<char const*, boost::mpl::vector<std::string> >; 

    number_position_track_tokens<lexer_type> word_count;   // Our lexer 
    numberGrammar<iterator_type> g (word_count); // Our parser 

    // read in the file int memory 
    std::string str ("34, 44, 55, 66, 77, 88"); 
    char const* first = str.c_str(); 
    char const* last = &first[str.size()];  

    if (r) { 
     std::cout << "nums: " << g.num << ", size: " << g.position <<std::endl; 
     for(auto data : g.numPosition){ 
      std::cout<<"position : "<<data<<std::endl; 
     } 
    } 
    else { 
     std::string rest(first, last); 
     std::cerr << "Parsing failed\n" << "stopped at: \"" 
        << rest << "\"\n"; 
    } 
} 

    } 

這是一些alternation.In愚見文檔Quickstart 3 - Counting Words Using a Parser的例子,這並不容易像這樣的小任務。如果這些模式對於std :: regex來描述並不困難;需要更快的速度或者兩者兼而有之,選擇spirit :: lex來跟蹤簡單模式的位置(就像我所展示的例子)是矯枉過正的。