《領域特定語言》一3 2解析器的工作方式

2021-09-23 09:59:44 字數 1338 閱讀 4500

所以,內部dsl和外部dsl的差別主要體現在解析上。雖然二者確實存在一些細節上的不同,但它們也有很多共通之處。

乙個最重要的共同點就是,解析都是乙個很強的層級操作。當解析文字時,把資料塊組織成乙個樹結構。考慮乙個簡單結構,狀態機中的事件列表。在外部dsl語法中,它看起來如下所示:

events

doorclosed d1cl

draweropened d2op

end

這個復合結構是乙個事件列表,包含一系列事件,每個事件都有名字和**。

用ruby編寫的內部dsl與上述**很類似:

event :doorclosed "d1cl"

event :draweropened "d2op"

對於整個列表,這裡沒有顯式的標記,但是每乙個事件本身仍是乙個層級:每個事件都有表示名字的符號和表示代 碼的字串。

無論何時看到這樣的指令碼,都可以把它想象為乙個層級,這樣的層級稱為語法樹(或者解析樹)。任何指令碼都可以轉化為許多潛在的語法樹─這取決於如何分解它。相對於單詞(word),語法樹是一種更有效的指令碼表現形 式,因為可以遍歷語法樹,使用各種不同的方式來對它進行操作。

如果用到「語義模型」(第11章),可以把乙個語法樹翻譯成語義模型(見圖3-2)。如果經常讀一些語言社群的資料,我們會發現,語法樹得到了非常多的關注─人們通常直接執行語法樹,或者基於語法樹生成**。更有效的做法是,語法樹可以直接當做語義模型來使用。但大多數時候,我不會這麼做,因為語法樹同dsl指令碼關聯非常緊密,這樣做只會讓dsl的處理同語法產生耦合。

目前為止,我都一直都在談論語法樹,彷彿它是系統裡一種有形的資料結構,就像xml dom一樣。有時候,它的確是,但更多的時候,它不是。很多時候,語法樹在呼叫棧中形成,在遍歷的過程中得到處理。所以,我們看不到整個樹,而只能看到當前處理的分支(類似於xml sax的工作方式)。儘管如此,嘗試理解隱匿於呼叫棧中鬼魅般的語法樹總是有幫助的。對乙個內部dsl而言,語法樹的形成有賴於方法呼叫(「巢狀函式」(第34章))的實參和巢狀物件(「方法級聯」(第35章))。有時候,我們看不到乙個很明顯的層次結構,不得不進行模擬(有層次結構的「函式序列」(第33章)可以由「語境變數」(第13章)模擬)。語法樹或許形似鬼魅,但它依然是一種有益的腦力工具。使用外部dsl會產生乙個更加顯式的語法樹,事實上,有時候我們確實生成了乙個完完全全的語法樹資料結構(「樹的構建」(第24章))。但即使是外部dsl,通常在處理過程中,也是在呼叫棧中不斷形成和修剪著語法樹。(這裡引用了幾個尚未描述的模式,如果是第一次讀到,放心略過即可,但以後再讀,這些引用會很有幫助。)

《領域特定語言》一2 3DSL的問題

前面已經討論了何時該採用dsl,接下來就該談論什麼時候不該採用dsl,或者至少是使用dsl應注意的問題。從根本上說,不使用dsl的唯一原因就是,在你的場景下,使用dsl得不到任何好處,或者,至少是dsl的好處不足以抵消構建它的成本。雖然dsl在有些場合下適用,但同樣會帶來一些問題。總的來說,我認為通...

《領域特定語言》一3 3 文法 語法和語義

如果要處理一種語言的語法,文法是一種很重要的工具。文法是一組規則,用以描述如何將文字流轉化為語法樹。大多數程式設計師都會在生命中的某一刻接觸文法,因為文法常用以描述我們日常使用的程式語言。文法由一系列產生式規則組成,每個生產規則都有乙個名字 term 以及乙個描述如何分解它的語句 statement...

PE解析器的編寫(一) 總體說明

之前自己學習了pe檔案的格式,後來自己寫了個pe檔案的解析器,這段時間工作上剛好要用到它,老闆需要能檢視某個exe中載入的dll的乙個工具,我在使用之前自己寫的這個東西的時候,發現很多東西都忘記了,所以,我在這回顧下當時的思路,並記錄下來,方便以後直接使用。也算是回顧下之前學習的內容,將學的東西學以...