orbitz avatar orbitz committed c6a2bf9

Initial support for export

Comments (0)

Files changed (8)

 	lexer.mli lexer.ml \
 	program_options.ml \
 	return.ml \
+	format_builder.mli format_builder.ml \
 	formatter.mli formatter.ml \
 	erlint.ml
 
 let usage = ""
 
 let parse_argv argv =
-  let file_path = ref "" in
-  let indent_spaces = ref 2 in
-  let max_line_length = ref 80 in
+  let file_path          = ref "" in
+  let indent_spaces      = ref 2 in
+  let max_line_length    = ref 80 in
   let code_comment_ratio = ref 100 in
+  let debug              = ref false in
   let params =
     Arg.align [ ( "-f"
 		, Arg.Set_string file_path
 		, Arg.Set_int code_comment_ratio
 		, "Int Number of lines of code per 1 line of comments (default 100)"
 	        )
+	      ; ( "-debug"
+		, Arg.Set debug
+		, " Turn debugging on or off"
+	        )
 	      ]
   in
   Arg.parse params (fun _ -> ()) usage;
-  { Po.file_path = if !file_path = "" then None else Some !file_path
-  ; Po.indent_spaces = !indent_spaces
-  ; Po.max_line_length = !max_line_length
+  { Po.file_path          = if !file_path = "" then None else Some !file_path
+  ; Po.indent_spaces      = !indent_spaces
+  ; Po.max_line_length    = !max_line_length
   ; Po.code_comment_ratio = !code_comment_ratio
+  ; Po.debug              = !debug
   }
 
 let list_of_stream stream =
   in
   let code_stream = Stream.of_channel in_chan in
   let code_lexed = list_of_stream (Lexer.lex code_stream) in
-  Token.pp_list code_lexed;
-  match Formatter.format program_options stdout code_lexed with
+  if program_options.Po.debug then
+    Token.pp_list code_lexed;
+  match
+    Formatter.format_to_channel
+      program_options
+      stdout
+      code_lexed
+  with
     | Return.Success [] ->
       ()
     | Return.Success warnings -> begin
+      print_newline ();
       Printf.printf "%% %d warnings\n" (List.length warnings);
       print_warnings warnings
     end
     | Return.Failure error ->
+      print_newline ();
       Printf.printf "%% Failed\nLine: %d\nMsg: %s\n"
 	error.Formatter.line_number
 	error.Formatter.msg

src/format_builder.ml

 
 let add_tokens line_builder tokens =
   let tokens = List.map (fun t -> Token t) tokens in
-  (List.rev tokens) ++ line_builder
+  (List.rev tokens) @ line_builder
+
+let append left right =
+  right @ left
 
 let add_space line_builder n =
   (Space n)::line_builder
   let buffer = Buffer.create initial_buffer_length in
   List.iter
     (function
-      | Token t -> Buffer.add_char buffer (string_of_token t)
+      | Token t -> Buffer.add_string buffer (string_of_token t)
       | Space n -> Buffer.add_string buffer (String.make n ' '))
-    (List.rev line_builder)
+    (List.rev line_builder);
+  Buffer.contents buffer
 
 
+
+

src/format_builder.mli

 
 val create      : unit -> t
 val add_token   : t -> Token.t -> t
+val add_tokens  : t -> Token.t list -> t
 val add_space   : t -> int -> t
-val line_length : t -> int
+val append      : t -> t -> t
 val to_string   : t -> (Token.t -> string) -> string
 	     ; msg         : string
 	     }
 
+type error_t =
+  | Forced_line_break
+  | Msg of string
+
 type warning = error
 
 type parser_state =
   | Top_level
   | Function
-  | Compiler_directive
 
 type state = { program_options   : Program_options.t
 	     (* The number of indentations, not the number of spaces *)
 	     (* This is current line number we are writing, starting at 0 *)
 	     ; dst_line_number   : int
 	     ; parser_state      : parser_state list
+	     ; line_builder      : Format_builder.t
 	     ; builder           : Format_builder.t
 	     ; warnings          : warning list
 	     }
   ; src_line_number   = 0
   ; dst_line_number   = 0
   ; parser_state      = [Top_level]
-  ; builder           = Format_builder.t
+  ; line_builder      = Format_builder.create ()
+  ; builder           = Format_builder.create ()
   ; warnings          = []
   }
 
   { state with src_line_number = incr state.src_line_number }
 
 let incr_dst_line state =
-  Buffer.add_string state.buffer (string_of_token Newline);
   { state with
     dst_line_number = incr state.dst_line_number;
-    imputed_line_length = 0
+    builder = Format_builder.add_token state.builder Newline
   }
 
 (*
 	       }::state.warnings
   }
 
-let is_line_too_long state line =
-  (String.length line
-   + state.indentation_level * state.program_options.Po.indent_spaces
+let add_token state token =
+  { state with
+    line_builder =
+      Format_builder.add_token
+	state.line_builder
+	token
+  }
+
+let add_tokens state tokens =
+  { state with
+    line_builder =
+      Format_builder.add_tokens
+	state.line_builder
+	tokens
+  }
+
+let add_space ?(num = 1) state =
+  { state with
+    line_builder =
+      Format_builder.add_space
+	state.line_builder
+	num
+  }
+
+
+let append_line state =
+  { state with
+    builder =
+      (Format_builder.append
+	 state.builder
+	 state.line_builder);
+    line_builder = Format_builder.create ()
+  }
+
+let is_line_too_long state =
+  (String.length
+     (Format_builder.to_string
+	state.line_builder
+	string_of_token)
    > state.program_options.Po.max_line_length)
 
-let succeed state =
-  R.Success (Buffer.contents state.buffer, state.warnings)
+let succeed state rest =
+  R.Success (state, rest)
 
 let rec format_top_level state = function
   | Newline::xs ->
-    format_top_level (incr_dst_line (incr_src_line state)) xs
-  | (Comment text)::xs -> begin
-    Buffer.add_string state.buffer (string_of_token (Comment text));
-    if is_line_too_long state text then
+    let state' = append_line state in
+    format_top_level (incr_dst_line (incr_src_line state')) xs
+  | (Comment text)::xs ->
+    let state =
+      add_token
+	state
+	(Comment text)
+    in
+    if is_line_too_long state then begin
       format_top_level
 	(add_warning state "Comment longer than maximum line length")
 	xs
+    end
     else
       format_top_level state xs
-  end
   | (Keyword "-")::(Atom "module")::xs ->
     bind
       format_top_level
       (format_module
-	 { state with
-	   state.parser_state =
-	     Compiler_directive::state.parser_state;
-	   line_builder =
-	     Line_builder.add_tokens
-	       state.line_builder
-	       [Keyword "-"; Atom "module"]
-	 }
+	 (add_tokens
+	    state
+	    [Keyword "-"; Atom "module"])
 	 xs)
-  | [] -> succeed state
+  | (Keyword "-")::(Atom "export")::xs ->
+    bind
+      format_top_level
+      (format_export
+	 (add_tokens
+	    state
+	    [Keyword "-"; Atom "export"])
+	 xs)
+  | [] ->
+    succeed (append_line state) []
+  (* TODO: This needs to be removed at some point *)
   | _::xs -> format_top_level state xs
 and format_module state = function
-  | (Keyword "(")::(Atom mod_name)::(Keyword ")")::Dot::Newline::xs ->
-    
-
+  | (Keyword "(")::(Atom mod_name)::(Keyword ")")::Dot::xs ->
+    succeed
+      (add_tokens
+	 state
+	 [Keyword "("; Atom mod_name; Keyword ")"; Dot])
+      xs
+  | _ ->
+    fail state "Unknown -module declaration"
+and format_export state = function
+  | (Keyword "(")::(Keyword "[")::xs -> begin
+    let state =
+      add_tokens
+	state
+	[Keyword "("; Keyword "["]
+    in
+    match format_list_oneline state xs with
+      | R.Success (state, rest) ->
+	bind
+	  format_top_level
+	  (format_export_end
+	     state
+	     rest)
+      | R.Failure Forced_line_break ->
+	bind
+	  format_top_level
+	  (format_list_multiline
+	     state
+	     xs)
+      | R.Failure (Msg msg) ->
+	fail state msg
+  end
+  | _ ->
+    fail state "Unknown -export declaration"
+and format_export_end state = function
+  | (Keyword ")")::Dot::xs ->
+    succeed
+      (add_tokens
+	 state
+	 [(Keyword ")"); Dot])
+      xs
+  | _ ->
+    fail state "Unexpected tokens in -export"
+and format_list_oneline state = function
+    | (Keyword "]")::xs ->
+      let state =
+	add_token
+	  state
+	  (Keyword "]")
+      in
+      if is_line_too_long state then
+	R.Failure Forced_line_break
+      else
+	succeed
+	  state
+	  xs
+    | (Keyword ",")::xs ->
+      format_list_oneline
+	(add_space
+	   (add_token
+	      state
+	      (Keyword ",")))
+	xs
+    | (Comment _)::_
+    | Newline::_ ->
+      R.Failure Forced_line_break
+    | x::xs ->
+      format_list_oneline
+	(add_token
+	   state
+	   x)
+	xs
+    | [] ->
+      R.Failure (Msg "Unexpected end of input")
+and format_list_multiline state = function
+    | _ -> fail state "Not implemented"
 
 let format_code program_options code =
   (*
   let state = default_state program_options buffer in
   match format_top_level state code with
     | R.Success (state, []) ->
-      succeed state
+      let code =
+	Format_builder.to_string
+	  state.builder
+	  string_of_token
+      in
+      R.Success (code, state.warnings)
     | R.Success (state, _) ->
       fail state "Did not consume entire input"
     | R.Failure error ->

src/formatter.mli

 
 type warning = error
 
-val format_code       : Program_otpions.t -> Token.t list -> ((string * warning list), error) Return.t
+val format_code       : Program_options.t -> Token.t list -> ((string * warning list), error) Return.t
 val format_to_channel : Program_options.t -> out_channel -> Token.t list -> (warning list, error) Return.t

src/program_options.ml

-type t = { file_path : string option
-	 ; indent_spaces : int
-	 ; max_line_length : int
+type t = { file_path          : string option
+	 ; indent_spaces      : int
+	 ; max_line_length    : int
 	 (*
 	  * Maximum number of lines of code per
 	  * lines of comments.  Must be positive
 	  * per comments
 	  *)
 	 ; code_comment_ratio : int
+	 ; debug              : bool
 	 }
     | Some Newline -> begin
       Printf.printf "(Newline)\n";
       Stream.junk stream;
-      pp stream
+      pp_stream stream
     end
     | Some token -> begin
       Printf.printf "(%s) " (token_to_string token);
       Stream.junk stream;
-      pp stream
+      pp_stream stream
     end
 
 let rec pp_list = function
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.