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