我正在尝试使用 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"
};