>백엔드 개발 >C++ >Boost Spirit을 사용하여 연산자 우선 순위에 따라 부울 표현식을 구문 분석할 수 있습니까?

Boost Spirit을 사용하여 연산자 우선 순위에 따라 부울 표현식을 구문 분석할 수 있습니까?

Linda Hamilton
Linda Hamilton원래의
2024-12-21 22:33:40906검색

How can Boost Spirit be used to parse Boolean expressions with operator precedence?

부울 표현식 구문 분석

"a and b xor (c and d or a and b);" 형식의 부울 표현식이 주어지면 목표는 다음과 같습니다. 우선순위 규칙(not, and, xor, or)을 준수하여 트리로 구문 분석합니다.

Boost Spirit 구현

Boost Spirit을 사용하여 표현식 템플릿을 기반으로 재귀 하강 파서를 생성할 수 있습니다. 구현은 다음과 같습니다.

추상 데이터 유형

struct op_or  {}; // tag
struct op_and {}; // tag
struct op_xor {}; // tag
struct op_not {}; // tag

typedef std::string var;
template <typename tag> struct binop;
template <typename tag> struct unop;

typedef boost::variant<var, 
        boost::recursive_wrapper<unop <op_not> >, 
        boost::recursive_wrapper<binop<op_and> >,
        boost::recursive_wrapper<binop<op_xor> >,
        boost::recursive_wrapper<binop<op_or> >
        > expr;

문법 규칙

template <typename It, typename Skipper = qi::space_type>
    struct parser : qi::grammar<It, expr(), Skipper>
{
    parser() : parser::base_type(expr_)
    {
        using namespace qi;
        expr_  = or_.alias();

        not_ = ("not" > simple       ) [ _val = phx::construct<unop <op_not>>(_1)     ] | simple [ _val = _1 ];
#ifdef RIGHT_ASSOCIATIVE
        or_  = (xor_ >> "or"  >> or_ ) [ _val = phx::construct<binop<op_or >>(_1, _2) ] | xor_   [ _val = _1 ];
        xor_ = (and_ >> "xor" >> xor_) [ _val = phx::construct<binop<op_xor>>(_1, _2) ] | and_   [ _val = _1 ];
        and_ = (not_ >> "and" >> and_) [ _val = phx::construct<binop<op_and>>(_1, _2) ] | not_   [ _val = _1 ];
#else
        or_  = xor_ [ _val = _1 ] >> *("or"  >> xor_ [ _val = phx::construct<binop<op_or>> (_val, _1) ]);
        xor_ = and_ [ _val = _1 ] >> *("xor" >> and_ [ _val = phx::construct<binop<op_xor>>(_val, _1) ]);
        and_ = not_ [ _val = _1 ] >> *("and" >> not_ [ _val = phx::construct<binop<op_and>>(_val, _1) ]);
#endif

        simple = (('(' > expr_ > ')') | var_);
        var_ = qi::lexeme[ +alpha ];
    }

  private:
    qi::rule<It, var() , Skipper> var_;
    qi::rule<It, expr(), Skipper> not_, and_, xor_, or_, simple, expr_;
};

구문 트리에서 작업

구문을 탐색하고 인쇄하려면 트리:

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

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

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

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

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

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

테스트 출력

파서는 우선순위 규칙과 출력을 올바르게 처리합니다.

result: ((a &amp; b) ^ ((c &amp; d) | (a &amp; b)))
result: ((a &amp; b) ^ ((c &amp; d) | (a &amp; b)))
result: (a &amp; b)
result: (a | b)
result: (a ^ b)
result: (!a)
result: ((!a) &amp; b)
result: (!(a &amp; b))
result: ((a | b) | c)

전체 코드 및 라이브 예제(Coliru)

[여기를 클릭하여 전체 코드를 확인하세요. 콜리루](https://coliru.stacked-crooked.com/a/a795dea9a310e79bb12db3fe86fa61cf)

위 내용은 Boost Spirit을 사용하여 연산자 우선 순위에 따라 부울 표현식을 구문 분석할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.