使用 Boost.Spirit 构建数学表达式计算器时出现编译错误
Compilation error in building math expression evaluator with Boost.Spirit
我正在尝试将数学表达式解析为树并稍后使用特定变量 (char) 对其求值。这是我的语法:
#include <boost/spirit/include/qi.hpp>
#include <boost/variant/recursive_variant.hpp>
struct Expression;
struct SubFunction;
using OperandVariant = boost::variant<double, char, boost::recursive_wrapper<SubFunction>, boost::recursive_wrapper<Expression>>;
struct SubFunction
{
std::string name;
std::vector<OperandVariant> arguments;
};
struct Operation
{
std::string type;
OperandVariant operand;
};
struct Expression
{
OperandVariant operand;
std::vector<Operation> operations;
};
BOOST_FUSION_ADAPT_STRUCT(
SubFunction,
(std::string, name)
(std::vector<OperandVariant>, arguments)
)
BOOST_FUSION_ADAPT_STRUCT(
Operation,
(std::string, type)
(OperandVariant, operand)
)
BOOST_FUSION_ADAPT_STRUCT(
Expression,
(OperandVariant, operand)
(std::vector<Operation>, operations)
)
template <typename Iterator>
struct FunctionGrammar : boost::spirit::qi::grammar<Iterator, Expression(), boost::spirit::ascii::space_type>
{
FunctionGrammar() : FunctionGrammar::base_type(logic)
{
using boost::spirit::qi::string;
using boost::spirit::qi::double_;
using boost::spirit::qi::lexeme;
using boost::spirit::qi::char_;
using boost::spirit::qi::lit;
using boost::spirit::qi::attr;
logic = relation >> *(string("&&") >> relation
| string("^^") >> relation
| string("||") >> relation);
relation = addition >> *(string("<=") >> addition
| string(">=") >> addition
| string("!=") >> addition
| string("==") >> addition
| char_('>') >> addition
| char_('<') >> addition);
addition = multiplication >> *(char_('+') >> multiplication
| char_('-') >> multiplication);
multiplication = value >> *(char_('*') >> value
| char_('/') >> value);
value = '(' >> logic >> ')'
| +(char_ - '(') >> '(' >> value % ',' >> ')'
| double_
| char_;
}
boost::spirit::qi::rule<Iterator, Expression(), boost::spirit::ascii::space_type> logic;
boost::spirit::qi::rule<Iterator, Expression(), boost::spirit::ascii::space_type> relation;
boost::spirit::qi::rule<Iterator, Expression(), boost::spirit::ascii::space_type> addition;
boost::spirit::qi::rule<Iterator, Expression(), boost::spirit::ascii::space_type> multiplication;
boost::spirit::qi::rule<Iterator, OperandVariant(), boost::spirit::ascii::space_type> value;
};
我根据官方文档中的 an example 做了这个并且它有效。但我想添加在 Subfunction
参数(由 ,
分割)中使用 +
、-
、*
等的功能。如果我更换这部分
+(char_ - '(') >> '(' >> value % ',' >> ')'
进入这个:
+(char_ - '(') >> '(' >> logic % ',' >> ')'
代码无法编译。我做错了什么?
+(char_ - '(') >> '(' >> value % ',' >> ')'
解析器有fusion::vector<std::string, std::vector<OperandVariant> >
属性类型,可以转换为SubFunction
存储在OperandVariant
中(value
规则的属性),而 +(char_ - '(') >> '(' >> logic % ',' >> ')'
解析器具有 fusion::vector<std::string, std::vector<Expression> >
属性类型,无法转换为 OperandVariant
可以容纳的任何类型。
也可以从 Clang 输出的这一部分破译该解释:
/opt/wandbox/boost-1.72.0/clang-head/include/boost/spirit/home/qi/detail/assign_to.hpp:153:20: error: no matching conversion for static_cast from 'const boost::fusion::vector<std::__1::vector<char, std::__1::allocator<char> >, std::__1::vector<Expression, std::__1::allocator<Expression> > >' to 'boost::variant<double, char, boost::recursive_wrapper<SubFunction>, boost::recursive_wrapper<Expression> >'
attr = static_cast<Attribute>(val);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
我正在尝试将数学表达式解析为树并稍后使用特定变量 (char) 对其求值。这是我的语法:
#include <boost/spirit/include/qi.hpp>
#include <boost/variant/recursive_variant.hpp>
struct Expression;
struct SubFunction;
using OperandVariant = boost::variant<double, char, boost::recursive_wrapper<SubFunction>, boost::recursive_wrapper<Expression>>;
struct SubFunction
{
std::string name;
std::vector<OperandVariant> arguments;
};
struct Operation
{
std::string type;
OperandVariant operand;
};
struct Expression
{
OperandVariant operand;
std::vector<Operation> operations;
};
BOOST_FUSION_ADAPT_STRUCT(
SubFunction,
(std::string, name)
(std::vector<OperandVariant>, arguments)
)
BOOST_FUSION_ADAPT_STRUCT(
Operation,
(std::string, type)
(OperandVariant, operand)
)
BOOST_FUSION_ADAPT_STRUCT(
Expression,
(OperandVariant, operand)
(std::vector<Operation>, operations)
)
template <typename Iterator>
struct FunctionGrammar : boost::spirit::qi::grammar<Iterator, Expression(), boost::spirit::ascii::space_type>
{
FunctionGrammar() : FunctionGrammar::base_type(logic)
{
using boost::spirit::qi::string;
using boost::spirit::qi::double_;
using boost::spirit::qi::lexeme;
using boost::spirit::qi::char_;
using boost::spirit::qi::lit;
using boost::spirit::qi::attr;
logic = relation >> *(string("&&") >> relation
| string("^^") >> relation
| string("||") >> relation);
relation = addition >> *(string("<=") >> addition
| string(">=") >> addition
| string("!=") >> addition
| string("==") >> addition
| char_('>') >> addition
| char_('<') >> addition);
addition = multiplication >> *(char_('+') >> multiplication
| char_('-') >> multiplication);
multiplication = value >> *(char_('*') >> value
| char_('/') >> value);
value = '(' >> logic >> ')'
| +(char_ - '(') >> '(' >> value % ',' >> ')'
| double_
| char_;
}
boost::spirit::qi::rule<Iterator, Expression(), boost::spirit::ascii::space_type> logic;
boost::spirit::qi::rule<Iterator, Expression(), boost::spirit::ascii::space_type> relation;
boost::spirit::qi::rule<Iterator, Expression(), boost::spirit::ascii::space_type> addition;
boost::spirit::qi::rule<Iterator, Expression(), boost::spirit::ascii::space_type> multiplication;
boost::spirit::qi::rule<Iterator, OperandVariant(), boost::spirit::ascii::space_type> value;
};
我根据官方文档中的 an example 做了这个并且它有效。但我想添加在 Subfunction
参数(由 ,
分割)中使用 +
、-
、*
等的功能。如果我更换这部分
+(char_ - '(') >> '(' >> value % ',' >> ')'
进入这个:
+(char_ - '(') >> '(' >> logic % ',' >> ')'
代码无法编译。我做错了什么?
+(char_ - '(') >> '(' >> value % ',' >> ')'
解析器有fusion::vector<std::string, std::vector<OperandVariant> >
属性类型,可以转换为SubFunction
存储在OperandVariant
中(value
规则的属性),而 +(char_ - '(') >> '(' >> logic % ',' >> ')'
解析器具有 fusion::vector<std::string, std::vector<Expression> >
属性类型,无法转换为 OperandVariant
可以容纳的任何类型。
也可以从 Clang 输出的这一部分破译该解释:
/opt/wandbox/boost-1.72.0/clang-head/include/boost/spirit/home/qi/detail/assign_to.hpp:153:20: error: no matching conversion for static_cast from 'const boost::fusion::vector<std::__1::vector<char, std::__1::allocator<char> >, std::__1::vector<Expression, std::__1::allocator<Expression> > >' to 'boost::variant<double, char, boost::recursive_wrapper<SubFunction>, boost::recursive_wrapper<Expression> >'
attr = static_cast<Attribute>(val);
^~~~~~~~~~~~~~~~~~~~~~~~~~~