(***** Langage Mini-C ****)

(** Analyse lexicale **)

(* les tokens *)

type tok_t = PtV | Plus | Prt | DPt (* ; + print : *)
     | Eq | ParG | ParD  (* = ( ) *)
     | Ident of string  (* identifiant *)
     | Num of int  (* nombre *)

let tok_of_string s = 
  (* transforme une chaîne de caractère matchée par la Regexp en token *)
  (* A COMPLETER *)
  print_endline s; PtV
;;

let analyse_lexicale (texte:string) : tok_t list =
  let re = Str.regexp "[a-z]+" in (* regexp A COMPLETER *)
  let rec tokenize texte i = (* renvoie la liste de tokens pour texte, pris à partir de l'indice i *)
    if i = String.length texte then
      []
    else 
      try
        let j = Str.search_forward re texte i in
        let str = Str.matched_string texte in
        if str = " " || str = "\n" then
          tokenize texte (j + String.length str)
        else
          (tok_of_string str) :: tokenize texte (j + String.length str)
      with 
        Not_found -> []
  in
  tokenize texte 0
;;

(* Tests *)
(* assert (analyse_lexicale "x := 3; print(x)" = [Ident "x"; DPt; Eq; Num 3; PtV; Prt; ParG; Ident "x"; ParD]);; *)
(* assert (analyse_lexicale "a b+33 c ==" = [Ident "a"; Ident "b"; Plus; Num 33; Ident "c"; Eq; Eq]);; *) 
(* assert (analyse_lexicale "(aaa(:print:" = [ParG; Ident "aaa"; ParG; DPt; Prt; DPt]);; *)


(** Analyse syntaxique **)

(* arbre de syntaxe abstraite *)

type progr_t = Uniq of instr_t | Seq of instr_t * progr_t

and instr_t = Affiche of expr_t | Affect of string * expr_t

and expr_t = Val of string | Add of expr_t * expr_t | Entier of int


let rec parse_progr l = 
  failwith "A FAIRE"
;;

let analyse_syntaxique tok_list = 
  let prog, l = parse_progr tok_list in
  if l = [] then prog else failwith "Erreur"
;;


(** Evaluation de l'arbre de syntaxe abstraite **)

(* Environnement d'évaluation *)

(* A FAIRE *)

(* Fonctions d'évaluation *)

(* A FAIRE *)


(** Fonction d'évaluation **)

let interprete filename =

  (* lecture du code source fichier *)
  let ch = open_in filename in
  let texte = ref "" in
  begin
  try 
    while true do
      let ligne = input_line ch in
      texte := !texte ^ ligne ^ "\n"
    done
  with
    End_of_file -> ()
  end;
  close_in ch;
  (* print_endline !texte; *)

  (* analyse lexicale *)
  analyse_lexicale !texte

  (* analyse syntaxique *)
  (* A FAIRE *)

  (* evaluation *)
  (* A FAIRE *)
;;

interprete Sys.argv.(1);;