这个问题的后续问题Handling boost spirit expression on string.再次感谢@sehe!但是当我尝试在名称空间中 Package 所有的语法和ast并从一个类中调用它们时,我得到了一个错误,短语_parse api说它期望6个参数而不是5个。
我正在尝试实现的代码:
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/variant.hpp>
#include <iomanip>
#include <list>
#include <string>
namespace client { namespace ast {
struct signed_;
struct program;
using operand = boost::variant<unsigned int, bool,
boost::recursive_wrapper<signed_>,
boost::recursive_wrapper<program>>;
struct signed_ { char sign; operand operand_; };
struct operation { char operator_; operand operand_; };
struct program { operand first; std::list<operation> rest; };
}} // namespace client::ast
BOOST_FUSION_ADAPT_STRUCT(client::ast::signed_, sign, operand_)
BOOST_FUSION_ADAPT_STRUCT(client::ast::operation, operator_, operand_)
BOOST_FUSION_ADAPT_STRUCT(client::ast::program, first, rest)
namespace client { namespace ast
{
///////////////////////////////////////////////////////////////////////////
// The AST evaluator
///////////////////////////////////////////////////////////////////////////
struct eval {
using result_type = int;
int operator()(auto const& n) const { return n; }
int operator()(operation const& x, int lhs) const {
int rhs = boost::apply_visitor(*this, x.operand_);
switch (x.operator_) {
case '+': return lhs + rhs;
case '-': return lhs - rhs;
case '*': return lhs * rhs;
case '/': return lhs / rhs;
case '|': return lhs | rhs;
case '&': return lhs & rhs;
}
BOOST_ASSERT(0);
return 0;
}
int operator()(signed_ const& x) const {
int rhs = boost::apply_visitor(*this, x.operand_);
switch (x.sign) {
case '-': return -rhs;
case '+': return +rhs;
case '!': return !rhs;
}
BOOST_ASSERT(0);
return 0;
}
int operator()(program const& x) const {
int state = boost::apply_visitor(*this, x.first);
for (auto& oper : x.rest) {
state = (*this)(oper, state);
}
return state;
}
};
}} // namespace client::ast
namespace client
{
namespace qi = boost::spirit::qi;
template <typename Iterator>
struct calculator : qi::grammar<Iterator, ast::program(), qi::space_type> {
calculator() : calculator::base_type(expression) {
using namespace qi::labels;
expression = term >> *(qi::char_("-+|&") >> term);
term = factor >> *(qi::char_("*/!") >> factor);
str = '"' >> *~qi::char_('"') >> '"';
equality_comparison = (str >> '=' >> '=' >> str)[_val = (_1 == _2)];
inequality_comparison = (str >> '!' >> '=' >> str)[_val = (_1 != _2)];
factor = inequality_comparison | equality_comparison | qi::uint_ | qi::bool_ | qi::char_("-+!") >> factor |
'(' >> expression >> ')';
}
private:
qi::rule<Iterator, ast::program(), qi::space_type> expression, term;
qi::rule<Iterator, ast::operand(), qi::space_type> factor, equality_comparison , inequality_comparison;
qi::rule<Iterator, std::string()> str;
};
}
class Expression_handler{
public:
int Execute_expression(std::string str){
using iterator_type = std::string::const_iterator;
using calculator = client::calculator<iterator_type>;
using ast_program = client::ast::program;
using ast_eval = client::ast::eval;
calculator const calc; // Our grammar
ast_eval const eval; // Evaluates the program
ast_program program;
auto f(std::begin(str)), l(std::end(str));
bool r = phrase_parse(f, l, calc, client::qi::space, program);
if (r && f == l) {
std::cout << "\nResult: " << quoted(str) << " -> " << eval(program) << std::endl;
return (eval(program));
}
else{
std::cout << "\nFailed at: " << quoted(std::string (f, l)) << "\n";
}
return 0;
};
};
int main(){
Expression_handler exp;
exp.Execute_expression("\"abc\" == \"abc\"");
return 0;
}
此代码生成的错误:
ion_handler.cpp:37:24: warning: use of ‘auto’ in parameter declaration only available with ‘-std=c++20’ or ‘-fconcepts’
37 | int operator()(auto const& n) const { return n; }
| ^~~~
In file included from /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:36,
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 Expression_handler.cpp:5:
/usr/include/boost/spirit/home/qi/reference.hpp: In instantiation of ‘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<client::ast::program&, boost::fusion::nil_>, boost::spirit::locals<> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >; Attribute = client::ast::program; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, client::ast::program(), 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>]’:
/usr/include/boost/spirit/home/qi/parse.hpp:168:45: required from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, boost::spirit::qi::skip_flag, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Expr = client::calculator<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >; 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> >, 0>; Attr = client::ast::program]’
/usr/include/boost/spirit/home/qi/parse.hpp:201:32: required from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Expr = client::calculator<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >; 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> >, 0>; Attr = client::ast::program]’
Expression_handler.cpp:114:30: required from here
/usr/include/boost/spirit/home/qi/reference.hpp:43:35: error: no matching function for call to ‘boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, client::ast::program(), 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>::parse(__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<client::ast::program&, boost::fusion::nil_>, boost::spirit::locals<> >&, const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >&, client::ast::program&) const’
43 | return ref.get().parse(first, last, context, skipper, attr_);
| ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included 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 Expression_handler.cpp:5:
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:282:14: note: candidate: ‘template<class Context, class Skipper, class Attribute> bool boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Context = Context; Skipper = Skipper; Attribute = Attribute; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = client::ast::program(); 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> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’
282 | bool parse(Iterator& first, Iterator const& last
| ^~~~~
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:282:14: note: template argument deduction/substitution failed:
In file included from /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:36,
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 Expression_handler.cpp:5:
/usr/include/boost/spirit/home/qi/reference.hpp:43:35: note: cannot convert ‘first’ (type ‘__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >’) to type ‘__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&’
43 | return ref.get().parse(first, last, context, skipper, attr_);
| ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included 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 Expression_handler.cpp:5:
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:333:14: note: candidate: ‘template<class Context, class Skipper, class Attribute, class Params> bool boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&, const Params&) const [with Context = Context; Skipper = Skipper; Attribute = Attribute; Params = Params; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = client::ast::program(); 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> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’
333 | bool parse(Iterator& first, Iterator const& last
| ^~~~~
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:333:14: note: template argument deduction/substitution failed:
In file included from /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:36,
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 Expression_handler.cpp:5:
/usr/include/boost/spirit/home/qi/reference.hpp:43:35: note: candidate expects 6 arguments, 5 provided
43 | return ref.get().parse(first, last, context, skipper, attr_);
| ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
它还期望哪个参数?我该如何解决这个问题?
1条答案
按热度按时间wqlqzqxt1#
你的字符串不是常量,因此迭代器类型与你声明的类型不匹配。
第一个月
只需添加
const
或const&
:或者不要使用
auto
来声明f
和l
:**一个
图纸