我无法为以下简化程序制作访问者:
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/qi_expect.hpp>
#include <boost/spirit/home/x3/directive/expect.hpp>
#include <iostream>
#include <ostream>
#include <string>
namespace x3 = boost::spirit::x3;
namespace ascii = x3::ascii;
namespace qi = boost::spirit::qi;
namespace wctl_parser {
struct Boolean;
struct Conjunction;
struct ArithmeticBinaryExpression;
using AtomicProp = std::string;
struct Boolean {
bool boolean;
};
using ArithmeticExpression = x3::variant<
unsigned long,
AtomicProp,
x3::forward_ast<ArithmeticBinaryExpression>
>;
using Expression = x3::variant<
AtomicProp,
Boolean,
x3::forward_ast<Conjunction>,
x3::forward_ast<ArithmeticExpression>
>;
struct Conjunction {
x3::forward_ast<Expression> left;
x3::forward_ast<Expression> right;
};
struct ArithmeticBinaryExpression {
x3::forward_ast<ArithmeticExpression> left;
std::string op;
x3::forward_ast<ArithmeticExpression> right;
};
} // End namespace
// BOOST_FUSION_ADAPT_STRUCT(wctl_parser::AtomicProp, prop)
BOOST_FUSION_ADAPT_STRUCT(wctl_parser::Boolean, boolean)
BOOST_FUSION_ADAPT_STRUCT(wctl_parser::Conjunction, left, right)
BOOST_FUSION_ADAPT_STRUCT(wctl_parser::ArithmeticBinaryExpression, left, op, right)
using namespace wctl_parser;
struct SyntaxTreePrinter {
SyntaxTreePrinter(std::ostream& out) : out(out) {};
using result_type = void;
template<typename T>
void operator()(const x3::forward_ast<T>& forwarded) {
(*this)(forwarded.get());
}
void operator()(const ArithmeticExpression& expression) {
// expression.apply_visitor(*this);
}
void operator()(const Expression& expression) {
// expression.apply_visitor(*this);
}
void operator()(const AtomicProp& property) {
out << '[' << property << ']';
}
void operator()(const long unsigned int expr) {
out << '[' << expr << ']';
}
void operator()(const Boolean& boolean) {
out << '[' << (boolean.boolean ? "true" : "false") << ']';
};
void operator()(const Conjunction& expr) {
out << "[AND ";
boost::apply_visitor(*this, expr.left);
out << ' ';
boost::apply_visitor(*this, expr.right);
out << ']';
};
void operator()(const ArithmeticBinaryExpression& expr) {
out << '[' << expr.op << ' ';
boost::apply_visitor(*this, expr.left);
out << ' ';
boost::apply_visitor(*this, expr.right);
out << ']';
};
private:
std::ostream& out;
};
int main() {
wctl_parser::Expression root;
auto visitor = SyntaxTreePrinter(std::cout);
root.apply_visitor(visitor);
return 0;
}
似乎x3 :: ast_forward和boost :: apply_visitor不兼容。我尝试在SyntaxTreePrinter中手动创建第一个模板,但它确实有帮助。我得到的编译错误是:
In instantiation of ‘typename Visitor::result_type boost::apply_visitor(Visitor&, Visitable&) [with Visitor = SyntaxTreePrinter; Visitable = const boost::spirit::x3::forward_ast<boost::spirit::x3::variant<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, wctl_parser::Boolean, boost::spirit::x3::forward_ast<wctl_parser::Conjunction>, boost::spirit::x3::forward_ast<boost::spirit::x3::variant<long unsigned int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::spirit::x3::forward_ast<wctl_parser::ArithmeticBinaryExpression> > > > >; typename Visitor::result_type = void]’:
./minimal_error.cpp:94:46: required from here
/boost_1_65_1/boost/variant/detail/apply_visitor_unary.hpp:70:22: error: ‘const class boost::spirit::x3::forward_ast<boost::spirit::x3::variant<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, wctl_parser::Boolean, boost::spirit::x3::forward_ast<wctl_parser::Conjunction>, boost::spirit::x3::forward_ast<boost::spirit::x3::variant<long unsigned int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::spirit::x3::forward_ast<wctl_parser::ArithmeticBinaryExpression> > > > >’ has no member named ‘apply_visitor’
return visitable.apply_visitor(visitor);
~~~~~~~~~~^~~~~~~~~~~~~
/boost_1_65_1/boost/variant/detail/apply_visitor_unary.hpp:70:43: error: return-statement with a value, in function returning 'void' [-fpermissive]
return visitable.apply_visitor(visitor);
如何正确构建AST的访问者?