[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