Recursion Prolog DCG:匹配链上的不同符号

Recursion Prolog DCG:匹配链上的不同符号,recursion,prolog,dcg,left-recursion,failure-slice,Recursion,Prolog,Dcg,Left Recursion,Failure Slice,我正在尝试匹配一些句子(例如001[0,0,1],(1+(1/0))['(',1,+,'(',1,/,0'),'),')],等等 我让自己跟随小DCG g3 --> s3. s3 --> e3. e3 --> eAdd. e3 --> eMin. e3 --> eMul. e3 --> eDiv. e3 --> n3. eAdd --> ['('],e3,['+'],e3,[')']. eMin --> ['('],e3,['-'],e3

我正在尝试匹配一些句子(例如001[0,0,1],(1+(1/0))['(',1,+,'(',1,/,0'),'),')],等等

我让自己跟随小DCG

g3 --> s3.
s3 --> e3.

e3 --> eAdd.
e3 --> eMin.
e3 --> eMul.
e3 --> eDiv.
e3 --> n3.

eAdd --> ['('],e3,['+'],e3,[')'].
eMin --> ['('],e3,['-'],e3,[')'].
eMul --> ['('],e3,['*'],e3,[')'].
eDiv --> ['('],e3,['/'],e3,[')'].


n3 --> d3.
n3 --> n3,d3.
d3 --> [0].
d3 --> [1].
现在我的问题是,它不会匹配使用-、*或/的句子,但它只适用于使用+的递归句子

例如:

会有用的,但是

phrase(g3,['(',1,'+','(',1,'/',1,')',')']).
不行


任何帮助都将不胜感激,谢谢!

您的问题是由于规则造成的

n3 --> n3,d3.
这是一个所谓的左递归规则。它说要匹配一个
n3
,必须首先匹配一个
n3
,必须首先匹配一个
n3
,必须先匹配一个
n3
,以此类推,这永远不会终止

基本上,您希望每个递归语法规则在执行递归调用之前首先匹配一些非终结符(类似地,在“普通”Prolog谓词体中,在任何递归调用之前都应该有其他目标)

如果将此规则更改为正确的递归变量

n3 --> d3,n3.
你的语法变得很好:

?- phrase(g3,['(',1,'+','(',1,'+',1,')',')']).
true ;
false.

?- phrase(g3,['(',1,'+','(',1,'/',1,')',')']).
true ;
false.

?- length(L, 6), phrase(g3, L).
L = ['(', 0, +, 0, 0, ')'] ;
L = ['(', 0, +, 0, 1, ')'] ;
L = ['(', 0, +, 1, 0, ')'] ;
L = ['(', 0, +, 1, 1, ')'] ;
L = ['(', 1, +, 0, 0, ')'] ;
L = ['(', 1, +, 0, 1, ')'] ;
L = ['(', 1, +, 1, 0, ')'] ;
L = ['(', 1, +, 1, 1, ')'] ;
等等

下面是一些关于DCGs中左递归的老问题,这些问题可能会提供额外的有用信息:


<> P> >首先,无论何时使用DCG,请考虑

:- set_prolog_flag(double_quotes, chars).
这允许使用更可读的语法 以及由于此约定而发生更改的查询

:- set_prolog_flag(double_quotes, chars).

eAdd --> "(", e3, "+", e3, ")".
eMin --> "(", e3, "-", e3, ")".
eMul --> "(", e3, "*", e3, ")".
eDiv --> "(", e3, "/", e3, ")".

d3 --> "0".
d3 --> "1".

?- phrase(g3,"(1+(1+1))").

?- phrase(g3,"(1+(1/1))").
请注意,您的第一个查询已经有问题了,即使它成功了。 这在顶层很容易看到:

?- phrase(g3,"(1+(1+1))").
true ;
ERROR: Out of local stack
因此,高层坚持认为,除了 实际成功。为了系统地缩小范围,我将使用 将
false
添加到常规目标和 语法中的
{false}

:- set_prolog_flag(double_quotes, chars). g3 --> s3, {false}. s3 --> e3, {false}. e3 --> {false}, eAdd. e3 --> {false}, eMin. e3 --> {false}, eMul. e3 --> {false}, eDiv. e3 --> n3, {false}. n3 --> {false}, d3. n3 --> n3, {false}, d3. ?- phrase(g3,"(1+(1+1))"), false. :-set_prolog_标志(双引号,字符)。 g3-->s3,{false}。 s3-->e3,{false}。 e3-->{false},eAdd。 e3-->{false},艾敏。 e3-->{false},eMul。 e3-->{false},eDiv。 e3-->n3,{false}。 n3-->{false},d3。 n3-->n3,{false},d3。 -短语(g3,“(1+(1+1))”),错误。 因为这个小片段循环,整个程序也循环 该
+
不再是程序的一部分!问题与此无关
不要用
+

哦,哇……太谢谢你了!我完全忘了那条规则!@重复:谢谢你! :- set_prolog_flag(double_quotes, chars). g3 --> s3, {false}. s3 --> e3, {false}. e3 --> {false}, eAdd. e3 --> {false}, eMin. e3 --> {false}, eMul. e3 --> {false}, eDiv. e3 --> n3, {false}. n3 --> {false}, d3. n3 --> n3, {false}, d3. ?- phrase(g3,"(1+(1+1))"), false.