我正在研究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报告工具,但它没有给我任何见解。
有什么想法吗?
由于
答案 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被缩短的解释。现在我们只接受这些部分,如果它们紧跟在记录的结尾或下一部分之后。我很想知道它是否真的有效,因为总是很难预测语法的行为:-)
规则末尾的()
(空非终端)确保我们可以在应用限制之前跳到下一部分的开头。这仅适用于语法中已存在布局最长匹配规则的情况。