diff --git a/topics/exercises/while3/Makefile b/topics/exercises/while3/Makefile new file mode 100644 index 00000000..7cba8acc --- /dev/null +++ b/topics/exercises/while3/Makefile @@ -0,0 +1,9 @@ +test: + swipl -f RunEvaluator.pro -t "main('input.txt')" + +debug: + cat input.txt + swipl -s RunEvaluator.pro + +clean: + rm -rf *~ diff --git a/topics/exercises/while3/Parser.pro b/topics/exercises/while3/Parser.pro new file mode 100644 index 00000000..8e916391 --- /dev/null +++ b/topics/exercises/while3/Parser.pro @@ -0,0 +1,98 @@ +% Program is a list of statements +program(S) --> statements(S). + +% Non-empty list +statements(slist(H,T)) --> + statement(H), + keyword(";"), + statements(T). + +% Empty list +statements(S) --> statement(S). + +% Statements +% Skip statement +statement(skip) --> + keyword("skip"). + +% Assign statement +statement(assign(identifier(V),E)) --> + identifier(V), + keyword(":="), + aexpression(E). + +% Conditional statement +statement(ifthenelse(E,S1,S2)) --> + keyword("if"), + bexpression(E), + keyword("then"), + statement(S1), + keyword("else"), + statement(S2). + +% Expressions +% Number is a an arithmetic expression +aexpression(number(N)) --> number(N). + +% Variable reference is a an arithmetic expression +aexpression(identifier(V)) --> identifier(V). + +% A sum of arithmetic expressions is also an arithmetic expression +aexpression(add(E1,E2)) --> + keyword("("), + aexpression(E1), + keyword("+"), + aexpression(E2), + keyword(")"). + +% Boolean primitives are boolean expressions +bexpression(true) --> keyword("true"). +bexpression(false) --> keyword("false"). + +% Comparison is a boolean expression: equality +bexpression(equals(E1,E2)) --> + aexpression(E1), + keyword("="), + aexpression(E2). + +% Comparison is a boolean expression: less than or equal to +bexpression(lte(E1,E2)) --> + aexpression(E1), + keyword("≤"), + aexpression(E2). + +% Dealing with spaces +spaces --> [0' ], spaces. %' +spaces --> []. + +% Keywords are space-consuming strings +keyword(X) --> + spaces, + string(X). + +% Bare strings +string([],X,X). +string([H|T1],[H|T2],X) :- string(T1,T2,X). + +% Numbers are space-consuming digits +number(N) --> + spaces, + digit(H), digits(T), + { number_chars(N,[H|T]) }. + +% Bare digits +digits([H|T]) --> digit(H), digits(T). +digits([]) --> []. +digit(H,[H|T],T) :- H >= 0'0, H =< 0'9. + +% Identifiers are space-consuming letters +identifier(V) --> + spaces, + letter(H), letters(T), + { atom_chars(V,[H|T]) }. + +% Bare letters +letters([H|T]) --> letter(H), letters(T). +letters([]) --> []. +letter(H,[H|T],T) :- H >= 0'a, H =< 0'z. + diff --git a/topics/exercises/while3/RunEvaluator.pro b/topics/exercises/while3/RunEvaluator.pro new file mode 100644 index 00000000..9c6b06e0 --- /dev/null +++ b/topics/exercises/while3/RunEvaluator.pro @@ -0,0 +1,19 @@ +:- ['Parser.pro','mappings.pro','compExpr.pro','bigStm.pro']. + +main(File) :- + parseFile(File,program,S), + write(S),nl,nl, + execute(S,[],M), + write(M),nl. + +parseFile(File,P,R) :- + open(File,read,Stream,[]), + read_stream_to_codes(Stream, Contents), + close(Stream), + apply(P,[R,Contents,Rest]), + eof(Rest,_). + +eof([],[]). +eof([0' |T],R) :- eof(T,R). %' +eof([10|T],R) :- eof(T,R). + diff --git a/topics/exercises/while3/bigStm.pro b/topics/exercises/while3/bigStm.pro index 7fdefad9..aa40bf0e 100644 --- a/topics/exercises/while3/bigStm.pro +++ b/topics/exercises/while3/bigStm.pro @@ -2,5 +2,22 @@ execute(skip,M,M). -execute(assign(X,A),M1,M2) :- evala(A,M1,Y), update(M1,X,Y,M2). +execute(slist(S1,S2),M1,M3) :- + execute(S1,M1,M2), + execute(S2,M2,M3). + +execute(assign(identifier(X),A),M1,M2) :- + evala(A,M1,Y), + update(M1,X,Y,M2). + +execute(ifthenelse(B,S1,S2),M1,M2) :- + evalb(B,M1,X), + ( + X == tt, + execute(S1,M1,M2) + ; + X == ff, + execute(S2,M1,M2) + ). + diff --git a/topics/exercises/while3/compExpr.pro b/topics/exercises/while3/compExpr.pro index 5e98f794..8488b606 100644 --- a/topics/exercises/while3/compExpr.pro +++ b/topics/exercises/while3/compExpr.pro @@ -1,23 +1,59 @@ -% Evaluate Boolean expressions +%% Evaluate arithmetic expressions -evalb(true,_,tt). +% Number is evaluated to its value +evala(number(V),_,V). -evalb(false,_,ff). +% Variable reference is evaluated to its current value +evala(identifier(X),M,Y) :- lookup(M,X,Y). -evalb(equal(A1,A2),M,V) :- +% Adddition +evala(add(A1,A2),M,V) :- evala(A1,M,V1), evala(A2,M,V2), - equal(V1,V2,V). + V is V1 + V2. +% Subtraction +evala(sub(A1,A2),M,V) :- + evala(A1,M,V1), + evala(A2,M,V2), + V is V1 - V2. -% Evaluate arithmetic expressions +% Multiplication +evala(mul(A1,A2),M,V) :- + evala(A1,M,V1), + evala(A2,M,V2), + V is V1 * V2. -evala(const(V),_,V). +%% Evaluate Boolean expressions -evala(var(X),M,Y) :- lookup(M,X,Y). +% True is tt +evalb(true,_,tt). +% False is ff +evalb(false,_,ff). + +% Negation +evalb(not(B),M,V) :- + evalb(B,M,V1), + not(V1,V). + +% Test for equality +evalb(equals(A1,A2),M,V) :- + evala(A1,M,V1), + evala(A2,M,V2), + equals(V1,V2,V). + +% Test for equality +evalb(lte(A1,A2),M,V) :- + evala(A1,M,V1), + evala(A2,M,V2), + lte(V1,V2,V). -% Basic operations +%% Basic operations +equals(V1,V2,tt) :- V1 == V2. +equals(V1,V2,ff) :- \+ V1 == V2. +lte(V1,V2,tt) :- V1 =< V2. +lte(V1,V2,ff) :- \+ V1 =< V2. +not(tt,ff). +not(ff,tt). -equal(V1,V2,tt) :- V1 == V2. -equal(V1,V2,ff) :- \+ V1 == V2. diff --git a/topics/exercises/while3/input.txt b/topics/exercises/while3/input.txt new file mode 100644 index 00000000..cf536f71 --- /dev/null +++ b/topics/exercises/while3/input.txt @@ -0,0 +1 @@ +y:=2; if y = 3 then z := y else z := 1000