% num1.pl

% this file is a simple recongizer. see num2.pl
% for an example of processing the string as we go

% standard demo predicate.
% ignore(X) ensures that we always get to the told
% (i.e. no open files left hanging)

demo :- tell('num1.out'), ignore(demo1), told.

% a failure drive loop- results not accessible
% after loop quicks except via global asserts.

demo1 :- demo2, fail.
demo1.

% note also that demo/1 can be tested and debugged
% without wasting disc space with disc I/O.

demo2 :-
	member(X,["23", " 23", "23.3 "]),
	% when calling a DCG parser, often best
	% to say the parse ends here; i.e. the
	% resulting list is the empty list
	num(X,[]),
	print(num(X)),
	nl.

space --> " ". % same as space --> [32].
tabb  --> [9].
dot   --> ".".
zero  --> "0".
one   --> "1".
two   --> "2".
three --> "3".
four  --> "4".
five  --> "5".
six   --> "6".
seven --> "7".
eight --> "8".
nine  --> "9".

% "|" is the same as ";" i.e. "or"
blank --> space
        | tabb. % can't use "tab" since that is a
                % standard prolog predicate. 
                % problem: single global name space
                % solution: 1) modules (non-portable)
                %           2) my accessor system

whitespace --> []
            | blank, whitespace.

digit --> one | two | three | four
        | five | six | seven | eight | nine | zero.

% problem: wasted computation- digit can get parsed twice.
% solution: 1) memoing- oldt resolution- non-standard prolog
%           2) dont write big parsers this way- use
%              operators and let the prolog reader
%              work it all out for you
digits --> digit
        |  digit, digits.

num1 --> digits
        | digits, dot, digits.

num --> whitespace,num1,whitespace.

% note the neat declarative nature of the above