Commits

camlspotter  committed 5a65f80

toplet

  • Participants
  • Parent commits 52b49b7

Comments (0)

Files changed (1)

 
 type stack = (kind * int) list with sexp
 
-type state = {
-  bases : stack; (** indentation stack *)
-  last_orig_region : Region.t;            (** the last token's region *)
-  orig_indent : int;  
-}
-
 let get_indent_chars = function
   | [] -> 0
   | (_,i)::_ -> i
 
 
-let pop bases t =
-  let open Parser in
-  let pop f = 
-    let rec pop = function
-      | (token, _) :: bs when f token -> bs
-      | (_, _) :: bs -> pop bs
-      | [] -> bases
-    in
-    pop bases
+open Parser
+
+let pop f bases = 
+  let rec pop = function
+    | (token, _) :: bs when f token -> bs
+    | (_, _) :: bs -> pop bs
+    | [] -> bases
   in
-  match t with
-  | RPAREN -> pop (function `LPAREN -> true | _ -> false)
-  | RBRACE -> pop (function `LBRACE -> true | _ -> false)
-  | END ->    pop (function `STRUCT | `SIG -> true | _ -> false)
-  | IN ->     pop (function `LET    -> true | _ -> false)
-  | _ -> bases
+  pop bases
 
 (* the indent of a line is computed from:
    - the state of the last line
    - the first token of the line
 *)
-let indent bases first_token =
-  pop bases first_token
-;;
+let indent bases ~prev t =
+  match t with
+  | RPAREN -> pop (function `LPAREN -> true | _ -> false) bases
+  | RBRACE -> pop (function `LBRACE -> true | _ -> false) bases
+  | END ->    pop (function `STRUCT | `SIG -> true | _ -> false) bases
+  | IN ->     pop (function `LET    -> true | _ -> false) bases
+  | LET ->
+      begin match prev with
+      | Some (LPAREN | LBRACE | BEGIN | IN | EQUAL)  (* .. *) -> 
+          bases
+      | _ -> 
+          pop (function `TOPLET -> true | _ -> false) bases
+      end
+  | _ -> bases
 
 (* 
    bases : If [t] is at the head of the line, [bases] must be updated by [indent]
    region : With indentation fix. It may not the region from the source.
 *)
 
-let token bases t fixed_region current_indent =
-  let open Parser in
-
+let token bases ~prev t fixed_region current_indent =
   let _columns = Region.columns fixed_region in
 
   match t with
   | STRUCT -> (`STRUCT, current_indent + 2) :: bases
   | SIG    -> (`SIG, current_indent + 2) :: bases
   | LET -> 
-      let rec is_top = function
-        | [] -> true
-        | ((`STRUCT | `SIG), _) :: _ -> true
-        | (`LET, _) :: _ -> false
-        | _ :: bases -> is_top bases
-      in
-
-      (`LET, current_indent + 2) :: bases
-  | LET ->    (`LET, current_indent + 2) :: bases
-  | _ ->   pop bases t
+      let bases = indent bases ~prev t in
+      begin match prev with
+      | Some (LPAREN | LBRACE | BEGIN | IN | EQUAL) (* .. *) -> 
+          (`LET, current_indent + 2) :: bases
+      | _ -> 
+          (`TOPLET, current_indent + 2) :: bases
+      end
+  | _ -> indent bases ~prev t
 ;;
 
 module Lexbuf = struct
   let region (_, lexbuf) = lexbuf.Lexing.lex_start_p, lexbuf.Lexing.lex_curr_p
 end
 
+type state = {
+  bases : stack; (** indentation stack *)
+  last_orig_region : Region.t;            (** the last token's region *)
+  orig_indent : int;  
+  prev_token : Parser.token option
+}
+
 let _ = 
   List.iter (fun path ->
     let ic = open_in path in
     try
       let reader = LexReader.create_from_channel ic in
       let rec loop state = 
-        let open Parser in
         match LexReader.lex reader Lexer.token with
         | EOF -> ()
         | t -> 
             (* the first token of the line may change the indentation of the line *)
             let tmp_bases = 
               if Region.lnum state.last_orig_region <>  Region.lnum orig_region then
-                indent state.bases t 
+                indent state.bases ~prev:state.prev_token t 
               else state.bases
             in
 
             (* fixed region *)
             let fixed_region = Region.move_chars (indent - orig_indent) orig_region in
 
-            let bases = token tmp_bases t fixed_region indent in
+            let bases = token tmp_bases ~prev:state.prev_token t fixed_region indent in
             
-            let state = 
+            let state' = 
               { bases = bases;
                 last_orig_region = orig_region; (* or just line number ? *)
-                orig_indent = orig_indent }
+                orig_indent = orig_indent;
+                prev_token = Some t
+              }
             in
 
             if new_line then begin
                 with
                 | _ -> "XXX"
               in
+
               Printf.printf "%s\n" space_between;
-(*
+
               print_string (String.make indent ' ');
               Format.printf "(* %a *)@." Sexplib.Sexp.pp_hum (sexp_of_stack tmp_bases); 
-*)
+
               print_string (String.make indent ' ');
               Printf.printf "%s" substr;
             end else begin
               print_string space_between;
               Printf.printf "%s" substr;
             end;
-            loop state
+            loop state'
       in
-      loop { bases = []; last_orig_region = Region.zero; orig_indent = 0 } 
+      loop { bases = []; last_orig_region = Region.zero; orig_indent = 0; prev_token = None } 
 
     with
     | e ->