提升apply_visitor和Sprit x3 :: forward_ast

时间:2017-11-03 12:41:07

标签: c++ boost boost-spirit boost-spirit-x3

我无法为以下简化程序制作访问者:

#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的访问者?

0 个答案:

没有答案