2013-10-18 1 views
1

비교 연산자 (wihtout 논리 연산자 (예 : |, &) 만 사용하여 a = b & s < 9와 같은 부울 식을 평가하고 싶습니다. 그리고!).상위 노드에서 자식 노드 (잎)에 액세스하는 방법

  = 
     /\ 
     / \ 
      a b 

또는

   & 
      /\ 
      / \ 
      =  < 
     /\ /\ 
     / \/\ 
      a b s 9 

잎 노드

이 값은 다음과 같습니다 우리는 다음과 같은 AST를 가질 수 있습니다. leave 노드의 부모는 항상 =,! =, <,>,> =, < =과 같은 비교 연산자입니다. 비교 노드의 부모는 논리 연산자 |, & 및!입니다. 부모 노드에서 값 노드 (잎)에 액세스하고이 값을 다른 함수 (나중에 구현 됨)에 전달하고 싶습니다. 구문 분석 단계는 정상입니다.

상위 노드에서 값 노드 (잎)에 액세스하는 방법. 내가에서 예제를 사용하고 있습니다 :

 

    struct eval : boost::static_visitor<bool> 
{ 
    eval() {} 

    // 
    bool operator()(const var& v) const 
    { 
     std::cout<<"feuille:\n"<<v<<std::endl; 
     return true; 
    } 

    bool operator()(const binop<op_and>& b) const 
    { 
     recurse(b.oper1) && recurse(b.oper2); 
    } 
    bool operator()(const binop<op_or>& b) const 
    { 
     recurse(b.oper1) || recurse(b.oper2); 
    } 
    bool operator()(const unop<op_not>& u) const 
    { 
     return !recurse(u.oper1); 
    } 

    //------------adding others operators---------------------------- 
    bool operator()(const binop<op_equal>& u) const 
    { 
     // will be implemented later 
     return true; 
    } 

    bool operator()(const binop<op_not_equal>& u) const 
    { 
     // will be implemented later 
     return true; 
    } 

    bool operator()(const binop<op_less>& u) const 
    { 
     // will be implemented later 
     return true; 
    } 

    bool operator()(const binop<op_less_equal>& u) const 
    { 
     // will be implemented later 
     return true; 
    } 

    bool operator()(const binop<op_greater>& u) const 
    { 
     // will be implemented later 
     return true; 
    } 
    bool operator()(const binop<op_greater_equal>& u) const 
    { 
     // will be implemented later 
     return true; 
    } 


감사합니다 : How to calculate boolean expression in Spirit

Boolean expression (grammar) parser in c++ 이 이러한 링크에서 가져온 평가 코드입니다. 어떤 제안이라도 환영합니다.

답변

0

기존 연산자에 대한 다른 평가 오버로드를 살펴 보셨습니까? 의 피연산자 값 (실제로 하위 표현 일 수 있음)을 어떻게 알아 냈습니까?

나를 예로 또는 바이너리를 보자 : 당신이 볼 수 있듯이

bool operator()(const binop<op_or>& b) const 
{ 
    return recurse(b.oper1) || recurse(b.oper2); 
} 

, 그냥 두 피연산자의 값에 ||을 적용합니다. 이 값은 AST [1]에 없습니다. 그래서, 우리는 각 피연산자를 하나의 표현식으로 취급하고, 단지 eval 메쏘드를 재귀 적으로 호출합니다. eval를 호출

표현 유형이 변형이기 때문에

이 실제로 변형에 방문자를 적용, 나는에게 had already written the helpful wrapper that does this so it's easy to recurse된다

private: 
template<typename T> 
    bool recurse(T const& v) const 
    { return boost::apply_visitor(*this, v); } 

을 따라서, 문법의 나머지 부분을 모르고 있지만 가정 당신은 그것을 확장 기존 문법과 동일한 맥락 :

bool operator()(const binop<op_equal>& u) const { 
    return recurse(b.oper1) == recurse(b.oper2); 
} 

정도면됩니다. 그 영리한 매크로, 당신은 매우 신속하게 수행 할 수 있습니다 참고 :

struct eval : boost::static_visitor<value> { 

    // terminal 
    value operator()(const var& v) const { 
     std::cout<<"feuille:\n"<<v<<std::endl; 
     return true; // TODO get value from var 
    } 

    // unary operator 
    value operator()(const unop<op_not>& u) const { return !recurse(u.oper1); } 

    /* 
    * binary operators 
    */ 
#define EXPR_DEF_BINOP(tag, op) \ 
    value operator()(const binop<tag>& u) const { \ 
     return recurse(b.oper1) op recurse(b.oper2); \ 
    } 

    EXPR_DEF_BINOP(op_and,   &&) 
    EXPR_DEF_BINOP(op_equal,   ==) 
    EXPR_DEF_BINOP(op_greater,  >) 
    EXPR_DEF_BINOP(op_greater_equal, >=) 
    EXPR_DEF_BINOP(op_less,   <) 
    EXPR_DEF_BINOP(op_less_equal, <=) 
    EXPR_DEF_BINOP(op_not_equal,  !=) 
    EXPR_DEF_BINOP(op_or,   ||) 

#undef EXPR_DEF_BINOP 

    private: 
    template<typename T> 
     value recurse(T const& v) const 
     { return boost::apply_visitor(*this, v); } 
}; 

좀 더 노트 : 나는 형식을 변경

  • 잎 노드 평가 함수에 TODO를 추가

    • value (bool에서). 이는 문법이 부울이 아닌 표현식을 지원하기 때문입니다. 그렇지 않으면 연산자 <=>=이 적합하지 않습니다.[2], 당신이 (너무) 다른 유형의 값을 가질 것이다 있도록 :

      using value = variant<bool, int32_t>; 
      

      나는을위한 나머지를 떠날거야 당신


    [1] AST = 추상 구문 트리를 기억하십시오. 원본의 1 : 1 표현입니다. (당신은 아직도 어떻게 리터럴의 값을 사용하는 평가자를 알려줄 필요가 있지만 "반 예외", 리터럴 될 것입니다.)

    [2] 틀림없이

    • a<b 암시 수 !a && b
    • a>b 의미 할 수 !b && a
    • a!=b 의미 할 수 a XOR b
    • a==b!(a XOR b)
  • +0

    을 의미 할 수 있습니다. 어떻게 부울 표현식 예제가 유니 코드를 지원할 수 있는지 궁금합니다. 나는 다음과 같이 시도했다 : – user2891256

    +0

    도움이되었다! 어떻게 부울 표현식 예제가 유니 코드를 지원할 수 있는지 궁금합니다. 나는 템플리트 대신에 템플릿을 시도했다. 고맙습니다. – user2891256

    +0

    선장 교체는 ecoding (IIRC'standard_wide'는 _namespace_입니까?)으로 대체 할 수 없습니다. 대신, [정보 둘러보기] (http://stackoverflow.com/search?tab=votes&q=%5bboost-spirit%5d%20OR%20%5bboost-spirit-qi%5d%20unicode). 유니 코드는 부울 표현식과 거의 관련이 없습니다. 그 문제에 대해서'wstring'도 마찬가지입니다. [이] (http://stackoverflow.com/questions/13679669/how-to-use-boostspirit-to-parse-utf-8/15820479#15820479) 매우 명확하게 보였습니다 – sehe

    관련 문제