Làm theo một số hướng dẫn (ví dụ: http://boost-spirit.com/home/articles/qi-example/nabialek-trick/) Tôi muốn sử dụng mẹo Nabialek để có trình phân tích cú pháp động. Phân tích cú pháp đã hoạt động tốt, nhưng tôi không nhận được các thuộc tính được vận chuyển. Các giải thích như https://stackoverflow.com/a/9109972/2524462 đề xuất, các thuộc tính đó sẽ có thể nhưng không phải là đối số.Boost.Spirit.Qi: Cách trả lại thuộc tính bằng mẹo Nabialek
Đây chỉ là một ví dụ nhỏ phân tích một chuỗi và một số thành một cấu trúc. Nó chỉ là để trưng bày vấn đề của tôi; phương pháp này nên được sử dụng trong một hệ thống lớn hơn sau này, nơi mà trình phân tích cú pháp động thực sự cần thiết.
Câu hỏi: Làm cách nào để chuyển các thuộc tính bằng thủ thuật Nabialek?
Tôi không phải là chuyên gia về tinh thần, vì vậy hãy chịu đựng với tôi. Tôi đang sử dụng gcc 4.8.1 và tăng 1.54.
#define BOOST_SPIRIT_DEBUG
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
//------------------------------------------------------------------------------
// Data structure
struct myline {
myline()
: _n(0), _s("") {
}
myline(int n, std::string s)
: _n(n), _s(s) {
}
void set(int n, std::string s) {
_n = n;
_s = s;
}
int _n;
std::string _s;
};
BOOST_FUSION_ADAPT_STRUCT(::myline, (int, _n) (std::string, _s))
//------------------------------------------------------------------------------
// Parser grammar
template<typename It, typename Skipper = qi::space_type>
struct parser: qi::grammar<It, myline(), Skipper> {
parser()
: parser::base_type(start) {
using namespace qi;
start = line;
string %= qi::lexeme["'" >> *~qi::char_("'") >> "'"];
one = (string >> "@" >> qi::int_)[_val = phx::construct<myline>(_2, _1)];
two = (qi::int_ >> "@" >> string);
keyword.add("one", &one)("two", &two);
line = keyword[_a = _1] >> qi::lazy(*_a);
on_error<fail>(
start,
std::cout << phx::val("Error! Expecting ") << _4
<< phx::val(" here: \"") << phx::construct<std::string>(_3, _2)
<< phx::val("\"\n"));
BOOST_SPIRIT_DEBUG_NODES((start)(line)(one)(two))
}
private:
template<typename Attr> using Rule = qi::rule<It, Attr(), Skipper>;
Rule<myline> start, one, two;
qi::rule<It, myline, Skipper, qi::locals<Rule<myline>*> > line;
Rule<std::string> string;
qi::symbols<char, Rule<myline>*> keyword;
};
//------------------------------------------------------------------------------
int main() {
for (const std::string input : std::vector<std::string> { "one 'test'@1",
"two [email protected]'test'" }) {
auto f(std::begin(input)), l(std::end(input));
const static parser<decltype(f)> p;
myline parsed_script;
bool ok = qi::phrase_parse(f, l, p, qi::space, parsed_script);
if (!ok) {
std::cout << "invalid input\n";
}
std::cout << parsed_script._n << ": " << parsed_script._s << std::endl;
if (f != l) {
std::cout << "unparsed: '" << std::string(f, l) << "'" << std::endl;
}
}
}
kết quả phân tích cú pháp:
<start>
<try>one 'test'@1</try>
<line>
<try>one 'test'@1</try>
<one>
<try> 'test'@1</try>
<success></success>
<attributes>[[1, [t, e, s, t]]]</attributes>
</one>
<success></success>
<attributes>[]</attributes><locals>(0x43b0e0)</locals>
</line>
<success></success>
<attributes>[[0, []]]</attributes>
</start>
<start>
<try>two [email protected]'test'</try>
<line>
<try>two [email protected]'test'</try>
<two>
<try> [email protected]'test'</try>
<success></success>
<attributes>[[2, [t, e, s, t]]]</attributes>
</two>
<success></success>
<attributes>[]</attributes><locals>(0x43b110)</locals>
</line>
<success></success>
<attributes>[[0, []]]</attributes>
</start>
Xem mẫu cố định ** [live on Coliru] (http://coliru.stacked-crooked.com/view?i d = 339ded0e400164a92e13f5cb65e2e54e-414c51b0c3fcfe921b347f2307ac5c70) ** – sehe
Cảm ơn bạn rất nhiều, hoạt động rất tốt.Dường như tôi vẫn cần nhiều bài học hơn ;-) –
Bạn đang làm tốt, không phải lo lắng. – sehe