位置跟蹤通常是個設計編譯器時的技巧性玩意兒。默認情況下,PLY跟蹤所有標記的行號和位置,這些信息可以這樣得到:
* p.lineno(num)返回第num個符號的行號
* p.lexpos(num)返回第num個符號的詞法位置偏移
例如:
~~~
def p_expression(p):
'expression : expression PLUS expression'
p.lineno(1) # Line number of the left expression
p.lineno(2) # line number of the PLUS operator
p.lineno(3) # line number of the right expression
...
start,end = p.linespan(3) # Start,end lines of the right expression
starti,endi = p.lexspan(3) # Start,end positions of right expression
~~~
注意:lexspan()方法只會返回的結束位置是最后一個符號的起始位置。
雖然,PLY對所有符號的行號和位置的跟蹤很管用,但經常是不必要的。例如,你僅僅是在錯誤信息中使用行號,你通常可以僅僅使用關鍵標記的信息,比如:
~~~
def p_bad_func(p):
'funccall : fname LPAREN error RPAREN'
# Line number reported from LPAREN token
print "Bad function call at line", p.lineno(2)
~~~
類似的,為了改善性能,你可以有選擇性的將行號信息在必要的時候進行傳遞,這是通過p.set_lineno()實現的,例如:
~~~
def p_fname(p):
'fname : ID'
p[0] = p[1]
p.set_lineno(0,p.lineno(1))
~~~
對于已經完成分析的規則,PLY不會保留行號信息,如果你是在構建抽象語法樹而且需要行號,你應該確保行號保留在樹上。
- 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 如何繼續