From 46b21dcb76d1df68222e2cf7c1a96ac6077450c4 Mon Sep 17 00:00:00 2001 From: grammarware Date: Mon, 9 Nov 2009 09:46:45 +0000 Subject: [PATCH] reference solutions git-svn-id: https://slps.svn.sourceforge.net/svnroot/slps@703 ab42f6e0-554d-0410-b580-99e487e6eeb2 --- topics/exercises/while2/Makefile | 9 ++ topics/exercises/while2/Parser.pro | 142 ++++++++++++++++++++++++++ topics/exercises/while2/RunParser.pro | 17 +++ topics/exercises/while2/input.txt | 7 ++ topics/exercises/while3/Parser.pro | 60 +++++++++-- topics/exercises/xml2/Makefile | 12 +++ topics/exercises/xml2/Parser.pro | 66 ++++++++++++ topics/exercises/xml2/RunParser.pro | 19 ++++ topics/exercises/xml2/bad.txt | 4 + topics/exercises/xml2/input.txt | 4 + 10 files changed, 332 insertions(+), 8 deletions(-) create mode 100644 topics/exercises/while2/Makefile create mode 100644 topics/exercises/while2/Parser.pro create mode 100644 topics/exercises/while2/RunParser.pro create mode 100644 topics/exercises/while2/input.txt create mode 100644 topics/exercises/xml2/Makefile create mode 100644 topics/exercises/xml2/Parser.pro create mode 100644 topics/exercises/xml2/RunParser.pro create mode 100644 topics/exercises/xml2/bad.txt create mode 100644 topics/exercises/xml2/input.txt diff --git a/topics/exercises/while2/Makefile b/topics/exercises/while2/Makefile new file mode 100644 index 00000000..010dfcf3 --- /dev/null +++ b/topics/exercises/while2/Makefile @@ -0,0 +1,9 @@ +test: + swipl -f RunParser.pro -t "main('input.txt')" + +debug: + cat input.txt + swipl -s Parser.pro + +clean: + rm -rf *~ diff --git a/topics/exercises/while2/Parser.pro b/topics/exercises/while2/Parser.pro new file mode 100644 index 00000000..85b99d4c --- /dev/null +++ b/topics/exercises/while2/Parser.pro @@ -0,0 +1,142 @@ +%% Parser for While language +% 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). + +% Loop statement +statement(while(E,S)) --> + keyword("while"), + bexpression(E), + keyword("do"), + statement(S). + + +%% Arithmetic 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(")"). + +% Same with subtraction +aexpression(sub(E1,E2)) --> + keyword("("), + aexpression(E1), + keyword("-"), + aexpression(E2), + keyword(")"). + +% ...and multiplication +aexpression(mul(E1,E2)) --> + keyword("("), + aexpression(E1), + keyword("*"), + aexpression(E2), + keyword(")"). + + +%% Boolean expressions +% 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). + +% Negation is a boolean expression +bexpression(not(E)) --> + keyword("¬"), + bexpression(E). + +% Disjunction of boolean expressions is also a boolean expression +bexpression(and(E1,E2)) --> + keyword("("), + bexpression(E1), + keyword("^"), + bexpression(E2), + keyword(")"). + + +%% Low-level details +% Dealing with layout +layout --> [0' ], layout. %' space +layout --> [0' ], layout. %' tab +layout --> [10], layout. % newline +layout --> []. + +% Keywords are space-consuming strings +keyword(X) --> + layout, + string(X). + +% Bare strings +string([],X,X). +string([H|T1],[H|T2],X) :- string(T1,T2,X). + +% Numbers are space-consuming digits +number(N) --> + layout, + 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) --> + layout, + 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/while2/RunParser.pro b/topics/exercises/while2/RunParser.pro new file mode 100644 index 00000000..93e8593a --- /dev/null +++ b/topics/exercises/while2/RunParser.pro @@ -0,0 +1,17 @@ +:- ['Parser.pro']. + +main(File) :- + parseFile(File,program,S), + write(S),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/while2/input.txt b/topics/exercises/while2/input.txt new file mode 100644 index 00000000..02f7e55c --- /dev/null +++ b/topics/exercises/while2/input.txt @@ -0,0 +1,7 @@ +if ¬x ≤ 0 + then + y:=((2+x)-y) + else + while z=0 do + z:=2; +skip diff --git a/topics/exercises/while3/Parser.pro b/topics/exercises/while3/Parser.pro index 8e916391..85b99d4c 100644 --- a/topics/exercises/while3/Parser.pro +++ b/topics/exercises/while3/Parser.pro @@ -1,3 +1,4 @@ +%% Parser for While language % Program is a list of statements program(S) --> statements(S). @@ -10,7 +11,7 @@ statements(slist(H,T)) --> % Empty list statements(S) --> statement(S). -% Statements +%% Statements % Skip statement statement(skip) --> keyword("skip"). @@ -30,7 +31,15 @@ statement(ifthenelse(E,S1,S2)) --> keyword("else"), statement(S2). -% Expressions +% Loop statement +statement(while(E,S)) --> + keyword("while"), + bexpression(E), + keyword("do"), + statement(S). + + +%% Arithmetic expressions % Number is a an arithmetic expression aexpression(number(N)) --> number(N). @@ -45,6 +54,24 @@ aexpression(add(E1,E2)) --> aexpression(E2), keyword(")"). +% Same with subtraction +aexpression(sub(E1,E2)) --> + keyword("("), + aexpression(E1), + keyword("-"), + aexpression(E2), + keyword(")"). + +% ...and multiplication +aexpression(mul(E1,E2)) --> + keyword("("), + aexpression(E1), + keyword("*"), + aexpression(E2), + keyword(")"). + + +%% Boolean expressions % Boolean primitives are boolean expressions bexpression(true) --> keyword("true"). bexpression(false) --> keyword("false"). @@ -61,13 +88,30 @@ bexpression(lte(E1,E2)) --> keyword("≤"), aexpression(E2). -% Dealing with spaces -spaces --> [0' ], spaces. %' -spaces --> []. +% Negation is a boolean expression +bexpression(not(E)) --> + keyword("¬"), + bexpression(E). + +% Disjunction of boolean expressions is also a boolean expression +bexpression(and(E1,E2)) --> + keyword("("), + bexpression(E1), + keyword("^"), + bexpression(E2), + keyword(")"). + + +%% Low-level details +% Dealing with layout +layout --> [0' ], layout. %' space +layout --> [0' ], layout. %' tab +layout --> [10], layout. % newline +layout --> []. % Keywords are space-consuming strings keyword(X) --> - spaces, + layout, string(X). % Bare strings @@ -76,7 +120,7 @@ string([H|T1],[H|T2],X) :- string(T1,T2,X). % Numbers are space-consuming digits number(N) --> - spaces, + layout, digit(H), digits(T), { number_chars(N,[H|T]) }. @@ -87,7 +131,7 @@ digit(H,[H|T],T) :- H >= 0'0, H =< 0'9. % Identifiers are space-consuming letters identifier(V) --> - spaces, + layout, letter(H), letters(T), { atom_chars(V,[H|T]) }. diff --git a/topics/exercises/xml2/Makefile b/topics/exercises/xml2/Makefile new file mode 100644 index 00000000..f622b2cc --- /dev/null +++ b/topics/exercises/xml2/Makefile @@ -0,0 +1,12 @@ +test: + swipl -f RunParser.pro -t "main('input.txt')" + +fail: + swipl -f RunParser.pro -t "main('bad.txt')" + +debug: + cat input.txt + swipl -s Parser.pro + +clean: + rm -rf *~ diff --git a/topics/exercises/xml2/Parser.pro b/topics/exercises/xml2/Parser.pro new file mode 100644 index 00000000..6ad16895 --- /dev/null +++ b/topics/exercises/xml2/Parser.pro @@ -0,0 +1,66 @@ +% A root tree is a regular tree with an opening and closing tags and a forest in between +tree(tree(N,AL,TL)) --> + layout, + string("<"), + name(N), + attrs(AL,_), + string(">"), + trees(TL), + string(""), + layout. + +% A non-empty forest +trees([H|T]) --> + tree(H), + trees(T). + +% An empty forest +trees([]) --> []. + +% Attribute list +attrs([H|T],[N|U]) --> + layout, + attr(H), + attrs(T,U), + { + H = [N,_], + not(member(N,U)) + }. +attrs([],[]) --> []. + +% Attribute +attr([N,V]) --> + name(N), + string("="), + value(V). + +% Bare strings +string([],X,X). +string([H|T1],[H|T2],X) :- string(T1,T2,X). + +% Consuming spaces +layout --> [0' ], layout. % space ' +layout --> [0' ], layout. % tab ' +layout --> [10], layout. % newline +layout --> []. + +% Only lowcased tag names are allowed +name(N) --> + letter(H), letters(T), + { atom_codes(N,[H|T]) }. + +% Bare letters +letters([H|T]) --> letter(H), letters(T). +letters([]) --> []. +letter(H,[H|T],T) :- H >= 0'a, H =< 0'z. + +value(V) --> + char(H), chars(T), + { atom_codes(V,[H|T]) }. + +chars([H|T]) --> char(H), chars(T). +chars([]) --> []. +char(H,[H|T],T) :- H >= 0'a, H =< 0'z. +char(H,[H|T],T) :- H >= 0'0, H =< 0'9. diff --git a/topics/exercises/xml2/RunParser.pro b/topics/exercises/xml2/RunParser.pro new file mode 100644 index 00000000..96dbf54c --- /dev/null +++ b/topics/exercises/xml2/RunParser.pro @@ -0,0 +1,19 @@ +:- ['Parser.pro']. + +main(File) + :- + parseFile(File,tree,S), + write(S), 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/xml2/bad.txt b/topics/exercises/xml2/bad.txt new file mode 100644 index 00000000..c35061b8 --- /dev/null +++ b/topics/exercises/xml2/bad.txt @@ -0,0 +1,4 @@ + + + + diff --git a/topics/exercises/xml2/input.txt b/topics/exercises/xml2/input.txt new file mode 100644 index 00000000..75c2eae5 --- /dev/null +++ b/topics/exercises/xml2/input.txt @@ -0,0 +1,4 @@ + + + +