2016-07-06 61 views
1

在Rascal中,爲什麼當在生產的可選部分的位置有佈局時,這會導致模糊性?例如。 "{ }"模糊爲Start1,而它從下面的語法中正確地解析爲Start2,我希望它會完全相同。爲什麼圍繞生產的可選部分佈局造成歧義?

layout Layout        = " "?; 
start syntax Start1       = "{" "c"? "}"; 
start syntax Start2       = "{" "c" "}" 
              | "{" "}"; 

另外,我想知道是否有另一種方式來表示Start2不重複比Start1,不會導致同樣的不確定性。

很顯然這段代碼沒有大量的重複,Start2在這裏是一個不錯的選擇,但這只是一個例子。我正在處理一個包含三個或四個可選部分的許多產品的語法,在最後一種情況下,顯示在Start2中的符號已經需要複製產品的非可選部分2^4 = 16次,這在我的工作中真的很麻煩意見。

回答

1

解析器被生成以類似於此之前你的語法第一擴展:用於將輸入像{ }(在花括號之間的空間)

layout Layout       = " "?; 
syntax " "?       = | " "; 
syntax Start1       = "{" Layout "c"? Layout "}"; 
syntax "c"?       = | "c"; 
lexical " "       = [\ ]; 
lexical "c"       = [c]; 
lexical "{"       = [{]; 
lexical "}"       = [}]; 
syntax Start2       = "{" Layout "c" Layout "}" 
             | "{" Layout "}"; 
syntax start[Start1] = Layout Start1 Layout; 
syntax start[Start2] = Layout Start2 Layout; 

所以,空間可通過的第一個實例中得到佈局在Start1規則的右側,或佈局的第二個實例。由於解析器產生所有的派生樹,在這種情況下,解析是含糊不清可以這麼說。

layout Layout = " "? !>> " " 

或(等效地)像這樣::

layout Layout = " "? !>> [\ ] 

限制性作爲對約束

典型地,該多義性是通過使用如下的限制,像這樣引入解決佈局規則:如果它後面有空格,它將不會派生任何東西(甚至不是空字符串)。這使得只有第一個派生有效,那麼空間會進入Start1的第一個Layout實例。此後有}滿足約束和解析是明確的。

+0

感謝您的詳細解答。當我看到語法如何擴展並且解決方案易於理解時,對我來說真的更有意義。儘管如此,我仍然覺得這有點奇怪。 當你不關心佈局的位置時,在問號(和星號)上有變體是否有用?我可以想象這會被使用很多。 –

+0

是的,我們也考慮過這個問題。但渴望?或*很容易導致解析錯誤,這是非常意想不到的,很難調試。在這方面,解決歧義比分析錯誤更容易。聲明性的消歧也可能引入解析錯誤,但至少是明確可見的。不過,我們正在考慮在正則標記子語言的詞彙層面上引入渴望的語義,同時保持上下文無關的部分。未來的工作! – jurgenv