yacc.py沒有構造抽像語法樹的特殊方法。不過,你可以自己很簡單的構造出來。
一個最為簡單的構造方法是為每個語法規則創建元組或者字典,并傳遞它們。有很多中可行的方案,下面是一個例子:
~~~
def p_expression_binop(p):
'''expression : expression PLUS expression
| expression MINUS expression
| expression TIMES expression
| expression DIVIDE expression'''
p[0] = ('binary-expression',p[2],p[1],p[3])
def p_expression_group(p):
'expression : LPAREN expression RPAREN'
p[0] = ('group-expression',p[2])
def p_expression_number(p):
'expression : NUMBER'
p[0] = ('number-expression',p[1])
~~~
另一種方法可以是為不同的抽象樹節點創建一系列的數據結構,并賦值給p[0]:
~~~
class Expr: pass
class BinOp(Expr):
def __init__(self,left,op,right):
self.type = "binop"
self.left = left
self.right = right
self.op = op
class Number(Expr):
def __init__(self,value):
self.type = "number"
self.value = value
def p_expression_binop(p):
'''expression : expression PLUS expression
| expression MINUS expression
| expression TIMES expression
| expression DIVIDE expression'''
p[0] = BinOp(p[1],p[2],p[3])
def p_expression_group(p):
'expression : LPAREN expression RPAREN'
p[0] = p[2]
def p_expression_number(p):
'expression : NUMBER'
p[0] = Number(p[1])
~~~
這種方式的好處是在處理復雜語義時比較簡單:類型檢查、代碼生成、以及其他針對樹節點的功能。
為了簡化樹的遍歷,可以創建一個通用的樹節點結構,例如:
~~~
class Node:
def __init__(self,type,children=None,leaf=None):
self.type = type
if children:
self.children = children
else:
self.children = [ ]
self.leaf = leaf
def p_expression_binop(p):
'''expression : expression PLUS expression
| expression MINUS expression
| expression TIMES expression
| expression DIVIDE expression'''
p[0] = Node("binop", [p[1],p[3]], p[2])
~~~
- 0 一些翻譯約定
- 1 前言和預備
- 2 介紹
- 3 PLY概要
- 4 Lex
- 4.1 Lex的例子
- 4.2 標記列表
- 4.3 標記的規則
- 4.4 標記的值
- 4.5 丟棄標記
- 4.6 行號和位置信息
- 4.7 忽略字符
- 4.8 字面字符
- 4.9 錯誤處理
- 4.10 構建和使用lexer
- 4.11 @TOKEN裝飾器
- 4.12 優化模式
- 4.13 調試
- 4.14 其他方式定義詞法規則
- 4.15 額外狀態維護
- 4.16 Lexer克隆
- 4.17 Lexer的內部狀態
- 4.18 基于條件的掃描和啟動條件
- 4.19 其他問題
- 5 語法分析基礎
- 6 Yacc
- 6.1 一個例子
- 6.2 將語法規則合并
- 6.3 字面字符
- 6.4 空產生式
- 6.5 改變起始符號
- 6.6 處理二義文法
- 6.7 parser.out調試文件
- 6.8 處理語法錯誤
- 6.9 行號和位置的跟蹤
- 6.10 構造抽象語法樹
- 6.11 嵌入式動作
- 6.12 Yacc的其他
- 7 多個語法和詞法分析器
- 8 使用Python的優化模式
- 9 高級調試
- 9.1 調試lex()和yacc()命令
- 9.2 運行時調試
- 10 如何繼續