Python 之父的解析器系列之六:給 PEG 語法添加動做

原題 | Adding Actions to a PEG Grammarpython

做者 | Guido van Rossum(Python之父)git

譯者 | 豌豆花下貓(「Python貓」公衆號做者)github

聲明 | 本翻譯是出於交流學習的目的,基於 CC BY-NC-SA 4.0 受權協議。爲便於閱讀,內容略有改動。算法

若是你在語法規則中還能夠添加(某些)語義,那麼語法就會更好。特別是對於我正在構建的 Python 解析器,我須要控制每一個備選項返回的 AST 節點,由於 AST 的格式已經規定好。緩存

【這是個人 PEG 系列的第 6 部分。其他部分請參閱系列概述 】(譯註:本系列的譯文已在 Github 開源,項目地址:https://github.com/chinesehuazhou/guido_blog_translation數據結構

許多語法都有支持給規則添加動做的約定,一般是 { 花括號 } 內的一段代碼塊。更確切地說,行動與備選項相關聯。動做塊中的代碼一般與編寫編譯器的語言相同,如 C 語言,增長一些工具,用於引用備選項中的條目。在 Python 原始的 pgen 中,我沒有添加此功能,但對於這個新項目,我但願使用它。函數

對於在這一系列博客文章中開發的簡化版解析器生成器,下面是咱們採用的作法。工具

通常而言,動做的語法以下:學習

rule: item item item { action 1 } | item item { action 2 }

由於它會使語法變得冗長,因此解析器生成器一般支持跨行分割規則,例如:ui

rule: item item item { action 1 }
    | item item { action 2}

它會使語法分析器變得複雜,但可讀性更重要,因此我會使用這種方式。

一個永恆的問題是什麼時候執行動做塊。在 Yacc / Bison 中,由於沒有回溯,一旦規則被解析器識別到,就會執行動做塊。每一個動做會當即執行,這意味着即便操做具備全局反作用,仍是會順利執行(例如更新符號表或其它編譯器數據結構)。

在 PEG 解析器中,由於有無限回溯,咱們有其它的選擇:

  • 延遲全部動做,直到解析完全部內容。這對個人目的沒有用,由於我想在解析期間構造一個 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 屬性來獲取字符串形式的標識符。

當一個備選項中屢次出現相同的規則名稱時,咱們該怎麼辦?對同一備選項中出現的規則,解析器生成器會給出惟一的名稱,即在隨後出現的規則上添加 一、2 等等。例如:

factor: atom '**' atom { atom ** atom1 }
      | atom { atom }

它的實現很無聊,因此我請大家 check out 代碼 ,本身看看。試試這個:

python3.8 -m story5.driver story5/calc.txt -g story5.calc.CalcParser

可視化功能如今支持使用左右箭頭鍵來回移動!

本文內容與示例代碼的受權協議:CC BY-NC-SA 4.0

公衆號【Python貓】, 本號連載優質的系列文章,有喵星哲學貓系列、Python進階系列、好書推薦系列、技術寫做、優質英文推薦與翻譯等等,歡迎關注哦。

相關文章
相關標籤/搜索