let rec saute_blancs flux =
  match flux with
    [< ' ` ` >] -> saute_blancs flux  (* ` ` est l'espace *)
  | [< ' `\t` >] -> saute_blancs flux (* `\t` est la tabulation *)
  | [< ' `\n` >] -> saute_blancs flux (* `\n` est la fin de ligne *)
  | [< >] -> ();;

let rec saute_blancs flux =
  match flux with
    [< ' (` ` | `\t` | `\n`) >] -> saute_blancs flux
  | [< >] -> ();;

let rec lire_entier accumulateur flux =
  match flux with
    [< '(`0`..`9` as c) >] ->
      lire_entier (10 * accumulateur + int_of_char c - 48) flux
  | [< >] -> accumulateur;;

let rec lire_décimales accumulateur échelle flux =
  match flux with
    [< '(`0`..`9` as c) >] ->
      lire_décimales
        (accumulateur +.
           float_of_int(int_of_char c - 48) *. échelle)
        (échelle /. 10.0) flux
  | [< >] -> accumulateur;;

let tampon = "----------------";;

let rec lire_mot position flux =
  match flux with
    [< '(`A`..`Z` | `a`..`z` | `é` | `è` | `_` as c) >] ->
      if position < string_length tampon then
        set_nth_char tampon position c;
      lire_mot (position+1) flux
  | [< >] ->
      sub_string tampon 0 (min position (string_length tampon));;

let rec lire_lexème flux =
  saute_blancs flux;
  match flux with
    [< '(`A`..`Z` | `a`..`z` | `é` | `è` as c) >] ->
      set_nth_char tampon 0 c;
      Mot(lire_mot 1 flux)
  | [< '(`0`..`9` as c) >] ->
      let n = lire_entier (int_of_char c - 48) flux in
      begin match flux with
        [< '`.` >] ->
          Constante_flottante
            (lire_décimales (float_of_int n) 0.1 flux)
      | [< >] -> Constante_entière(n)
      end
  | [< 'c >] -> Symbole c;;

let analyseur_lexical flux =
  stream_from (fun () -> lire_lexème flux);;
