Python 之父的解析器系列之四:可視化 PEG 解析

原題 | Visualizing PEG Parsingpython

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

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

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

上週我展現了一個簡單的 PEG 解析器生成器。本週我將展現生成的解析器在解析程序時實際執行的操做。我深刻研究了 ASCII 藝術的復古世界,特別是一個名爲「curses」的庫,它能夠在 Linux 和 Mac 的 Python 標準庫中找到,也能夠做爲 Windows 的附加組件。算法

【這是個人 PEG 系列的第 4 部分。見第1部分第2部分第3部分第5部分 】(譯註:對應的譯文,第1篇第2篇第3篇、第5篇待譯 )segmentfault

讓咱們來看看可視化已取得的進展。截圖裏的屏幕被分隔爲三個部分,分別是簡單的 ASCII 字符,以及用連字符劃出的線:緩存

  • 上部分顯示瞭解析器的調用堆棧,你可能還記得它是一個具備無限回溯的遞歸降低解析器。我將在下面解釋如何閱讀它。
  • 中間的單行部分展現了標記符緩衝區的內容,光標指向下一個要解析的標記符。
  • 在底部,咱們呈現 packrat 解析算法使用的記憶緩存。它的條目相似於一些解析器堆棧條目(具備結果的條目)。

閱讀此圖表時,要注意的主要事項是:頂部和底部部分的縮進線與標記符緩衝區相對應。(譯註:最好看一下後面的 gif 動圖,再往下看這部份內容。)學習

  • 前兩行(以statementassignment 開頭)表示還沒有返回的解析方法調用,而且當標記位置處在第一個標記符('aap' )以前時調用。
  • 接下來的兩行(以exprterm 開頭)與標記符'cat' 的開頭垂直對齊,後者是調用相應解析方法的地方。
  • 堆棧部分所顯示的第五行和最後一行是一個expect('/') 調用,它返回 None 。它是在標記符'+' 處被調用的。

緩存部分的條目的縮進也對應着標記符緩衝區的位置。例如,在底部,咱們看到有負數緩存條目(negative cache entries)在標記符緩衝區的開頭查找標記符'if' 以及規則if_statement 。咱們還發現標記符'='NAME (特別是'cat' )所成功緩存的條目,它們與未來的輸入位置相對應。動畫

在顯示出來的解析器堆棧和緩存中,已返回的調用被顯示成function(args) -> result 。有時解析器堆棧也會顯示幾個已返回的方法——我這樣作是爲了減小顯示時的「跳躍性」。 ui

(說到「跳躍」,頂部顯示的解析器堆棧會在一個調用被添加到堆棧時,向上移動,而當從堆棧中彈出一個調用時,它則向下移動。彷佛咱們的眼睛跟隨這樣的動做不會有太大問題——至少我沒有。這極可能由於咱們大腦中有一塊區域是用於跟蹤移動的物體。:-)

緩存被可視化爲一種 LRU 緩存,最近使用過的緩存條目位於頂部,較少使用的項目則向屏幕底部掉落。(我在以前的帖子中展現的 packrat 解析器原型不使用 LRU,但它多是改善其內存使用的好策略。)

讓咱們看一下解析堆棧在顯示時的更多一些細節。前四個條目對應於還沒有返回的解析方法,每一行顯示了語法中的一行。帶下劃線的條目會引發下一次調用。

在這種狀況下,咱們看到咱們處於 statement 的第二種選擇,也即 assignment,而且在該規則中咱們處於第三項,即 expr。在 expr 規則中,咱們只是在第一個可選項的第一個條目(term '+' expr );而在 term 規則中,咱們處在最後的選項(atom)。

在那以後,咱們看到致使第二個選項(atom '/' term )失敗的結果:expect('/') - > None 用 '+' 標記符縮進。當咱們將可視化向前移動時,咱們會看到它沉入緩存中。

但固然了,你確定寧願本身看動畫!我已經錄製了示例程序的完整解析。你也能夠本身玩代碼,但請注意,這只是一個臨時的黑科技。

gif圖: https://raw.githubusercontent...

示例代碼:https://github.com/gvanrossum...

當你在觀看錄製的GIF時,可能會感到有些迷惑,有時下一個標記符還未顯示(例如,在最開始時,堆棧在標記符'aap' 被顯示以前,就增加了幾個條目)。

這正是解析器所看到的:標記符緩衝區被延遲地填充,而且在解析器經過調用 expect() 來請求它們以前,並不會掃描標記符。一旦標記符出如今緩衝區中,它就會保留在那裏,即使在解析器回溯時也如此。

標記符緩衝區中的光標向左跳躍,顯示了回溯過程;該動圖中有不少次出現這種現象。你還能夠在 gif 中觀察到緩存填充,解析器在那不會進行額外的遞歸調用。(發現這種狀況時,我應該加以強調,但我沒時間了。)

下週我將進一步開發解析器,極可能會添加我對左遞歸語法規則的實現。(它們很棒!)

致謝:錄製時所用的ttygif (Ilia Choly 開發) 和 ttyrec (Matthew Jording 開發)。

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

英文原文:https://medium.com/@gvanrossum_83706/visualizing-peg-parsing-93a36f259423

做者簡介: Guido van Rossum,Python 的創造者,一直是「終身仁慈獨裁者」,直到 2018 年 7 月 12 日退位。目前,他是新的最高決策層的五位成員之一,依然活躍在社區中。本文出自他在 Medium 開博客所寫的解析器系列,該系列仍在連載中,每週日更新。

譯者簡介: 豌豆花下貓,生於廣東畢業於武大,現爲蘇漂程序員,有一些極客思惟,也有一些人文情懷,有一些溫度,還有一些態度。公衆號:「Python貓」(python_cat)。

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

相關文章
相關標籤/搜索