I'm trying to simply the spirit parser found in this answer:
Boolean expression (grammar) parser in c++
To remove the xor operator and logic. I'm failing to see how to do it, I tried using
expr_ = or_.alias();
or_ = (and__ >> "or" >> or_ )[ _val = phx::construct<binop<op_or >>(_1, _2) ] | and_ [ _val = _1 ];
and_ = (not_ >> "and" >> and_) [ _val = phx::construct<binop<op_and>>(_1, _2) ] | not_ [ _val = _1 ];
not_ = ("not" > simple ) [ _val = phx::construct<unop <op_not>>(_1) ] | simple [ _val = _1 ];
for the rule definitions, but I get a cryptic compiler message that I don't understand:
test\test.cpp `boost::spirit::_2' cannot appear in a constant-expression
If anyone can shed some light, I'd appreciate it.
Here is the log:
compiler: Default compiler Building Makefile:
"D:\Dev-Cpp\test\Makefile.win" Executing make... make.exe -f
"D:\Dev-Cpp\test\Makefile.win" all g++.exe -c test.cpp -o test.o
-I"D:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include" -I"D:/Dev-Cpp/include/c++/3.4.2/backward" -I"D:/Dev-Cpp/include/c++/3.4.2/mingw32" -I"D:/Dev-Cpp/include/c++/3.4.2" -I"D:/Dev-Cpp/include"
test.cpp: In constructor `parser<It, Skipper>::parser()':
test.cpp:76: error: `boost::spirit::_1' cannot appear in a
constant-expression test.cpp:76: error: a comma operator cannot
appear in a constant-expression test.cpp:76: error:
`boost::spirit::_2' cannot appear in a constant-expression
test.cpp:76: error: `>>' should be `> >' within a nested template
argument list
test.cpp:77: error: `boost::spirit::_1' cannot appear in a
constant-expression
test.cpp:77: error: a comma operator cannot appear in a
constant-expression test.cpp:77: error: `boost::spirit::_2' cannot
appear in a constant-expression test.cpp:77: error: `>>' should be `>
>' within a nested template argument list
test.cpp:78: error: `boost::spirit::_1' cannot appear in a
constant-expression
test.cpp:78: error: `>>' should be `> >' within a nested template
argument list
test.cpp: In function `int main()': test.cpp:98: error: expected
primary-expression before "auto" test.cpp:98: error: expected `;'
before "auto"
test.cpp:111: error: expected primary-expression before ')' token
test.cpp:111: error: expected `;' before ')' token test.cpp:113:
error: ISO C++ forbids declaration of `f' with no type test.cpp:113:
error: `begin' is not a member of `std' test.cpp:113: error: `input'
undeclared (first use this function) test.cpp:113: error: (Each
undeclared identifier is reported only once for each function it
appears in.) test.cpp:113: error: ISO C++ forbids declaration of `l'
with no type test.cpp:113: error: `end' is not a member of `std'
test.cpp:114: error: `f' cannot appear in a constant-expression
test.cpp:114: error: a function call cannot appear in a
constant-expression test.cpp:114: error: template argument 1 is
invalid test.cpp:114: error: invalid type in declaration before ';'
token
test.cpp:126: error: `f' cannot appear in a constant-expression
test.cpp:126: error: a function call cannot appear in a
constant-expression test.cpp:126: error: template argument 1 is
invalid test.cpp:126: error: ISO C++ forbids declaration of `e' with
no type
test.cpp:128: error: expected primary-expression before '(' token
test.cpp:128: error: `first' has not been declared test.cpp:128:
error: request for member of non-aggregate type before ',' token
test.cpp:128: error: `last' has not been declared test.cpp:128:
error: request for member of non-aggregate type before ')' token
D:/Dev-Cpp/include/c++/3.4.2/bits/stl_iterator_base_types.h: At
global scope:
D:/Dev-Cpp/include/c++/3.4.2/bits/stl_iterator_base_types.h: In
instantiation of `std::iterator_traits<int>':
D:/Dev-Cpp/include/boost/detail/iterator.hpp:83: instantiated from
`boost::detail::iterator_traits<int>'
D:/Dev-Cpp/include/boost/concept_check.hpp:509: instantiated from
`boost::InputIterator<int>'
D:/Dev-Cpp/include/boost/concept_check.hpp:545: instantiated from
`boost::ForwardIterator<int>'
D:/Dev-Cpp/include/boost/concept/detail/has_constraints.hpp:42:
instantiated from
`boost::concepts::not_satisfied<boost::ForwardIterator<int> >'
D:/Dev-Cpp/include/boost/mpl/if.hpp:67: instantiated from
`boost::mpl::if_<boost::concepts::not_satisfied<boost::ForwardIterator<int>
>, boost::concepts::constraint<boost::ForwardIterator<int> >, boost::concepts::requirement<boost::concepts::failed************boost::ForwardIterator<int>::************>
>' D:/Dev-Cpp/include/boost/concept/detail/general.hpp:56: instantiated from `boost::concepts::requirement_<void
(*)(boost::ForwardIterator<int>)>'
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp:149: instantiated
from `bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const
Expr&, const Skipper&, boost::spirit::qi::skip_flag::enum_type,
Attr&) [with Iterator = int, Expr = bool, Skipper =
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::standard> >, 0l>, Attr =
boost::variant<var, boost::recursive_wrapper<unop<op_not> >,
boost::recursive_wrapper<binop<op_and> >,
boost::recursive_wrapper<binop<op_or> >,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_>]'
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp:197: instantiated
from `bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const
Expr&, const Skipper&, Attr&) [with Iterator = int, Expr = bool,
Skipper = boost::spirit::standard::space_type, Attr = expr]'
test.cpp:119: instantiated from here
D:/Dev-Cpp/include/c++/3.4.2/bits/stl_iterator_base_types.h:129:
error: `int' is not a class, struct, or union type
D:/Dev-Cpp/include/c++/3.4.2/bits/stl_iterator_base_types.h:130:
error: `int' is not a class, struct, or union type
D:/Dev-Cpp/include/c++/3.4.2/bits/stl_iterator_base_types.h:131:
error: `int' is not a class, struct, or union type
D:/Dev-Cpp/include/c++/3.4.2/bits/stl_iterator_base_types.h:132:
error: `int' is not a class, struct, or union type
D:/Dev-Cpp/include/c++/3.4.2/bits/stl_iterator_base_types.h:133:
error: `int' is not a class, struct, or union type
D:/Dev-Cpp/include/boost/concept_check.hpp: In instantiation of
`boost::InputIterator<int>':
D:/Dev-Cpp/include/boost/concept_check.hpp:545: instantiated from
`boost::ForwardIterator<int>'
D:/Dev-Cpp/include/boost/concept/detail/has_constraints.hpp:42:
instantiated from
`boost::concepts::not_satisfied<boost::ForwardIterator<int> >'
D:/Dev-Cpp/include/boost/mpl/if.hpp:67: instantiated from
`boost::mpl::if_<boost::concepts::not_satisfied<boost::ForwardIterator<int>
>, boost::concepts::constraint<boost::ForwardIterator<int> >, boost::concepts::requirement<boost::concepts::failed************boost::ForwardIterator<int>::************>
>' D:/Dev-Cpp/include/boost/concept/detail/general.hpp:56: instantiated from `boost::concepts::requirement_<void
(*)(boost::ForwardIterator<int>)>'
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp:149: instantiated
from `bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const
Expr&, const Skipper&, boost::spirit::qi::skip_flag::enum_type,
Attr&) [with Iterator = int, Expr = bool, Skipper =
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::standard> >, 0l>, Attr =
boost::variant<var, boost::recursive_wrapper<unop<op_not> >,
boost::recursive_wrapper<binop<op_and> >,
boost::recursive_wrapper<binop<op_or> >,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_>]'
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp:197: instantiated
from `bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const
Expr&, const Skipper&, Attr&) [with Iterator = int, Expr = bool,
Skipper = boost::spirit::standard::space_type, Attr = expr]'
test.cpp:119: instantiated from here
D:/Dev-Cpp/include/boost/concept_check.hpp:509: error: no type named
`value_type' in `struct boost::detail::iterator_traits<int>'
D:/Dev-Cpp/include/boost/concept_check.hpp:510: error: no type named
`difference_type' in `struct boost::detail::iterator_traits<int>'
D:/Dev-Cpp/include/boost/concept_check.hpp:511: error: no type named
`reference' in `struct boost::detail::iterator_traits<int>'
D:/Dev-Cpp/include/boost/concept_check.hpp:512: error: no type named
`pointer' in `struct boost::detail::iterator_traits<int>'
D:/Dev-Cpp/include/boost/concept_check.hpp:513: error: no type named
`iterator_category' in `struct boost::detail::iterator_traits<int>'
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp: In function `bool
boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&,
const Skipper&, boost::spirit::qi::skip_flag::enum_type, Attr&) [with
Iterator = int, Expr = bool, Skipper =
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::standard> >, 0l>, Attr =
boost::variant<var, boost::recursive_wrapper<unop<op_not> >,
boost::recursive_wrapper<binop<op_and> >,
boost::recursive_wrapper<binop<op_or> >,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_>]':
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp:197: instantiated
from `bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const
Expr&, const Skipper&, Attr&) [with Iterator = int, Expr = bool,
Skipper = boost::spirit::standard::space_type, Attr = expr]'
test.cpp:119: instantiated from here
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp:155: error:
conversion from
`mpl_::failed************(boost::spirit::qi::phrase_parse(Iterator&,
Iterator, const Expr&, const Skipper&,
boost::spirit::qi::skip_flag::enum_type, Attr&) [with Iterator = int,
Expr = bool, Skipper =
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::standard> >, 0l>, Attr =
boost::variant<var, boost::recursive_wrapper<unop<op_not> >,
boost::recursive_wrapper<binop<op_and> >,
boost::recursive_wrapper<binop<op_or> >,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_,
boost::detail::variant::void_>]::error_invalid_expression::************)(bool)'
to non-scalar type `mpl_::assert< false>' requested
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp:155: error:
enumerator value for `mpl_assertion_in_line_155' not integer constant
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp:197: instantiated
from `bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const
Expr&, const Skipper&, Attr&) [with Iterator = int, Expr = bool,
Skipper = boost::spirit::standard::space_type, Attr = expr]'
test.cpp:119: instantiated from here
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp:164: error: request
for member `parse' in `boost::spirit::compile [with Domain =
boost::spirit::qi::domain, Expr = bool](((const bool&)(+expr)))',
which is of non-class type `bool'
D:/Dev-Cpp/include/boost/concept_check.hpp: In destructor
`boost::ForwardIterator<TT>::~ForwardIterator() [with TT = int]':
D:/Dev-Cpp/include/boost/concept/detail/general.hpp:38:
instantiated from `static void
boost::concepts::requirement<boost::concepts::failed************Model::************>::failed()
[with Model = boost::ForwardIterator<int>]'
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp:149: instantiated
from `bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const
Expr&, const Skipper&, boost::spirit::qi::skip_flag::enum_type,
Attr&) [with Iterator = int, Expr = bool, Skipper =
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::standard> >, 0l>, Attr =
boost::variant<var, boost::recursive_wrapper<unop<op_not> >,
boost::recursive_wrapper<binop<op_and> >,
boost::recursive_wrapper<binop<op_or> >,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_>]'
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp:197: instantiated
from `bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const
Expr&, const Skipper&, Attr&) [with Iterator = int, Expr = bool,
Skipper = boost::spirit::standard::space_type, Attr = expr]'
test.cpp:119: instantiated from here
D:/Dev-Cpp/include/boost/concept_check.hpp:548: error: no type named
`iterator_category' in `struct boost::ForwardIterator<int>'
D:/Dev-Cpp/include/boost/concept_check.hpp:548: error: `failed' is
not a member of `<declaration error>'
D:/Dev-Cpp/include/boost/concept_check.hpp:553: error: no type named
`reference' in `struct boost::InputIterator<int>'
D:/Dev-Cpp/include/boost/concept_check.hpp:554: error: no type named
`reference' in `struct boost::InputIterator<int>'
D:/Dev-Cpp/include/boost/spirit/home/qi/char/char_parser.hpp: In
member function `bool boost::spirit::qi::char_parser<Derived, Char,
Attr>::parse(Iterator&, const Iterator&, Context&, const Skipper&,
Attribute&) const [with Iterator = int, Context = const
boost::spirit::unused_type, Skipper = boost::spirit::unused_type,
Attribute = const boost::spirit::unused_type, Derived =
boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::standard> >, Char = char, Attr =
char]': D:/Dev-Cpp/include/boost/spirit/home/qi/skip_over.hpp:27:
instantiated from `void boost::spirit::qi::skip_over(Iterator&, const
Iterator&, const T&) [with Iterator = int, T =
boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::standard> >]'
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp:169: instantiated
from `bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const
Expr&, const Skipper&, boost::spirit::qi::skip_flag::enum_type,
Attr&) [with Iterator = int, Expr = bool, Skipper =
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::standard> >, 0l>, Attr =
boost::variant<var, boost::recursive_wrapper<unop<op_not> >,
boost::recursive_wrapper<binop<op_and> >,
boost::recursive_wrapper<binop<op_or> >,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_>]'
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp:197: instantiated
from `bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const
Expr&, const Skipper&, Attr&) [with Iterator = int, Expr = bool,
Skipper = boost::spirit::standard::space_type, Attr = expr]'
test.cpp:119: instantiated from here
D:/Dev-Cpp/include/boost/spirit/home/qi/char/char_parser.hpp:68:
error: invalid type argument of `unary *'
D:/Dev-Cpp/include/boost/spirit/home/qi/char/char_parser.hpp:70:
error: invalid type argument of `unary *'
D:/Dev-Cpp/include/boost/concept_check.hpp: In destructor
`boost::InputIterator<TT>::~InputIterator() [with TT = int]':
D:/Dev-Cpp/include/boost/concept_check.hpp:547: instantiated from
`boost::ForwardIterator<TT>::~ForwardIterator() [with TT = int]'
D:/Dev-Cpp/include/boost/concept/detail/general.hpp:38:
instantiated from `static void
boost::concepts::requirement<boost::concepts::failed************Model::************>::failed()
[with Model = boost::ForwardIterator<int>]'
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp:149: instantiated
from `bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const
Expr&, const Skipper&, boost::spirit::qi::skip_flag::enum_type,
Attr&) [with Iterator = int, Expr = bool, Skipper =
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::standard> >, 0l>, Attr =
boost::variant<var, boost::recursive_wrapper<unop<op_not> >,
boost::recursive_wrapper<binop<op_and> >,
boost::recursive_wrapper<binop<op_or> >,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_>]'
D:/Dev-Cpp/include/boost/spirit/home/qi/parse.hpp:197: instantiated
from `bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const
Expr&, const Skipper&, Attr&) [with Iterator = int, Expr = bool,
Skipper = boost::spirit::standard::space_type, Attr = expr]'
test.cpp:119: instantiated from here
D:/Dev-Cpp/include/boost/concept_check.hpp:517: error: no type named
`difference_type' in `struct boost::detail::iterator_traits<int>'
D:/Dev-Cpp/include/boost/concept_check.hpp:517: error: `failed' is
not a member of `<declaration error>'
D:/Dev-Cpp/include/boost/concept_check.hpp:518: error: no type named
`iterator_category' in `struct boost::detail::iterator_traits<int>'
D:/Dev-Cpp/include/boost/concept_check.hpp:518: error: `failed' is
not a member of `<declaration error>'
D:/Dev-Cpp/include/boost/concept_check.hpp:521: error: invalid type
argument of `unary *'
make.exe: *** [test.o] Error 1
Execution terminated
You accidentally mistyped and_ as and__.
Changing and__ to and_ will make it compile.
Here's a more cleaned up version, removing the now-unneeded declarations relating to xor:
Edit Also 'backported' for old compilers that don't know about auto, decltype, proper template parsing (>> vs. > >) etc.):
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/variant/recursive_wrapper.hpp>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
struct op_or {};
struct op_and {};
struct op_not {};
typedef std::string var;
template <typename tag> struct binop;
template <typename tag> struct unop;
typedef boost::variant<var,
boost::recursive_wrapper<unop <op_not> >,
boost::recursive_wrapper<binop<op_and> >,
boost::recursive_wrapper<binop<op_or> >
> expr;
template <typename tag> struct binop
{
explicit binop(const expr& l, const expr& r) : oper1(l), oper2(r) { }
expr oper1, oper2;
};
template <typename tag> struct unop
{
explicit unop(const expr& o) : oper1(o) { }
expr oper1;
};
struct printer : boost::static_visitor<void>
{
printer(std::ostream& os) : _os(os) {}
std::ostream& _os;
//
void operator()(const var& v) const { _os << v; }
void operator()(const binop<op_and>& b) const { print(" & ", b.oper1, b.oper2); }
void operator()(const binop<op_or >& b) const { print(" | ", b.oper1, b.oper2); }
void print(const std::string& op, const expr& l, const expr& r) const
{
_os << "(";
boost::apply_visitor(*this, l);
_os << op;
boost::apply_visitor(*this, r);
_os << ")";
}
void operator()(const unop<op_not>& u) const
{
_os << "(";
_os << "!";
boost::apply_visitor(*this, u.oper1);
_os << ")";
}
};
std::ostream& operator<<(std::ostream& os, const expr& e)
{ boost::apply_visitor(printer(os), e); return os; }
template <typename It, typename Skipper = qi::space_type>
struct parser : qi::grammar<It, expr(), Skipper>
{
parser() : parser::base_type(expr_)
{
using namespace qi;
expr_ = or_.alias();
or_ = (and_ >> "or" >> or_ ) [ _val = phx::construct<binop<op_or > >(_1, _2) ] | and_ [ _val = _1 ];
and_ = (not_ >> "and" >> and_) [ _val = phx::construct<binop<op_and> >(_1, _2) ] | not_ [ _val = _1 ];
not_ = ("not" > simple ) [ _val = phx::construct<unop <op_not> >(_1) ] | simple [ _val = _1 ];
simple = (('(' > expr_ > ')') | var_);
var_ = qi::lexeme[ +alpha ];
BOOST_SPIRIT_DEBUG_NODE(expr_);
BOOST_SPIRIT_DEBUG_NODE(or_);
BOOST_SPIRIT_DEBUG_NODE(and_);
BOOST_SPIRIT_DEBUG_NODE(not_);
BOOST_SPIRIT_DEBUG_NODE(simple);
BOOST_SPIRIT_DEBUG_NODE(var_);
}
private:
qi::rule<It, var() , Skipper> var_;
qi::rule<It, expr(), Skipper> not_, and_, or_, simple, expr_;
};
int main()
{
const std::string inputs[] = {
// From the OP:
std::string("(a and b) or ((c and d) or (a and b));"),
std::string("a and b or (c and d or a and b);"),
/// Simpler tests:
std::string("a and b;"),
std::string("a or b;"),
std::string("a or b;"),
std::string("not a;"),
std::string("not a and b;"),
std::string("not (a and b);"),
std::string("a or b or c;"),
std::string("") // marker
};
for (const std::string *i = inputs; !i->empty(); ++i)
{
typedef std::string::const_iterator It;
It f(i->begin()), l(i->end());
parser<It> p;
try
{
expr result;
bool ok = qi::phrase_parse(f,l,p > ';',qi::space,result);
if (!ok)
std::cerr << "invalid input\n";
else
std::cout << "result: " << result << "\n";
} catch (const qi::expectation_failure<It>& e)
{
std::cerr << "expectation_failure at '" << std::string(e.first, e.last) << "'\n";
}
if (f!=l) std::cerr << "unparsed: '" << std::string(f,l) << "'\n";
}
return 0;
}
Output of running this sample is
result: ((a & b) | ((c & d) | (a & b)))
result: ((a & b) | ((c & d) | (a & b)))
result: (a & b)
result: (a | b)
result: (a | b)
result: (!a)
result: ((!a) & b)
result: (!(a & b))
result: (a | (b | c))
Related
This code is not my actual code, but just illustrates the issue. I have a rule that matches 0 or more digits, and an action that is supposed to count them and return that count as the synthesized attribute.
The attribute of *qi::ascii::digit should be a std::vector of the matched digits. So, I wrote the action so that it simply calls .size() and assigns the result to the synthesized attribute. To call .size(), I use boost.phoenix to bind a lambda that calls .size().
#include <boost/phoenix/bind/bind_function_object.hpp>
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/operator.hpp>
#include <boost/spirit/include/qi.hpp>
#include <cstdint>
#include <iostream>
#include <string>
namespace phx = boost::phoenix;
namespace qi = boost::spirit::qi;
using It = std::string::iterator;
struct Parser : qi::grammar<std::string::iterator, size_t()> {
Parser() : Parser::base_type(r) {
auto count = [](auto&& v) { return v.size(); };
r %= (*qi::ascii::digit)[qi::_val = phx::bind(count, qi::_1)];
}
qi::rule<It, size_t()> r;
};
int main() {
using namespace std;
std::string s = "123";
int c;
Parser p;
qi::parse(s.begin(), s.end(), p, c);
std::cout << c << '\n';
}
But it doesn't work. I expect this code to compile and print 3. Instead, I get a very long compile error. The error is roughly what I would expect if the action were simply qi::_val = qi::_1, which perplexes me.
In file included from /usr/local/include/boost/type_traits/is_convertible.hpp:20,
from /usr/local/include/boost/type_traits/is_empty.hpp:12,
from /usr/local/include/boost/mpl/empty_base.hpp:23,
from /usr/local/include/boost/fusion/sequence/intrinsic/at.hpp:15,
from /usr/local/include/boost/phoenix/core/expression.hpp:11,
from /usr/local/include/boost/phoenix/bind/bind_function_object.hpp:17,
from spirit2.cpp:1:
/usr/local/include/boost/spirit/home/qi/parse.hpp: In instantiation of ‘bool boost::spirit::qi::parse(Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Expr = int; Attr = Parser]’:
/usr/local/include/boost/spirit/home/qi/parse.hpp:100:25: required from ‘bool boost::spirit::qi::parse(const Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Expr = int; Attr = Parser]’
spirit2.cpp:27:39: required from here
/usr/local/include/boost/spirit/home/qi/parse.hpp:85:9: error: static assertion failed: error_invalid_expression
BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/local/include/boost/spirit/home/qi/detail/parse_auto.hpp:14,
from /usr/local/include/boost/spirit/home/qi/auto.hpp:16,
from /usr/local/include/boost/spirit/home/qi.hpp:15,
from /usr/local/include/boost/spirit/include/qi.hpp:16,
from spirit2.cpp:4:
/usr/local/include/boost/spirit/home/qi/parse.hpp:88:42: error: request for member ‘parse’ in ‘boost::spirit::compile<boost::spirit::qi::domain, int>((* & expr))’, which is of non-class type ‘boost::spirit::result_of::compile<boost::spirit::qi::domain, boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<int>, 0>, boost::spirit::unused_type, void>::type’ {aka ‘int’}
return compile<qi::domain>(expr).parse(first, last, context, unused, attr);
~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
In file included from /usr/local/include/boost/spirit/home/qi/auxiliary/attr.hpp:18,
from /usr/local/include/boost/spirit/home/qi/auxiliary.hpp:19,
from /usr/local/include/boost/spirit/home/qi.hpp:16,
from /usr/local/include/boost/spirit/include/qi.hpp:16,
from spirit2.cpp:4:
/usr/local/include/boost/spirit/home/qi/detail/assign_to.hpp: In instantiation of ‘static void boost::spirit::traits::assign_to_attribute_from_value<Attribute, T, Enable>::call(const T_&, Attribute&, mpl_::false_) [with T_ = std::vector<char, std::allocator<char> >; Attribute = long unsigned int; T = std::vector<char, std::allocator<char> >; Enable = void; mpl_::false_ = mpl_::bool_<false>]’:
/usr/local/include/boost/spirit/home/qi/detail/assign_to.hpp:171:17: required from ‘static void boost::spirit::traits::assign_to_attribute_from_value<Attribute, T, Enable>::call(const T&, Attribute&) [with Attribute = long unsigned int; T = std::vector<char, std::allocator<char> >; Enable = void]’
/usr/local/include/boost/spirit/home/qi/detail/assign_to.hpp:370:63: required from ‘void boost::spirit::traits::detail::assign_to(const T&, Attribute&, mpl_::false_) [with T = std::vector<char, std::allocator<char> >; Attribute = long unsigned int; mpl_::false_ = mpl_::bool_<false>]’
/usr/local/include/boost/spirit/home/qi/detail/assign_to.hpp:393:26: required from ‘void boost::spirit::traits::assign_to(const T&, Attribute&) [with T = std::vector<char, std::allocator<char> >; Attribute = long unsigned int]’
/usr/local/include/boost/spirit/home/qi/detail/attributes.hpp:27:30: required from ‘static void boost::spirit::qi::default_transform_attribute<Exposed, Transformed>::post(Exposed&, const Transformed&) [with Exposed = long unsigned int; Transformed = std::vector<char, std::allocator<char> >]’
/usr/local/include/boost/spirit/home/qi/action/action.hpp:71:36: required from ‘bool boost::spirit::qi::action<Subject, Action>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<long unsigned int&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::unused_type; Attribute = long unsigned int; Subject = boost::spirit::qi::kleene<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::digit, boost::spirit::char_encoding::ascii> > >; Action = boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::phoenix::actor<boost::spirit::attribute<0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<Parser::Parser()::<lambda(auto:1&&)> >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> >]’
/usr/local/include/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:73:54: [ skipping 3 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/local/include/boost/function/function_template.hpp:720:7: required from ‘boost::function4<R, T1, T2, T3, T4>::function4(Functor, typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::action<boost::spirit::qi::kleene<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::digit, boost::spirit::char_encoding::ascii> > >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::phoenix::actor<boost::spirit::attribute<0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<Parser::Parser()::<lambda(auto:1&&)> >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> > >, mpl_::bool_<true> >; R = bool; T0 = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<long unsigned int&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::unused_type&; typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type = int]’
/usr/local/include/boost/function/function_template.hpp:1068:16: required from ‘boost::function<R(T0, T1, T2, T3)>::function(Functor, typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::action<boost::spirit::qi::kleene<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::digit, boost::spirit::char_encoding::ascii> > >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::phoenix::actor<boost::spirit::attribute<0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<Parser::Parser()::<lambda(auto:1&&)> >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> > >, mpl_::bool_<true> >; R = bool; T0 = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<long unsigned int&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::unused_type&; typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type = int]’
/usr/local/include/boost/function/function_template.hpp:1121:5: required from ‘typename boost::enable_if_<(! 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::action<boost::spirit::qi::kleene<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::digit, boost::spirit::char_encoding::ascii> > >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::phoenix::actor<boost::spirit::attribute<0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<Parser::Parser()::<lambda(auto:1&&)> >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> > >, mpl_::bool_<true> >; R = bool; T0 = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<long unsigned int&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::unused_type&; typename boost::enable_if_<(! boost::is_integral<Functor>::value), boost::function<R(T0, T1, T2, T3)>&>::type = boost::function<bool(__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<long unsigned int&, boost::fusion::nil_>, boost::fusion::vector<> >&, const boost::spirit::unused_type&)>&]’
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:185: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_<true>; Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::dereference, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::digit, boost::spirit::char_encoding::ascii> >, 0>&>, 1>&, const boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::phoenix::actor<boost::spirit::attribute<0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<Parser::Parser()::<lambda(auto:1&&)> >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> >&>, 2>; Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; T1 = long unsigned int(); T2 = boost::spirit::unused_type; 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:249:31: required from ‘boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>& boost::spirit::qi::operator%=(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, Expr&&) [with Expr = const boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::dereference, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::digit, boost::spirit::char_encoding::ascii> >, 0>&>, 1>&, const boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::phoenix::actor<boost::spirit::attribute<0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<Parser::Parser()::<lambda(auto:1&&)> >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> >&>, 2>; Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; T1 = long unsigned int(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’
spirit2.cpp:16:69: required from here
/usr/local/include/boost/spirit/home/qi/detail/assign_to.hpp:153:20: error: invalid static_cast from type ‘const std::vector<char, std::allocator<char> >’ to type ‘long unsigned int’
attr = static_cast<Attribute>(val);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
The solution is to drop %:
r = (*qi::ascii::digit)[qi::_val = phx::bind(count, qi::_1)];
The important error message is in the last line: error: invalid static_cast from type ‘const std::vector<char, std::allocator<char> >’ to type ‘long unsigned int’
For why it produces vector<char> see here.
There is use of semantic action and:
r %= p and r = p are equivalent if there are no semantic actions
associated with p.
Read more about it here.
The doqtor did an excellent job of introducing the relevant concepts. I'd just like to show some simplification if you have a recent compiler (which it looks like you do):
phx::function count { [](auto&& v) { return v.size(); } };
r = (*digit)[_val = count(_1)];
Live On Coliru
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace phx = boost::phoenix;
namespace qi = boost::spirit::qi;
using It = std::string::const_iterator;
struct Parser : qi::grammar<It, size_t()> {
Parser() : Parser::base_type(r) {
using namespace qi;
phx::function count { [](auto&& v) { return v.size(); } };
r = (*digit)[_val = count(_1)];
}
private:
qi::rule<It, size_t()> r;
};
int main() {
std::string const s = "123";
int c;
Parser p;
if (qi::parse(s.begin(), s.end(), p, c)) {
std::cout << "Number of digits: " << c << "\n";
}
}
Prints
Number of digits: 3
I have been writing a grammar in C++ using Spirit Qi from Boost library. As a novice in the language, it was a tough to get used to the syntax and quirks of the library but now I kind of understand how it works.
I am having an error when using qi::lexeme. My actual grammar is quite big, so I made a small code snippet where the same problem is present. The following code compiles without errors:
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <set>
#include <iostream>
#include <string>
#include <complex>
namespace client
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
typedef boost::tuple<char, char> range;
}
namespace client
{
template <typename Iterator>
struct employee_parser : qi::grammar<Iterator, range(), ascii::space_type>
{
employee_parser() : employee_parser::base_type(start)
{
using qi::lit;
using qi::lexeme;
using ascii::char_;
range_rule =
char_("a-z") >> lit("-") >> char_("a-z")
| char_("A-Z") >> lit("-") >> char_("A-Z")
| char_("0-9") >> lit("-") >> char_("0-9")
;
start = range_rule;
}
qi::rule<Iterator, range(), ascii::space_type> range_rule;
qi::rule<Iterator, range(), ascii::space_type> start;
};
}
int main()
{
typedef std::string::const_iterator iterator_type;
typedef client::employee_parser<iterator_type> employee_parser;
employee_parser g;
return 0;
}
Now, if I replace the line start = range_rule; and use start = lexeme[range_rule]; instead, the compilation fails.
As I read from the docs, lexeme[a] should preserve the subject parser's attributes, so I can't understand why it fails. The output error is huge and pretty cryptic so I don't have any clues:
In file included from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal.hpp:14:0,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi.hpp:21,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/include/qi.hpp:16,
from cpp/tests/test2.cpp:2:
/home/martin/vscode_cpp_projects/boost_1_68_0/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<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::detail::unused_skipper<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >; Attribute = boost::tuples::tuple<char, char>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = boost::tuples::tuple<char, 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> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’:
/home/martin/vscode_cpp_projects/boost_1_68_0/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<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::detail::unused_skipper<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >; Attribute = boost::tuples::tuple<char, char>; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/directive/lexeme.hpp:66:64: required from ‘typename boost::disable_if<boost::spirit::qi::detail::is_unused_skipper<Skipper>, bool>::type boost::spirit::qi::lexeme_directive<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<boost::tuples::tuple<char, 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 = boost::tuples::tuple<char, char>; Subject = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> >; typename boost::disable_if<boost::spirit::qi::detail::is_unused_skipper<Skipper>, bool>::type = bool]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:43:54: required from ‘bool boost::spirit::qi::detail::parser_binder<Parser, Auto>::call(Iterator&, const Iterator&, Context&, const Skipper&, mpl_::false_) const [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >; Context = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >; Parser = boost::spirit::qi::lexeme_directive<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> > >; Auto = mpl_::bool_<false>; mpl_::false_ = mpl_::bool_<false>]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:53:24: required from ‘bool boost::spirit::qi::detail::parser_binder<Parser, Auto>::operator()(Iterator&, const Iterator&, Context&, const Skipper&) const [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >; Context = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >; Parser
= boost::spirit::qi::lexeme_directive<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> > >; Auto = mpl_::bool_<false>]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:138:22: required from ‘static R boost::detail::function::function_obj_invoker4<FunctionObj, R, T0, T1, T2, T3>::invoke(boost::detail::function::function_buffer&, T0, T1, T2, T3) [with FunctionObj = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::lexeme_directive<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, 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> >, 0>, 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<boost::tuples::tuple<char, 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> >&]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:936:38: [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:1074: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::lexeme_directive<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, 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> >, 0>, 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<boost::tuples::tuple<char, 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]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:1127: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::lexeme_directive<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, 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> >, 0>, 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<boost::tuples::tuple<char, 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<boost::tuples::tuple<char, 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> >&)>&]’
/home/martin/vscode_cpp_projects/boost_1_68_0/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::subscript, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::lexeme>, 0>&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = boost::tuples::tuple<char, 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> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type; mpl_::true_ = mpl_::bool_<true>]’
/home/martin/vscode_cpp_projects/boost_1_68_0/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::subscript, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::lexeme>, 0>&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = boost::tuples::tuple<char, 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> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’
cpp/tests/test2.cpp:40:19: required from ‘client::employee_parser<Iterator>::employee_parser() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >]’
cpp/tests/test2.cpp:56:21: required from here
/home/martin/vscode_cpp_projects/boost_1_68_0/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::tuples::tuple<char, 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> >&)>}) (__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> >, boost::tuples::tuple<char, 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>::context_type&, const boost::spirit::qi::detail::unused_skipper<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 /home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/detail/maybe_include.hpp:43:0,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/detail/function_iterate.hpp:14,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/preprocessor/iteration/detail/iter/forward1.hpp:67,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/function.hpp:70,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/rule.hpp:16,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal.hpp:14,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi.hpp:21,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/include/qi.hpp:16,
from cpp/tests/test2.cpp:2:
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:763: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::tuples::tuple<char, 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> >&; boost::function4<R, T1, T2, T3, T4>::result_type = bool]
result_type operator()(BOOST_FUNCTION_PARMS) const
^~~~~~~~
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:763:17: note: no known conversion for argument 4 from ‘const boost::spirit::qi::detail::unused_skipper<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >’ to ‘const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&’
As I read from the docs, lexeme[a] should preserve the subject parser's attributes, so I can't understand why it fails.
Yes it preserves the attributes. It does NOT preserve the skipper (for obvious reasons), and your range_rule declares one. The compiler messages contain this info:
BOOST_STATIC_ASSERT_MSG((is_same<skipper_type, unused_type>::value ||
!is_same<Skipper, unused_type>::value),
"The rule was instantiated with a skipper type but you have not pass any. "
"Did you use `parse` instead of `phrase_parse`?");
So, drop the skipper from the range_rule. Ironically, just dropping it will implicitly make it behave like a lexeme so you wouldn't need the lexeme[] around it anyways.
See also Boost spirit skipper issues
In short:
can't call rule that requires a skipper without one
okay to call an implicit lexeme rule from a parser with a skipper context
I usually group my rules to indicate as much, and preface them with a comment, like:
private:
qi::rule<Iterator, range(), ascii::space_type> start;
// lexmes
qi::rule<Iterator, range()> range_rule;
But I also usually encapsulate the skipper unless it really makes sense (?!) for the caller to change the skipper.
See also similar tasks:
Parsing comma-separated list of ranges and numbers with semantic actions
method for expand a-z to abc...xyz form
Suggested Fixes
Live On Coliru
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <set>
#include <iostream>
#include <string>
#include <complex>
namespace client
{
namespace qi = boost::spirit::qi;
typedef boost::tuple<char, char> range;
}
namespace client
{
template <typename Iterator>
struct employee_parser : qi::grammar<Iterator, range()>
{
employee_parser() : employee_parser::base_type(start)
{
using qi::lit;
using qi::lexeme;
using qi::ascii::char_;
range_rule =
char_("a-z") >> lit("-") >> char_("a-z")
| char_("A-Z") >> lit("-") >> char_("A-Z")
| char_("0-9") >> lit("-") >> char_("0-9")
;
start = qi::skip(qi::ascii::space) [ range_rule ];
}
private:
qi::rule<Iterator, range()> start;
// lexmes
qi::rule<Iterator, range()> range_rule;
};
}
int main()
{
typedef std::string::const_iterator iterator_type;
typedef client::employee_parser<iterator_type> employee_parser;
employee_parser g;
std::string const input("a-k");
client::range r;
return parse(begin(input), end(input), g, r)
? 0
: 1;
}
I am trying to build a parser using boost::spirit that, besides other stuff, should be able to parse pairs of integers such as "(3,4)".
My code is working but I also want to accept pairs that contain spaces, i.e. "( 4 , 6 )". When trying to add the space_type skipper as shown in the boost spirit tutorial the following code fails to compile. I can not see the grave mistake I am making (I suspected using the wrong namespace but it seems to be the correct one).
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/std_pair.hpp>
using namespace std;
using namespace boost::spirit::qi;
using position = std::pair<int, int>;
template<typename Iterator>
struct position_grammar : grammar<Iterator, position(), boost::spirit::ascii::space_type> {
position_grammar() : position_grammar::base_type(start) {
start = lit("(") >> int_ >> lit(",") >> int_ >> lit(")");
}
rule<Iterator, position(),boost::spirit::ascii::space_type> start;
};
int main() {
std::string s = "(1,2)";
position_grammar<std::string::iterator> grammar;
position p;
bool r = parse(s.begin(), s.end(), grammar,p);
cout << "parsing: " << r << " position: " << p.first << ", " << p.second << "\n";
return 0;
}
Compiler output:
In file included from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14:0,
from /usr/include/boost/spirit/home/qi.hpp:21,
from /usr/include/boost/spirit/include/qi.hpp:16,
from /home/pansen/proggs/foo/src/foo/model/routing_parser_test.cpp:2:
/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::pair<int, int>&, boost::fusion::nil_>, boost::spirit::locals<> >; Skipper = boost::spirit::unused_type; Attribute = std::pair<int, int>; Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; T1 = std::pair<int, int>(); 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:72: required from ‘bool boost::spirit::qi::reference<Subject>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<std::pair<int, int>&, boost::fusion::nil_>, boost::spirit::locals<> >; Skipper = boost::spirit::unused_type; Attribute = std::pair<int, int>; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >, std::pair<int, int>(), 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<char*, std::__cxx11::basic_string<char> >; Expr = position_grammar<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> > >; Attr = std::pair<int, int>]’
/usr/include/boost/spirit/home/qi/parse.hpp:98:25: required from ‘bool boost::spirit::qi::parse(const Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Expr = position_grammar<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> > >; Attr = std::pair<int, int>]’
/home/pansen/proggs/foo/src/foo/model/routing_parser_test.cpp:23:46: required from here
/usr/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<char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<std::pair<int, int>&, 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<char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >, std::pair<int, int>(), 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&)’
if (f(first, last, context, skipper))
^
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:21,
from /usr/include/boost/spirit/include/qi.hpp:16,
from /home/pansen/proggs/foo/src/foo/model/routing_parser_test.cpp:2:
/usr/include/boost/function/function_template.hpp:767: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<char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<std::pair<int, int>&, 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]
result_type operator()(BOOST_FUNCTION_PARMS) const
^
/usr/include/boost/function/function_template.hpp:767: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> >&’
The error points to if (f(first, last, context, skipper)) which looks like the error here (see answer by sehe). But I already correctly specify the attribute (at least I think so).
If you wish to use a skipper, you must pass an instance of it, by calling phrase_parse instead of parse:
bool r = phrase_parse(s.begin(), s.end(), grammar, qi::space, p);
Alternatively, you can hide the details about the skipper by declaring it in a enclosing skipper-less rule with skip(qi::space) [ real_start_rule_with_skipper ]
See also: Boost spirit skipper issues
Notes:
do not use using namespace - especially not both std and boost::spirit::qi at the same time. You can always use using namespace qi; locally
no need to wrap every literal in lit(). Here's the rule simplified:
position_rule = '(' >> qi::int_ >> ',' >> qi::int_ >> ')';
DEMO
Live On Coliru
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
namespace qi = boost::spirit::qi;
using position = std::pair<int, int>;
template <typename Iterator> struct position_grammar : qi::grammar<Iterator, position()> {
position_grammar() : position_grammar::base_type(start) {
position_rule = '(' >> qi::int_ >> ',' >> qi::int_ >> ')';
start = qi::skip(boost::spirit::ascii::space) [ position_rule ];
}
qi::rule<Iterator, position()> start;
qi::rule<Iterator, position(), boost::spirit::ascii::space_type> position_rule;
};
int main() {
std::string s = " ( 1\t,\r\n2 )";
position_grammar<std::string::iterator> grammar;
position p;
bool r = parse(s.begin(), s.end(), grammar, p);
std::cout << "parsing: " << r << " position: " << p.first << ", " << p.second << "\n";
}
Prints
parsing: 1 position: 1, 2
This question already has an answer here:
Spirit Qi attribute propagation issue with single-member struct
(1 answer)
Closed 8 years ago.
#include <iostream>
#include <vector>
#include <string>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
namespace qi = boost::spirit::qi;
struct VectorWrapper
{
std::vector<std::string> data;
};
BOOST_FUSION_ADAPT_STRUCT(
VectorWrapper,
(std::vector<std::string>, data)
)
int main ()
{
std::string input("aa aa aa");
std::string::iterator strbegin = input.begin();
qi::rule<std::string::iterator, VectorWrapper(), qi::space_type > testRule =
+(qi::string("aa"));
VectorWrapper result;
bool ok = qi::phrase_parse(
strbegin,
input.end(),
testRule,
qi::space,
result);
if (ok && strbegin == input.end()) {
std::cout << result.data.size();
for (int i = 0; i < result.data.size(); ++i) {
std::cout << result.data[i] << " ";
}
} else {
std::cout << "fail" << std::endl;
std::cout << std::string(strbegin, input.end()) << std::endl;
}
}
I need help to find out problem in this code. Compiler complains about type in VectorWrapper struct but shouldn't BOOST_FUSION_ADAPT_STRUCT add it?
After adding dummy field (from this answer)I am getting the same error:
struct VectorWrapper
{
std::vector<std::string> data;
qi::unused_type dummy;
};
BOOST_FUSION_ADAPT_STRUCT(
VectorWrapper,
(std::vector<std::string>, data)
(qi::unused_type, dummy)
)
The error message:
In file included from /usr/local/include/boost/spirit/home/support/string_traits.hpp:16:0,
from /usr/local/include/boost/spirit/home/support/nonterminal/expand_arg.hpp:20,
from /usr/local/include/boost/spirit/home/support/context.hpp:18,
from /usr/local/include/boost/spirit/home/qi/domain.hpp:18,
from /usr/local/include/boost/spirit/home/qi/meta_compiler.hpp:15,
from /usr/local/include/boost/spirit/home/qi/action/action.hpp:14,
from /usr/local/include/boost/spirit/home/qi/action.hpp:14,
from /usr/local/include/boost/spirit/home/qi.hpp:14,
from /usr/local/include/boost/spirit/include/qi.hpp:16,
from main.cpp:4:
/usr/local/include/boost/spirit/home/support/container.hpp: In instantiation of ‘boost::spirit::traits::container_value<VectorWrapper, void>’:
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp:296:66: instantiated from ‘bool boost::spirit::qi::detail::pass_container<F, Attr, Sequence>::dispatch_attribute(const Component&, mpl_::true_) const [with Component = boost::spirit::qi::literal_string<const char (&)[3], false>, F = boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> > >, Attr = VectorWrapper, Sequence = mpl_::bool_<false>, mpl_::true_ = mpl_::bool_<true>]’
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp:331:61: instantiated from ‘bool boost::spirit::qi::detail::pass_container<F, Attr, Sequence>::operator()(const Component&) const [with Component = boost::spirit::qi::literal_string<const char (&)[3], false>, F = boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> > >, Attr = VectorWrapper, Sequence = mpl_::bool_<false>]’
/usr/local/include/boost/spirit/home/qi/operator/plus.hpp:63:13: instantiated from ‘bool boost::spirit::qi::plus<Subject>::parse_container(F) const [with F = boost::spirit::qi::detail::pass_container<boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> > >, VectorWrapper, mpl_::bool_<false> >, Subject = boost::spirit::qi::literal_string<const char (&)[3], false>]’
/usr/local/include/boost/spirit/home/qi/operator/plus.hpp:85:13: instantiated from ‘bool boost::spirit::qi::plus<Subject>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Context = boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, Attribute = VectorWrapper, Subject = boost::spirit::qi::literal_string<const char (&)[3], false>]’
/usr/local/include/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:43:54: instantiated from ‘bool boost::spirit::qi::detail::parser_binder<Parser, Auto>::call(Iterator&, const Iterator&, Context&, const Skipper&, mpl_::false_) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, Context = boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, Parser = boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, Auto = mpl_::bool_<false>, mpl_::false_ = mpl_::bool_<false>]’
/usr/local/include/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:53:67: [ skipping 3 instantiation contexts ]
/usr/local/include/boost/function/function_template.hpp:722:7: instantiated from ‘boost::function4<R, T1, T2, T3, T4>::function4(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, mpl_::bool_<false> >, R = bool, T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T1 = const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T2 = boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/usr/local/include/boost/function/function_template.hpp:1069:16: instantiated from ‘boost::function<R(T0, T1, T2, T3)>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, mpl_::bool_<false> >, R = bool, T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T1 = const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T2 = boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/usr/local/include/boost/function/function_template.hpp:1124:5: instantiated from ‘typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::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::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, mpl_::bool_<false> >, R = bool, T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T1 = const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T2 = boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, boost::function<R(T0, T1, T2, T3)>&>::type = boost::function<bool(__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&)>&]’
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:182:13: instantiated 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::unary_plus, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::string, boost::spirit::char_encoding::standard>, boost::fusion::vector1<const char (&)[3]> > >, 0l>&>, 1l>, Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, T1 = VectorWrapper(), 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::standard> >, 0l>, T3 = boost::spirit::unused_type, T4 = boost::spirit::unused_type, boost::spirit::qi::rule<Iterator, T1, T2, T3, T4> = boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, VectorWrapper(), 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::standard> >, 0l> >, mpl_::true_ = mpl_::bool_<true>]’
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:191:13: instantiated from ‘boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::rule(const Expr&, const string&) [with Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::unary_plus, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::string, boost::spirit::char_encoding::standard>, boost::fusion::vector1<const char (&)[3]> > >, 0l>&>, 1l>, Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, T1 = VectorWrapper(), 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::standard> >, 0l>, T3 = boost::spirit::unused_type, T4 = boost::spirit::unused_type, std::string = std::basic_string<char>]’
main.cpp:27:27: instantiated from here
/usr/local/include/boost/spirit/home/support/container.hpp:116:12: error: no type named ‘value_type’ in ‘struct VectorWrapper’
In file included from /usr/local/include/boost/spirit/home/qi/operator/kleene.hpp:20:0,
from /usr/local/include/boost/spirit/home/qi/directive/repeat.hpp:18,
from /usr/local/include/boost/spirit/home/qi/directive.hpp:23,
from /usr/local/include/boost/spirit/home/qi.hpp:19,
from /usr/local/include/boost/spirit/include/qi.hpp:16,
from main.cpp:4:
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp: In member function ‘bool boost::spirit::qi::detail::pass_container<F, Attr, Sequence>::dispatch_attribute(const Component&, mpl_::true_) const [with Component = boost::spirit::qi::literal_string<const char (&)[3], false>, F = boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> > >, Attr = VectorWrapper, Sequence = mpl_::bool_<false>, mpl_::true_ = mpl_::bool_<true>]’:
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp:331:61: instantiated from ‘bool boost::spirit::qi::detail::pass_container<F, Attr, Sequence>::operator()(const Component&) const [with Component = boost::spirit::qi::literal_string<const char (&)[3], false>, F = boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> > >, Attr = VectorWrapper, Sequence = mpl_::bool_<false>]’
/usr/local/include/boost/spirit/home/qi/operator/plus.hpp:63:13: instantiated from ‘bool boost::spirit::qi::plus<Subject>::parse_container(F) const [with F = boost::spirit::qi::detail::pass_container<boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> > >, VectorWrapper, mpl_::bool_<false> >, Subject = boost::spirit::qi::literal_string<const char (&)[3], false>]’
/usr/local/include/boost/spirit/home/qi/operator/plus.hpp:85:13: instantiated from ‘bool boost::spirit::qi::plus<Subject>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Context = boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, Attribute = VectorWrapper, Subject = boost::spirit::qi::literal_string<const char (&)[3], false>]’
/usr/local/include/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:43:54: instantiated from ‘bool boost::spirit::qi::detail::parser_binder<Parser, Auto>::call(Iterator&, const Iterator&, Context&, const Skipper&, mpl_::false_) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, Context = boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, Parser = boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, Auto = mpl_::bool_<false>, mpl_::false_ = mpl_::bool_<false>]’
/usr/local/include/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:53:67: instantiated from ‘bool boost::spirit::qi::detail::parser_binder<Parser, Auto>::operator()(Iterator&, const Iterator&, Context&, const Skipper&) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, Context = boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, Parser = boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, Auto = mpl_::bool_<false>]’
/usr/local/include/boost/function/function_template.hpp:132:42: [ skipping 2 instantiation contexts ]
/usr/local/include/boost/function/function_template.hpp:722:7: instantiated from ‘boost::function4<R, T1, T2, T3, T4>::function4(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, mpl_::bool_<false> >, R = bool, T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T1 = const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T2 = boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/usr/local/include/boost/function/function_template.hpp:1069:16: instantiated from ‘boost::function<R(T0, T1, T2, T3)>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, mpl_::bool_<false> >, R = bool, T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T1 = const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T2 = boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/usr/local/include/boost/function/function_template.hpp:1124:5: instantiated from ‘typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::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::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, mpl_::bool_<false> >, R = bool, T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T1 = const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T2 = boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, boost::function<R(T0, T1, T2, T3)>&>::type = boost::function<bool(__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&)>&]’
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:182:13: instantiated 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::unary_plus, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::string, boost::spirit::char_encoding::standard>, boost::fusion::vector1<const char (&)[3]> > >, 0l>&>, 1l>, Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, T1 = VectorWrapper(), 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::standard> >, 0l>, T3 = boost::spirit::unused_type, T4 = boost::spirit::unused_type, boost::spirit::qi::rule<Iterator, T1, T2, T3, T4> = boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, VectorWrapper(), 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::standard> >, 0l> >, mpl_::true_ = mpl_::bool_<true>]’
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:191:13: instantiated from ‘boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::rule(const Expr&, const string&) [with Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::unary_plus, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::string, boost::spirit::char_encoding::standard>, boost::fusion::vector1<const char (&)[3]> > >, 0l>&>, 1l>, Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, T1 = VectorWrapper(), 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::standard> >, 0l>, T3 = boost::spirit::unused_type, T4 = boost::spirit::unused_type, std::string = std::basic_string<char>]’
main.cpp:27:27: instantiated from here
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp:296:66: error: no type named ‘type’ in ‘struct boost::spirit::traits::container_value<VectorWrapper, void>’
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp:309:15: error: no type named ‘type’ in ‘struct boost::spirit::traits::container_value<VectorWrapper, void>’
make: *** [all] Error 1
You need to emit an unused type in your rule:
qi::rule<std::string::iterator, VectorWrapper(), qi::space_type > testRule =
+(qi::string("aa")) >> qi::attr(false);
The linked answer should be enough. Since you report trouble still: here's something that works on my compilers:
qi::rule<std::string::iterator, VectorWrapper(), qi::space_type > testRule =
qi::eps >> +(qi::string("aa"));
See it Live On Coliru
I'm having some trouble using karma to generate output for a struct that is held in a vector of boost::shared_ptrs. I've got a small test case using ints that doesn't compile. I was thinking I could use the deref_iterator customization point to handle this case or that perhaps that out-of-the-box spirit would notice that my container held a pointer type and do the extra dereference. Anyway here's the test case:
#include <boost/spirit/include/karma.hpp>
#include <boost/shared_ptr.hpp>
#include <vector>
typedef boost::shared_ptr< int > ptr;
typedef std::vector< ptr > vec;
namespace boost {
namespace spirit {
namespace traits {
// specialise how iterators into containers of pointers are dereferenced
template <>
struct deref_iterator< typename container_iterator< vec const >::type >
{
typedef int type;
static
type
call( typename container_iterator< vec const >::type & it ) {
return **it;
}
};
} // namespace traits
} // namespace spirit
} // namespace boost
int
main() {
vec v;
v.push_back( ptr( new int( 1 ) ) );
v.push_back( ptr( new int( 2 ) ) );
v.push_back( ptr( new int( 3 ) ) );
using namespace boost::spirit::karma;
using boost::spirit::ascii::space;
generate_delimited(
std::ostream_iterator< char >( std::cout ),
*int_,
space,
v
);
return 0;
}
and here are the compile errors:
...patience...
...patience...
...found 1986 targets...
...updating 3 targets...
gcc.compile.c++ /home/john/Dev/Bio/bin/Bio/gcc-4.6/release/src/spirit/vector-of-ptrs.o
In file included from /home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/numeric/bool_policies.hpp:16:0,
from /home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/numeric/bool.hpp:29,
from /home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/numeric.hpp:13,
from /home/john/src/boost/boost_1_51_0/boost/spirit/home/karma.hpp:15,
from /home/john/src/boost/boost_1_51_0/boost/spirit/include/karma.hpp:16,
from src/spirit/vector-of-ptrs.cpp:1:
/home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp: In static member function ‘static boost::shared_ptr<
int> boost::spirit::traits::absolute_value<boost::shared_ptr<int>, void>::call(boost::shared_ptr<int>)’:
/home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp:149:41: instantiated from ‘boost::spirit::traits::absolute_value<boost::shared_ptr<int> >::ame boost
::spirit::traits::absolute_value<T>::type = boost::shared_ptr<int> boost::spirit::traits::get_absolute_value(boost::shared_ptr<int>)’
/home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/numeric/int.hpp:213:57: instantiated from ‘static bool boost::spirit::karma::any_int_generator<
int, boost::spirit::unused_type, boost::spirit::unused_type, 10u, false
>::insert_int(boost::spirit::karma::detail::output_iterator<ostream_iterator<char>, mpl_::int_<0>, boost::spirit::unused_type> &, const boost::shared_ptr<int> &)’
/home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/numeric/int.hpp:242:39: instantiated from ‘static bool boost::spirit::karma::any_int_generator<
int, boost::spirit::unused_type, boost::spirit::unused_type, 10u, false
>::generate(
boost::spirit::karma::detail::output_iterator<ostream_iterator<char>, mpl_::int_<0>, boost::spirit::unused_type> &, boost::spirit::context<
boost::fusion::cons<const vector<boost::shared_ptr<int> > &, boost::fusion::nil>, boost::spirit::locals<> > &, const boost::spirit::karma::any_space<boost::spirit::char_encoding::ascii> &
, const boost::shared_ptr<int> &)’
/home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/detail/fail_function.hpp:36:62: instantiated from ‘bool boost::spirit::karma::detail::fail_function<
boost::spirit::karma::detail::output_iterator<ostream_iterator<char>, mpl_::int_<0>, boost::spirit::unused_type>, boost::spirit::context<
boost::fusion::cons<const vector<boost::shared_ptr<int> > &, boost::fusion::nil>, boost::spirit::locals<> >, boost::spirit::karma::any_space<boost::spirit::char_encoding::ascii> >
::operator()(const boost::spirit::karma::any_int_generator<int, boost::spirit::unused_type, boost::spirit::unused_type, 10u, false> &, const boost::shared_ptr<int> &) const’
/home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/detail/pass_container.hpp:274:13: instantiated from ‘bool boost::spirit::karma::detail::pass_container<
boost::spirit::karma::detail::fail_function<
boost::spirit::karma::detail::output_iterator<ostream_iterator<char>, mpl_::int_<0>, boost::spirit::unused_type>, boost::spirit::context<
boost::fusion::cons<const vector<boost::shared_ptr<int> > &, boost::fusion::nil>, boost::spirit::locals<> >, boost::spirit::karma::any_space<boost::spirit::char_encoding::ascii> >,
vector<boost::shared_ptr<int> >, boost::spirit::karma::detail::indirect_iterator<vector<boost::shared_ptr<int> >::const_iterator>, mpl_::bool_<false>
>::dispatch_container(const boost::spirit::karma::any_int_generator<int, boost::spirit::unused_type, boost::spirit::unused_type, 10u, false> &, mpl_::mpl_::bool_<false>) const’
/home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/detail/pass_container.hpp:321:61: [ skipping 2 instantiation contexts ]
/home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/operator/kleene.hpp:53:32: instantiated from ‘bool boost::spirit::karma::base_kleene<
boost::spirit::karma::any_int_generator<int, boost::spirit::unused_type, boost::spirit::unused_type, 10u, false>, mpl_::bool_<false>, boost::spirit::karma::kleene<
boost::spirit::karma::any_int_generator<int, boost::spirit::unused_type, boost::spirit::unused_type, 10u, false> >
>::generate_subject(
boost::spirit::karma::detail::pass_container<
boost::spirit::karma::detail::fail_function<
boost::spirit::karma::detail::output_iterator<ostream_iterator<char>, mpl_::int_<0>, boost::spirit::unused_type>, boost::spirit::context<
boost::fusion::cons<const vector<boost::shared_ptr<int> > &, boost::fusion::nil>, boost::spirit::locals<> >, boost::spirit::karma::any_space<boost::spirit::char_encoding::ascii> >
, vector<boost::shared_ptr<int> >, boost::spirit::karma::detail::indirect_iterator<vector<boost::shared_ptr<int> >::const_iterator>, mpl_::bool_<false> >, const vector<
boost::shared_ptr<int> > &, mpl_::mpl_::bool_<false>) const’
/home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/operator/kleene.hpp:126:17: instantiated from ‘bool boost::spirit::karma::base_kleene<
boost::spirit::karma::any_int_generator<int, boost::spirit::unused_type, boost::spirit::unused_type, 10u, false>, mpl_::bool_<false>, boost::spirit::karma::kleene<
boost::spirit::karma::any_int_generator<int, boost::spirit::unused_type, boost::spirit::unused_type, 10u, false> >
>::generate(
boost::spirit::karma::detail::output_iterator<ostream_iterator<char>, mpl_::int_<0>, boost::spirit::unused_type> &, boost::spirit::context<
boost::fusion::cons<const vector<boost::shared_ptr<int> > &, boost::fusion::nil>, boost::spirit::locals<> > &, const boost::spirit::karma::any_space<boost::spirit::char_encoding::ascii> &
, const vector<boost::shared_ptr<int> > &) const’
/home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/generate.hpp:161:53: instantiated from ‘bool boost::spirit::karma::generate_delimited(
boost::spirit::karma::detail::output_iterator<ostream_iterator<char>, mpl_::int_<0> > &, const boost::proto::exprns_::expr<
boost::proto::tagns_::tag::dereference, boost::proto::argsns_::list1<const boost::spirit::terminal<boost::spirit::tag::int_> &>, 1l> &, const 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
::karma::delimit_flag::enum_type, const vector<boost::shared_ptr<int> > &)’
/home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/generate.hpp:185:82: instantiated from ‘bool boost::spirit::karma::generate_delimited(
ostream_iterator<char> &, const boost::proto::exprns_::expr<boost::proto::tagns_::tag::dereference, boost::proto::argsns_::list1<const boost::spirit::terminal<boost::spirit::tag::int_> &>,
1l> &, const 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
::karma::delimit_flag::enum_type, const vector<boost::shared_ptr<int> > &)’
/home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/generate.hpp:227:48: instantiated from ‘bool boost::spirit::karma::generate_delimited(
const ostream_iterator<char> &, const boost::proto::exprns_::expr<
boost::proto::tagns_::tag::dereference, boost::proto::argsns_::list1<const boost::spirit::terminal<boost::spirit::tag::int_> &>, 1l> &, const 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> &, const vector<
boost::shared_ptr<int> > &)’
src/spirit/vector-of-ptrs.cpp:46:2: instantiated from here
/home/john/src/boost/boost_1_51_0/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp:60:26: error: No match for ‘fabs(boost::shared_ptr<int> &)’
STL Decryptor reminder:
Use the /cand:L option to see all suppressed template candidates
"/home/john/src/stlfilt/gfilt" -ftemplate-depth-128 -Wno-deprecated -Wno-unused -Wno-error -O3 -finline-functions -Wno-inline -Wall -fPIC -Wno-deprecated -Wno-unused -DBOOST_FILESYSTEM_VERSION=3 -DNDEBUG -DWITH_NONAMESPACES -DXML_LIBRARY -I"../Bio" -I"../Hmm" -I"/home/john/src/boost/boost_1_51_0" -c -o "/home/john/Dev/Bio/bin/Bio/gcc-4.6/release/src/spirit/vector-of-ptrs.o" "src/spirit/vector-of-ptrs.cpp"
...failed gcc.compile.c++ /home/john/Dev/Bio/bin/Bio/gcc-4.6/release/src/spirit/vector-of-ptrs.o...
...removing /home/john/Dev/Bio/bin/Bio/gcc-4.6/release/src/spirit/vector-of-ptrs.o
...skipped <p/home/john/Dev/Bio/bin/Bio/gcc-4.6/release>spirit-vector-of-ptrs for lack of <p/home/john/Dev/Bio/bin/Bio/gcc-4.6/release>src/spirit/vector-of-ptrs.o...
...failed updating 1 target...
...skipped 1 target...
A bit of experimentation lead me to the reason why the specialization wasn't instantiatied, where expected: the iterator has become wrapped (with karma::detail::indirect_iterator) somewhere during the evalation of the generator expression.
Here is the fix that works for me:
namespace boost {
namespace spirit {
namespace traits {
// specialise how iterators into containers of pointers are dereferenced
template <>
struct deref_iterator< karma::detail::indirect_iterator<vec::const_iterator> >
{
typedef karma::detail::indirect_iterator<vec::const_iterator> It;
typedef int type;
static type call( It const & it ) {
return **it;
}
};
} // namespace traits
} // namespace spirit
} // namespace boost