我正在尝试使用Spirit解析器来解析像id 1234
这样的字符串。它可以很好地处理内联start = qi::lit("id") >> qi::int_;
,但是如果我想把它放到一个单独的基于qi::语法的结构中,就不行了。请参见以下示例中的案例1、2和3:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <iostream>
#include <fstream>
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
struct Context{};
template <typename Iterator, typename SkipParser>
struct IdGrammar : qi::grammar<Iterator, SkipParser>
{
explicit IdGrammar(Context& out) : IdGrammar::base_type(start, "IdGrammar")
{
start = qi::lit("id") >> qi::int_;
}
qi::rule<Iterator, SkipParser> start;
};
template <typename Iterator, typename SkipParser>
struct MyGrammar : qi::grammar<Iterator, SkipParser>
{
explicit MyGrammar(Context& out)
: MyGrammar::base_type(start, "MyGrammar")
{
IdGrammar<Iterator, SkipParser> idGrammar(out);
// start = idGrammar >> *(',' >> idGrammar); // 1 = Parsing fails
start = idGrammar; // 2 = Parsing fails
// start = qi::lit("id") >> qi::int_; // 3 = Parsing succeeds
start.name("the start");
qi::on_error<qi::fail>(
start,
phoenix::ref(std::cout) << phoenix::val("Parsing error: expecting ") << qi::_4 // what failed?
<< phoenix::val(" here: \"")
<< phoenix::construct<std::string>(qi::_3, qi::_2) // iterators to error-pos, end
<< phoenix::val("\"")
<< std::endl);
}
qi::rule<Iterator, SkipParser> start;
};
int main()
{
typedef std::string::const_iterator iterator_type;
Context ctx;
MyGrammar<iterator_type, qi::space_type> roman_parser(ctx); // Our grammar
std::string str = "id 5012";
iterator_type iter = str.begin(), end = str.end();
bool r = phrase_parse(iter, end, roman_parser, qi::space);
if (r && iter == end)
{
std::cout << "Parsing succeeded\n";
}
else
{
std::string rest(iter, end);
std::cout << "Parsing failed\n";
std::cout << "stopped at: \"" << rest << "\"\n";
}
}
失败案例(1和2)的输出为:
Parsing failed
stopped at: "id 5012"
是什么造成了这里的差异?请记住,我删除了整型结果的所有赋值,以保持示例的最小化-假设这与问题无关。
发布于 2017-08-01 11:45:54
idGrammar
的生命周期必须比构造函数作用域更长。将其设置为成员变量:
template <typename Iterator, typename SkipParser>
struct MyGrammar : qi::grammar<Iterator, SkipParser>
{
explicit MyGrammar(Context& out)
: MyGrammar::base_type(start, "MyGrammar")
, idGrammar(out)
{
start = idGrammar >> *(',' >> idGrammar); // 1 = Now parsing succeeds
// start = idGrammar; // 2 = Now parsing succeeds
// start = qi::lit("id") >> qi::int_; // 3 = Parsing succeeds
start.name("the start");
qi::on_error<qi::fail>(
start,
phoenix::ref(std::cout) << phoenix::val("Parsing error: expecting ") << qi::_4 // what failed?
<< phoenix::val(" here: \"")
<< phoenix::construct<std::string>(qi::_3, qi::_2) // iterators to error-pos, end
<< phoenix::val("\"")
<< std::endl);
}
qi::rule<Iterator, SkipParser> start;
IdGrammar<Iterator, SkipParser> idGrammar;
};
https://stackoverflow.com/questions/45434476
复制相似问题