c++ - boost::spirit 算术公式解析器编译失败

标签 c++ boost-spirit-qi boost-variant boost-fusion

我正在尝试为填充抽象语法树的算术表达式编写精神解析器。如果我不尝试填充 AST,解析器会编译,但在当前版本中会失败(有一个 24K 错误)。我正在使用带有 -std=c++11 的 clang++ 3.5.0,并在 Ubuntu 14.4 上运行。

#include <string>
#include <vector>
#include <utility>

#include <boost/spirit/include/qi.hpp>

#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/adapted.hpp>
#include <boost/fusion/include/adapted.hpp>

#include <boost/variant/variant.hpp>
#include <boost/variant/recursive_wrapper.hpp>

using std::string;
using std::vector;
using std::pair;

using boost::spirit::qi::grammar;
using boost::spirit::qi::space_type;
using boost::spirit::qi::rule;

struct Term; // forward dec
typedef boost::recursive_wrapper<Term> RWTerm;
typedef pair<char, RWTerm> OpAndRWTerm;
typedef pair<RWTerm, vector<OpAndRWTerm> > Expr;
typedef boost::variant<Expr, double> Factor;
typedef pair<char, Factor> OpAndFactor;
struct Term : public pair<Factor, vector<OpAndFactor> >{};

template<typename It>
struct formula_parser : grammar<It, Expr(), space_type> {
  formula_parser() : formula_parser::base_type(expr_rule) {
    using boost::spirit::qi::double_;
    using boost::spirit::ascii::char_;

    factor_rule %= double_ | parenthesis_rule;
    parenthesis_rule %= '(' >> expr_rule >> ')';
    op_and_factor_rule %= char_("/*") >> factor_rule;
    term_rule %= factor_rule >> *op_and_factor_rule;
    op_and_term_rule %= char_("+-") >> term_rule;
    expr_rule %= term_rule >> *op_and_term_rule;
  }
  rule<It, OpAndRWTerm(), space_type> op_and_term_rule;
  rule<It, Expr(), space_type> expr_rule;
  rule<It, OpAndFactor(), space_type> op_and_factor_rule;
  rule<It, RWTerm(), space_type> term_rule;
  rule<It, Expr(), space_type> parenthesis_rule;
  rule<It, Factor(), space_type> factor_rule;
};

int main() {
  formula_parser<string::const_iterator> grammar;
}

我从错误消息中了解到,融合在规则 term_rule 中混淆了 Types Factor 和 RWTerm。

我做错了什么?

最佳答案

如果我改变两件事,它会为我编译:

  1. Term继承自 std::pair , Term是一种类型。为此,您需要申请 BOOST_FUSION_ADAPT_STRUCTTerm , 无论这是否已经为 std::pair 完成在<boost/fusion/adapted/std_pair.hpp> :

    BOOST_FUSION_ADAPT_STRUCT(
        Term,
        (Factor, first)
        (std::vector<OpAndFactor>, second)
    )
    

    或者,您可以制作 Term具有两个成员的独立结构,然后应用 BOOST_FUSION_ADAPT_STRUCT对此:

    struct Term { Factor f; std::vector<OpAndFactor>  o;};
    
    BOOST_FUSION_ADAPT_STRUCT(
        Term,
        (Factor, f)
        (std::vector<OpAndFactor>, o)
    )
    

    顺便说一句:你必须完全符合条件 std::vector在这里,因为以下 will not compile :

    using std::vector;
    BOOST_FUSION_ADAPT_STRUCT(
        Term,
        (Factor, f)
        (vector<OpAndFactor>, o)
    )
    
  2. 使用 Term而不是 RWTerm声明 term_rule 时:

    rule<It, Term(), space_type> term_rule;
    

完整代码:

#include <string>
#include <vector>
#include <utility>

#include <boost/spirit/include/qi.hpp>

#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/adapted.hpp>
#include <boost/fusion/include/adapted.hpp>

#include <boost/variant/variant.hpp>
#include <boost/variant/recursive_wrapper.hpp>

using boost::spirit::qi::grammar;
using boost::spirit::qi::space_type;
using boost::spirit::qi::rule;

struct Term; // forward dec
typedef boost::recursive_wrapper<Term> RWTerm;
typedef std::pair<char, RWTerm> OpAndRWTerm;
typedef std::pair<RWTerm, std::vector<OpAndRWTerm> > Expr;
typedef boost::variant<Expr, double> Factor;
typedef std::pair<char, Factor> OpAndFactor;
struct Term : public std::pair<Factor, std::vector<OpAndFactor> >{};

BOOST_FUSION_ADAPT_STRUCT(
    Term,
    (Factor, first)
    (std::vector<OpAndFactor>, second)
)


template<typename It>
struct formula_parser : grammar<It, Expr(), space_type> {
  formula_parser() : formula_parser::base_type(expr_rule) {
    using boost::spirit::qi::double_;
    using boost::spirit::ascii::char_;

    factor_rule %= double_ | parenthesis_rule;
    parenthesis_rule %= '(' >> expr_rule >> ')';
    op_and_factor_rule %= char_("/*") >> factor_rule;
    term_rule %= factor_rule >> *op_and_factor_rule;
    op_and_term_rule %= char_("+-") >> term_rule;
    expr_rule %= term_rule >> *op_and_term_rule;
  }
  rule<It, OpAndRWTerm(), space_type> op_and_term_rule;
  rule<It, Expr(), space_type> expr_rule;
  rule<It, OpAndFactor(), space_type> op_and_factor_rule;
  rule<It, Term(), space_type> term_rule;
  rule<It, Expr(), space_type> parenthesis_rule;
  rule<It, Factor(), space_type> factor_rule;
};

int main() {
  formula_parser<std::string::const_iterator> grammar;
}

live example

关于c++ - boost::spirit 算术公式解析器编译失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33433911/

相关文章:

c++ - Visual Studio 是否具有命名空间敏感的宏替换选项?

c++ - 如何使用 qi 解析和验证有序的整数列表

c++ - 从模板值获取类型,C++

c++ - 如何绘制像阴影按钮一样的 Windows 7 任务栏

c++ - 禁止在没有用户定义构造函数的情况下显式复制数据成员

c++ - 当迭代器指向 std::begin() 时,对迭代器调用 operator-- 是否有效

c++ - 灵气 : Completely ignoring output of some rules

c++ - 用元素的混合物解析化学式

C++ 模板访问具有不同类型的函数

c++ - boost::variant 对象构建计数 VS 销毁计数