boost::spirit 算术公式解析器编译失败
boost::spirit arithmetic formulas parser fails to compile
我正在尝试为填充抽象语法树的算术表达式编写精神解析器。如果我不尝试填充 AST,解析器会编译,但在当前版本中会失败(有一个 24K 错误)。我在 Ubuntu 14.4.
上使用带有 -std=c++11 和 运行 的 clang++ 3.5.0
#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 中的类型因子和 RWTerm。
我做错了什么?
如果我改变两件事,它会为我编译:
由于 Term
继承自 std::pair
,Term
是 new 类型。因此,您需要将 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
,因为下面的 will not compile:
using std::vector;
BOOST_FUSION_ADAPT_STRUCT(
Term,
(Factor, f)
(vector<OpAndFactor>, o)
)
在声明 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;
}
我正在尝试为填充抽象语法树的算术表达式编写精神解析器。如果我不尝试填充 AST,解析器会编译,但在当前版本中会失败(有一个 24K 错误)。我在 Ubuntu 14.4.
上使用带有 -std=c++11 和 运行 的 clang++ 3.5.0#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 中的类型因子和 RWTerm。
我做错了什么?
如果我改变两件事,它会为我编译:
由于
中对Term
继承自std::pair
,Term
是 new 类型。因此,您需要将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
,因为下面的 will not compile:using std::vector; BOOST_FUSION_ADAPT_STRUCT( Term, (Factor, f) (vector<OpAndFactor>, o) )
在声明
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;
}