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

boost::spirit arithmetic formulas parser fails to compile

本文关键字:失败 编译 spirit boost      更新时间:2023-10-16

我正在尝试为算术表达式编写一个spirit解析器,它填充一个抽象语法树。如果我没有尝试填充AST,但在当前版本中失败(有一个24K错误),解析器就会编译。我使用clang++3.5.0和-std=c++11,并在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_STRUCT应用于Term,而不管是否已经在<boost/fusion/adapted/std_pair.hpp>:中为std::pair执行了此操作

    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,因为以下内容不会编译:

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

    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;
}

实例