Implement a simple C-like language in Prolog?

I am new to the prologue, so this is a pretty difficult task for me. I have to implement a simple C-like language in Prolog.

the ultimate goal is to be able to execute something like this: ?- run([begin,a,:=,10,while,a,>,5,begin,write,a,a,:=,a,-,1,end,end]). and get: 10 9 8 7 6 yes 

However, I was stuck in the first step. This is what I have achieved so far. from the local stack!

 statement(Vars,_Vars) --> assign(Vars,_Vars). statement(Vars,Vars2) --> statement(Vars,Vars1), statement(Vars1,Vars2). assign(Vars,_Vars) --> default_assign(Vars,_Vars). assign(Vars,_Vars) --> simple_assign(Vars,_Vars). % a //default value 0 default_assign(Vars,_Vars) --> var_name(Var_Name), {update_vars([Var_Name,0],Vars,_Vars)}. % a = 0 simple_assign(Vars,_Vars) --> var_name(Var_Name),[=],var_value(Var_Value), {update_vars([Var_Name,Var_Value],Vars,_Vars)}. % a = b simple_assign(Vars,_Vars) --> var_name(Var_Name1),[=],var_name(Var_Name2), { update_vars([Var_Name1,Var_Value],Vars,_Vars) }. var_name(Var_Name) --> [Var_Name],{\+number(Var_Name2)}. var_value(Var_Value) -->[Var_Value],{number(Var_Value)}. % found match, update update_vars(Var,Vars,_Vars):- member(Var,Vars), update(Var,Vars,_Vars), _Vars\==[]. % no match, append update_vars(Var,Vars,_Vars):- \+member(Var,Vars), append(Var,Vars,_Vars). update([Name,Value],[],[]). update([Name,Value],[[Name,Old_Value]|T1],[[Name,Value]|T2]):- update([Name,Value],T1,T2). update([Name,Value],[[Name1,Value1]|T1],[[Name1,Value1]|T2]):- [Name,Value]\=[Name1,Value1], update([Name,Value],T1,T2). append([Name,Value],[],[[Name,Value]]). append([Name,Value],[H|T1],[H|T2]):- append([Name,Value],T1,T2). 

Here is my logic. First, I want to be able to consume a list (as I interpret it - -!), So the structure of the grammar is really important. And I also think about using a list of Vars variables in the forms [[Name, Value], [a, 1], [b, 2] ...] and the updated version - "_Vars". Therefore, I can pass it to other operators, for example, in a loop and write.

 statement(Vars,Vars2) --> statement(Vars,Vars1), statement(Vars1,Vars2). % this seems wrong... 

But ... It seems that from the very beginning the logic is wrong.: \ Below is a simplified version. I would really appreciate it if you can help me here. And I really hope that I will not take this with me on Christmas Day. TT

 statement --> assign. statement --> statement, statement. assign --> simple_assign. assign --> default_assign. default_assign --> var_name(Var_Name). simple_assign --> var_name,[=],var_value. var_name --> [Var_Name],{\+number(Var_Name)}. var_value --> [Var_Value],{number(Var_Value)}. 
+6
source share
2 answers

Here's how I do it:

  • converts source code to abstract syntax tree

     begin a := 1 while a < 5 begin a := a + 1; end end 

    becomes

     statements([ assign(a, number(1)), while(greater(variable(a), number(5))), statements([ assign(a, plus(variable(a), number(1))) ]) ) ]) 
  • build an interpreter for it.

    There are various translators. The easiest is a vanilla translator. Here I will start with:

     interpret(number(N), State, N, State). interpret(assign(Variable, Statement), State, Value, NewState) :- interpret(Statement, State, Value, NewState1), assignVariable(Variable, Value, NewState1, NewState). 
+2
source

Your code seems appropriate, only some typos around leading to singleons, which are likely to harm your work.

There are + 2 singletones in simple_assign (Var_Name2 and Var_Value) and + Var_Name2 is a singleton in var_name

I think you are not using an IDE with suitable syntax highlighting ...

edit single loners, I have to say that the user's response is more useful than mine (+1). Trying to provide a mutable environment while parsing does not work. Here's how I tested, with a slightly different version of your grammar:

 test :- phrase(statement(S), [begin,a,:=,10,while,a,>,5,begin,write,a,a,:=,a,-,1,end,end]), eval(S, [], _). % grammar statement(Var := Expr) --> var(Var), [:=], expr(Expr). statement(write(E)) --> [write], expr(E). statement(while(C, S)) --> [while], condition(C), statement(S). statement(S) --> [begin], statements(S), [end]. statements([S|R]) --> statement(S), statements(R). statements([]) --> []. condition(L > R) --> expr(L), [>], expr(R). expr(L - R) --> (var(L) ; num(L)), [-], expr(R). expr(E) --> (var(E) ; num(E)). var(var(V)) --> [V], {atom(V)}. num(num(N)) --> [N], {number(N)}. % evaluation eval([S|R], Vs, Us) :- eval(S, Vs, V1), eval(R, V1, Us). eval([], Vs, Vs). eval(V := E, Vs, Us) :- exprv(E, Vs, Ve), ( select(V := _, Vs, R) -> Us = [V := Ve | R] ; Us = [V := Ve | Vs] ). eval(write(E), Vs, Vs) :- exprv(E, Vs, Ve), writeln(Ve). eval(while(C, S), Vs, Ts) :- satisfied(C, Vs) -> eval(S, Vs, Us), eval(while(C, S), Us, Ts) ; Vs = Ts. % no side effect here exprv(LE, Vs, Ve) :- exprv(L, Vs, Vl), exprv(E, Vs, R), Ve is Vl - R. exprv(num(N), _, N). exprv(var(V), Vs, Vv) :- memberchk(var(V) := Vv, Vs). satisfied(L > R, Vs) :- exprv(L, Vs, Vl), exprv(R, Vs, Vr), Vl > Vr. 
+2
source

All Articles