boost spirit 编译错误
boost spirit compilation error
我是第一次尝试使用 boost::spirit,我 运行 遇到了一些我不知道如何解决的编译错误。
这似乎暗示它与我正在使用的 Skipper 有关,但我在所有地方都使用相同的 Skipper,并且我尝试了很多不同的 Skipper 配置,none 其中的工作正常:(
我的示例文件如下:
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
template <typename Iterator>
struct Grammar: qi::grammar<Iterator, std::vector<std::string>, ascii::space_type>
{
Grammar(): Grammar::base_type(ident_list)
{
ident = qi::lexeme[*qi::alnum];
ident_list = *ident;
}
qi::rule<Iterator, std::vector<std::string>, ascii::space_type> ident_list;
qi::rule<Iterator, std::string, ascii::space_type> ident;
};
int main()
{
Grammar<std::string::const_iterator> grammar;
std::vector<std::string> result;
std::string string_to_parse = "My list of ident";
std::string::const_iterator start = string_to_parse.begin();
std::string::const_iterator end = string_to_parse.end();
phrase_parse(
start,
end,
grammar,
ascii::space,
result
);
return 0;
}
这里是编译错误:
In file included from /usr/local/include/boost/spirit/home/qi/nonterminal.hpp:14:0,
from /usr/local/include/boost/spirit/home/qi.hpp:21,
from /usr/local/include/boost/spirit/include/qi.hpp:16,
from main.cpp:1:
/usr/local/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::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >; Attribute = const boost::spirit::unused_type; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = std::__cxx11::basic_string<char>; 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/local/include/boost/spirit/home/qi/reference.hpp:43:72: 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::__cxx11::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >; Attribute = const boost::spirit::unused_type; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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/local/include/boost/spirit/home/qi/detail/fail_function.hpp:38:20: required from 'bool boost::spirit::qi::detail::fail_function<Iterator, Context, Skipper>::operator()(const Component&, Attribute&) const [with Component = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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> >; Attribute = const boost::spirit::unused_type; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >]'
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp:309:39: required from 'bool boost::spirit::qi::detail::pass_container<F, Attr, Sequence>::dispatch_attribute(const Component&, mpl_::false_) const [with Component = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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> >; F = boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >; Attr = std::vector<std::__cxx11::basic_string<char> >; Sequence = mpl_::bool_<false>; mpl_::false_ = mpl_::bool_<false>]'
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp:351:61: required from 'bool boost::spirit::qi::detail::pass_container<F, Attr, Sequence>::operator()(const Component&) const [with Component = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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> >; F = boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >; Attr = std::vector<std::__cxx11::basic_string<char> >; Sequence = mpl_::bool_<false>]'
/usr/local/include/boost/spirit/home/qi/operator/kleene.hpp:65:23: required from 'bool boost::spirit::qi::kleene<Subject>::parse_container(F) const [with F = boost::spirit::qi::detail::pass_container<boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >, std::vector<std::__cxx11::basic_string<char> >, mpl_::bool_<false> >; Subject = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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/local/include/boost/spirit/home/qi/operator/kleene.hpp:84:13: [ skipping 6 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/local/include/boost/function/function_template.hpp:1072:16: required from 'boost::function<R(T0, T1, T2, T3)>::function(Functor, typename boost::enable_if_c<(! boost::is_integral<Functor>::value), int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::kleene<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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> > >, mpl_::bool_<false> >; R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&; typename boost::enable_if_c<(! boost::is_integral<Functor>::value), int>::type = int]'
/usr/local/include/boost/function/function_template.hpp:1125:5: required from 'typename boost::enable_if_c<(! boost::is_integral<Functor>::value), boost::function<R(T0, T1, T2, T3)>&>::type boost::function<R(T0, T1, T2, T3)>::operator=(Functor) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::kleene<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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> > >, mpl_::bool_<false> >; R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&; typename boost::enable_if_c<(! boost::is_integral<Functor>::value), boost::function<R(T0, T1, T2, T3)>&>::type = boost::function<bool(__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >&, const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&)>&]'
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:183:19: required from 'static void boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const Expr&, mpl_::true_) [with Auto = mpl_::bool_<false>; Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::dereference, boost::proto::argsns_::list1<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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>&>, 1l>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = std::vector<std::__cxx11::basic_string<char> >; 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; mpl_::true_ = mpl_::bool_<true>]'
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:221:32: required from 'boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>& boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::operator=(const Expr&) [with Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::dereference, boost::proto::argsns_::list1<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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>&>, 1l>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = std::vector<std::__cxx11::basic_string<char> >; 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]'
main.cpp:12:20: required from 'Grammar<Iterator>::Grammar() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >]'
main.cpp:21:42: required from here
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:304:17: error: no match for call to '(const function_type {aka const boost::function<bool(__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<boost::spirit::unused_type&, boost::fusion::nil_>, boost::fusion::vector<> >&, const boost::spirit::qi::literal_string<const std::__cxx11::basic_string<char>, true>&)>}) (__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&)'
if (f(first, last, context, skipper))
^~
In file included from /usr/local/include/boost/function/detail/maybe_include.hpp:33:0,
from /usr/local/include/boost/function/detail/function_iterate.hpp:14,
from /usr/local/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:67,
from /usr/local/include/boost/function.hpp:64,
from /usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:16,
from /usr/local/include/boost/spirit/home/qi/nonterminal.hpp:14,
from /usr/local/include/boost/spirit/home/qi.hpp:21,
from /usr/local/include/boost/spirit/include/qi.hpp:16,
from main.cpp:1:
/usr/local/include/boost/function/function_template.hpp:765:17: note: candidate: 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::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<boost::spirit::unused_type&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::literal_string<const std::__cxx11::basic_string<char>, true>&; boost::function4<R, T1, T2, T3, T4>::result_type = bool]
result_type operator()(BOOST_FUNCTION_PARMS) const
^~~~~~~~
/usr/local/include/boost/function/function_template.hpp:765:17: note: no known conversion for argument 4 from 'const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >' to 'const boost::spirit::qi::literal_string<const std::__cxx11::basic_string<char>, true>&'
这个 char_class 不能转换成这个 literal_string 吗?
只有当我引入一个中间规则(这里"ident")时才会出现错误,如果我定义:
ident_list = *qi::lexeme[*qi::alnum]
它编译得很好。
规则上的签名略有拼写错误:
qi::rule<Iterator, std::vector<std::string>, ascii::space_type> ident_list;
qi::rule<Iterator, std::string, ascii::space_type> ident;
应该是
qi::rule<Iterator, std::vector<std::string>(), ascii::space_type> ident_list;
qi::rule<Iterator, std::string(), ascii::space_type> ident;
// and also
struct Grammar: qi::grammar<Iterator, std::vector<std::string>(), ascii::space_type>
现在可以编译了。
更多注意事项:只要 ident
是一个词素,您就可以简单地从中删除船长(参见 Boost spirit skipper issues)。
还有另一个错误,它匹配 *qi::alnum
,这意味着 0 个字符是匹配的。您至少要使用 1 个字符:+qi::alnum
.
这是一个工作示例(它还显示了我将船长编码到语法中的首选方法,因为它通常是语法的一部分):
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
template <typename Iterator> struct Grammar : qi::grammar<Iterator, std::vector<std::string>()> {
Grammar() : Grammar::base_type(start) {
using namespace qi;
ident = +alnum;
ident_list = *ident;
start = skip(ascii::space) [ident_list];
}
private:
qi::rule<Iterator, std::vector<std::string>()> start;
qi::rule<Iterator, std::vector<std::string>(), qi::ascii::space_type> ident_list;
qi::rule<Iterator, std::string()> ident;
};
int main() {
Grammar<std::string::const_iterator> grammar;
std::vector<std::string> result;
std::string const input = "My list of ident";
auto start = input.begin(), end = input.end();
if (parse(start, end, grammar, result))
std::cout << "Parsed " << result.size() << " tokens\n";
else
std::cout << "Parsing failed\n";
if (start != end)
std::cout << "Remaining unparsed input: '" << std::string(start,end) << "'\n";
}
版画
Parsed 4 tokens
奖金
对于这么简单的语法,考虑直接内联:
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main() {
for (std::string const input : { "My list of ident", " My list of ident " }) {
auto f = input.begin(), l = input.end();
std::list<std::string> result;
if (qi::phrase_parse(f, l, *qi::lexeme[+qi::graph], qi::space, result))
std::cout << "Parsed " << result.size() << " tokens\n";
else
std::cout << "Parsing failed\n";
if (f != l)
std::cout << "Remaining unparsed input: '" << std::string(f,l) << "'\n";
}
}
我是第一次尝试使用 boost::spirit,我 运行 遇到了一些我不知道如何解决的编译错误。
这似乎暗示它与我正在使用的 Skipper 有关,但我在所有地方都使用相同的 Skipper,并且我尝试了很多不同的 Skipper 配置,none 其中的工作正常:(
我的示例文件如下:
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
template <typename Iterator>
struct Grammar: qi::grammar<Iterator, std::vector<std::string>, ascii::space_type>
{
Grammar(): Grammar::base_type(ident_list)
{
ident = qi::lexeme[*qi::alnum];
ident_list = *ident;
}
qi::rule<Iterator, std::vector<std::string>, ascii::space_type> ident_list;
qi::rule<Iterator, std::string, ascii::space_type> ident;
};
int main()
{
Grammar<std::string::const_iterator> grammar;
std::vector<std::string> result;
std::string string_to_parse = "My list of ident";
std::string::const_iterator start = string_to_parse.begin();
std::string::const_iterator end = string_to_parse.end();
phrase_parse(
start,
end,
grammar,
ascii::space,
result
);
return 0;
}
这里是编译错误:
In file included from /usr/local/include/boost/spirit/home/qi/nonterminal.hpp:14:0,
from /usr/local/include/boost/spirit/home/qi.hpp:21,
from /usr/local/include/boost/spirit/include/qi.hpp:16,
from main.cpp:1:
/usr/local/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::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >; Attribute = const boost::spirit::unused_type; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = std::__cxx11::basic_string<char>; 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/local/include/boost/spirit/home/qi/reference.hpp:43:72: 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::__cxx11::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >; Attribute = const boost::spirit::unused_type; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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/local/include/boost/spirit/home/qi/detail/fail_function.hpp:38:20: required from 'bool boost::spirit::qi::detail::fail_function<Iterator, Context, Skipper>::operator()(const Component&, Attribute&) const [with Component = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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> >; Attribute = const boost::spirit::unused_type; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >]'
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp:309:39: required from 'bool boost::spirit::qi::detail::pass_container<F, Attr, Sequence>::dispatch_attribute(const Component&, mpl_::false_) const [with Component = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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> >; F = boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >; Attr = std::vector<std::__cxx11::basic_string<char> >; Sequence = mpl_::bool_<false>; mpl_::false_ = mpl_::bool_<false>]'
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp:351:61: required from 'bool boost::spirit::qi::detail::pass_container<F, Attr, Sequence>::operator()(const Component&) const [with Component = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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> >; F = boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >; Attr = std::vector<std::__cxx11::basic_string<char> >; Sequence = mpl_::bool_<false>]'
/usr/local/include/boost/spirit/home/qi/operator/kleene.hpp:65:23: required from 'bool boost::spirit::qi::kleene<Subject>::parse_container(F) const [with F = boost::spirit::qi::detail::pass_container<boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >, std::vector<std::__cxx11::basic_string<char> >, mpl_::bool_<false> >; Subject = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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/local/include/boost/spirit/home/qi/operator/kleene.hpp:84:13: [ skipping 6 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/local/include/boost/function/function_template.hpp:1072:16: required from 'boost::function<R(T0, T1, T2, T3)>::function(Functor, typename boost::enable_if_c<(! boost::is_integral<Functor>::value), int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::kleene<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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> > >, mpl_::bool_<false> >; R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&; typename boost::enable_if_c<(! boost::is_integral<Functor>::value), int>::type = int]'
/usr/local/include/boost/function/function_template.hpp:1125:5: required from 'typename boost::enable_if_c<(! boost::is_integral<Functor>::value), boost::function<R(T0, T1, T2, T3)>&>::type boost::function<R(T0, T1, T2, T3)>::operator=(Functor) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::kleene<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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> > >, mpl_::bool_<false> >; R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&; typename boost::enable_if_c<(! boost::is_integral<Functor>::value), boost::function<R(T0, T1, T2, T3)>&>::type = boost::function<bool(__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<std::vector<std::__cxx11::basic_string<char> >&, boost::fusion::nil_>, boost::fusion::vector<> >&, const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&)>&]'
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:183:19: required from 'static void boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const Expr&, mpl_::true_) [with Auto = mpl_::bool_<false>; Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::dereference, boost::proto::argsns_::list1<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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>&>, 1l>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = std::vector<std::__cxx11::basic_string<char> >; 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; mpl_::true_ = mpl_::bool_<true>]'
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:221:32: required from 'boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>& boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::operator=(const Expr&) [with Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::dereference, boost::proto::argsns_::list1<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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>&>, 1l>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = std::vector<std::__cxx11::basic_string<char> >; 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]'
main.cpp:12:20: required from 'Grammar<Iterator>::Grammar() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >]'
main.cpp:21:42: required from here
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:304:17: error: no match for call to '(const function_type {aka const boost::function<bool(__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<boost::spirit::unused_type&, boost::fusion::nil_>, boost::fusion::vector<> >&, const boost::spirit::qi::literal_string<const std::__cxx11::basic_string<char>, true>&)>}) (__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, 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::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&)'
if (f(first, last, context, skipper))
^~
In file included from /usr/local/include/boost/function/detail/maybe_include.hpp:33:0,
from /usr/local/include/boost/function/detail/function_iterate.hpp:14,
from /usr/local/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:67,
from /usr/local/include/boost/function.hpp:64,
from /usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:16,
from /usr/local/include/boost/spirit/home/qi/nonterminal.hpp:14,
from /usr/local/include/boost/spirit/home/qi.hpp:21,
from /usr/local/include/boost/spirit/include/qi.hpp:16,
from main.cpp:1:
/usr/local/include/boost/function/function_template.hpp:765:17: note: candidate: 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::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<boost::spirit::unused_type&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::literal_string<const std::__cxx11::basic_string<char>, true>&; boost::function4<R, T1, T2, T3, T4>::result_type = bool]
result_type operator()(BOOST_FUNCTION_PARMS) const
^~~~~~~~
/usr/local/include/boost/function/function_template.hpp:765:17: note: no known conversion for argument 4 from 'const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >' to 'const boost::spirit::qi::literal_string<const std::__cxx11::basic_string<char>, true>&'
这个 char_class 不能转换成这个 literal_string 吗? 只有当我引入一个中间规则(这里"ident")时才会出现错误,如果我定义:
ident_list = *qi::lexeme[*qi::alnum]
它编译得很好。
规则上的签名略有拼写错误:
qi::rule<Iterator, std::vector<std::string>, ascii::space_type> ident_list;
qi::rule<Iterator, std::string, ascii::space_type> ident;
应该是
qi::rule<Iterator, std::vector<std::string>(), ascii::space_type> ident_list;
qi::rule<Iterator, std::string(), ascii::space_type> ident;
// and also
struct Grammar: qi::grammar<Iterator, std::vector<std::string>(), ascii::space_type>
现在可以编译了。
更多注意事项:只要 ident
是一个词素,您就可以简单地从中删除船长(参见 Boost spirit skipper issues)。
还有另一个错误,它匹配 *qi::alnum
,这意味着 0 个字符是匹配的。您至少要使用 1 个字符:+qi::alnum
.
这是一个工作示例(它还显示了我将船长编码到语法中的首选方法,因为它通常是语法的一部分):
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
template <typename Iterator> struct Grammar : qi::grammar<Iterator, std::vector<std::string>()> {
Grammar() : Grammar::base_type(start) {
using namespace qi;
ident = +alnum;
ident_list = *ident;
start = skip(ascii::space) [ident_list];
}
private:
qi::rule<Iterator, std::vector<std::string>()> start;
qi::rule<Iterator, std::vector<std::string>(), qi::ascii::space_type> ident_list;
qi::rule<Iterator, std::string()> ident;
};
int main() {
Grammar<std::string::const_iterator> grammar;
std::vector<std::string> result;
std::string const input = "My list of ident";
auto start = input.begin(), end = input.end();
if (parse(start, end, grammar, result))
std::cout << "Parsed " << result.size() << " tokens\n";
else
std::cout << "Parsing failed\n";
if (start != end)
std::cout << "Remaining unparsed input: '" << std::string(start,end) << "'\n";
}
版画
Parsed 4 tokens
奖金
对于这么简单的语法,考虑直接内联:
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main() {
for (std::string const input : { "My list of ident", " My list of ident " }) {
auto f = input.begin(), l = input.end();
std::list<std::string> result;
if (qi::phrase_parse(f, l, *qi::lexeme[+qi::graph], qi::space, result))
std::cout << "Parsed " << result.size() << " tokens\n";
else
std::cout << "Parsing failed\n";
if (f != l)
std::cout << "Remaining unparsed input: '" << std::string(f,l) << "'\n";
}
}