打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
c – boost :: qi :: parse似乎导致编译错误

我正在尝试使用Boost :: Spirit编写解析器,并且我编写了解析器并进行了编译.问题是,当我尝试编译解析函数时,编译器会抛出一堆模板错误.这是Qi语法:

template<typename Iterator>struct etf_parser : qi::grammar<Iterator, std::map<std::string, etfnode>(), ascii::space_type> {    etf_parser() : etf_parser::base_type(start) {            using qi::int_;            using qi::lit;            using qi::double_;            using qi::bool_;            using qi::lexeme;            using ascii::char_;            quoted_string %= lexeme['"' >>  (char_ - '"') >> '"'];            dataVal %= (quoted_string | double_ | int_ | bool_ | listObj | pairObj | mapObj);            pairObj %= ('<' >> dataVal >> ',' >> dataVal >> '>');            listObj %= '{' >> dataVal % ',' >> '}';            mapKey %=  qi::char_("a-zA-Z_-0-9.");            mapPair %= mapKey >> lit('=') >> dataVal;            mapObj %= '(' >> mapPair % ',' >> ')';            start %= mapPair >> ';';    }    qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;    // Data value parsers    qi::rule<Iterator, etfnode(), ascii::space_type> dataVal;    qi::rule<Iterator, std::vector<etfnode>(), ascii::space_type> listObj;    qi::rule<Iterator, std::pair<etfnode, etfnode>(), ascii::space_type> pairObj;    qi::rule<Iterator, std::map<std::string, etfnode>(), ascii::space_type> mapObj;    qi::rule<Iterator, std::pair<std::string, etfnode>(), ascii::space_type> mapPair;    qi::rule<Iterator, std::string(), ascii::space_type> mapKey;    qi::rule<Iterator, std::map<std::string, etfnode>(), ascii::space_type> start;};

这是解析功能.当我注释掉qi :: parse调用时,代码编译正常:

ETFDocument::ETFDocument(std::string content) {    etf_parser<std::string::const_iterator> parser;    std::map<std::string, rwnode> results;    std::string::const_iterator begin = content.begin();    std::string::const_iterator end = content.end();    bool result = qi::parse(begin, end, parser, results);    if(result) printf("Parsing succeeded\n"); else printf("Parsing failed\n");    m_root = etfnode(results);}

我尝试编译时编译器吐出以下错误:

In file included from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14:0,             from /usr/include/boost/spirit/home/qi.hpp:20,             from /usr/include/boost/spirit/include/qi.hpp:16,             from libmcg/etf.cpp:8:/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp: In instantiation of ‘bool boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Context = boost::spirit::context<boost::fusion::cons<std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >&, boost::fusion::nil>, boost::spirit::locals<> >; Skipper = boost::spirit::unused_type; Attribute = std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >; Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >; T1 = std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >(); T2 = boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’:/usr/include/boost/spirit/home/qi/reference.hpp:43:71:   required from ‘bool boost::spirit::qi::reference<Subject>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >&, boost::fusion::nil>, boost::spirit::locals<> >; Skipper = boost::spirit::unused_type; Attribute = std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::spirit::unused_type, boost::spirit::unused_type>]’/usr/include/boost/spirit/home/qi/parse.hpp:86:82:   required from ‘bool boost::spirit::qi::parse(Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >; Expr = etf_parser<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> > >; Attr = std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >]’libmcg/etf.cpp:113:53:   required from here/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:303:17: error: no match for call to ‘(const function_type {aka const boost::function<bool(__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >&, boost::fusion::nil>, boost::fusion::vector0<> >&, const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&)>}) (__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::spirit::unused_type, boost::spirit::unused_type>::context_type&, const boost::spirit::unused_type&)’In file included from /usr/include/boost/function/detail/maybe_include.hpp:33:0,             from /usr/include/boost/function/detail/function_iterate.hpp:14,             from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:67,             from /usr/include/boost/function.hpp:64,             from /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:16,             from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14,             from /usr/include/boost/spirit/home/qi.hpp:20,             from /usr/include/boost/spirit/include/qi.hpp:16,             from libmcg/etf.cpp:8:/usr/include/boost/function/function_template.hpp:1021:7: note: candidate is:/usr/include/boost/function/function_template.hpp:754:17: note: boost::function4<R, T1, T2, T3, T4>::result_type boost::function4<R, T1, T2, T3, T4>::operator()(T0, T1, T2, T3) const [with R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >&, boost::fusion::nil>, boost::fusion::vector0<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&; boost::function4<R, T1, T2, T3, T4>::result_type = bool]/usr/include/boost/function/function_template.hpp:754:17: note:   no known conversion for argument 4 from ‘const boost::spirit::unused_type’ to ‘const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&’

据我所知,它正在寻找一个船长,但转而使用boost :: spirit :: unused_type.我不确定为什么会发生这种情况,因为我在解析器定义中指定了一个Skipper.我在gcc 4.7.1上使用boost v1.49.0.

编辑:这是etfnode的定义.在cpp文件的开头(包含其他代码片段)有一个typedef,它将“etfnode”别名为“rwnode”.

enum DataType {    DT_INT,    DT_STRING,    DT_FLOAT,    DT_BOOL,    DT_LIST,    DT_PAIR,    DT_MAP};struct etfnode;typedef boost::recursive_wrapper<etfnode> rwnode;typedef boost::variant<        int,        std::string,        double,        bool,        std::vector<rwnode>,        std::pair<rwnode, rwnode>,        std::map<std::string, rwnode> > etfvalue;struct etfnode {    DataType type;    etfvalue value;    etfnode(const std::string& s);    etfnode(const int i);    etfnode(const double d);    etfnode(const bool b);    etfnode(const std::vector<rwnode>& n);    etfnode(const std::pair<rwnode, rwnode>& p);    etfnode(const std::map<std::string, rwnode>& p);    etfnode();};

还有一个测试字符串:

foo = 6;bar = <"bar", 16.5>;baz = {    (        foobar = "foo",        bar = 12    ),    "foobar"};

解决方法:

我认为最重要的罪魁祸首是你使用qi :: parse而不是qi :: phrase_parse这一事实,而你的语法明确地使用了一个队长.

我还重写了etfvalue递归变体的定义.我不确定你的版本是否应该有效,但至少现在,你可以在你期望的所有地方使用etfnode.这样看起来对我来说更加一致.

这是为我编译好的代码.它使用以下输出解析示例输入(请参阅main()):

Parsing succeededUnparsed remaining: ';'

如果你真的想接受尾随;,修改主要规则更像

start   = *(mapPair >> ';'); // or  *(mapPair >> (';'|qi::eoi))

祝好运!

//add streaming operators for etfnode and etfvalue if you want to debug this://#define BOOST_SPIRIT_DEBUG#include <map>#include <string>#include <boost/variant/recursive_wrapper.hpp>#include <boost/spirit/include/qi.hpp>#include <boost/fusion/adapted.hpp>namespace qi = boost::spirit::qi;namespace ascii = boost::spirit::ascii;enum DataType {    DT_INT,    DT_STRING,    DT_FLOAT,    DT_BOOL,    DT_LIST,    DT_PAIR,    DT_MAP};struct etfnode;typedef boost::variant<        int,        std::string,        double,        bool,         boost::recursive_wrapper<std::vector<etfnode> >,        boost::recursive_wrapper<std::pair<etfnode, etfnode> >,        boost::recursive_wrapper<std::map<std::string, etfnode> >         > etfvalue;struct etfnode {    DataType type;    etfvalue value;    etfnode(const std::string& s)                       { value = s; type = DT_STRING; }    etfnode(const int i)                                { value = i; type = DT_INT; }    etfnode(const double d)                             { value = d; type = DT_FLOAT; }    etfnode(const bool b)                               { value = b; type = DT_BOOL; }    etfnode(const std::vector<etfnode>& n)              { value = n; type = DT_LIST; }    etfnode(const std::pair<etfnode, etfnode>& p)       { value = p; type = DT_PAIR; }    etfnode(const std::map<std::string, etfnode>& p)    { value = p; type = DT_MAP; }    etfnode() { }};template<typename Iterator>struct etf_parser : qi::grammar<Iterator, std::map<std::string, etfnode>(), ascii::space_type> {    etf_parser() : etf_parser::base_type(start) {            using qi::int_;            using qi::lit;            using qi::double_;            using qi::bool_;            using qi::lexeme;            using ascii::char_;            quoted_string = lexeme['"' >>  (char_ - '"') >> '"'];            dataVal = (quoted_string | double_ | int_ | bool_                     | listObj    | pairObj                     | mapObj                    );            listObj = '{' >> dataVal % ',' >> '}';            pairObj = lit('<') >> dataVal >> ',' >> dataVal >> '>';            mapKey  =  qi::char_("a-zA-Z_-0-9.");            mapPair = mapKey >> lit('=') >> dataVal;            mapObj  = '(' >> mapPair % ',' >> ')';            start   = mapPair % ';';            BOOST_SPIRIT_DEBUG_NODE(quoted_string);            BOOST_SPIRIT_DEBUG_NODE(dataVal);            BOOST_SPIRIT_DEBUG_NODE(listObj);            //BOOST_SPIRIT_DEBUG_NODE(pairObj);            BOOST_SPIRIT_DEBUG_NODE(mapObj);            BOOST_SPIRIT_DEBUG_NODE(mapKey);            BOOST_SPIRIT_DEBUG_NODE(mapPair);            BOOST_SPIRIT_DEBUG_NODE(start);    }    qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;    // Data value parsers    qi::rule<Iterator, etfnode(),                           ascii::space_type> dataVal;    qi::rule<Iterator, std::vector<etfnode>(),              ascii::space_type> listObj;    qi::rule<Iterator, std::pair<etfnode, etfnode>(),       ascii::space_type> pairObj;    qi::rule<Iterator, std::map<std::string, etfnode>(),    ascii::space_type> mapObj;    qi::rule<Iterator, std::pair<std::string, etfnode>(),   ascii::space_type> mapPair;    qi::rule<Iterator, std::string(),                       ascii::space_type> mapKey;    qi::rule<Iterator, std::map<std::string, etfnode>(),    ascii::space_type> start;};int main(){    etf_parser<std::string::const_iterator> parser;    std::map<std::string, etfnode> results;    std::string content = "foo = 6;\n"        "bar = <\"bar\", 16.5>;\n"        "baz = {\n"        "       (\n"        "                foobar = \"foo\",\n"        "                bar = 12\n"        "   ),\n"        "   \"foobar\"\n"        "};";    std::string::const_iterator begin = content.begin();    std::string::const_iterator end = content.end();    bool result = qi::phrase_parse(begin, end, parser, ascii::space, results);    if(result) printf("Parsing succeeded\n"); else printf("Parsing failed\n");    if (begin!=end)        std::cout << "Unparsed remaining: '" << std::string(begin,end) << "'\n";    //m_root = etfnode(results);}
来源:https://www.icode9.com/content-4-433951.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
也谈表达式分析和计算
解析字符串
正则表达式内存耗尽异常解决方案 - 星星的日志 - 网易博客
boost库区间range基本原理及使用实例
为游戏添加脚本系统
正则表达式 boost Regex
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服