2013-12-17 2 views
6

Я новичок в прологе, так что это довольно сложный вопрос для меня. Я должен реализовать простой C-подобный язык в Prolog.реализовать простой C-подобный язык в 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 

Однако я застрял на первом шаге. Это то, что я достиг до сих пор. из локального стека!

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). 

Вот моя логика. Сначала я хочу, чтобы иметь возможность потреблять список (вот как я его интерпретирую - -!), Поэтому структура грамматики действительно важна. И я также думаю об использовании списка переменных Vars в формах [[Name, Value], [a, 1], [b, 2] ...] и обновленной версии - «_Vars». Поэтому я могу передать его другим операторам, таким как цикл и запись.

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

Но ... Похоже, что логика ошибочна с самого начала. : \ ниже - упрощенная версия. Я бы очень признателен, если вы можете помочь мне здесь. И я очень надеюсь, что я не возьму это со мной в Рождество. 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)}. 
+3

C-like, вы уверены? Это выглядит ужасно, как Pascal :) –

+3

Это интересное упражнение, в отличие от всего, что я видел. – hardmath

+0

Ха-ха. Я буду держать этот пост обновленным. – Hashbug

ответ

2

Это, как я бы об этом:

  1. преобразования исходного кода в абстрактном синтаксическом дереве

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

    становится

    statements([ 
        assign(a, number(1)), 
        while(greater(variable(a), number(5))), 
          statements([ 
           assign(a, plus(variable(a), number(1))) 
            ]) 
         ) 
          ]) 
    
  2. сборки переводчик для Это.

    Существуют различные переводчики. Самый простой - это переводчик ванили. Вот один я бы начал с:

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

Эта структура уже неявно обрабатывается DCG, как используется в вопросе OP. – CapelliC

+0

Проблема, с которой я сейчас сталкиваюсь, - это шаблон рекурсии, а также обновление и передача списка переменных. Но все равно спасибо. абстрактное синтаксическое дерево рода колец колокол. – Hashbug

+0

Я думаю, что вы можете обойти рекурсию, используя «повторить», связать и развязать переменные или использовать список всех состояний с несвязанной переменной в конце, который специализирован для каждого повтора ИЛИ, используя 'assert' и' retract'. – User

2

Ваш код представляется целесообразным, лишь некоторая опечатка вокруг, в результате чего одиночек, что, вероятно, вред разумности вашей попытки.

Есть + 2 одиночек в simple_assign (Var_Name2 и Var_Value) и + Var_Name2 является синглтон в var_name

Я предполагаю, что вы не используете и IDE с правильной подсветкой синтаксиса ...

Редактировать одиночные игры, я должен сказать, что ответ пользователя более полезен, чем мой (+1). Попытка предоставить изменяемую среду в то время как синтаксический разбор не работает. Вот как я протестировал, с несколько иной версией вашей грамматики:

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(L-E, 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

... и игнорирование предупреждений компилятора .... –

+1

спасибо, ребята. Я использую текстовое сопряжение с прокси-синтаксисом. Я стараюсь игнорировать синглтоны. – Hashbug

+0

@Hashbug Вы не должны игнорировать синглтоны, так как они могут указывать на ошибку. – lurker

Смежные вопросы