? “ Python貓 ” ,一個值得加星標的 公眾號
現在,我把譯文提到 Github 上了( guido_blog_translation ),希望有熱心腸的同學能來幫忙審閱指正,或者認領翻譯任務吧。最后,提前祝大家中秋節快樂,闔家團圓,諸事和美。
如果你在語法規則中還可以添加(某些)語義,那么語法就會更好。特別是對于我正在構建的 Python 解析器,我需要控制每個備選項返回的 AST 節點,因為 AST 的格式已經規定好。
許多語法都有支持給規則添加動作的約定,通常是 { 花括號 } 內的一段代碼塊。更確切地說,行動與備選項相關聯。動作塊中的代碼通常與編寫編譯器的語言相同,如 C 語言,增加一些工具,用于引用備選項中的條目。在 Python 原始的 pgen 中,我沒有添加此功能,但對于這個新項目,我希望使用它。
對于在這一系列博客文章中開發的簡化版解析器生成器,下面是我們采用的做法。
一般而言,動作的語法如下:
rule:?item?item?item?{?action?1?}?|?item?item?{?action?2?}
因為它會使語法變得冗長,所以解析器生成器通常支持跨行分割規則,例如:
rule:?item?item?item?{?action?1?}
????|?item?item?{?action?2}
它會使語法分析器變得復雜,但可讀性更重要,所以我會使用這種方式。
一個永恒的問題是何時執行動作塊。在 Yacc / Bison 中,因為沒有回溯,一旦規則被解析器識別到,就會執行動作塊。每個動作會立即執行,這意味著即使操作具有全局副作用,還是會順利執行(例如更新符號表或其它編譯器數據結構)。
-
延遲所有動作,直到解析完所有內容。這對我的目的沒有用,因為我想在解析期間構造一個 AST。
-
只要識別出動作所對應的備選項就執行之,但要求操作代碼是冪等的(即無論執行多少次,都具有相同的效果)。這意味著可以執行某個動作,但其結果最終會被丟棄。
-
緩存動作的結果,因此只有第一次在給定位置識別到備選項時,對應的動作才執行。
我要采用第三個選項——正好我們用 packrat 算法緩存東西,所以我們也可以緩存動作的結果。
關于 {花括號} 里面的內容,傳統上是使用 C 語言,它約定用
$
符號來引用已識別的備選項(例如,
$1
引用第一個條目),并賦值給
$$
以指示動作的結果。
在我看來這太老古董了(我記得曾在 Algol-60 中使用對函數名的賦值,來指定返回值),所以我會用一些更 Pythonic 的方式:在括號內,你需要放置一個單一的表達式,它的值是動作的值,而條目的引用則是一些簡單的名稱,給出著條目的文本。
舉個例子,這是一個簡單計算器,可作加減法:
start:?expr?NEWLINE?{?expr?}
expr:?expr?'+'?term?{?expr?+?term?}
????|?expr?'-'?term?{?expr?-?term?}
????|?term?{?term?}
term:?NUMBER?{?float(number.string)?}
當我們運行時,給定輸入
100+50-38-70
,它會識別出各部分并計算答案,計算成
((100+50)-38)-70
,當然得出結果為 42。
一個小細節:在
term
的動作中,變量
number
保存了一個
TokenInfo
對象,因此該動作必須使用其
.string
屬性來獲取字符串形式的標識符。
當一個備選項中多次出現相同的規則名稱時,我們該怎么辦?對同一備選項中出現的規則,解析器生成器會給出唯一的名稱,即在隨后出現的規則上添加 1、2 等等。例如:
factor:?atom?'**'?atom?{?atom?**?atom1?}
??????|?atom?{?atom?}
它的實現很無聊,所以我請你們 check out 代碼 ,自己看看。試試這個:
python3.8?-m?story5.driver?story5/calc.txt?-g?story5.calc.CalcParser
可視化功能現在支持使用左右箭頭鍵來回移動!

優質文章,推薦閱讀:
Python 的整數與 Numpy 的數據溢出
編程語言之問:何時該借用,何時該創造?
GIL 已經被殺死了么?
Python進階:設計模式之迭代器模式
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
