【问题标题】:Compilation error in building math expression evaluator with Boost.Spirit使用 Boost.Spirit 构建数学表达式求值器时出现编译错误
【发布时间】:2020-01-27 19:24:30
【问题描述】:

我正在尝试将数学表达式解析为一棵树,并稍后使用特定变量 (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 % ',' >> ')'

代码将无法编译。我做错了什么?

【问题讨论】:

    标签: c++ boost boost-spirit


    【解决方案1】:

    +(char_ - '(') &gt;&gt; '(' &gt;&gt; value % ',' &gt;&gt; ')'解析器有fusion::vector&lt;std::string, std::vector&lt;OperandVariant&gt; &gt;属性类型,可以转换成SubFunction并存储在OperandVariantvalue规则的属性),而+(char_ - '(') &gt;&gt; '(' &gt;&gt; logic % ',' &gt;&gt; ')'解析器有fusion::vector&lt;std::string, std::vector&lt;Expression&gt; &gt;属性类型和无法转换为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);
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~
    

    【讨论】:

    • 我如何告诉语法将此值扩展为 std::vector?我认为使用 logic % ',' 可以让您自动执行此操作。
    • 我扩展了我的答案。请重新阅读它(以及编译器错误)。问题出在您的 AST 中。语法和 AST 是紧密耦合的,如果你改变一个,很可能你也需要改变另一个。
    • 谢谢,将arguments类型改为std::vector&lt;Expression&gt;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多