《編程語言實現模式》筆記(一)詞法和句法分析


《編程語言實現模式?可以理解為編程語言的《設計模式》,這本書的中文翻譯通俗易懂,非常適合沒有基礎的人閱讀。 本節主要介紹第一部分,詞法分析和句法分析。

 

1.為什么需要學習這些模式

因為需要自定義DSL(領域自定義語言). 
人的智能非常強大,能夠靈活地處理各種問題。計算機雖然迅速,但遠遠不及人類靈活。因此才有編程語言作為橋梁,建立人和機器的溝通方式。 
然而,通用語言功能強大,但針對特定的應用環境,可能不夠簡潔,同時有很多噪音,也可能難以被領域專家理解。更誇張的情況是,一些方法用通用語言非常難實現,而使用DSL則容易得多,比如正則表達式。 
在我們還不能構造出足夠智能的機器前,使用DSL簡潔流暢地反映人的算法和概念,便是一種折中的選擇。

即使不去設計DSL,能理解DSL的原理和方法,對編程水平的提高都非常有幫助。

設計DSL看起來有難度,但當有足夠的經驗之后,就會發現其實有很多固定的模式可以借鑒,通過學習和熟悉這些模式,就能夠更快速,方便,精確的構造自己的DSL和語言應用。

2.詞法分析

字母的組合構成單詞,單詞的組合構成句子,所有正確的句子的組合則構成一門語言。 
對語言來說,如何判定句子是否正確?規定句子是否正確的規則稱為文法。 
為了能夠正確理解句子,就需要先將句子拆分成多個單詞。對自然語言這叫做分詞;對編程語言,則叫做詞法分析。 
通常來說,一個TOKEN可能是數字,符號,單詞,或是字符串。因而通過正則表達式,可以流式的切分並確定TOKEN的類型。 
值得指出,TOKEN的類型由於二義性,並不能在詞法分析,而需要在語法分析時確定。

3.語法分析

在完成詞法分析后,就是語法分析的階段。語法分析的目標是將文本翻譯為句法樹。

LL(1)模式

語法分析就像貪吃蛇,詞法分析得到的單詞就像一顆顆的糖豆,最簡單的語法分析可以理解為一次吃一顆糖豆。 
如果沒有遞歸子結構,形成的結果更像一個鏈表,而非樹結構。 
一旦語言支持嵌套結構,就需要遞歸下降語法分析器。如果使用本模式,生成的將是直接調用自身而無限遞歸的函數。 
遞歸下降的問題是,無法識別左遞歸,否則將陷入無限循環。另外,由於只向前看一個單元,可能並不能直接判斷出當前的文法。

LL(k)模式

為了解決這個問題,可能需要向前多看幾個單元。往前看的單元越多,貪吃蛇就在遇到交叉時順着不同的路徑看的更遠,從而越知道該選擇哪條路徑。而做解析決策的能力越強,語言就更容易編寫。 
最簡單的方式,就是使用數組來緩沖所有的輸入符號,以整數輸入作為下標的指針。使用環形緩沖區能夠方便地保存數據。

回溯解析器

有時,當文法要求語言能夠支持任意多的重復結構時,要求LL(k)中的緩沖要無限大,這是不可能的。為了解決這個問題,需要采用回溯解析。 
其概念就像走迷宮,既然不能只看不走,那么就嘗試去走每一個可能的選項,直到找到合適的為止。這樣等價於任意地向前看。 
回溯可以設計為遇到成功的,就不嘗試其他路徑;也可以不論是否成功,都嘗試全部路徑,最后選擇最長,最短,或其他自定義的篩選方法。 
回溯解析的性能遠遠不及LL(k),其中一大原因是重復。可能兩個路徑A和B, B路徑中又包含了A路徑。這樣A路徑就可能探查兩遍。為了避免重復,可以通過消耗少量的內存引入記憶機制。

記憶解析器

記憶解析器使用了類似動態規划的概念,記錄在某一位置時,使用某條文法的嘗試結果,如成功,失敗或其他的匹配特征。這樣就能大大減少重復,使得回溯解析能盡可能地達到LL(k)模式的性能。

謂詞解析器

有時,通過純粹的文法很難判斷選擇哪一條匹配路徑,因而可以通過嵌入判斷邏輯,借助運行時信息調整解析策略。 
謂詞解析的常用實現,是在文法中嵌入代碼(如通用語言),解析引擎在運行時執行這些代碼,來調整決策。

3.語言優化

生成AST結構之后,就可以對樹進行操作了。主要的操作有兩部分,遍歷和規約。 
節點結構本身的設計值得考量,基本上有兩種風格:

  • 同構弱類型:所有的節點類型一致,只通過標識符區分操作,通過列表保存子節點。 優點是開發方便,缺點是少了運行時檢查。
  • 異構強類型:節點類型不一致,但都繼承於一個基類。如果方法很多,會產生大量的節點類型。對於編程的工作量可能較大。另外,也不適合自動工具生成時嵌入自定義代碼。

遍歷

所謂遍歷,看似很容易。但有一些需要注意的點。

  • 訪問和執行是其實是分離的,先訪問不一定代表先執行。根據執行代碼相對於訪問代碼的位置,可以生成前序,中序和后序遍歷。
  • 遍歷中肯定要執行操作,對操作的描述可以放在節點定義文件中,也可以設計外部訪問器

規約

在生成句法樹后,可能一些樹結構是冗余或無效的,也可能可以被優化為更好的結構,例如: 
0*(x+5) 由於任何數字乘以0都為0,所以應該直接被規約為0。 
規約涉及到兩個問題,首先要識別特定的樹結構,這就需要對樹進行模式匹配,ANLNR已經有現成的工具和語法支持這類操作。

 

4.總結

編譯原理的書看似很枯燥(確實很枯燥),所以一定要去實踐,實踐后再去看這些概念,就會覺得非常漂亮了。
目前已經采用這些技術,開發了 面向序列模式發現和抽取的一套DSL。不久后將會發布。未來將開發針對樹結構的分析DSL。
下一部分的內容,是該書的后半部分,程序的解釋執行。然而這一部分,我還沒有深入去研究,因此估計周期會比較長了。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM