home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Moscow ML 1.31 / source code / mosml / src / lex / Output.sml < prev    next >
Encoding:
Text File  |  1996-07-03  |  5.1 KB  |  208 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_action (i : int, act) =
  28. (
  29.   output(!os, "action_" ^ makestring i ^ " lexbuf = (\n");
  30.   copy_chunk act;
  31.   output(!os, ")\nand ")
  32. );
  33.  
  34. (* 2- Generating the states *)
  35.  
  36. val states = ref (Array.array0 : automata Array.array);
  37.  
  38. fun enumerate_vect v =
  39.   let open Array infix 9 sub
  40.       fun enum env pos =
  41.         if pos >= length v then env else
  42.           let val pl = lookup (v sub pos) env in
  43.             pl := pos :: !pl; enum env (pos+1)
  44.           end
  45.           handle Subscript =>
  46.             enum ((v sub pos, ref [pos]) :: env) (pos+1) 
  47.   in
  48.     Sort.sort
  49.       (fn (e1, ref pl1) => fn (e2, ref pl2) => 
  50.          List.length pl1 >= List.length pl2)
  51.       (enum [] 0)
  52.   end
  53. ;
  54.  
  55. fun output_move Backtrack =
  56.       output(!os, "backtrack lexbuf")
  57.   | output_move (Goto dest) =
  58.       case Array.sub(!states, dest) of
  59.         Perform act_num =>
  60.           output(!os, "action_" ^ makestring act_num ^ " lexbuf")
  61.       | _ =>
  62.           output(!os, "state_" ^ makestring dest ^ " lexbuf")
  63. ;
  64.  
  65. fun output_char_const os (i : int) =
  66.   if i <= 127 then
  67.     output(os, makestring(Char.chr i))
  68.   else
  69.     (output(os, "#\"\\");
  70.      output(os, makestring i);
  71.      output(os, "\""))
  72. ;
  73.  
  74. fun addToInterv c acc =
  75.   case acc of
  76.       [] => [(c, c)]
  77.     | (c1, c2) :: rest =>
  78.         if c+1 = c1 then
  79.           (c, c2) :: rest
  80.         else
  81.           (c, c) :: acc
  82. ;
  83.  
  84. fun mkIntervals cs =
  85.   foldL addToInterv [] cs
  86. ;
  87.  
  88. fun addInterv dest (c1, c2) (intervs, singls) =
  89.   if c1 > c2 then
  90.     (intervs, singls)
  91.   else if c2 - c1 >= 5 then
  92.     ((dest, (c1, c2)) :: intervs, singls)
  93.   else
  94.     addInterv dest (c1+1, c2) (intervs, (dest, c1) :: singls)
  95. ;
  96.  
  97. fun unzipInterv trans =
  98.   foldR
  99.     (fn (dest, chars) => fn acc =>
  100.        foldR (addInterv dest) acc (mkIntervals (!chars)))
  101.     ([], [])
  102.     trans
  103. ;
  104.  
  105. fun output_one_trans_i (dest, (c1, c2)) =
  106. (
  107.   output(!os, " if currChar >= ");
  108.   output_char_const (!os) c1;
  109.   output(!os, " andalso currChar <= ");
  110.   output_char_const (!os) c2;
  111.   output(!os, " then  ");
  112.   output_move dest;
  113.   output(!os, "\n else")
  114. );
  115.  
  116. fun output_one_trans_s (dest, c) =
  117. (
  118.   output_char_const (!os) c;
  119.   output(!os, " => ");
  120.   output_move dest;
  121.   output(!os, "\n |  ")
  122. );
  123.  
  124. fun output_all_trans_i trans =
  125.   app output_one_trans_i trans
  126. ;
  127.  
  128. fun output_all_trans_s trans =
  129. (
  130.   output(!os, " case currChar of\n    ");
  131.   app output_one_trans_s trans;
  132.   output(!os, "_ => ")
  133. );
  134.  
  135. fun output_all_trans trans =
  136. (
  137.   case enumerate_vect trans of
  138.       [] =>
  139.         raise Fail "output_all_trans"
  140.     | (default, _) :: rest =>
  141.         (output(!os, " let val currChar = getNextChar lexbuf in\n");
  142.          case unzipInterv rest of
  143.              ([], trans_s) =>
  144.                (output_all_trans_s trans_s;
  145.                 output_move default)
  146.            | (trans_i, []) =>
  147.                (output_all_trans_i trans_i;
  148.                 output(!os, " ");
  149.                 output_move default)
  150.            | (trans_i, trans_s) =>
  151.                (output_all_trans_i trans_i;
  152.                 output_all_trans_s trans_s;
  153.                 output_move default));
  154.   output(!os, "\n end)\nand ")
  155. );
  156.  
  157. fun output_state (state_num : int) = fn
  158.     Perform i =>
  159.       ()
  160.   | Shift(what_to_do, moves) =>
  161.       (output(!os,
  162.          "state_"  ^ makestring state_num ^ " lexbuf = (\n");
  163.        (case what_to_do of
  164.             No_remember => ()
  165.           | Remember i =>
  166.               (output(!os,
  167.                  " setLexLastPos lexbuf (getLexCurrPos lexbuf);\n");
  168.                output(!os,
  169.                  (" setLexLastAction lexbuf (magic action_" ^
  170.                                   makestring i ^ ");\n"))));
  171.        output_all_trans moves)
  172. ;
  173.  
  174. (* 3- Generating the entry points *)
  175.  
  176. fun output_entries [] = 
  177.       raise Fail "output_entries"
  178.   | output_entries ((name, state_num : int) :: rest) =
  179.       (output(!os, name ^ " lexbuf =\n");
  180.        output(!os,
  181.          "  (setLexStartPos lexbuf (getLexCurrPos lexbuf);\n");
  182.        output(!os,
  183.          "   state_" ^ makestring state_num ^ " lexbuf)\n");
  184.        case rest of
  185.          [] => output(!os, "\n")
  186.        | _  => (output(!os, "\nand "); output_entries rest))
  187. ;
  188.  
  189. (* All together *)
  190.  
  191. fun output_lexdef header (initial_st, st, actions) =
  192. (
  193.   output(std_out, makestring (Array.length st)); 
  194.   output(std_out, " states, ");
  195.   output(std_out, makestring(List.length actions)); 
  196.   output(std_out, " actions.\n"); flush_out std_out;
  197.   output(!os, "local open Obj Lexing in\n\n");
  198.   copy_chunk header;
  199.   output(!os, "\nfun ");
  200.   states := st;
  201.   app output_action actions;
  202.   for (fn i => output_state i (Array.sub(st, i)))
  203.       0 (Array.length st - 1);
  204.   output_entries initial_st;
  205.   output(!os, "\nend\n")
  206. );
  207.  
  208.