删除DCG中的左递归 - Prolog

时间:2012-05-19 08:29:38

标签: prolog grammar dcg left-recursion prolog-tabling

我在这个语法中有一个左递归的小问题。我正在尝试在Prolog中编写它,但我不知道如何删除左递归。

<expression> -> <simple_expression>
<simple_expression> -> <simple_expression> <binary_operator> <simple_expression>
<simple_expression> -> <function>
<function> -> <function> <atom>
<function> -> <atom>
<atom> -> <number> | <variable>

<binary_operator> -> + | - | * | /

expression(Expr) --> simple_expression(SExpr), { Expr = SExpr }.
simple_expression(SExpr) --> simple_expression(SExpr1), binary_operator(Op), simple_expression(SExpr2), { SExpr =.. [Op, SExpr1, SExpr2] }.
simple_expression(SExpr) --> function(Func), { SExpr = Func }.
function(Func) --> function(Func2), atom(At), { Func = [Func2, atom(At)] }.
function(Func) --> atom(At), { Func = At }.

我写过类似的东西,但它根本不起作用。如何更改它以使该程序正常工作?

5 个答案:

答案 0 :(得分:2)

程序的问题确实是递归;它应该被删除,否则你将陷入无限循环

要删除立即左递归,请替换表单的每个规则

A->A a1|A a2|....|b1|b2|....

使用:

A -> b1 A'|b2 A'|....
A' -> ε | a1 A'| a2 A'|....

所以功能将是

function -> atom, functionR.
funtionR -> [].

wiki page

答案 1 :(得分:2)

问题只会出现,因为您正在使用反向链接。在正向链接中,可以直接处理左递归语法规则。提供表格的语法规则:

NT ==> NT'

不要形成一个循环。您还可以使用辅助计算,即{}/1,如果将它们放在主体的非终端之后,并且头部中的非终端没有专门进入辅助计算的参数。即自下而上的条件。

这是一个左递归语法示例,在前向链接中以这种方式完美运行:

:- use_module(library(minimal/chart)).
:- use_module(library(experiment/ref)).

:- static 'D'/3.

expr(C) ==> expr(A), [+], term(B), {C is A+B}.
expr(C) ==> expr(A), [-], term(B), {C is A-B}.
expr(A) ==> term(A).

term(C) ==> term(A), [*], factor(B), {C is A*B}.
term(C) ==> term(A), [/], factor(B), {C is A/B}.
term(A) ==> factor(A).

factor(A) ==> [A], {integer(A)}.

这是图表解析器源代码的link。通过此链接,还可以找到前向链接器的源代码。在下面的示例会话中显示:

?- use_module(library(minimal/hypo)).

?- chart([1,+,2,*,3], N) => chart(expr(X), N).
X = 7

在解析图表时,解析器将以自下而上的方式填充图表。对于上述产品中的每个非终端p / n,将存在事实p / n + 2。以下是上述示例的图表结果:

:- thread_local factor/3.
factor(3, 4, 5).
factor(2, 2, 3).
factor(1, 0, 1).

:- thread_local term/3.
term(3, 4, 5).
term(2, 2, 3).
term(6, 2, 5).
term(1, 0, 1).

:- thread_local expr/3.
expr(3, 4, 5).
expr(2, 2, 3).
expr(6, 2, 5).
expr(1, 0, 1).
expr(3, 0, 3).
expr(7, 0, 5).

答案 2 :(得分:1)

@thanosQR的答案相当不错,但适用于比DCG更通用的上下文,并且需要在解析树中进行更改。实际上,解析的“结果”已被删除,这并不好。

如果您只是对解析表达式感兴趣,我发布了here一些有用的东西。

答案 3 :(得分:1)

许多Prolog系统提供表格。有表格终止 在许多情况下,也可以扩展到左递归语法。 这是一个使用新的SWI-Prolog标签功能的解决方案:

:- use_module(library(tabling)).
:- table expr/3.
:- table term/3.
:- table factor/3.

expr(C) --> expr(A), [+], term(B), {C is A+B}.
expr(C) --> expr(A), [-], term(B), {C is A-B}.
expr(A) --> term(A).

term(C) --> term(A), [*], factor(B), {C is A*B}.
term(C) --> term(A), [/], factor(B), {C is A/B}.
term(A) --> factor(A).

factor(A) --> [A], {integer(A)}.

由于这个feature在SWI-Prolog中相对较新,所以它只是 当你打开调试模式时,它可以工作:

?- debug.

?- phrase(expr(X), [1,+,2,*,3], []).
X = 7

答案 4 :(得分:1)

答案集编程(ASP)提供了另一种实现语法的途径。 ASP可以使用非确定性前向链接来实现,这就是 我们的库(最小/ asp)提供。 ASP的结果就是不同的模型

给定规则的

。我们在这里使用ASP模型来表示Cocke-Younger-Kasami 图表。我们从要分析的给定单词开始图表, 用字/ 3事实表示。与DCG相比,我们不再绕过

仅列出单词位置。 Prolog文本calc2.p显示了这样的实现 基于ASP的解析器。现在所有规则都是(<=)/ 2条规则,表示它们是前进的 链接规则。现在所有负责人都选择/ 1负责人,这意味着他们制作了ASP

型号选择。我们解释如何实现expr,术语“实现相似”。 由于我们没有自动翻译,因此我们手动进行翻译。 我们将提供从右到左的单词,并且仅在开始时触发

每个属性语法规则的

choose([expr(C, I, O)]) <= posted(expr(A, I, H)), word('+', H, J), term(B, J, O),  C is A+B.
choose([expr(C, I, O)]) <= posted(expr(A, I, H)), word('-', H, J), term(B, J, O),  C is A-B.
choose([expr(B, I, O)]) <= posted(word('-', I, H)), term(A, H, O), B is -A.
choose([expr(A, I, O)]) <= posted(term(A, I, O)).

可以看出,不需要多余的谓词expr_rest,并且翻译自 规则的语法是1-1。学期也是如此。这样的语法的执行 要求首先将单词从右向左发布,结果可以

然后从相应的非终端读取:

?- post(word(78,7,8)), post(word('+',6,7)), post(word(56,5,6)), post(word('*',4,5)),
    post(word(34,3,4)), post(word('+',2,3)), post(word(12,1,2)), post(word('-',0,1)),
    expr(X,0,8).
X = 1970

我们还制作了Prolog文本show.p,可以将ASP模型可视化为 解析图表。我们仅使用常见的三角矩阵表示形式。的 以上算术表达式的解析表如下所示:

enter image description here

PeterSchüller(2018)-语言学的答案集编程
https://peterschueller.com//pub/2018/2018-schueller-asp-linguistics.pdf

用户手册-模块“ asp”
http://www.jekejeke.ch/idatab/doclet/prod/en/docs/15_min/10_docu/02_reference/07_theory/01_minimal/06_asp.html