2017-11-08 9 views
1

infixNotation (이전 operatorPrecedence)을 사용하여 문법을 쓰려고하는데 setResultsName을 사용하는 방법을 알 수 없습니다.요약 : setResultsName과 infixnotation을 결합

내가 이것을하려고하는 이유는 부울 검색 쿼리를위한 문법을 ​​searchparser 상단에 작성했지만 아주 긴 표현식의 경우 RecursionError: maximum recursion depth exceeded in comparison으로 실행됩니다.

그래서 그것을합니다 (searchparser하지 않음) infixNotation를 사용하여, 나는이 오류로 실행 피할 수 있음을 보였다. 그래서 필자는 infixNotation에 문법을 적용하려고 시도하고 있지만, 필자의 평가는 구조화 된 구문 분석 결과에서 각 연산자의 이름을 사용하는 데 크게 의존하며, 특히 연산자의 인수에 쉽게 액세스 할 수 있어야합니다.

내가 대한 파싱 책에 주어진 예에서 시작했다 :

and_ = CaselessLiteral("and") 
or_ = CaselessLiteral("or") 
not_ = CaselessLiteral("not") 
searchTerm = Word(alphanums) | quotedString.setParseAction(removeQuotes) 
searchExpr = infixNotation(searchTerm, 
     [ 
     (not_, 1, opAssoc.RIGHT), 
     (and_, 2, opAssoc.LEFT), 
     (or_, 2, opAssoc.LEFT), 
     ]) 

그래서, 내가 어떻게 여기 ParseResultName을 설정합니까?

내가 운영자로 설정하려고하면 :

or_ = CaselessLiteral("or").setResultsName("OR") 

이 같은 모양이 문자열 ('용어 1이나 용어 2 또는 term3')에 대한 결과 parseResult :

<ITEM> 
    <word> 
    <word> 
     <ITEM>term1</ITEM> 
    </word> 
    <OR>or</OR> 
    <word> 
     <ITEM>term2</ITEM> 
    </word> 
    <OR>or</OR> 
    <word> 
     <ITEM>term3</ITEM> 
    </word> 
    </word> 
</ITEM> 

: 나는 조건이 연산자의 인수로 배열 같은 것을 원하는 반면 모든 용어와 연산자, 같은 수준에있는 것을 의미한다

<OR> 
    <OR> 
    <word> 
     <ITEM>term1</ITEM> 
    </word> 
    <OR> 
     <word> 
     <ITEM>term2</ITEM> 
     </word> 
     <word> 
     <ITEM>term3</ITEM> 
     </word> 
    </OR> 
    </OR> 
</OR> 

나는 내 이전 문법이 같은함으로써이를 달성하는 데 사용 :

operatorOr << (Group(
      operatorAnd + Suppress(Keyword("OR", caseless=True)) + operatorOr 
     ).setResultsName("OR") | operatorAnd) 

하지만 운영자 만든 그룹에 결과 이름을 설정하는 방법을 파악하고 두 개의 인수 할 수 ?

답변

0

나는 결과 이름을 사용하는 것이 아니라, 동작 노드의 트리를 구축, 구문 분석 동작으로 클래스를 사용하는 것을 고려하는 것이 좋습니다 것입니다. 여기

class OpNode: 
    def __repr__(self): 
     return "{}({}):{!r}".format(self.__class__.__name__, 
            self.operator, self.operands) 
class UnOp(OpNode): 
    def __init__(self, tokens): 
     self.operator = tokens[0][0] 
     self.operands = [tokens[0][1]] 

class BinOp(OpNode): 
    def __init__(self, tokens): 
     self.operator = tokens[0][1] 
     self.operands = tokens[0][::2] 

and_ = CaselessLiteral("and") 
or_ = CaselessLiteral("or") 
not_ = CaselessLiteral("not") 
searchTerm = Word(alphanums) | quotedString.setParseAction(removeQuotes) 
searchExpr = infixNotation(searchTerm, 
     [ 
     (not_, 1, opAssoc.RIGHT, UnOp), 
     (and_, 2, opAssoc.LEFT, BinOp), 
     (or_, 2, opAssoc.LEFT, BinOp), 
     ]) 

이 방법을 보여주는 샘플 문자열입니다 : 아래의 코드에서

, 나는 operator와 그 클래스의 인스턴스를 다시 제공하고 operands가 제대로 할당 된 속성 각 infixNotation 운영자 수준에 UnOp 및 BinOp 클래스를 첨부 이 노드가 반환됩니다 :

test = "term1 or term2 or term3 and term4 and not term5" 
print(searchExpr.parseString(test)) 

을 제공합니다 :

[BinOp(or):['term1', 'term2', BinOp(and):['term3', 'term4', UnOp(not):['term5']]]] 

이 파싱 된 트리를 탐색하고 해당 노드 유형 및 운영자를 기준으로 다른 노드를 평가할 수 있습니다.

또한 asXML()은 구문 분석 된 데이터를 덤프하는 데 가장 좋은 도구가 아니므로 dump() 메서드를 사용하는 것이 좋습니다.