home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Moscow ML 1.42 / src / lex / Output.sml < prev    next >
Encoding:
Text File  |  1997-08-18  |  5.5 KB  |  222 lines  |  [TEXT/R*ch]

  1. (* Generating a DFA as a set of mutually recursive functions *)
  2.  
  3. open List BasicIO Nonstdio Fnlib Syntax;
  4.  
  5. val is = ref std_in;
  6. val os = ref std_out;
  7.  
  8. (* 1- Generating the actions *)
  9.  
  10. val copy_buffer = CharArray.array(1024, #" ");
  11.  
  12. fun copy_chunk (Location(start,stop)) =
  13.   let fun copy s =
  14.     if s <= 0 then () else
  15.       let val n = if s < 1024 then s else 1024
  16.           val m = buff_input (!is) copy_buffer 0 n
  17.       in
  18.         buff_output (!os) copy_buffer 0 m;
  19.         copy (s - m)
  20.       end
  21.   in
  22.     seek_in (!is) start;
  23.     copy (stop - start)
  24.   end
  25. ;
  26.  
  27. fun output_actname (i : int) =
  28.     output(!os, "action_" ^ makestring i);
  29.  
  30. fun output_action (i : int, act) =
  31.     (output_actname i; 
  32.      output(!os, " lexbuf = (\n");
  33.      copy_chunk act;
  34.      output(!os, ")\nand ")
  35.      );
  36.  
  37. fun output_actcheck []  = ()
  38.   | output_actcheck [_] = ()
  39.   | output_actcheck ((a1, _) :: ar) =
  40.     (output(!os, "val _ = fn _ => [");
  41.      output_actname a1;
  42.      app (fn (a, _) => (output(!os, ", "); output_actname a)) ar;
  43.      output(!os, "];\n")
  44.      );
  45.  
  46. (* 2- Generating the states *)
  47.  
  48. val states = ref (Array.fromList [] : automata Array.array);
  49.  
  50. fun enumerate_vect v =
  51.   let open Array infix 9 sub
  52.       fun enum env pos =
  53.         if pos >= length v then env else
  54.           let val pl = lookup (v sub pos) env in
  55.             pl := pos :: !pl; enum env (pos+1)
  56.           end
  57.           handle Subscript =>
  58.             enum ((v sub pos, ref [pos]) :: env) (pos+1) 
  59.   in
  60.     Sort.sort
  61.       (fn (e1, ref pl1) => fn (e2, ref pl2) => 
  62.          List.length pl1 >= List.length pl2)
  63.       (enum [] 0)
  64.   end
  65. ;
  66.  
  67. fun output_move Backtrack =
  68.       output(!os, "backtrack lexbuf")
  69.   | output_move (Goto dest) =
  70.       case Array.sub(!states, dest) of
  71.         Perform act_num =>
  72.           output(!os, "action_" ^ makestring act_num ^ " lexbuf")
  73.       | _ =>
  74.           output(!os, "state_" ^ makestring dest ^ " lexbuf")
  75. ;
  76.  
  77. fun output_char_const os (i : int) =
  78.   if i <= 127 then
  79.     output(os, makestring(Char.chr i))
  80.   else
  81.     (output(os, "#\"\\");
  82.      output(os, makestring i);
  83.      output(os, "\""))
  84. ;
  85.  
  86. fun addToInterv c acc =
  87.   case acc of
  88.       [] => [(c, c)]
  89.     | (c1, c2) :: rest =>
  90.         if c+1 = c1 then
  91.           (c, c2) :: rest
  92.         else
  93.           (c, c) :: acc
  94. ;
  95.  
  96. fun mkIntervals cs =
  97.   foldL addToInterv [] cs
  98. ;
  99.  
  100. fun addInterv dest (c1, c2) (intervs, singls) =
  101.   if c1 > c2 then
  102.     (intervs, singls)
  103.   else if c2 - c1 >= 5 then
  104.     ((dest, (c1, c2)) :: intervs, singls)
  105.   else
  106.     addInterv dest (c1+1, c2) (intervs, (dest, c1) :: singls)
  107. ;
  108.  
  109. fun unzipInterv trans =
  110.   foldR
  111.     (fn (dest, chars) => fn acc =>
  112.        foldR (addInterv dest) acc (mkIntervals (!chars)))
  113.     ([], [])
  114.     trans
  115. ;
  116.  
  117. fun output_one_trans_i (dest, (c1, c2)) =
  118. (
  119.   output(!os, " if currChar >= ");
  120.   output_char_const (!os) c1;
  121.   output(!os, " andalso currChar <= ");
  122.   output_char_const (!os) c2;
  123.   output(!os, " then  ");
  124.   output_move dest;
  125.   output(!os, "\n else")
  126. );
  127.  
  128. fun output_one_trans_s (dest, c) =
  129. (
  130.   output_char_const (!os) c;
  131.   output(!os, " => ");
  132.   output_move dest;
  133.   output(!os, "\n |  ")
  134. );
  135.  
  136. fun output_all_trans_i trans =
  137.   app output_one_trans_i trans
  138. ;
  139.  
  140. fun output_all_trans_s trans =
  141. (
  142.   output(!os, " case currChar of\n    ");
  143.   app output_one_trans_s trans;
  144.   output(!os, "_ => ")
  145. );
  146.  
  147. fun output_all_trans trans =
  148. (
  149.   case enumerate_vect trans of
  150.       [] =>
  151.         raise Fail "output_all_trans"
  152.     | (default, _) :: rest =>
  153.         (output(!os, " let val currChar = getNextChar lexbuf in\n");
  154.          case unzipInterv rest of
  155.              ([], trans_s) =>
  156.                (output_all_trans_s trans_s;
  157.                 output_move default)
  158.            | (trans_i, []) =>
  159.                (output_all_trans_i trans_i;
  160.                 output(!os, " ");
  161.                 output_move default)
  162.            | (trans_i, trans_s) =>
  163.                (output_all_trans_i trans_i;
  164.                 output_all_trans_s trans_s;
  165.                 output_move default));
  166.   output(!os, "\n end)\nand ")
  167. );
  168.  
  169. fun output_state (state_num : int) = fn
  170.     Perform i =>
  171.       ()
  172.   | Shift(what_to_do, moves) =>
  173.       (output(!os,
  174.          "state_"  ^ makestring state_num ^ " lexbuf = (\n");
  175.        (case what_to_do of
  176.             No_remember => ()
  177.           | Remember i =>
  178.               (output(!os,
  179.                  " setLexLastPos lexbuf (getLexCurrPos lexbuf);\n");
  180.                output(!os,
  181.                  (" setLexLastAction lexbuf (magic action_" ^
  182.                                   makestring i ^ ");\n"))));
  183.        output_all_trans moves)
  184. ;
  185.  
  186. (* 3- Generating the entry points *)
  187.  
  188. fun output_entries [] = 
  189.       raise Fail "output_entries"
  190.   | output_entries ((name, state_num : int) :: rest) =
  191.       (output(!os, name ^ " lexbuf =\n");
  192.        output(!os,
  193.          "  (setLexStartPos lexbuf (getLexCurrPos lexbuf);\n");
  194.        output(!os,
  195.          "   state_" ^ makestring state_num ^ " lexbuf)\n");
  196.        case rest of
  197.          [] => output(!os, "\n")
  198.        | _  => (output(!os, "\nand "); output_entries rest))
  199. ;
  200.  
  201. (* All together *)
  202.  
  203. fun output_lexdef header (initial_st, st, actions) =
  204. (
  205.   output(std_out, makestring (Array.length st)); 
  206.   output(std_out, " states, ");
  207.   output(std_out, makestring(List.length actions)); 
  208.   output(std_out, " actions.\n"); flush_out std_out;
  209.   output(!os, "local open Obj Lexing in\n\n");
  210.   copy_chunk header;
  211.   output(!os, "\nfun ");
  212.   states := st;
  213.   app (app output_action) actions;
  214.   for (fn i => output_state i (Array.sub(st, i)))
  215.       0 (Array.length st - 1);
  216.   output_entries initial_st;
  217.   output(!os, "(* The following checks type consistency of actions *)\n");
  218.   app output_actcheck actions;
  219.   output(!os, "\nend\n")
  220. );
  221.  
  222.