2015-05-27 29 views
2

在Rascal中處理複雜文字的最佳做法是什麼?從JavaScript(我的DSL也有類似的情況下)在Rascal中處理複雜詞彙

兩個例子:

  • 絃樂與\逃逸 - 必須轉義成實際值。
  • 正則表達式文字 - 需要自己的子AST。

implode拒絕的詞彙映射到抽象的樹木,他們顯然handed differently從語法生產,儘管有完整的解析樹可用。例如,下面的解析失敗,IllegalArgument("Missing lexical constructor")

module lexicals 

import Prelude; 

lexical Char = "\\" ![] | ![\\]; // potentially escaped character 
lexical String = "\"" Char* "\""; // if I make this "syntax", implode works as expected 

start syntax Expr = string: String; 

data EXPR = string(list[str] chars); 

void main(list[str] args) { 
    str text = "\"Hello\\nworld\""; 
    print(implode(#EXPR, parse(#Expr, text))); 
} 

我至今唯一的想法是使用單獨定義的語法,而不佈局空白來捕獲所有的詞彙用原始字符串並在稍後重新解析它們(破滅和所有) 。希望有更好的方法。

回答

2

implode將解析樹轉換爲ast的方式是rascal tutor:implode中的文檔。這包含以下規則:

根據ADT中的預期類型,未標記的詞法對於str,int,real,bool而言是內化的。爲了將詞法分解爲除str以外的其他類型,PDB使用整數和雙精度分析函數。布爾詞彙應該匹配「true」或「false」。注意:即使詞彙不明確,詞彙也會以這種方式崩潰。

因此,解決方案1是一個標籤添加到您的生產:

lexical String = string: "\"" Char* "\""; 

另外,也許你並不需要有一個AST您解析樹旁邊?至少沒有一個必須與你的語法緊密匹配。兩種常見的情況是:

  1. 您需要AST,因爲語法結構不適合您的目的。在這種情況下,您必須手動編寫您的implode函數。
  2. 你的分析樹的結構足夠好。在這種情況下,請檢查Concrete Syntax的示例。這是一個非常乾淨的方式與嵌套在流氓軟件中的目標語言一起工作。

我們越來越傾向於棄用implode函數,因爲我們的具體語法在大多數情況下足夠強大。

+0

標註「string:」與現有構造函數衝突。用別的標籤(「string1:」)導致「找不到EXPR的構造函數」。 (我的後綴錯誤與我的實際定義有很大關係,使用版本0.7.2.201501130937)我的AST非常接近語法(這是一個典型的「Expr」語法),但我需要應用大量的術語重寫(規範化和優化),這就是爲什麼我首先使用Rascal:這是一種簡單但實用的語言,它既內置瞭解析和重寫。 –

+0

我認爲這可以通過將它們分成兩個模塊來解決。事實上,流氓是解析和重寫的一種非常好的語言。並且在某種程度上,這也可以在解析樹上進行。 –

+0

將步驟implode和手動將解析樹映射到「核心語言」可能比解析詞法更好,我會繼續。討論:我理解在具體語法(TXL粉絲在這裏)工作背後的想法,但是真正令人遺憾的是,Rascal正在朝着這個方向發展。不可變的數據和內置的回溯('失敗')使其成爲經典的「AST構建動作解析器」方法的理想宿主。輕量級的樹型構建語法(一個ANTLR 3)+帶佈局數據(空白和註釋)的自動裝飾+自動解析...可以做夢。 –