L'analyse des commandes est une partie peu intéressante du point de vue de la programmation système. Nous en donnons une implémentation minimale ne reconnaissant pas les commandes complexes emboîtées, mais permettant de faire quelques tests interactifs simples.

Nous ajoutons quelques commandes primitives (pwd, cd) à titre d'illustration.
      
let tokenize s =
  let space_regexp = Str.regexp "[ \t\n]+" in
  Str.split space_regexp s;;

type phrase =
    Com of bool * string list
  | Seq of phrase list
  | And of phrase list
  | Or of phrase list

let rec quick_parse right =
  let rec split left right =
    let get () =
      match left with
        "&" :: cl -> Com (falseList.rev cl)
      | cl -> Com (trueList.rev clin
    match right with
    | ";" :: rest  -> Seq [ get(); quick_parse rest ]
    | "&&" :: rest -> And [ get(); quick_parse rest ]
    | "||" :: rest -> Or [ get(); quick_parse rest ]
    | a :: rest -> split (a :: leftrest
    | [] -> get () in
  split [] right;;

let internal_command f x =
  try f x; 0
  with Unix_error (_,_,_) -> 1

(* Un ^C provoque Break, trois ^C de suite provoquent un exit 1 *)
let breaks = ref 0;;
let handle_int _ = if !breaks >= 3 then exit 1 else incr breaks;;
let _ = signal sigint (Signal_handle handle_int);;

let flatten =
  List.map

let break_retcode = 129;;
let rec command cmd =
  try
    match cmd with
    | Com (_, []) -> 0
    | Com (_"pwd" :: _) ->
        internal_command (fun () -> print_endline (getcwd())) ()
    | Com (_"cd" :: args) ->
        let p = match args with h::_ -> h | _ -> getenv "HOME" in
        internal_command chdir p;
    | Com (_"jobs" :: _) -> jobs(); 0
    | Com (_"fg" :: _) -> fg()
    | Com (_"bg" :: _) -> bg()
    | Com (fgcmd :: args) ->
        let args' = Array.of_list args in
        if fg then command_wait cmd args'
        else command_bg cmd args'
    | Seq cmd_arg_list ->
        complex_command command_seq cmd_arg_list
    | And cmd_arg_list ->
        complex_command command_and cmd_arg_list
    | Or cmd_arg_list ->
        complex_command command_or cmd_arg_list
  with Sys.Break -> break_retcode
and complex_command oper cmd_arg_list =
  let flat = function
      Com (_com::args) -> comArray.of_list args
    | _ ->
        eprintf "Embeded complex commands  not implemented\n";
        exit 1 in
  oper (List.map flat cmd_arg_list);;

let eval_string s = command (quick_parse (tokenize s));;

let prompt_string = "# ";;
let rec eval_loop () =
  let last = ref 0 in
  try
    while true do
      clear_process_table();
      print_string prompt_string;
      flush Pervasives.stdout;
      breaks := 0;
      last := eval_string (read_line())
    done
  with End_of_file -> exit !last;;
      
let main() =
  match Array.to_list Sys.argv with
    _ :: "-c" :: cmd :: _ -> exit (eval_string cmd)
  | [ _ ] -> eval_loop()
  | d  ->
      eprintf "Usage: %s [ -c cmd ]\n"
        (if d = [] then "shell" else List.hd d);
      exit 2
let _ = handle_unix_error main();;