[net.sources] Prolog library: rdtok.pl

pereira@sri-unix.UUCP (08/15/83)

%   File: RdTok         Author: R.A.O'Keefe         Updated: 18 November 82
 
/*  This file is an interface to the Prolog system routine $read_tokens.
    For some reason which I agreed to at the time but now forget, the
    tokeniser is only accessible from compiled code.  Now that the plsys(_)
    mask exists for nasty internal things, it could really go there.
    However, the structures returned by the tokeniser are unpleasant enough
    that an extra interface is worth having.
 
        read_tokens(TokenList, VarList)
 
    returns a list of Tokens and a list of Variables, where the elements
    of the VarList have the form Atom=Variable.  For example, reading
    the term above might result in ['TokenList'=_1, 'VarList'=_2].  The
    elements of the TokenList take the form
        var(Var,Name)   -- the name is retained for error messages
        integer(Int)    -- 18-bit integers or xwd(_,_) pairs
        atom(Name)      -- most atoms
        string(ChList)  -- for string constants "..."
        Punct           -- for special punctuation ( ) [ ] { } , |
*/
 
:- public
        read_tokens/2.
 
:-  mode
%       clean_neg(+, +, -),
        clean_pos(+, +, -),
        clean_tok_list(+, -),
        clean_var_list(+, -),
        read_tokens(-, -),
        sixbit_to_ascii(+, -).
 
 
read_tokens(Toks, Vars) :-
        '$read_tokens'(RawToks, RawVars),
        clean_var_list(RawVars, Vars), !,
        clean_tok_list(RawToks, Toks).
 
clean_var_list([var(Name,Var,_)|Rest], [Atom=Var|More]) :-
        sixbit_to_ascii(Name, VarName),
        name(Atom, VarName), !,
        clean_var_list(Rest, More).
clean_var_list([], []).
 
sixbit_to_ascii([Three|Rest], Ascii) :-
        A is (Three>>12)/\63,
        B is (Three>> 6)/\63,
        C is (Three    )/\63,
        one_sixbit_char(A, Ascii, A1),
        one_sixbit_char(B, A1, A2),
        one_sixbit_char(C, A2, More), !,
        sixbit_to_ascii(Rest, More).
sixbit_to_ascii([], []).
 
one_sixbit_char(0, X, X) :- !.
one_sixbit_char(A, [H|T], T) :- A < 27, !, H is 96+A.
one_sixbit_char(63,[95|T], T) :- !.
one_sixbit_char(Z, [H|T], T) :- Z > 36, !, H is 28+Z.
one_sixbit_char(D, [H|T], T) :- H is 21+D.
 
%clean_tok_list([atom(-),xwd(Hi,Lo)|Rest], [integer(Int)|More]) :-
%       clean_neg(Hi, Lo, Int), !,
%       clean_tok_list(Rest, More).
clean_tok_list([xwd(Hi,Lo)|Rest], [integer(Int)|More]) :-
        clean_pos(Hi, Lo, Int), !,
        clean_tok_list(Rest, More).
clean_tok_list([var(Var,Name)|Rest], [var(Var,Atom)|More]) :-
        sixbit_to_ascii(Name, VarName),
        name(Atom, VarName), !,
        clean_tok_list(Rest, More).
clean_tok_list([Other|Rest], [Other|More]) :- !,
        clean_tok_list(Rest, More).
clean_tok_list([], []).
 
%   reading a negative number is complicated by the fact that the token
%   reader will accept 36-bit numbers.  Unfortunately, the interpreter
%   will not (X is xwd(_,_) truncates).  On the whole, the simplest
%   thing to do seems to be to represent the result as an integer where
%   we can, otherwise to represent it as xwd(-,-) or -xwd(-,-).  Then at
%   least eval(-,-) in LONG will do the right thing.
 
clean_pos(0,  N, N) :- !(N) =< 8'377777, !.
clean_pos(-1, N, N) :- !(N) >  8'377777, !.
clean_pos(Hi,Lo, xwd(Hi,Lo)).
 
%clean_neg(0,  N, M) :- !(N) =< 8'377777+1, !, M is -N.
%clean_neg(-1, N, M) :- !(N) >= 8'377777,   !, M is -N.
%clean_neg(Hi,Lo, -xwd(Hi,Lo)).