Prolog DCG中的可选或重复项

5

所以我正在使用Definite Clause Grammars在SWI-Prolog中编写一个简单的Pascal解析器。

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

例如,在EBNF中,Pascal的“program”为:

"PROGRAM" identifier "(" identifierlist ")" ";" block "."

“identifierlist”指:

identifier { "," identifier }

"identifier" 是指:

letter { letter | digit }

我知道在Prolog的DCG形式中程序是这样的:

program --> ["PROGRAM"], identifier, ["("], identifierlist, [")"], [";"], block, ["."].

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


当你说“可选重复”时,你是指它可以为空吗?你对identifierlist的定义似乎没有表明这一点。 - lurker
如果它可以为空,则“identifierlist --> []”应该能解决问题。因此,我不认为我在引用空情况。 - Marcus Hallett
1个回答

3

在Prolog中,只要EBNF确实是您想要的,几乎可以按照EBNF的方式编写代码。

identifierlist = identifier { "," identifier }

你也可以这样写:

identifierlist = identifier
identifierlist = identifier , identifierlist

在Prolog中,你应该这样写:
identifier_list --> identifier.
identifier_list --> identifier, ",", identifier_list.

如果您想包含一个空标识符列表,则需要更加详细的步骤:
identifier_list --> [].
identifier_list --> nonempty_identifier_list.

nonempty_identifier_list--> identifier.
nonempty_identifier_list--> identifier, ",", nonempty_identifier_list.

您的原始EBNF没有包括一个空的标识符列表。如果有的话,上面的代码可能会看起来很像EBNF。


正如@false在评论中指出的那样,非空标识符列表的另一个呈现方式是:

nonempty_identifier_list --> identifier, ( [] | ",", nonempty_identifier_list ).

这与我想象中的情况差不多;然而,我的Prolog经验非常有限,所以我不能确定。 - Marcus Hallett
@MisterCrazy8 你会习惯的。 :) 对于一个谓词有多个子句会给你带来“或”的效果。 - lurker
@MisterCrazy8 如果您认为我的答案可接受,也许您可以将其标记为已接受,或者让我知道是否有其他需要我澄清的事情。 - lurker
而且,“非空标识符列表-->标识符,([]|“,”非空标识符列表)”可能更可取。 - false
@false,谢谢,我不确定。我考虑了其他语法并选择了“显式”视图,但是是的,我可以那样做。 - lurker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接