(*RICM LP2 2006/2007, éléments de correction de la première partie*) (*Laure Gonnord et Mathias Peron*) (*pour évaluer décommenter la ligne suivante:*) #load "camlp4o.cma" (* pour compiler taper dans le terminal par ex *) (* sous win, il sera peut être nécessaire de compiler avec -o tp4-cor.exe*) (* ocamlc -pp "camlp4o pa_extend.cmo" -I +camlp4 -c tp4-cor.ml *) (* ocamlc tp4-cor.cmo -o tp4-cor *) (*pour utiliser, faire ./tp4-cor toto.txt avec toto.txt contenant par ex 42-2+3*) open Format (*pour printf*) open Sys (*pour les entrees/sorties*) (*Analyse Lexicale*) (*traduction charactère -> chiffre*) let valchiffre c = (Char.code c - Char.code '0') (*traitement des entiers*) let rec integer accu = parser | [< ' (('0'..'9') as c);stream >] -> integer (10*accu + valchiffre c ) stream | [<>] -> accu (* val calcule_int : int -> char Stream.t -> int = *) (*Le type expression*) type expr = Plus of expr * expr | Moins of expr * expr | Int of int type token = TEnt of int | TPlus | TMoins (* type token = TEnt of int | TPlus | TMoins *) (*analyse lexicale proprement dite*) let rec make_lex = parser [< ' ('0'..'9') as c; entier = integer (valchiffre c); stream >] -> [< 'TEnt(entier); make_lex stream >] | [< ''+'; stream >] -> [<'TPlus; make_lex stream >] | [< ''-'; stream >] -> [<'TMoins; make_lex stream >] | [< '' '; stream >] -> make_lex stream | [<>] -> [<>] (*on aurait pu utiliser Stream.from *) (* let rec next_lex = parser *) (* [< ' ('0'..'9') as c; entier = integer (valchiffre c); stream >] -> Some (TEnt(entier)) *) (* | [< ''+'; stream >] -> Some TPlus *) (* | [< ''-'; stream >] -> Some TMoins *) (* | [< '' '; stream >] -> next_lex stream *) (* | [<>] -> None *) (* let make_lex2 stream = Stream.from (fun _ -> next_lex stream) *) (*fin d'utilisation de Stream.from*) (*tests qui ne servent à rien pour la compilation, mais je les laisse*) (* let ex1 = "42-2+3" *) (* val ex1 : string = "42-2+3" *) (* let lex1 = make_lex (Stream.of_string ex1) *) (* let _ = list_of_stream lex1 (*ATTENTION ÇA DETRUIT*) *) (* - : token list = [Tent 42; Tmoins; Tent 2; Tplus; Tent 3] *) (*ANALYSE SYNTAXIQUE*) (*avec la syntaxe du cours*) (*Remarquer la recursivité mutuelle, mot clef and *) let rec p_expr = parser | [< nb = p_terminal ; t=p_add nb>] -> t and p_add u = parser | [< 'TPlus; t = p_terminal; res = p_add (Plus(u,t)) >] -> res | [< 'TMoins; t = p_terminal; res = p_add (Moins(u,t)) >] -> res | [< >] -> u and p_terminal = parser | [< 'TEnt(n) >] -> Int(n) (* val p_expr : token Stream.t -> expr = *) (* val p_add : token Stream.t -> expr = expr = *) (*tests de developpement, je les laisse...*) (* let lex1 = make_lex (Stream.of_string ex1) *) (* let e1 = p_expr lex1 *) (* val e1 : expr = Plus (Moins (Int 42, Int 2), Int 3) *) (* let ex2 = "42-2-3" in *) (* let lex2 = make_lex (Stream.of_string ex2) in p_expr lex2 *) (* - : expr = Moins (Moins (Int 42, Int 2), Int 3) *) (*FONCTION EVAL*) let rec eval = function | Int(n) -> n | Plus(a,b) -> (eval a) + (eval b) | Moins(a,b) -> (eval a) - (eval b) (*traitement global*) exception WrongNb (*fonction exécutée afin de traiter le in_channel chan_fich*) (*elle est de type void, elle imprime uniquement le résultat de l'évaluation*) let main chan_fich = ( let string = input_line chan_fich (*on suppose qu'on lit la premiere ligne*) in let flux1 = make_lex (Stream.of_string string) in let resu = eval (p_expr flux1) in printf "resultat = %i \n" resu ) (*FONCTION PRINCIPALE DU PROGRAMME, c'est elle qui est exécutée*) let _ = try ( let nb_of_args = Array.length (Sys.argv) in if nb_of_args <> 2 then raise WrongNb else let name = Sys.argv.(1) in let chan = open_in name in printf "%s is now open \n" name; (*apres ouverture du fichier, exécuter la fonction nommée main*) main chan; close_in chan; printf "%s has closed successfully \n" name; ) with | Sys_error(s) -> prerr_string ("Sys_error "^s);prerr_newline() | WrongNb -> prerr_string ("File not found") ;prerr_newline()