[m-rev.] EDCG example
Peter Nicholas MALKIN
pnmalk at students.cs.mu.oz.au
Thu Mar 15 19:32:32 AEDT 2001
Hi,
To illustrate using EDCGs I have converted the file calculator.m in the
samples directory to use EDCGs.
Here it is:
% A simpler calculator - parses and evaluates integer expressions.
% This example uses EDCGs and is based upon the calculator example in the
% samples directory that does not use EDCGs.
:- module calculator.
:- interface.
:- import_module io.
:- pred main(io__state::di, io__state::uo) is det.
:- implementation.
:- import_module list, char, int, string.
:- etype(char_list, list(char)).
:- emode(char_list, changed(in, out)).
:- type expr
---> number(int)
; plus(expr, expr)
; minus(expr, expr)
; times(expr, expr)
; div(expr, expr).
main -->
io__read_line(Res),
( { Res = error(_) },
io__write_string("Error reading from stdin\n")
; { Res = eof },
io__write_string("EOF\n")
; { Res = ok(Line) },
( { fullexpr(X, Line, []) } ->
{ evalexpr(X, Num) },
io__write_int(Num),
io__write_string("\n")
;
io__write_string("Syntax error\n")
),
main % recursively call ourself for the next line(s)
).
:- pred evalexpr(expr::in, int::out) is det.
evalexpr(number(Num), Num).
evalexpr(plus(X,Y), Z) :- evalexpr(X,A), evalexpr(Y,B), Z is A + B.
evalexpr(minus(X,Y), Z) :- evalexpr(X,A), evalexpr(Y,B), Z is A - B.
evalexpr(times(X,Y), Z) :- evalexpr(X,A), evalexpr(Y,B), Z is A * B.
evalexpr(div(X,Y), Z) :- evalexpr(X,A), evalexpr(Y,B), Z is A // B.
:- pred fullexpr(expr::out, list(character)::in, list(character)::out)
is semidet.
fullexpr(X, CharListIn, CharListOut) :-
expr(X)+edcg(char_list(CharListIn, ['\n'|CharListOut])).
:- pred expr(expr::out) +edcg(changed(char_list)) is semidet.
expr(Expr) -->>
factor(Factor),
expr2(Factor, Expr).
:- pred expr2(expr::in, expr::out) +edcg(changed(char_list)) is semidet.
expr2(Factor, Expr) -->>
(
$char_list = ['+'|$=char_list]
->
factor(Factor2),
expr2(plus( Factor, Factor2), Expr)
;
$char_list = ['-'|$=char_list]
->
factor(Factor2),
expr2(minus(Factor, Factor2), Expr)
;
Expr = Factor
).
:- pred factor(expr::out) +edcg(changed(char_list)) is semidet.
factor(Factor) -->>
term(Term),
factor2(Term, Factor).
:- pred factor2(expr::in, expr::out) +edcg(changed(char_list))
is semidet.
factor2(Term, Factor) -->>
(
$char_list = ['*'|$=char_list]
->
term(Term2),
factor2(times(Term,Term2), Factor)
;
$char_list = ['/'|$=char_list]
->
term(Term2),
factor2(div(Term,Term2), Factor)
;
Factor = Term
).
:- pred term(expr::out) +edcg(changed(char_list)) is semidet.
term(Term) -->>
(
const(Const)
->
string__from_char_list(Const, ConstString),
string__to_int(ConstString, Num),
Term = number(Num)
;
$char_list = ['('|$=char_list],
expr(Term),
$char_list = [')'|$=char_list]
).
:- pred const(list(character)::out) +edcg(changed(char_list)) is semidet.
const([Digit|Rest]) -->>
digit(Digit),
(
const(Const)
->
Rest = Const
;
Rest = []
).
:- pred digit(character::out) +edcg(changed(char_list)) is semidet.
digit(Char) -->>
$char_list = [Char|$=char_list],
char__is_digit(Char).
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list