這是我的快速實現(C++ 11)。你可以找到很多的情況下如何解決在boost-spirit-qi各種問題和我同意的學習探索精神,需要一些努力:-)
#define BOOST_RESULT_OF_USE_DECLTYPE
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
struct SInsert
{
struct result
{
typedef void type;
};
void operator()(std::vector<std::string>&out,
std::vector<std::string>&in, int counter) const
{
for(int i=0; i<counter; ++i)
std::copy(in.begin(), in.end(), std::back_inserter(out));
}
};
boost::phoenix::function<SInsert> inserter;
int main()
{
namespace qi = boost::spirit::qi;
namespace ph = boost::phoenix;
namespace ascii = boost::spirit::ascii;
for (auto &str : std::vector<std::string>
{ "w1/ w2 /w4 ",
"[w2]1 /w4 ",
"[w2/w3]2 /w4 ",
"[]0",
"[]0/w4"
}
)
{
std::cout << "input:" << str << std::endl;
std::string::const_iterator iter(str.begin());
std::string::const_iterator last(str.end());
std::vector<std::string> v;
qi::rule<std::string::const_iterator,
qi::locals< std::vector<std::string> >,
ascii::space_type ,std::vector<std::string>()> mrule =
(qi::as_string[ qi::lexeme[ +(qi::graph -"/"-"[") ] ][ ph::push_back(qi::_val,qi::_1)] |
(
qi::lit("[")
>> -(
qi::eps[ ph::clear(qi::_a) ]
>> qi::as_string[ qi::lexeme[ +(qi::graph-"/"-"]") ] ][ ph::push_back(qi::_a ,qi::_1) ]
% qi::lit("/")
)
)
>> qi::lit("]")
>> qi::int_[ inserter(qi::_val,qi::_a,qi::_1) ]
)
% qi::lit("/");
if(qi::phrase_parse(iter, last, mrule , ascii::space, v) && iter==last)
std::copy(v.begin(), v.end(),
std::ostream_iterator<std::string>(std::cout,"\n"));
else
std::cerr << "parsing failed:" << *iter << std::endl;
}
return 0;
}
可以進一步簡化mrule
使屬性會被自動合成,而不是使用語義動作 - 即使你不會完全避免他們:
qi::rule<std::string::const_iterator,
qi::locals< std::vector<std::string> >,
ascii::space_type ,std::vector<std::string>()> mrule;
mrule %=
(
qi::as_string[ qi::lexeme[ +(qi::graph -"/"-"[") ] ] |
qi::lit("[")
>> -(
qi::eps[ ph::clear(qi::_a) ]
>> qi::as_string[ qi::lexeme[ +(qi::graph-"/"-"]") ] ][ ph::push_back(qi::_a ,qi::_1) ]
% qi::lit("/")
)
>> qi::lit("]")
>> qi::omit[ qi::int_[ inserter(qi::_val,qi::_a,qi::_1-1) ] ]
)
% qi::lit("/");
至於sehe
指出了一些醜陋的結構,這裏是次要的簡化:
qi::rule<std::string::const_iterator,
qi::locals< std::vector<std::string> >,
ascii::space_type ,std::vector<std::string>()> mrule;
mrule %= (
qi::as_string[ qi::lexeme[ +qi::alnum ] ] |
qi::lit("[")
>> -(
qi::eps[ ph::clear(qi::_a) ] >>
qi::as_string[ qi::lexeme[ +qi::alnum ] ][ ph::push_back(qi::_a ,qi::_1) ]
% qi::lit("/")
)
>> qi::lit("]")
>> qi::omit[ qi::int_[ inserter(qi::_val,qi::_a,qi::_1-1) ] ]
) % qi::lit("/");
你應該先寫下來您想要解析的格式的ebnf語法。 – PlasmaHH
歡迎使用堆棧溢出。你爲這個問題選擇的標題有點模糊。 Boost.Spirit的全部目的是解析字符串。你認爲你可以編輯它,以便它更具體到*你的問題,而不是同樣適用於每一個*精神問題? –