将DCG更改为确定性

时间:2012-04-01 07:21:32

标签: prolog dcg left-recursion

如何将此语法更改为确定性

e --> [].
e --> "*".
e --> s_e.
e --> e, s_e.
s_e --> ("a",e);("b",e).

我只是不知道放在哪里以避免回溯。

1 个答案:

答案 0 :(得分:2)

您可以按如下方式重写最后一条规则:

s_e --> "a", e.
s_e --> "b", e.

现在放置以下剪辑可能是有意义的:

s_e --> "a", !, e.
s_e --> "b", !, e.

您也可以将剪裁放在原始的紧凑型中 形式与(;)/ 2,但我发现上面更透明。 如果未多次调用s_e,则上述条件有效 具有相同输入列表的时间。

但你的语法有一个缺陷,e是递归的, 和s_e将被多次调用相同 输入列表。意味着你的语法将是例如 否定句子的循环,即它将无法 拒绝他们,你的语法将循环 重做正面句子,即输入时 已被接受。

所以你需要另外消除左边 递归自正常Prolog深度拳头搜索 不能处理它。最简单的是替换它 使用新的非终端进行正确的递归。就是你 可以按如下方式为e编写作品:

 e --> s_e, rest_e.
 e --> "*", rest_e.
 e --> [].

 rest_e --> s_e, rest_e.
 rest_e --> "*", rest_e.
 rest_e --> [].

我们也可以进行削减:

 e --> s_e, !, rest_e.
 e --> "*", !, rest_e.
 e --> [].

 rest_e --> s_e, !, rest_e.
 rest_e --> "*", !, rest_e.
 rest_e --> [].

上面的语法也略有修改 多个空电子制作没有的感觉 通过s_e进入e本身。还有更多 贪婪,因为副作品总是充分的 解析。例如,句子:

 aaa

仅解析为:

 a(a(a))

而不是:

 a(a)a

或者:

 aa(a)

或者:

 aaa

但是否则它应该接受与DCG相同的句子 将自下而上执行,但不会 左递归的问题。

最好的问候