
%% This file contains a set of predicates used for 
%% reading user input at terminal, such as commands, 
%% selection numbers etc. However, these predicates 
%% just read strings of chars/digits, don't actually 
%% determine what specific command given. (That task 
%% handled by predicates in file: read_commands.) 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% get_alphanum_strings:
% returns input upto carriage return or fullstop,
% as a list of lists of one-char atoms, where each
% sublist corresponds to a continuous sequence of
% alphanumeric chars (i.e. a `word'). 
%
% e.g. with input: the 10 men
% would return X = [[t,h,e],[1,0],[m,e,n]]
%

get_alphanum_strings(X):- 
   get_char_strings(Y),   % get input as ASCII codes
   name_list(X,Y).        % convert to one-char atoms

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% get_char_strings/1 :
% Just like get_alphanum_strings, except returns 
% input as list of lists of ASCII codes. 

get_char_strings(Ss):-
     get0(C),                    % get first char
     get_char_strings(C,Ss), !.  % main predicate
get_char_strings([]):- 
     nl,                         % failure case
     write(': ** Unrecognised character **'), nl.  

get_char_strings(C,[S|Ss]):-
     char(C), !,              % if first char is alphanumeric,
     char_string(C,S,C1),     % get next `word',
     get_char_strings(C1,Ss). % then recurse 
get_char_strings(C,Ss):-
     space(C), !,             % next char a space, ignore it, 
     get0(C1),                % Get new next char,
     get_char_strings(C1,Ss). % then recurse 
get_char_strings(C,[]):-
     endline(C),  !.          % nextchar <CR>, stop. 
get_char_strings(C,[]):-
     fullstop(C),  !,         % nextchar fullstop, 
     clear_rest_line(C).      % flush rest line, and stop. 
get_char_strings(C,[]):-
     !,                       % failure catch-all:
     clear_rest_line(C),      % flush input line, and fail. 
     fail.  

clear_rest_line(C):-         % flush out rest of input
     endline(C).             % upto newline
clear_rest_line(C):- 
     \+(endline(C)), 
     get0(C1), 
     clear_rest_line(C1).

char_string(C,[C|Cs],C0):-   % gets next `word', i.e.  
     char(C),!,              % continuous sequence of 
     get0(C1),               % alphanumeric chars
     char_string(C1,Cs,C0).
char_string(C,[],C):-
     \+ (char(C)).


% test predicates for alphanumeric chars, etc.

char(C):- (97 =< C, C =< 122) ; % lowercase alphabetic
          (65 =< C, C =< 90)  ; % uppercase alphabetic
          (C = 95)            ; % underscore
          (48 =< C, C =< 57).   % numerical
	  
space(32).
endline(13).  %%m
endline(10).  %%u
fullstop(46). %%u

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Read a string of digits from input. 
% E.g. with input: 12 45
% returns Ns = [1,2,4,5]

read_digits(Ns):-
   get_char_strings(As), 
   appendn(As,Bs), 
   name_list(Ns,Bs), 
   digit_string(Ns), !. 
read_digits([]):-
   nl, write(': ** Non-digit char **'). 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Reads a list of numbers (posints) from input. 
% E.g. with input: 12 45
% returns Ns = [12,45]

read_numbers(Ns):-
   get_alphanum_strings(As),
   digit_strings_to_numbers(As,Ns), !. 
read_numbers([]):- 
   nl, write(': ** Non-digit char **'). 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Reads a single number (posint) from input. 

read_number(N):- read_numbers([N]). 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Converts a list of lists of digits to a list of 
% numbers.
% E.g.  [[1,2],[3,4]]   becomes  [12,34] 

digit_strings_to_numbers([],[]). 
digit_strings_to_numbers([D|Ds],[N|Ns]):- 
   digits_to_number(D,N), 
   digit_strings_to_numbers(Ds,Ns). 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

digit_string([]).         % succeeds if argument is 
digit_string([D|Ds]):-    % a list of digits. 
   number(D),             % e.g.   [2,5,0,1]
   0 =< D, D =< 9, 
   digit_string(Ds). 

digit_strings(Xs):-      % succeeds if argument is a  
   appendn(Xs,Ys),       % list of lists of digits.
   digit_string(Ys).     % e.g.   [[2,5],[0,1],[7]]

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Converts list of digits (Arg 1) to corresponding
% decimal number (Arg 2). 
% e.g.  [1,4,6]   ->  146

digits_to_number(Ds,N):- 
    digit_string(Ds), 
    digits_to_number(Ds,N,_). 

% digits_to_number/3:

digits_to_number([X|Xs],N,V1):-
    digits_to_number(Xs,M,V), 
    V1 is 10 * V, 
    N is M + (V * X).
digits_to_number([],0,1).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
