Pregunta

Estoy trabajando en una tarea donde he creado un analizador para un lenguaje aritmético de notación de prefijos.Necesito escribir un predicado que construye un AST para cualquier valor V (es decir, generar un AST AT, de tal manera que cada vez que se evalúe, su valor es V).Mi idea era bastante simple:

genAst(Val, Env, Ast) :-
   ev(Ast, Env, Val).

donde EV es el predicado de evaluación.Cuando ejecuto esto, recibo el error en el título con respecto a esta parte del predicado EV:

ev(xer_(power(N)), Env, V) :-
   integer(N),
   V is Env^N. %THIS LINE

donde ambos v y n están sin consultar.Estoy luchando por pensar en otra forma elegante de hacer esto, ¿alguien sabe cómo podría hacer que el prólogo genere enteros para estas dos variables?

Espero que esto sea comprensible :)

¿Fue útil?

Solución

Como se plantea, su problema parece insoluble, entonces creo que abordaría todo el problema de manera diferente, generándolo todos ASTS hasta un número máximo de tokens.

genAst(Val, Env, Ast) :-
    length(Tokens, N),
    (N > 10, !, fail ; true),
    phrase(sum(Ast), Tokens),
    ev(Ast, Env, Val).

sum(sum(A,B)) --> [+], mul(A), sum(B).
sum(N) --> mul(N).

mul(mul(N,X)) --> [*], xer(X), num(N).
mul(N) --> xer(N).

xer(exp(x,N)) --> [^,x], num(N).
xer(var(x)) --> [x].
xer(N) --> num(N).

%num(num(X)) --> [X], {var(X) -> between(1,9,X) ; integer(X)}.
num(num(X)) --> [X], {X=2;X=3}.

rendimientos

?- genAst(6,2,A).
A = sum(num(3), num(3)) ;
A = mul(num(3), var(x)) ;
A = mul(num(3), num(2)) ;
A = mul(num(2), num(3)) ;
A = sum(mul(num(2), var(x)), var(x)) ;
A = sum(mul(num(2), var(x)), num(2)) ;
A = sum(mul(num(2), num(2)), var(x)) ;
A = sum(mul(num(2), num(2)), num(2)) ;
A = sum(exp(x, num(2)), var(x)) ;
A = sum(exp(x, num(2)), num(2)) ;
A = sum(var(x), sum(var(x), var(x))) ;
A = sum(var(x), sum(var(x), num(2))) ;
A = sum(var(x), sum(num(2), var(x))) ;
A = sum(var(x), sum(num(2), num(2))) ;
A = sum(var(x), mul(num(2), var(x))) ;
A = sum(var(x), mul(num(2), num(2))) ;
A = sum(var(x), exp(x, num(2))) ;
A = sum(num(2), sum(var(x), var(x))) ;
A = sum(num(2), sum(var(x), num(2))) ;
A = sum(num(2), sum(num(2), var(x))) ;
A = sum(num(2), sum(num(2), num(2))) ;
A = sum(num(2), mul(num(2), var(x))) ;
A = sum(num(2), mul(num(2), num(2))) ;
A = sum(num(2), exp(x, num(2))) ;
false.

La limitación de la longitud de la entrada en este DCG se requiere debido a la suma no terminal recursiva derecha // 1

Otros consejos

Use library(clpfd) .Contiene exactamente ese tipo de funcionalidad.¡Y no hay necesidad de generar valores concretos, siempre y cuando no los necesite!

?- X #= Y^Z.
Y^Z#=X.

?- X #= Y^Z, [Y,Z]ins 1..3.
 Y^Z#=X,
Y in 1..3,
Z in 1..3.

?- X #= Y^Z, [Y,Z]ins 1..3, labeling([], [Y,Z]).
X = Y, Y = Z, Z = 1 ;
X = Y, Y = 1,
Z = 2 ;
X = Y, Y = 1,
Z = 3 ;
X = Y, Y = 2,
Z = 1 ;
X = 4,
Y = Z, Z = 2 ;
X = 8,
Y = 2,
Z = 3 ;
X = Y, Y = 3,
Z = 1 ;
X = 9,
Y = 3,
Z = 2 ;
X = 27,
Y = Z, Z = 3.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top