2015-05-28 54 views
1

我正在研究Rascal中的Delphi語法,我在解析其「記錄」類型時遇到了一些問題。德爾福代碼中的相關部分可以看看如下:如何從這段Delphi語法中刪除歧義

record 

private 
a,b,c : Integer; 
x : Cardinal; 

end 

這裏的「私人」可以是可選的,變量聲明線路也可選配。

我試着用下面的規則來解釋本節:

syntax FieldDecl = IdentList ":" Type 
     | IdentList ":" Type ";" 
     ; 

syntax FieldSection = FieldDecl 
     | "var" FieldDecl 
     | "class" "var" FieldDecl 
     ; 

syntax Visibility = "private" | "protected" | "public"| "published" ; 

syntax VisibilitySectionContent = FieldSection 
      | MethodOrProperty 
      | ConstSection 
      | TypeSection 
      ; 

syntax VisibilitySection = Visibility? VisibilitySectionContent+  
     ; 

syntax RecordType = "record" "end" 
     | "record" VisibilitySection+ "end" 
     ; 

問題是含糊不清。 「record」和「end」之間的整個文本可以在單個VisibilitySection中解析,但是每一行本身也可以是一個單獨的VisibilitySection。

我可以改變規則VisibilitySection到

syntax VisibilitySection = Visibility 
     | VisibilitySectionContent 
     ; 

然後語法不再是模糊的,但VisibilitySection變得平坦,沒有嵌套了一個可選的「私人」節點下的變線,我更喜歡。

有關如何解決此問題的任何建議?我想要做的是在VisibilitySection的VisibilitySectionContent +符號上請求最長/最貪婪的匹配。

但改變

syntax VisibilitySection = Visibility? VisibilitySectionContent+  

syntax VisibilitySection = Visibility? VisibilitySectionContent+ !>> VisibilitySectionContent 

似乎並沒有對這項工作。

我也在Rascal上運行了歧義報告工具,但它沒有提供任何見解。

有什麼想法?

感謝

+0

嗨。由於語法不完整,我無法重現歧義。你有沒有提到完整的定義? – jurgenv

+0

'!>>'表示法只適用於右側的終端,如'!>>「private」' – jurgenv

+0

迄今爲止的語法位於:http://www.ilsmoija.nl/download/DelphiGrammar。 rsc – Martijn

回答

0

我無法檢查,因爲你沒有提供完整的語法,但我相信這應該工作,讓您的「最長匹配」的行爲:

syntax VisibilitySection 
    = Visibility? VisibilitySectionContent+() 
    >> "public" 
    >> "private" 
    >> "published" 
    >> "protected" 
    >> "end" 
    ; 

在我看來這地方應該刪除您解讀嵌套的VisibilitySections被縮短。現在我們只接受這些部分,如果他們緊接着是記錄的結尾或下一部分。我很想知道它是否真的起作用,因爲它總是很難預測語法的行爲:-)

規則末尾的()(空的非終端)確保我們可以跳到在應用限制之前下一部分的開始。這隻適用於在語法中已經存在佈局上最長匹配規則的情況。

+0

儘管每個'follow'操作符似乎都需要處於自己的生產規則中,但它幾乎完美地工作。問題在於VisibilitySectionContent部分和「私人」部分之間似乎沒有考慮佈局?當它們之間沒有任何佈局部件時,它可以完美解析,但是當添加布局時,它會生成一個解析錯誤。當預期的佈局部分明確地添加到規則中時,它在雙空白部分上是不明確的。 – Martijn

+0

啊,的確如此。我將用另一個解決方法更改解決方案。如果它然後工作,請接受答案:-) – jurgenv

+0

它的工作,很好。感謝您的回答:^) – Martijn

0

VisibilitySectionContent+VisibilitySection應該VisibilitySectionContent(不Kleene加號)。

我在這裏猜測,但你的意圖可能是允許記錄類型中的多個部分/聲明,其中任何一個可能有或沒有Visibility修飾符。爲避免在每個部分中放入此可選Visibility,您創建了一個非終結符,它基本上模擬了「記錄類型定義中可能發生的事情」,每個非終結符只需一次,而不必擔心可見性修飾符。在這種情況下,如果您從RecordType中指定VisibilitySection,那麼您可以在VisibilitySection之間使用VisibilitySectionContent,因爲存在明確的重複。

+0

感謝這個想法,但是當我使用這種方法時,記錄的內部結構變得「平坦」,我想保留變量嵌套在「private」和「public」標籤下。 – Martijn