2016-08-04 14 views
1

어떻게 '|'를 고려하여 추상 구문 트리를 만들 수 있습니까? 이 내 코드를 사용하여 플라이</p> <pre><code>expr : expr '+' term | expr '-' term | term term : term '*' factor | term '/' factor | factor factor : '(' expr ')' | identifier | number </code></pre> <p>입니다 : 다음 문법 고려 (플라이/Yacc에)

from ply import lex, yacc 

tokens = [ 
    "identifier", 
    "number", 
    "plus", 
    "minus", 
    "mult", 
    "div" 
] 

t_ignore = r" \t" 
t_identifier = r"^[a-zA-Z]+$" 
t_number = r"[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?" 
t_plus = r"\+" 
t_minus = r"-" 
t_mult = r"\*" 
t_div = r"/" 

def p_stmt(p): 
    """stmt : expr""" 
    p[0] = ("stmt", p[1]) 

def p_expr(p): 
    """expr : expr plus term 
      | expr minus term 
      | term""" 
    p[0] = ("expr", p[1], p[2]) # Problem here <<< 

def p_term(p): 
    """term : term mult factor 
      | term div factor 
      | factor""" 

def p_factor(p): 
    """factor : '(' expr ')' 
       | identifier 
       | number""" 


if __name__ == "__main__": 
    lex.lex() 
    yacc.yacc() 
    data = "32 + 10" 
    result = yacc.parse(data) 
    print(result) 

내가 표현이있는 AST를 구축하기로하고 어떻게 액세스 할 수없는 경우 통신 수? p_expr_plus와 같은 함수를 분리 할 수 ​​있지만이 경우 연산자 우선 순위가 제거됩니다. docs은 초보자이며이 문제를 해결할 수 없으므로별로 도움이되지 않습니다. 내가 주제 is this에서 찾은 최고의 소재이지만, 연산자 우선 순위의 복잡성은 고려하지 않았습니다.

편집 : IndexError (용어 만 일치)를 얻었으므로 p 2 또는 p [3]에 액세스 할 수 없습니다. 필자가 링크 한 PDF에서 이들은 ('+', p 1, p 2)와 같이 연산자를 명시 적으로 튜플에 넣었으므로 우선 순위를 고려하여 내 문제를 수정했습니다 (함수를 구분할 수는 없지만 표현식 식을 고려하면 파이프를 고려하고 모든 연산자에 액세스 할 수있는 방법이 있어야합니다.

+0

에서 조각을 살펴보십시오. 우선 순위에는 아무런 문제가 없습니다. 당신은 우선 순위를 사용하지 않습니다. 문법은 모호하지 않으며 연산자 우선 순위는 문법에 내재되어 있습니다. 두 개의 서로 다른 액션 함수 사이에 비 터미널을 나누어도 문법이 변경되지 않고 더 간단한 액션이 만들어집니다. – rici

답변

1

내가 볼 수있는 한, p[0] = ("expr", p[1], p[2])에서 p 1은 왼쪽 수식이고 p [2]는 연산자이며 p [3] (사용하지 않는 것)은 오른손이됩니다 기간.

p [2]를 사용하여 연산자를 결정하고, p [3]을 추가하십시오. 필요할 것이므로, 가야합니다.

또한 p의 항목 수를 확인해야합니다. 마지막 규칙 인 | term"""이 일치하면 p는 4 개가 아닌 2 개의 항목 만 갖기 때문입니다.

당신이 있기 때문에 우선 순위의 "기능을 분리 할 수"있다고 생각하는 이유를 이해하지 않는 GardenSnake example:

def p_comparison(p): 
    """comparison : comparison PLUS comparison 
        | comparison MINUS comparison 
        | comparison MULT comparison 
        | comparison DIV comparison 
        | comparison LT comparison 
        | comparison EQ comparison 
        | comparison GT comparison 
        | PLUS comparison 
        | MINUS comparison 
        | power""" 
    if len(p) == 4: 
     p[0] = binary_ops[p[2]]((p[1], p[3])) 
    elif len(p) == 3: 
     p[0] = unary_ops[p[1]](p[2]) 
    else: 
     p[0] = p[1] 
+0

문제는 p [3]을 사용할 때리스트 인덱스가 범위를 벗어난다는 것입니다. 운영자는 고려하지 않습니다. 내가 링크 한 PDF에서 연산자를 명시 적으로 "저장"합니다 ('+', p [1], p [2]). 이 문제는 모든 운영자가 될 수 있기 때문에 우선 순위를 고려해야합니다. –

+0

아, 맞아. 마지막 행 때문에,'| term "" ":이 마지막 규칙이 매치 될 때,'p'는 4 대신에 2 개의 아이템만을 가질 것입니다. –

+0

expr과 term이 모두 끝나기 때문에"32 + 10 "은"expr plus term "과 일치해야하기 때문에 이상합니다. –