經過一番研究,我發現單獨使用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來跟蹤簡單模式的位置(就像我所展示的例子)是矯枉過正的。
標記你的問題[標籤:助推精神]將最大限度地提高它將達到圖書館專家的機會。一個簡單的搜索引導我到這個網站[這個答案](http://stackoverflow.com/a/8365427/2417774),可能會有所幫助。 – llonesmiz
@cv_and_he謝謝,我研究過這個例子,但它太難閱讀了,很難說這是一個很好的例子來展示如何使用「line_pos_iterator」。無論如何,如果我能理解如何使用它,我會發布答案。 – StereoMatching
使用'on_success'進行調查,最近的問題和答案顯示瞭如何使用它。創建一個'double_ast'結構和規則,並且對於規則(只是由'double_'組成)添加一個'on_success'處理函數,將解析信息綁定到'double_ast'值。這就是我爲我的項目所做的(儘管它是一個基本的'ast_node'類和一個廣義的'on_success'處理程序)。 – GManNickG