c++ - 如何从此示例更改代码

标签 c++ compiler-errors boost-spirit boost-spirit-x3

如何更改代码source以显示结果?

我无法转换以提升精神x3

Live Code

#include <string>
#include <vector>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/adapted.hpp>
namespace x3 = boost::spirit::x3;

namespace client {    namespace ast {
    struct op_or {};
    struct op_and {};
    struct op_xor {};
    struct op_not {};
    template <typename tag> struct combination_op;
    template <typename tag>    struct unop;
    typedef std::string var;
    typedef boost::variant<
        var,
        boost::recursive_wrapper<unop<op_not>>,
        boost::recursive_wrapper<combination_op<op_and>>,
        boost::recursive_wrapper<combination_op<op_xor>>,
        boost::recursive_wrapper<combination_op<op_or>>
    >expr;
    template <typename tag> struct combination_op {
        typedef std::vector<expr> operands_t;
        combination_op() = default;
        combination_op(operands_t const& operands) : operands(operands) {}
        operands_t operands;
    };
    template <typename tag> struct unop {
        unop() = default;
        unop(const expr& o) : operand(o) {}
        expr operand;
    };
}}
BOOST_FUSION_ADAPT_STRUCT(client::ast::combination_op<client::ast::op_and>, operands)
BOOST_FUSION_ADAPT_STRUCT(client::ast::combination_op<client::ast::op_xor>, operands)
BOOST_FUSION_ADAPT_STRUCT(client::ast::combination_op<client::ast::op_or>, operands)
BOOST_FUSION_ADAPT_STRUCT(client::ast::unop<client::ast::op_not>, operand)

namespace client {    namespace parser {
    x3::rule<class var,  ast::var> var{ "var" };
    x3::rule<class not,  ast::unop<ast::op_not>> not{ "not" };
    x3::rule<class and,  ast::combination_op<ast::op_and>> and{ "and" };
    x3::rule<class xor,  ast::combination_op<ast::op_xor>> xor{ "xor" };
    x3::rule<class or,   ast::combination_op<ast::op_or >>  or{ "or" };
    x3::rule<class expr, ast::expr> expr { "expr" };

    auto const expr_def = xor | and | or | not | var;
    auto const expr_list = *expr;
    auto const or_def  = x3::no_case["or"]  >> '(' >> expr_list >> ')';
    auto const xor_def = x3::no_case["xor"] >> '(' >> expr_list >> ')';
    auto const and_def = x3::no_case["and"] >> '(' >> expr_list >> ')';
    auto const not_def = x3::no_case["not"] >> expr;
    auto const var_def = x3::lexeme[+x3::alpha];

    BOOST_SPIRIT_DEFINE(var,not,and,xor,or,expr);
}}

namespace client {    namespace ast {
    struct printer :boost::static_visitor<void> {
        printer() {}
        void operator()(const var& v) const{        }
        void operator()(const combination_op<op_and>& b) const { recurse(b); }
        void operator()(const combination_op<op_xor>& b) const { recurse(b); }
        void operator()(const combination_op<op_or>& b) const {  recurse(b); }
        void operator()(const unop<op_not>& u) const { recurse(u.operand); }
        template<typename T>
        void recurse(T const& v) const {
            //boost::apply_visitor(*this, v);
         }
    };
}}

int main() {
    std::string storage = "a or (b and c)";
    client::ast::expr result;
    typedef std::string::const_iterator iterator_t;
    iterator_t iter = storage.begin(), end = storage.end();
    using x3::ascii::space;
    bool ok = phrase_parse(iter, end, client::parser::expr, space, result);
    if (ok && iter == end) {
        boost::apply_visitor(client::ast::printer(), result);
    }
    return 0;
}

最佳答案

void operator()(const combination_op<op_and>& b) const { recurse(b); }
void operator()(const combination_op<op_xor>& b) const { recurse(b); }
void operator()(const combination_op<op_or>& b) const { recurse(b); }
void operator()(const unop<op_not>& u) const { recurse(u.operand); }

您认为这些功能做什么?如果查看链接的示例,则会看到具体的实现:

Originally, here:
struct printer : boost::static_visitor<void>
{
    printer(std::ostream& os) : _os(os) {}
    std::ostream& _os;

    //
    void operator()(const var& v) const { _os << v; }

    void operator()(const binop<op_and>& b) const { print(" & ", b.oper1, b.oper2); }
    void operator()(const binop<op_or >& b) const { print(" | ", b.oper1, b.oper2); }
    void operator()(const binop<op_xor>& b) const { print(" ^ ", b.oper1, b.oper2); }

    void print(const std::string& op, const expr& l, const expr& r) const
    {
        _os << "(";
            boost::apply_visitor(*this, l);
            _os << op;
            boost::apply_visitor(*this, r);
        _os << ")";
    }

    void operator()(const unop<op_not>& u) const
    {
        _os << "(";
            _os << "!";
            boost::apply_visitor(*this, u.oper1);
        _os << ")";
    }
};

std::ostream& operator<<(std::ostream& os, const expr& e)
{ boost::apply_visitor(printer(os), e); return os; }

因此,您期望编写如下内容:
struct printer {
    using result_type = void;
    std::ostream& _os;

    static auto name(op_and /*unused*/) { return "AND"; }
    static auto name(op_not /*unused*/) { return "NOT"; }
    static auto name(op_or /*unused*/) { return "OR"; }
    static auto name(op_xor /*unused*/) { return "XOR"; }

    void operator()(const var& v) const { _os << v; }
    template <typename Op>
    void operator()(const unop<Op>& u) const {
        _os << "(" << name(Op{}) << " ";
        operator()(u.operand);
        _os << ")";
    }
    template <typename Op>
    void operator()(const combination_op<Op>& b) const {
        _os << "(";
        bool first = true;
        for (auto& e : b.operands) {
            if (!std::exchange(first, false)) {
                _os << " " << name(Op{}) << " ";

            }

            operator()(e);
        }
        _os << ")";
    }

    void operator()(expr const& v) const {
        boost::apply_visitor(*this, v);
    }
};

哪个打印(Live On Coliru)
"or(a and(b c))" -> (a OR (b AND c))

如果您想要输出类似于您解析的内容:
    template <typename Op> void operator()(const unop<Op>& u) const {
        operator()(combination_op<Op>{{u.operand}});
    }
    template <typename Op> void operator()(const combination_op<Op>& b) const {
        _os << name(Op{}) << "(";
        for (auto& e : b.operands) {
            _os << " ";
            operator()(e);
        }
        _os << ")";
    }

列印(Live On Coliru):
"or(a and(b c))" -> OR( a AND( b c))

As you can see, I that implementation highlights that the "function call" syntax doesn't essentially require difference between unary and binary operators



完整 list

第一种变化:
// #define BOOST_SPIRIT_X3_DEBUG
#include <boost/fusion/adapted.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <string>
#include <iostream>
#include <iomanip>
#include <vector>
namespace x3 = boost::spirit::x3;

namespace client { namespace ast {
    struct op_or {};
    struct op_and {};
    struct op_xor {};
    struct op_not {};
    template <typename tag> struct combination_op;
    template <typename tag> struct unop;
    typedef std::string var;
    typedef boost::variant<var, boost::recursive_wrapper<unop<op_not>>,
                           boost::recursive_wrapper<combination_op<op_and>>,
                           boost::recursive_wrapper<combination_op<op_xor>>,
                           boost::recursive_wrapper<combination_op<op_or>>>
        expr;
    template <typename tag> struct combination_op {
        typedef std::vector<expr> operands_t;
        combination_op() = default;
        combination_op(operands_t const& operands) : operands(operands) {}
        operands_t operands;
    };
    template <typename tag> struct unop {
        unop() = default;
        unop(const expr& o) : operand(o) {}
        expr operand;
    };
} }

BOOST_FUSION_ADAPT_STRUCT(client::ast::combination_op<client::ast::op_and>, operands)
BOOST_FUSION_ADAPT_STRUCT(client::ast::combination_op<client::ast::op_xor>, operands)
BOOST_FUSION_ADAPT_STRUCT(client::ast::combination_op<client::ast::op_or>, operands)
BOOST_FUSION_ADAPT_STRUCT(client::ast::unop<client::ast::op_not>, operand)

namespace client { namespace parser {
    x3::rule<class var, ast::var> var{ "var" };
    x3::rule<class not_, ast::unop<ast::op_not>> not_ { "not" };
    x3::rule<class and_, ast::combination_op<ast::op_and>> and_ { "and" };
    x3::rule<class xor_, ast::combination_op<ast::op_xor>> xor_ { "xor" };
    x3::rule<class or_, ast::combination_op<ast::op_or>> or_ { "or" };
    x3::rule<class expr, ast::expr> expr{ "expr" };

    auto const expr_def = xor_ | and_ | or_ | not_ | var;
    auto const expr_list = *expr;
    auto const or__def = x3::no_case["or"] >> '(' >> expr_list >> ')';
    auto const xor__def = x3::no_case["xor"] >> '(' >> expr_list >> ')';
    auto const and__def = x3::no_case["and"] >> '(' >> expr_list >> ')';
    auto const not__def = x3::no_case["not"] >> expr;
    auto const var_def = x3::lexeme[+x3::alpha];

    BOOST_SPIRIT_DEFINE(var, not_, and_, xor_, or_, expr)
} }

namespace client { namespace ast {
    struct printer {
        using result_type = void;
        std::ostream& _os;

        static auto name(op_and /*unused*/) { return "AND"; }
        static auto name(op_not /*unused*/) { return "NOT"; }
        static auto name(op_or /*unused*/) { return "OR"; }
        static auto name(op_xor /*unused*/) { return "XOR"; }

        void operator()(const var& v) const { _os << v; }
        template <typename Op>
        void operator()(const unop<Op>& u) const {
            _os << "(" << name(Op{}) << " ";
            operator()(u.operand);
            _os << ")";
        }
        template <typename Op>
        void operator()(const combination_op<Op>& b) const {
            _os << "(";
            bool first = true;
            for (auto& e : b.operands) {
                if (!std::exchange(first, false)) {
                    _os << " " << name(Op{}) << " ";

                }

                operator()(e);
            }
            _os << ")";
        }

        void operator()(expr const& v) const {
            boost::apply_visitor(*this, v);
        }
    };
} }

int main() {
    std::string storage = "or(a and(b c))";
    client::ast::expr result;
    typedef std::string::const_iterator iterator_t;
    iterator_t iter = storage.begin(), end = storage.end();
    using x3::ascii::space;
    bool ok = phrase_parse(iter, end, client::parser::expr, space, result);
    if (ok && iter == end) {
        client::ast::printer print{std::cout};
        std::cout << std::quoted(storage) << " -> ";
        print(result);
        std::cout << "\n";
    } else {
        std::cout << "Failed\n";
    }
    if (iter != end) {
        std::cout << "Remaining: " << std::quoted(std::string(iter, end)) << "\n";
    }
}

关于c++ - 如何从此示例更改代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61639325/

相关文章:

c++ - OpenCV SurfDescriptorExtractor 编译错误

c++ - 语法分解问题

c++ - 使用 boost spirit x3 解析逗号分隔的 0 个或多个列表

c++ - Boost Spirit 可选解析器和回溯

c++ - C++中如何处理相互依赖的类

c++ - C++17/C++2a 编译时的哈希类型

c++ - 如何在 Qt 中为我们可以使用 Windows Narrator 阅读的任何 QLabel 设置可访问的名称

c++ - 运算符 >> 和 << 无法识别

Java 异常 IOException 永远不会在相应的 try 语句主体中抛出?

objective-c - Swift 方法在 Objective-C 中不可见