Premier commit avec ce qui a été fait pendant la séance.

This commit is contained in:
Mysaa 2022-01-22 22:18:16 +01:00
commit 101555a3d3
Signed by: Mysaa
GPG Key ID: 7054D5D6A90F084F
11 changed files with 303 additions and 0 deletions

3
Rendu0/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
_build/
fouine
main.native

11
Rendu0/Makefile Normal file
View File

@ -0,0 +1,11 @@
all:
ocamlbuild -yaccflag -v -lib unix main.native #on dit de fabriquer main.native
ln -f -s main.native fouine
chmod +x fouine
byte:
ocamlbuild -yaccflag -v main.byte
clean:
ocamlbuild -clean
rm -f fouine

21
Rendu0/README.txt Normal file
View File

@ -0,0 +1,21 @@
Ce répertoire contient un sequelette de départ à partir duquel vous
pouvez programmer votre fouine.
Pour compiler, faites
make
qui aura pour effet de créer l'exécutable appelé fouine.
Faites ensuite
./fouine
pour lancer l'exécutable et saisir une expression au clavier.
./fouine tests/basic.ml pour lancer fouine sur le fichier basic.ml
main.ml : fichier principal
expr.ml : définition des expressions et de l'évaluation
affichage.ml : fonctions d'affichage
lexer.mll : lexèmes, analyse lexicale
parser.mly : règles de grammaire, analyse syntaxique
tests/ : sous-répertoire de tests
Makefile : pour la compilation, à ne pas modifier a priori

42
Rendu0/affichage.ml Normal file
View File

@ -0,0 +1,42 @@
open Expr
let affiche_val v = match v with
| VInt k -> print_int k
| VBool b -> print_string (if b then "Vrai" else "Faux")
(* fonction d'affichage *)
let rec affiche_expr e =
let aff_aux s a b =
begin
print_string s;
affiche_expr a;
print_string ", ";
affiche_expr b;
print_string ")"
end
in
match e with
| Const k -> print_int k
| BConst b -> affiche_val (VBool b)
| Add(e1,e2) -> aff_aux "Add(" e1 e2
| Mul(e1,e2) -> aff_aux "Mul(" e1 e2
| Min(e1,e2) -> aff_aux "Min(" e1 e2
| Eq(e1,e2) -> aff_aux "Eq(" e1 e2
| Gt(e1,e2) -> aff_aux "Gt(" e1 e2
| Lt(e1,e2) -> aff_aux "Lt(" e1 e2
| Gte(e1,e2) -> aff_aux "Gte(" e1 e2
| Lte(e1,e2) -> aff_aux "Lte(" e1 e2
| Band(e1,e2) -> aff_aux "BooleanAnd(" e1 e2
| Bor(e1,e2) -> aff_aux "BooleanOr(" e1 e2
| ITE(ec,e1,e2) ->
begin print_string "IF(";
affiche_expr ec;
print_string ", ";
affiche_expr e1;
print_string ", ";
affiche_expr e2;
print_string ")"
end
| PrInt(e1) -> print_string "PrInt(";affiche_expr e1;print_string ")"

60
Rendu0/expr.ml Normal file
View File

@ -0,0 +1,60 @@
(* définition des différents types : tout est à reprendre et étendre *)
type expr =
Const of int
| BConst of bool
| Add of expr*expr
| Mul of expr*expr
| Min of expr*expr
| Eq of expr*expr
| Gt of expr*expr
| Lt of expr*expr
| Gte of expr*expr
| Lte of expr*expr
| Band of expr*expr
| Bor of expr*expr
| ITE of expr*expr*expr
| PrInt of expr
type valeur = VInt of int | VBool of bool
type env = unit
let empty_env = ()
exception InvalidTypeException
let rec intIntOp op e1 e2 env = match (eval e1 env, eval e2 env) with
| VInt k1,VInt k2 -> VInt(op k1 k2)
| _ -> raise InvalidTypeException
and intBoolOp op e1 e2 env = match (eval e1 env, eval e2 env) with
| VInt k1,VInt k2 -> VBool(op k1 k2)
| _ -> raise InvalidTypeException
(* sémantique opérationnelle à grands pas *)
and eval e env = match e with
| Const(k) -> VInt k
| BConst(b) -> VBool b
| Add(e1,e2) -> intIntOp ( + ) e1 e2 env
| Mul(e1,e2) -> intIntOp ( * ) e1 e2 env
| Min(e1,e2) -> intIntOp ( - ) e1 e2 env
| Gt(e1,e2) -> intBoolOp ( > ) e1 e2 env
| Lt(e1,e2) -> intBoolOp ( < ) e1 e2 env
| Gte(e1,e2) -> intBoolOp ( >= ) e1 e2 env
| Lte(e1,e2) -> intBoolOp ( <= ) e1 e2 env
| Eq(e1,e2) -> (match (eval e1 env, eval e2 env) with
| VInt k1,VInt k2 -> VBool (k1=k2)
| VBool k1,VBool k2 -> VBool (k1=k2)
| _ -> raise InvalidTypeException)
| Band(e1,e2) -> (match (eval e1 env, eval e2 env) with
| VBool b1,VBool b2 -> VBool (b1 && b2)
| _ -> raise InvalidTypeException)
| Bor(e1,e2) -> (match (eval e1 env, eval e2 env) with
| VBool b1,VBool b2 -> VBool (b1 || b2)
| _ -> raise InvalidTypeException)
| ITE(ec,e1,e2) -> (match (eval ec env) with
| VBool bc -> eval (if bc then e1 else e2) env
| _ -> raise InvalidTypeException)
| PrInt e1 -> (match (eval e1 env) with
| VInt k -> VInt k
| _ -> raise InvalidTypeException)

32
Rendu0/lexer.mll Normal file
View File

@ -0,0 +1,32 @@
{
open Parser
exception Eof
}
rule token = parse (* la "fonction" aussi s'appelle token .. *)
| [' ' '\t'] { token lexbuf } (* on saute les blancs et les tabulations *)
(* token: appel récursif *)
(* lexbuf: argument implicite
associé au tampon sont
lus les caractères *)
| '\n' { EOL }
| '+' { PLUS }
| '*' { TIMES }
| '-' { MINUS }
| '(' { LPAREN }
| ')' { RPAREN }
| ['0'-'9']+ as s { INT (int_of_string s) }
| "true" { TRUE }
| "false" { FALSE }
| '>' { GT }
| '<' { LT }
| ">=" { GTE }
| ">=" { LTE }
| '=' { EQ }
| "&&" { BAND }
| "||" { BOR }
| "if" { IF }
| "then" { THEN }
| "else" { ELSE }
| "prInt" { PRINT }
| eof { raise Eof } (* fin du fichier *)

67
Rendu0/main.ml Normal file
View File

@ -0,0 +1,67 @@
open Expr
open Affichage
(* "incantations" qu'il n'est pas nécessaire de comprendre dans un premier
temps : on récupère l'entrée, dans un fichier ou sur le clavier *)
let nom_fichier = ref ""
let recupere_entree () =
Arg.parse [] (fun s -> nom_fichier := s) "";
try
let where_from = match !nom_fichier with
| "" -> stdin
| s -> open_in s in
let lexbuf = Lexing.from_channel where_from in
let parse () = Parser.main Lexer.token lexbuf in
parse ()
with e -> (Printf.printf "problème de saisie\n"; raise e)
(* mettre à true et recompiler si l'on veut voir l'exécution pas à pas de l'automate *)
let trace = ref false
let _ = Stdlib.Parsing.set_trace !trace
let rec affiche_printexpr e env = begin
match e with
| Add(e1,e2) -> affiche_printexpr e1 env;affiche_printexpr e2 env
| Mul(e1,e2) -> affiche_printexpr e1 env;affiche_printexpr e2 env
| Min(e1,e2) -> affiche_printexpr e1 env;affiche_printexpr e2 env
| Eq(e1,e2) -> affiche_printexpr e1 env;affiche_printexpr e2 env
| Gt(e1,e2) -> affiche_printexpr e1 env;affiche_printexpr e2 env
| Lt(e1,e2) -> affiche_printexpr e1 env;affiche_printexpr e2 env
| Gte(e1,e2) -> affiche_printexpr e1 env;affiche_printexpr e2 env
| Lte(e1,e2) -> affiche_printexpr e1 env;affiche_printexpr e2 env
| Band(e1,e2) -> affiche_printexpr e1 env;affiche_printexpr e2 env
| Bor(e1,e2) -> affiche_printexpr e1 env;affiche_printexpr e2 env
| ITE(ec,e1,e2) -> affiche_printexpr ec env;affiche_printexpr e1 env;affiche_printexpr e2 env
| _ -> ()
end;
begin
match e with
| PrInt e -> (match (eval e env) with
| VInt(k) -> print_int k;print_newline ()
| _ -> raise InvalidTypeException)
| _ -> ()
end
(* le traitement d'une expression en entrée *)
let execute e =
begin
affiche_printexpr e Expr.empty_env;
print_newline();
let v = Expr.eval e Expr.empty_env in
affiche_val v;
print_newline()
end
(* la boucle principale *)
let calc () =
try
let saisie = recupere_entree () in
execute saisie; flush stdout
with e -> raise e
let _ = calc()

64
Rendu0/parser.mly Normal file
View File

@ -0,0 +1,64 @@
%{
(* --- préambule: ici du code Caml --- *)
open Expr (* rappel: dans expr.ml:
type expr = Const of int | Add of expr*expr | Mull of expr*expr *)
%}
/* description des lexèmes, ceux-ci sont décrits (par vous) dans lexer.mll */
%token <int> INT /* le lexème INT a un attribut entier */
%token TRUE FALSE
%token IF THEN ELSE
%token PRINT
%token BAND BOR
%token EQ GT LT GTE LTE
%token PLUS TIMES MINUS
%token LPAREN RPAREN
%token EOL /* retour à la ligne */
%nonassoc IF THEN ELSE
%left BAND BOR
%left EQ
%nonassoc GT LT GTE LTE
%left PLUS MINUS /* associativité gauche: a+b+c, c'est (a+b)+c */
%left TIMES /* associativité gauche: a*b*c, c'est (a*b)*c */
%nonassoc PRINT
%nonassoc UMINUS /* un "faux token", correspondant au "-" unaire */
/* cf. son usage plus bas : il sert à "marquer" une règle pour lui donner la précédence maximale */
%start main /* "start" signale le point d'entrée: */
/* c'est ici main, qui est défini plus bas */
%type <Expr.expr> main /* on _doit_ donner le type associé au point d'entrée */
%%
/* --- début des règles de grammaire --- */
/* à droite, les valeurs associées */
main: /* <- le point d'entrée (cf. + haut, "start") */
expression EOL { $1 } /* on veut reconnaître une expression */
;
expression: /* règles de grammaire pour les expressions */
| INT { Const $1 }
| TRUE { BConst true }
| FALSE { BConst false }
| LPAREN expression RPAREN { $2 } /* on récupère le deuxième élément */
| expression PLUS expression { Add($1,$3) }
| expression TIMES expression { Mul($1,$3) }
| expression MINUS expression { Min($1,$3) }
| expression EQ expression { Eq($1,$3) }
| expression GT expression { Gt($1,$3) }
| expression LT expression { Lt($1,$3) }
| expression GTE expression { Gte($1,$3) }
| expression LTE expression { Lte($1,$3) }
| expression BAND expression { Band($1,$3) }
| expression BOR expression { Bor($1,$3) }
| PRINT expression { PrInt($2) }
| IF expression THEN expression ELSE expression { ITE($2,$4,$6)}
| MINUS expression %prec UMINUS { Min(Const 0, $2) }
;

1
Rendu0/tests/arith0.ml Normal file
View File

@ -0,0 +1 @@
1+2+3+4*5*(6+7-8)

1
Rendu0/tests/basic.ml Normal file
View File

@ -0,0 +1 @@
3+2*4

1
Rendu0/tests/booleans.ml Normal file
View File

@ -0,0 +1 @@
if (5+6=11) then (if 5-9=9 && 3+3=6 then 42 else 5+98) else 4*2