Premier commit avec ce qui a été fait pendant la séance.
This commit is contained in:
commit
101555a3d3
3
Rendu0/.gitignore
vendored
Normal file
3
Rendu0/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
_build/
|
||||||
|
fouine
|
||||||
|
main.native
|
||||||
11
Rendu0/Makefile
Normal file
11
Rendu0/Makefile
Normal 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
21
Rendu0/README.txt
Normal 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
42
Rendu0/affichage.ml
Normal 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
60
Rendu0/expr.ml
Normal 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
32
Rendu0/lexer.mll
Normal 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 où 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
67
Rendu0/main.ml
Normal 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
64
Rendu0/parser.mly
Normal 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
1
Rendu0/tests/arith0.ml
Normal file
@ -0,0 +1 @@
|
|||||||
|
1+2+3+4*5*(6+7-8)
|
||||||
1
Rendu0/tests/basic.ml
Normal file
1
Rendu0/tests/basic.ml
Normal file
@ -0,0 +1 @@
|
|||||||
|
3+2*4
|
||||||
1
Rendu0/tests/booleans.ml
Normal file
1
Rendu0/tests/booleans.ml
Normal file
@ -0,0 +1 @@
|
|||||||
|
if (5+6=11) then (if 5-9=9 && 3+3=6 then 42 else 5+98) else 4*2
|
||||||
Loading…
x
Reference in New Issue
Block a user