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

时间:2015-05-28 21:16:42

标签: rascal

我正在研究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变得扁平,在可选的“私有”节点下不再有可变行的嵌套,我更喜欢这样。

有关如何解决此问题的任何建议?我想要做的是在VisibilitySection的VisibilitySectionContent +符号上要求最长/最贪婪的匹配。

但改变

syntax VisibilitySection = Visibility? VisibilitySectionContent+    

syntax VisibilitySection = Visibility? VisibilitySectionContent+ !>> VisibilitySectionContent

似乎不适用于此。

我还在Rascal上运行了Ambiguity报告工具,但它没有给我任何见解。

有什么想法吗?

由于

2 个答案:

答案 0 :(得分:0)

VisibilitySectionContent+中的VisibilitySection应为VisibilitySectionContent(不含Kleene加)。

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

答案 1 :(得分:0)

我无法检查,因为你没有提供完整的语法,但我相信这应该有助于你的“最长匹配”行为:

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

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

规则末尾的()(空非终端)确保我们可以在应用限制之前跳到下一部分的开头。这仅适用于语法中已存在布局最长匹配规则的情况。