簡體   English   中英

考慮到“|”,如何創建抽象語法樹? (層/Yacc)

[英]How can I create an abstract syntax tree considering '|'? (Ply / Yacc)

考慮以下語法:

expr : expr '+' term | expr '-' term | term
term : term '*' factor | term '/' factor | factor
factor : '(' expr ')' | identifier | number

這是我使用ply的代碼:

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 這樣的函數分開,但在這種情況下,我將消除運算符優先級。 文檔不是很有幫助,因為我是初學者,無法解決這個問題。 我在這個主題上找到的最好的材料是 this ,但它沒有考慮運算符優先級的復雜性。

編輯:我無法訪問 p 2或 p[3],因為我得到了一個 IndexError(它只匹配術語)。 在我鏈接的 PDF 中,他們明確地將運算符放在元組中,例如: ('+', p 1 , p 2 ),因此,考慮到優先級證明了我的問題(我無法將函數、表達式分開是表達式,應該有一種方法來考慮管道並訪問任何運算符)。

據我所知,在p[0] = ("expr", p[1], p[2])p[1]將是左手表達式, p[2]將是運算符,並且p[3] (您沒有使用)將是右手術語。

只需使用p[2]來確定運算符,添加p[3] ,因為您將需要它,並且您應該很高興。

此外,您必須驗證p有多少項,因為如果最后一條規則是| term""" | term"""匹配, p將只有兩個項目而不是四個。

看一下GardenSnake 示例中的一個片段

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]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM