问题
I have written a program that takes a parse tree as input and evaluates it. It works when the identifiers in the tree do not reoccur. I want the evaluator to take in multiple statements, and use the values assigned to identfiers when I solve later statements. Here is my program.
add_op --> ['+'].
assign_op --> ['='].
ident(ident(Ident)) --> [Ident], {atom(Ident)}. /* True if an identifier */
int(int(Int)) --> [Int], {integer(Int)}. /* True if an integer */
semicolon --> [';'].
evaluator(statements(Assignment),VariablesOut):-
evaluator(Assignment,VariablesOut).
evaluator(statements(Assignment,Statements),VariablesOut):-
evaluator(Assignment,List1),
evaluator(Statements,List2),
merge(List1,List2,VariablesOut).
evaluator(assignment(ident(Ident),assign_op,int(Int),add_op,int(Int2),semicolon),Answer5):-
Answer2 is Int + Int2,
atom_concat(Ident,' = ',Answer1),
atom_concat(Answer1,Answer2,Answer3),
read_term_from_atom(Answer3, (Answer4), []), /*removes quotation marks*/
Answer5 = [Answer4].
The following execution uses a parse tree for a = 2 + 3 ; b = 3 + 4 ; This execution works because my program is only evaluating the answers to a and b, and the evaluation of b does not contain a.
evaluator(statements(assignment(ident(a), assign_op, int(2), add_op, int(3), semicolon), statements(assignment(ident(b), assign_op, int(3), add_op, int(4), semicolon))), Answer).
Answer = [a=5, b=7].
The following uses a parse tree for a = 2 + 3 ; b = a + 4 ;
This one does not work, because b must be the result of 4 added to a, and a is not assigned to the value 5 within the program.
evaluator(statements(assignment(ident(a), assign_op, int(2), add_op, int(3), semicolon), statements(assignment(ident(b), assign_op, int(a), add_op, int(4), semicolon))), Answer).
ERROR: Arithmetic: `a/0' is not a function
ERROR: In:
ERROR: [11] _2952 is a+4
...
Update
I found a similar solution, but I'm not sure exactly how it works. I don't know where any evaluation is happening and I don't see how the maplist and WithSym =.. lines are needed.
exp_symbols(Symbols, Expr, WithSym) :-
Expr =.. [F|Args], /*F is sent to the first element of Expr which in my case would be a = 5 */
( member(F=V, Symbols) -> G = V ; G = F ), /* if F followed by a colon and some element V is in the equation, set G to be assign to both V and F */
maplist(exp_symbols(Symbols), Args, ArgsSWithSym), /*perform the current function on all elements left **/
WithSym =.. [G|ArgsSWithSym]. /** Set WithSym to be the first element in ArgsSWithSym /**
evaluate(Exp, LstVars, Val) :-
exp_symbols(LstVars, Exp, NewExp),
Val is NewExp.
来源:https://stackoverflow.com/questions/48143072/prolog-evaluator-that-uses-previously-solved-information-as-input