Reputation: 2479
I trying to write a grammar that generates expresions. If I do not set a depth limit the recursion goes throw the last variable and be infinity. I do not know how to limit depth branching the tree recursion.
I try this:
constant('c1').
variable('v1').
operator('+').
expresion(C) :- constant(C).
expresion(V) :- variable(V).
expresion(bin(E1,O,E2)) :-
expresion(E1),
operator(O),
expresion(E2).
expresionL(C, 0) :- constant(C).
expresionL(V, 0) :- variable(V).
expresionL(bin(E1,O,E2), N) :-
N_1 is N-1,
expresionL(E1, N_1),
operator(O),
expresionL(E2, N_1).
Here is a live online version.
If I query Expresion(X)
y obtain:
X = c1
X = v1
X = bin(c1, (+), c1)
X = bin(c1, (+), v1)
X = bin(c1, (+), bin(c1, (+), c1))
X = bin(c1, (+), bin(c1, (+), v1))
X = bin(c1, (+), bin(c1, (+), bin(c1, (+), c1)))
...to infiniy and beyond! (recursing over the las expresion). I never see v1
.
I write expresionL
to be a depth limited version of expression.
If I query expresion(bin('v1','+','c1')).
or query expresion(bin('v1','+','c1')).
I get true
.
If I query expresionL(X,1).
I get:
X = bin(c1, (+), c1)
X = bin(c1, (+), v1)
Stack limit (0.2Gb) exceeded
Stack sizes: local: 0.2Gb, global: 51.1Mb, trail: 1Kb
Stack depth: 1,673,655, last-call: 0%, Choice points: 13
Possible non-terminating recursion:
[1,673,655] expresionL(_1404, -1673622)
[1,673,654] expresionL(<compound bin/3>, -1673621)
I do not see v1
in the first parameter of bin
of any answers. The inifite recursion does not stops.
expresion(E, N)
version that limit recursion to N steps?Notes:
<= N levels
Upvotes: 0
Views: 156
Reputation: 3489
The problem is that you allow the expression to be evaluated recursively even if N <= 0
, because while backtracking, the last rule is a viable option even if N becomes zero or even less. You need to rule that out in the last rule using N > 0
.
Adding that to the code:
expresionL(C, 0) :- constant(C).
expresionL(V, 0) :- variable(V).
expresionL(bin(E1,O,E2), N) :-
N > 0, # select this rule only when the others fail
N_1 is N-1,
expresionL(E1, N_1),
operator(O),
expresionL(E2, N_1).
results in:
?- expresionL(X,1).
X = bin(c1, +, c1) ;
X = bin(c1, +, v1) ;
X = bin(v1, +, c1) ;
X = bin(v1, +, v1) ;
false.
Upvotes: 2