2013-12-17 12 views
6

私はプロローグを初めて使ったので、これは私にとって大きな課題です。 私はPrologのような単純なC言語を実装することになっています。は、PrologでシンプルなC言語を実装していますか?

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

ここに私の論理があります。まず、リストを使うことができるようにしたいのです(それは私がどのように解釈するかです!)ので、文法構造は本当に重要です。 また、[[名前、値]、[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のようなものですか?これはパスカルのようにひどく見えます:) –

+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

この構造体は、OPの質問で使用されているように、DCGによって既に暗黙的に処理されています。 – CapelliC

+0

私が直面している問題は、再帰パターンと変数リストの更新と渡しです。とにかくありがとう。抽象構文木の種類リングの鐘。 – Hashbug

+0

私は、あなたが 'repeat'を使用して変数をバインドしたりアンバインドしたりすることで、再帰を回避することができると思います。あるいは、すべてのステートのリストを、' 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

関連する問題