首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Boost Spirit Qi解析器在分解到qi::语法中时无法工作

Boost Spirit Qi解析器在分解到qi::语法中时无法工作
EN

Stack Overflow用户
提问于 2017-08-01 17:47:39
回答 1查看 36关注 0票数 1

我正在尝试使用Spirit解析器来解析像id 1234这样的字符串。它可以很好地处理内联start = qi::lit("id") >> qi::int_;,但是如果我想把它放到一个单独的基于qi::语法的结构中,就不行了。请参见以下示例中的案例1、2和3:

代码语言:javascript
运行
复制
#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";
    }
}

Run example on Coliru

失败案例(1和2)的输出为:

代码语言:javascript
运行
复制
Parsing failed
stopped at: "id 5012"

是什么造成了这里的差异?请记住,我删除了整型结果的所有赋值,以保持示例的最小化-假设这与问题无关。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-08-01 19:45:54

idGrammar的生命周期必须比构造函数作用域更长。将其设置为成员变量:

代码语言:javascript
运行
复制
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;
};
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45434476

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档