home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / lifeos2.zip / LIFE-1.02 / LIB / TOKENIZE.LF < prev    next >
Text File  |  1996-06-04  |  14KB  |  650 lines

  1. %    $Id: tokenizer.lf,v 1.2 1994/12/09 00:26:37 duchier Exp $    
  2. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3. %
  4. %                          TOKENIZER FOR LIFE
  5. %                             (in wild_life)
  6. %
  7. % This file contains a complete tokenizer for Life programs. The obtained
  8. % tokens are used as inputs by the life parser in life (see parser.lf)
  9. %
  10. % Tokens are of the following types:
  11. %    - variable(X) where X is the name of the variable; 
  12. %    - construct(X) represents a constructor X. 
  13. %      The type of a constructor is a subsort of construct: numb, chaine, or
  14. %      atom. X is the "value" of the atom (string, number, or unevaluated atom)
  15. %    - any syntactic object like "[" or "?", or defined by syntact_object(X)
  16. % The dot may be tokenized in three different ways, depending on the context in
  17. % which it appears:
  18. %   - It is not returned as a token if it occurs inside a floating point
  19. %     number;
  20. %   - It is returned as a syntactic object "." if it is followed by a void
  21. %     character (tab, nl, space, or end_of_file)
  22. %   - it is returned as atom(".") otherwise.
  23. %
  24. % The tokenizer is written as an attribute grammar, using the grammar
  25. % translator. It reads two characters in advance.
  26. %
  27. % Use of this file:
  28. %      tokenize(Filename) ? 
  29. % reads in  the file Filename and writes the obtained tokens in the file
  30. % Filename_toks. 
  31. %    
  32. % All the necessary files are automatically loaded if they are in the same
  33. % directory.  
  34. %
  35. %
  36. % Author: Bruno Dumant
  37. %
  38. % Copyright 1992 Digital Equipment Corporation
  39. % All Rights Reserved
  40. %
  41. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  42.  
  43. module("tokenizer") ?
  44.  
  45. public( atom,construct,numb,chaine,syntact_object,variable,
  46.     tokenize,first_token,rest_token,next_token,
  47.     rest_chars) ?
  48.  
  49.  
  50. %%% load utilities
  51.  
  52. import("accumulators") ?
  53.  
  54. %%% set the right function for handling terminals in the grammar.
  55.  
  56. set_C( token_C) ?
  57.  
  58.  
  59. %%% changed for efficiency
  60.  
  61. acc_info(dcg,Term, Xs, Ys, acc_pred => 'C'(Term,false,Xs,Ys),
  62.      in_name => 0, out_name => rest)?
  63.  
  64.  
  65. token_C([],true,Xs,Ys) -> succeed | Xs = Ys.
  66. token_C([],false,Xs,Ys) -> Xs = Ys.
  67.  
  68. token_C([A],true,Xs,Ys) ->  (`evalin(D) = Ys) | Xs = [A|D].
  69. token_C([A],false,Xs,Ys) -> (  Xs = [A|D], `evalin(D) = Ys ).
  70.  
  71. %%% Types.
  72.  
  73. non_strict(atom) ?
  74. atom <| construct.
  75. numb <| construct.
  76. chaine <| construct.
  77.  
  78. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  79. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  80. %
  81. % Grammar of the tokenizer.
  82. %
  83. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  84. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  85.  
  86. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  87. %
  88. % Main Predicates
  89. %
  90. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  91.  
  92. token(0 => []) :- !, fail.
  93. token(0 => W:[A|B], T, rest => R) :-
  94.     (
  95.         A >= 97 and A =< 122,!,
  96.         non_quoted_atom(SA,0 => W,rest => R),
  97.         cond(  
  98.                 is_syntactic(SA),
  99.             T = SA,
  100.             ( U = str2psi(SA,current_module), T = atom(U))
  101.         )
  102.     ;
  103.         A >= 65 and A=< 90,!,
  104.         variable(V, 0 => W,rest => R),
  105.         T = variable(str2psi(V))
  106.     ;
  107.         cond(   A >= 48 and A =< 57,
  108.                 ( 
  109.             number(N,0 => W,rest => R),
  110.             T = numb(N)
  111.             ),
  112.             str2psi(strcon("tk",int2str(A)))
  113.                    & @(T,0 => W,rest  => R)
  114.         )
  115.     ).
  116.  
  117.  
  118. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  119. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  120. %
  121. % First Character
  122. %
  123. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  124. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  125.  
  126. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  127. %
  128. % variables
  129. %
  130. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  131.  
  132. tk95(T) -->                                      % variables starting with _
  133.     [_],
  134.     var_chars(Y), 
  135.     {   
  136.             (
  137.         Y $== "",!,
  138.         T = atom(@)                     % _ is @
  139.         )                     
  140.     ;
  141.         T = variable(str2psi(strcon("_",Y)))
  142.     } .                  
  143.  
  144. variable(X) -->                                  % variables starting with
  145.     [Y],                                     % a capital letter
  146.     var_chars(Z), 
  147.     { X = strcon(chr(Y),Z) } .
  148.  
  149. var_chars(Z) -->
  150.     simple_atom_chars(Y),
  151.     (
  152.         primes(P),!,                         % variables may end with '
  153.         { Z = strcon(Y,P) }
  154.     ;
  155.         { Z = Y }
  156.     ).
  157.  
  158. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  159. %
  160. % syntactic objects
  161. %
  162. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  163.  
  164.  
  165. tk40( "(") --> [_] .
  166. tk41( ")") --> [_] .
  167. tk63( "?") --> [_] .
  168. tk123( "{") --> [_] .
  169. tk125( "}") --> [_] .
  170.  
  171.  
  172. %%% "." is a syntactic dot, or the special operator ".": the distinction is
  173. %%% done thanks to the following character.
  174.  
  175. tk46( ".",0 => [46])     -->                             %%% end of file
  176.     [_] , ! .
  177. %%%tk46( T,0 => [46,K|L]) -->                  % . is followed by space, tab,
  178. %%%                           % percent or newline.
  179. %%%    { cond(   has_feature(K,void_table),
  180. %%%                  T = ".",
  181. %%%          T = atom(".")
  182. %%%          )
  183. %%%    },
  184. %%%    [_] .
  185.  
  186. tk46( T,0 => [46,K|L]) -->
  187.     (   has_feature(K,void_table),!,
  188.         { T = "." },
  189.         [_]
  190.     ;
  191.         tk46bis(T)
  192.     ).
  193.  
  194. tk46bis(T) -->
  195.     [_],
  196.     op_atom_chars(Z),
  197.     {  
  198.             X = strcon(".",Z),
  199.         ( is_syntactic(X),!,
  200.           T = X
  201.         ;
  202.           U = str2psi(X,current_module),
  203.           T = atom(U)
  204.         )
  205.     } .
  206.  
  207. tk91(T) --> 
  208.     [_],
  209.     ( 
  210.         [124],!,
  211.         (
  212.         [93],!, { T = "[|]"}
  213.         ;
  214.             {T = "[|"}
  215.         )
  216.     ;
  217.         {T = "["}
  218.     ) .
  219.     
  220. tk93( "]") --> [_] .
  221.  
  222. %% special case: "|]"
  223.  
  224. tk124(T) -->
  225.     [_],
  226.     (
  227.         [93],!, { T = "|]"}
  228.     ;
  229.         op_atom_chars(Z),
  230.         {  
  231.             X = strcon("|",Z),
  232.         cond(   is_syntactic(X),
  233.                 T = X,
  234.             ( U = str2psi(X,current_module), T = atom(U))
  235.             )
  236.         } 
  237.     ) . 
  238.         
  239. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  240. %
  241. % constructors
  242. %
  243. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  244.  
  245.  
  246. %%% simple atoms
  247.        
  248. non_quoted_atom(X) --> 
  249.     [Y], 
  250.     simple_atom_chars(Z), 
  251.     { X = strcon(chr(Y),Z) } .
  252.  
  253. %%% quoted atoms
  254.  
  255. tk39(T) --> 
  256.     [_],
  257.         quoted_atom_end(X),
  258.     {  cond(   is_syntactic(X),
  259.                T = X,
  260.            ( U = str2psi(X,current_module), T = atom(U) )
  261.            )
  262.     } .
  263.  
  264.  
  265. %%% Numbers: it is necessary to read two characters in advance.
  266.  
  267. number(X, 0 => W, rest => R) :-
  268.     digits( V1, 0 => W, rest => R1),
  269.     (
  270.         R1 = [46,D|R2], 
  271.         digits(0 => [D|R2],V2,length => L2,rest => R3), 
  272.         R4 = evalin(R3),
  273.         Vint = V1 + V2 * 10^(-L2),
  274.         !
  275.     ;
  276.         Vint = V1,
  277.         R4 = R1
  278.  
  279.     ),
  280.     (
  281.         R4 = [{101;69}|R5],!,    %% e or E
  282.         exponent(E,0 => evalin(R5),rest=> R),
  283.         X = Vint * 10^(E)
  284.     ;
  285.         X = Vint, R4 = R
  286.     ).
  287.  
  288.  
  289. %%% Strings
  290.  
  291. tk34(chaine(X)) --> 
  292.     [_],
  293.         char_chaine_end(X) .
  294.  
  295. %%% op_atoms
  296.  
  297. gen_op_char_ass_pred_def(Char) :-
  298.     S = chr(Char),
  299.     str2psi(strcon("tk",int2str(Char))) = PredName,
  300.     Head = PredName & @(T),
  301.     (
  302.         Head --> 
  303.              [_],
  304.          op_atom_chars(Z),
  305.          {  
  306.              X = strcon(S,Z),
  307.              cond(   is_syntactic(X),
  308.                      T = X,
  309.                  ( U = str2psi(X,current_module), T = atom(U))
  310.              )
  311.          } 
  312.     ).
  313.     
  314. maprel(gen_op_char_ass_pred_def,
  315.        [33,35,36,37,38,42,43,45,47,58,60,61,62,92,94,126]) ?
  316.  
  317.  
  318. %%% special cases: @ , ; `
  319.  
  320. tk64( atom(@)) --> [_] .
  321. tk96( atom(`)) --> [_] .
  322. tk44( atom(,)) --> [_] .    
  323. tk59( atom(;)) --> [_] .
  324.  
  325. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  326. %
  327. % Other Characters
  328. %
  329. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  330.  
  331.  
  332. %%% void chars
  333.  
  334. void_chars -->                                  % space, tab, new line
  335.     [{9;10;32}],!,
  336.     void_chars .   
  337. void_chars -->                                  % comments
  338.     [37],!, 
  339.     comment_chars, 
  340.     void_chars .
  341. void_chars -->                                  % nested comments
  342.     nested_comments,
  343.     void_chars .
  344. void_chars --> [] .
  345.  
  346. comment_chars --> [10], ! .                     % a comment ends with a nl.
  347. comment_chars --> [X],!, comment_chars .
  348. comment_chars --> [] .                          % nothing left to read
  349.  
  350.  
  351. %%% nested_comments
  352.  
  353. nested_comments( 0 => [47,42|_]) -->
  354.     [_],[_],
  355.     end_nested_comments .
  356.  
  357. end_nested_comments( 0 => [42,47|_]) -->
  358.         [_],[_],! .
  359.  
  360. end_nested_comments -->
  361.     (
  362.         nested_comments
  363.     ;
  364.         [_]
  365.     ),
  366.     end_nested_comments .
  367.  
  368. %%% simple atom characters
  369.  
  370. simple_atom_chars(Z) --> 
  371.     simple_atom_char(X), !,
  372.     simple_atom_chars(Y), 
  373.     { Z = strcon(X,Y)} .
  374. simple_atom_chars("") --> [] .
  375.  
  376.  
  377. simple_atom_char(X, 0 => [Y|R1], rest => R2) :- 
  378. %%    Y >= 48 and Y =< 57        % chiffre
  379. %%     or Y >= 65 and Y =< 90        % majuscule
  380. %%     or Y =:= 95                   % underscore
  381. %%     or Y >= 97 and Y =< 122,      % minuscule 
  382. %%     R2 = evalin(R1),
  383. %%     X = chr(Y).
  384.         has_feature(Y,simple_atom_table,X),
  385.     R2 = evalin(R1).
  386.  
  387. at_least_1_simple_atom_char(Z) -->
  388.     simple_atom_char(X), !,
  389.     simple_atom_chars(Y), 
  390.     { Z = strcon(X,Y) } .
  391.  
  392. %%% primes
  393.  
  394. primes(P) -->
  395.     [39],
  396.     (
  397.         primes(Q), {P = strcon("'",Q), !}
  398.     ;
  399.         {P = "'"}
  400.     ). 
  401.  
  402. %%% quoted atoms
  403.  
  404. quoted_atom_end(X) --> 
  405.     [39], !,
  406.     ( 
  407.         [39], !,quoted_atom_end(Y), X = strcon("'",Y) 
  408.     ; 
  409.         { X = "" }
  410.     ) .
  411.  
  412. quoted_atom_end(X) --> 
  413.     any_char(Y),
  414.     quoted_atom_end(Z),
  415.     {  X = strcon(Y,Z)} .
  416.  
  417.  
  418. %%% numbers
  419.  
  420. digits(V, length=>L) --> 
  421.     digit( V1), 
  422.     ( digits(V2,length => L2),!,
  423.       { L = L2+1, V = V1*10^L2 + V2} ;
  424.           { V = V1, L = 1}) .
  425.  
  426. digit(0 => [48+N|R], N, rest => Rest)  :-
  427.     N =< 9 and N >= 0,
  428.     Rest = evalin(R).
  429.  
  430. exponent(V) --> sign(S), digits(V1), {!, V = S*V1} .
  431.  
  432. sign(1) --> [] .
  433. sign(-1) --> [45], ! .
  434. sign(1) --> [43] .
  435.  
  436.  
  437. %%% strings 
  438.  
  439. char_chaine_end(X) --> 
  440.     [34], !,
  441.     ( [34], !,char_chaine_end(Y), {X = strcon("""",Y)} ; 
  442.           { X = "" }) .
  443. char_chaine_end(X) --> 
  444.     any_char(Y),
  445.     char_chaine_end(Z),
  446.     { X = strcon(Y,Z)} .
  447.  
  448.  
  449. %%% characters for "operators"
  450.  
  451. op_atom_char(X, 0=> [Y|R1], rest => R2) :- 
  452.     has_feature(Y,op_chars_table,X),
  453.     R2 = evalin(R1).
  454.  
  455. op_atom_chars(X) --> 
  456.     op_atom_char(Y),!, 
  457.     op_atom_chars(Z),
  458.     { X = strcon(Y,Z)} .
  459. op_atom_chars("") -->
  460.     [] .
  461.  
  462.  
  463. %%% any character
  464.  
  465. any_char(Y) -->
  466.     [X], { Y = chr(X) } .
  467.  
  468. %
  469. % reset C function
  470. %
  471.  
  472. reset_C ?
  473.  
  474. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  475. %
  476. % characters tables
  477. %
  478. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  479. gen_char_table(Table,[A|B]) :-
  480.     !,
  481.     Table.A <<- chr(A),
  482.     gen_char_table(Table,B).
  483. gen_char_table.
  484.  
  485. persistent(void_table) ?
  486. gen_char_table(void_table,[9,10,32,37]) ?
  487.  
  488. persistent(simple_atom_table) ?
  489. gen_char_table(simple_atom_table,
  490.           [48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,
  491.        71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,
  492.        89,90,95,97,98,99,100,101,102,103,104,105,106,107,
  493.        108,109,110,111,112,113,114,115,116,117,118,119,120,121,122]) ?
  494.  
  495. persistent(op_chars_table) ?
  496. gen_char_table(op_chars_table,[33,35,36,37,38,42,43,45,46,47,
  497.                            58,60,61,62,92,94,124,126]) ?
  498.  
  499.  
  500. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  501. %
  502. %  definition of new syntactic objects
  503. %
  504. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  505.  
  506. is_syntactic(X) -> has_feature(X,syntact_objects_table).
  507.  
  508. persistent(syntact_objects_table) ?
  509.  
  510. syntact_object(X) :-
  511.     is_value(X),!,
  512.     nl_err,
  513.     write_err(
  514.         "*** Error: numbers or strings cannot be syntactic objects."),
  515.     nl_err
  516.     ;
  517.     syntact_objects_table.X = true.
  518.  
  519. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  520. %
  521. % char handler
  522. %
  523. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  524.  
  525. persistent(read_tok) ?
  526. read_tok <<- false ?
  527. persistent(rest_chars) ?
  528. rest_chars <<- [] ?
  529. persistent(rest_token) ?
  530. rest_token <<- none ?
  531.  
  532. next_char -> 
  533.     L 
  534.     |   
  535.         get(X),
  536.     cond( X :=< end_of_file , 
  537.           L=[] ,
  538.               L = [X|T] ),
  539.         T = `next_char.
  540.  
  541. next_token -> L |
  542.          (
  543.           cond( R:copy_term(rest_chars) = [A,B],
  544.             Chars = [A,B|`next_char],
  545.            Chars = R ),
  546.              call_once(read_new_token(Tok, Chars)) = TT,
  547.          (
  548.          TT :== false, !, fail 
  549.          ; 
  550.          Tok :== none, !,
  551.          L = []
  552.          ;
  553.              rest_token <<- `Tok,
  554.          fail 
  555.          )
  556.      ;
  557.          L = [copy_term(rest_token)|`next_token]
  558.      ).
  559.  
  560.  
  561.  
  562. first_token ->
  563.     L
  564.     |   
  565.         FC = next_char,
  566.         NC = evalin(FC),                   %% 2 characters must be read
  567.         read_new_token(Tok,NC),
  568.     cond( Tok :== none,
  569.           L = [],
  570.           L = [Tok|T]),
  571.     T = `next_token.
  572.  
  573.  
  574. read_new_token( Tok, X) :- 
  575.     void_chars(0 => X, rest => R1),!,
  576.     (
  577.         R1 = [], !, Tok = none
  578.     ;
  579.         token( 0 => R1, Tok, rest => R2),
  580.         ( 
  581.         R2 = [A,B|R],!,
  582.         rest_chars <<- [A,B]
  583.         ;
  584.         rest_chars <<- R2
  585.         )
  586.     ).
  587.  
  588. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  589. %
  590. % Interface Predicates
  591. %
  592. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  593.  
  594. tokens(true,X,S1) :-
  595.     read_tok <<- false,
  596.     void_chars(0 => X, rest => R1),!,
  597.     (
  598.         R1 = [], !,
  599.         open_out("stdout",S),
  600.         nl,nl,
  601.         write("*** File '",S1.input_file_name,"' tokenized"),
  602.         nl
  603.     ;
  604.         (  
  605.         token( 0 => R1, T, rest => R2),
  606.         nl,writeq(T),
  607.         read_tok <<- true,
  608.         cond( R2 = [A,B|_],
  609.               rest_chars <<- [A,B],
  610.               rest_chars <<- R2),
  611.         fail
  612.         ;
  613.             cond( R:copy_term(rest_chars) = [A,B],
  614.                Chars = [A,B|`next_char],
  615.               Chars = R ),
  616.         tokens(read_tok,Chars,S1)
  617.         )
  618.     ).
  619. tokens(false,_,S1) :- 
  620.     open_out("stdout",S),
  621.     nl_err,nl_err,
  622.     write_err("*** Token error near line ",S1.line_count,
  623.               " in file '",S1.input_file_name,"'"),
  624.     nl_err.
  625.  
  626. tokenize(File:string) :- 
  627.     open_in(File,S1),
  628.     open_out(strcon(File,"_toks"),S2),
  629.     FC = next_char,
  630.     NC = evalin(FC),
  631.     tokens(true,NC,S1),
  632.     close(S1),
  633.     close(S2).
  634.  
  635. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  636. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.