如何消除这段 Delphi 语法中的歧义

How to remove ambiguity from this piece of Delphi grammar

我正在研究 Rascal 中的 Delphi 语法,我在解析其“记录”类型时遇到了一些问题。 Delphi 代码的相关部分如下所示:

record

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

end

其中"private"可以是可选的,变量声明行也可以是可选的

我尝试使用以下规则解释此部分:

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 变得平坦,在可选的 'private' 节点下不再有可变行的嵌套,我更喜欢这样。

关于如何解决这个问题有什么建议吗?我想要做的是要求对 VisibilitySection 的 VisibilitySectionContent+ 符号进行最长/贪婪匹配。

但是改变

syntax VisibilitySection = Visibility? VisibilitySectionContent+    

syntax VisibilitySection = Visibility? VisibilitySectionContent+ !>> VisibilitySectionContent

似乎不​​适用于此。

我也 运行 Rascal 上的歧义报告工具,但它没有为我提供任何见解。

有什么想法吗?

谢谢

VisibilitySection中的VisibilitySectionContent+应该是VisibilitySectionContent(没有Kleene plus)。

我在这里猜测,但您的意图可能是在记录类型中允许多个 sections/declarations,并且其中任何一个可能有也可能没有 Visibility 修饰符。为了避免在每个部分中放置这个可选的 Visibility,您创建了一个 VisibilitySectionContent 非终结符,它基本上模拟“记录类型定义中可能发生的事情”,每个非终结符一个,而不用担心可见性修饰符。在这种情况下,每个 VisibilitySection 使用一个 VisibilitySectionContent 就可以了,因为无论如何,当您从 RecordType 引用 VisibilitySection 时存在明确的重复。

我无法检查,因为你没有提供完整的语法,但我相信这应该可以让你的 "longest match" 行为:

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

在我看来,这应该消除嵌套 VisibilitySections 被缩短的解释。现在我们只接受这些部分,如果它们紧跟在记录的末尾或下一部分。我很想知道它是否真的有效,因为总是很难预测语法的行为:-)

规则末尾的 ()(空非终结符)确保我们可以在应用限制之前跳到下一部分的开头。仅当您在语法中某处已有最长的布局匹配规则时才有效。