有很多支持包含迷你語言的編程語言。 PHP嵌入在HTML中。 XML可以嵌入到JavaScript中。 Linq可以嵌入到C#中。正則表達式可以嵌入到Perl中。可組合語法
// JavaScript example
var a = <node><child/></node>
想一想,大多數編程語言都可以建模爲不同的迷你語言。 Java中,例如,可以細分成至少四個不同的小語言:
- 一個類型聲明的langauge(package指令,導入指令,類聲明)
- 成員聲明語言(訪問修飾符,方法聲明,構件乏)
- 聲明語言(控制流程中,順序執行)
- 的表達式語言(文字,作業,比較,運算)
由於能夠要將這四種概念語言實現爲四種不同的語法,肯定會減少我通常在複雜的解析器和編譯器實現中看到的大量意大利麪。我使用ANTLR,JavaCC和自定義遞歸下降解析器實現了各種不同語言的解析器,當語言變得非常龐大而複雜時,通常最終會生成一個huuuuuuge語法,並且解析器的實現真的很難看。
理想情況下,爲這些語言之一編寫解析器時,最好將它作爲可組合的解析器的集合實現,並在它們之間來回傳遞控制。
棘手的是,通常,包含的語言(例如Perl)爲包含的語言(例如,正則表達式)定義它自己的終點標記。這裏有一個很好的例子:
my $result ~= m|abc.*xyz|i;
在這段代碼,主要Perl代碼定義了一個非標準的終點「|」爲正則表達式。實現正則表達式解析器完全不同於perl解析器會非常困難,因爲正則表達式解析器不知道如何在不查詢父解析器的情況下找到表達式終點。
或者,可以說我有這使得LINQ表達式中包含一種語言,但不是以分號結束(如C#一樣),我想責成LINQ表達式出現在方括號內:
var linq_expression = [from n in numbers where n < 5 select n]
如果我在母語語法中定義了Linq語法,我可以使用語法向量來輕鬆地爲「LinqExpression」編寫一個明確的生成以找到括號。但是,那麼我的父語法將不得不吸收整個Linq規範。這是一個阻力。另一方面,一個單獨的子Linq解析器將會很難找出停止的地方,因爲它需要爲外部的令牌類型實現前瞻。
而且這幾乎排除使用單獨的lexing/parsing階段,因爲Linq解析器會定義一個完全不同於父解析器的不同標記化規則集。如果您一次掃描一個令牌,您怎麼知道何時將控制權交還給母語的詞法分析器?
你們認爲什麼?現在可用的最佳技術是實現用於在較大的父語言中包含迷你語言的獨特的,分離的和可組合的語言語法?
OMeta有這個!您可以將多個語法組合在一起,或者甚至可以繼承OOP樣式中的現有語法。 – CMCDragonkai 2014-11-05 13:31:38