Prolog DCG 中的可选或重复项目

Mar*_*ett 5 parsing prolog ebnf dcg

因此,我正在使用定语从句语法在 SWI-Prolog 中为 Pascal 编写一个简单的解析器。

我不明白如何实现重复(2 个或更多)或可选重复(1 个或更多)谓词。

例如,在 EBNF 中,对于 Pascal 的“程序”是:

"PROGRAM" identifier "(" identifierlist ")" ";" block "."
Run Code Online (Sandbox Code Playgroud)

其中“标识符列表”是:

identifier { "," identifier }
Run Code Online (Sandbox Code Playgroud)

而“标识符”是:

letter { letter | digit }
Run Code Online (Sandbox Code Playgroud)

我知道prolog的DCG形式程序是:

program --> ["PROGRAM"], identifier, ["("], identifierlist, [")"], [";"], block, ["."].
Run Code Online (Sandbox Code Playgroud)

如何实现“identifierlist”甚至“identifier”,其中包含可选重复数量的“identifier”或“letter”或“digit”谓词?

lur*_*ker 3

在 Prolog 中,只要 EBNF 确实是您想要的,您就可以将其与 EBNF 完全一样地编写。

identifierlist = identifier { "," identifier }
Run Code Online (Sandbox Code Playgroud)

您也可以将其写为:

identifierlist = identifier
identifierlist = identifier , identifierlist
Run Code Online (Sandbox Code Playgroud)

在 Prolog 中,您可以将其写为:

identifier_list --> identifier.
identifier_list --> identifier, ",", identifier_list.
Run Code Online (Sandbox Code Playgroud)

如果你想包含一个空的标识符列表,那么它会更复杂一些:

identifier_list --> [].
identifier_list --> nonempty_identifier_list.

nonempty_identifier_list--> identifier.
nonempty_identifier_list--> identifier, ",", nonempty_identifier_list.
Run Code Online (Sandbox Code Playgroud)

您的原始 EBNF 不包含空标识符列表。如果是的话,上面的代码可能看起来很像 EBNF。


正如 @false 在评论中指出的,另一个渲染nonempty_identifier_list是:

nonempty_identifier_list --> identifier, ( [] | ",", nonempty_identifier_list ).
Run Code Online (Sandbox Code Playgroud)