From 8a4e107ecda66614b9f90af3e85a411d11a91666 Mon Sep 17 00:00:00 2001 From: Guillotin Damien Date: Sun, 12 Dec 2021 18:25:08 +0100 Subject: [PATCH] feat: typedef --- src/ast.ml | 9 ++- src/fichiersRat/src-rat-tam-test/typedef1.rat | 8 +++ src/fichiersRat/src-rat-tam-test/typedef2.rat | 9 +++ src/lexer.mll | 7 ++- src/parser.mly | 16 +++++- src/passeTdsRat.ml | 55 ++++++++++++++++--- src/printerAst.ml | 6 +- src/tds.ml | 1 + src/tds.mli | 2 + src/testTam.ml | 11 ++++ src/type.ml | 2 +- src/type.mli | 2 +- 12 files changed, 112 insertions(+), 16 deletions(-) create mode 100644 src/fichiersRat/src-rat-tam-test/typedef1.rat create mode 100644 src/fichiersRat/src-rat-tam-test/typedef2.rat diff --git a/src/ast.ml b/src/ast.ml index eb1b7a0..e5cdb9f 100644 --- a/src/ast.ml +++ b/src/ast.ml @@ -29,6 +29,9 @@ type affectable = (* Identifiant *) | Ident of string +(* Déclaration d'un nouveau type *) +type typedef = TypeDef of string * typ + (* Expressions de Rat *) type expression = (* Appel de fonction représenté par le nom de la fonction et la liste des paramètres réels *) @@ -52,6 +55,7 @@ type expression = (* Instructions de Rat *) type bloc = instruction list + and instruction = (* Déclaration de variable représentée par son type, son nom et l'expression d'initialisation *) | Declaration of typ * string * expression @@ -67,6 +71,8 @@ and instruction = | TantQue of expression * bloc (* return d'une fonction *) | Retour of expression + (* Définition d'un type local *) + | LocalTypeDef of typedef (* Structure des fonctions de Rat *) (* type de retour - nom - liste des paramètres (association type et nom) - corps de la fonction *) @@ -74,7 +80,7 @@ type fonction = Fonction of typ * string * (typ * string) list * bloc (* Structure d'un programme Rat *) (* liste de fonction - programme principal *) -type programme = Programme of fonction list * bloc +type programme = Programme of typedef list * fonction list * bloc end @@ -119,6 +125,7 @@ struct | Retour of expression | Empty (* les nœuds ayant disparus: Const *) + (* On remplace les typedefs par leurs "vrais" types, dans les infos *) (* Structure des fonctions dans notre langage *) (* type de retour - informations associées à l'identificateur (dont son nom) - liste des paramètres (association type et information sur les paramètres) - corps de la fonction *) diff --git a/src/fichiersRat/src-rat-tam-test/typedef1.rat b/src/fichiersRat/src-rat-tam-test/typedef1.rat new file mode 100644 index 0000000..ba32701 --- /dev/null +++ b/src/fichiersRat/src-rat-tam-test/typedef1.rat @@ -0,0 +1,8 @@ +main{ + typedef Int2 = int; + Int2 a = 2; + typedef PInt = int *; + PInt px = &a; + int y = (*px); + print y; +} diff --git a/src/fichiersRat/src-rat-tam-test/typedef2.rat b/src/fichiersRat/src-rat-tam-test/typedef2.rat new file mode 100644 index 0000000..fa4bc02 --- /dev/null +++ b/src/fichiersRat/src-rat-tam-test/typedef2.rat @@ -0,0 +1,9 @@ +typedef Int2 = int; +Int2 plus (Int2 a Int2 b) { + return (a+b); +} +main{ + Int2 a = 1; + int b = 1; + print (a+b); +} diff --git a/src/lexer.mll b/src/lexer.mll index 1a60d45..42b2989 100644 --- a/src/lexer.mll +++ b/src/lexer.mll @@ -13,7 +13,7 @@ (* on utilise une table pour les mots-clefs de façon à éviter l'ajout *) (* d'états à l'automate résultant *) let ident = - let kws = Hashtbl.create 16 in + let kws = Hashtbl.create 17 in List.iter (fun (kw, token) -> Hashtbl.add kws kw token) [ "const", CONST; @@ -32,11 +32,15 @@ "return", RETURN; "null", NULL; "new", NEW; + "typedef", TYPEDEF; ]; fun id -> match Hashtbl.find_opt kws id with | Some kw -> kw | None -> ID id + + let identMaj = fun id -> TID id + } rule token = parse @@ -70,6 +74,7 @@ rule token = parse (* identifiants et mots-clefs *) | ['a'-'z'](['A'-'Z''a'-'z''0'-'9']|"-"|"_")* as n { ident n } +| ['A'-'Z'](['A'-'Z''a'-'z''0'-'9']|"-"|"_")* as n { identMaj n } (* fin de lecture *) | eof { EOF } diff --git a/src/parser.mly b/src/parser.mly index 44a7354..2b9f7c7 100644 --- a/src/parser.mly +++ b/src/parser.mly @@ -7,6 +7,7 @@ open Ast.AstSyntax %token ENTIER %token ID +%token TID %token RETURN %token PV %token AO @@ -38,6 +39,7 @@ open Ast.AstSyntax %token NULL %token NEW %token AMP +%token TYPEDEF (* Type de l'attribut synthétisé des non-terminaux *) %type prog @@ -58,10 +60,16 @@ open Ast.AstSyntax main : lfi=prog EOF {lfi} prog : -| lf=fonc lfi=prog {let (Programme (lf1,li))=lfi in (Programme (lf::lf1,li))} -| ID li=bloc {Programme ([],li)} +| ltd=td lf=fonc lfi=prog {let (Programme (_, lf1, li))=lfi in (Programme (ltd, lf::lf1,li))} +(* | lf=fonc lfi=prog {let (Programme ( lf1, li))=lfi in (Programme ( lf::lf1,li))} *) +| ID li=bloc {Programme ([], [], li)} -fonc : t=typ n=ID PO p=dp PF AO li=is AF {Fonction(t,n,p,li)} +td : +| {[]} +| TYPEDEF tid=TID EQUAL type1=typ PV td1=td {(TypeDef(tid, type1))::td1} + +fonc : +| t=typ n=ID PO p=dp PF AO li=is AF {Fonction(t,n,p,li)} bloc : AO li = is AF {li} @@ -79,6 +87,7 @@ i : | RETURN exp=e PV {Retour (exp)} | aff=a EQUAL exp=e PV {Affectation (aff, exp)} | aff=a PLUS EQUAL exp=e PV {Affectation (aff, Binaire (Plus, Affectable(aff), exp))} +| TYPEDEF tid=TID EQUAL type1=typ PV {LocalTypeDef (TypeDef(tid, type1))} dp : | {[]} @@ -89,6 +98,7 @@ typ : | INT {Int} | RAT {Rat} | t1=typ MULT {Pointeur (t1)} +| t1=TID {TIdent (t1)} e : | CALL n=ID PO lp=cp PF {AppelFonction (n,lp)} diff --git a/src/passeTdsRat.ml b/src/passeTdsRat.ml index c974ab0..bf0233b 100644 --- a/src/passeTdsRat.ml +++ b/src/passeTdsRat.ml @@ -6,12 +6,28 @@ struct open Exceptions open Ast open AstTds - open PrinterAst + open Type type t1 = Ast.AstSyntax.programme type t2 = Ast.AstTds.programme +let rec recherche_type tds t = + match t with + | TIdent(t_nom) -> + begin + match chercherGlobalement tds t_nom with + | None -> raise (IdentifiantNonDeclare (t_nom)) + | Some i -> + begin + match info_ast_to_info i with + | InfoType(_, t2) -> recherche_type tds t2 + | _ -> failwith "un truc louche ca" + end + end + | _ -> t + + let rec analyse_tds_affectable tds a modif = match a with | AstSyntax.Dref new_aff -> @@ -95,6 +111,21 @@ let rec analyse_tds_expression tds e = | _ -> raise (MauvaiseUtilisationIdentifiant(n)) end +let rec analyse_tds_typedef tds (AstSyntax.TypeDef(n, t)) = + begin + match chercherLocalement tds n with + | None -> + (* L'identifiant n'est pas trouvé dans la tds locale, + il n'a donc pas été déclaré dans le bloc courant *) + (* Ajout dans la tds de la constante *) + ajouter tds n (info_to_info_ast (InfoType (n, t))); + Empty + | Some _ -> + (* L'identifiant est trouvé dans la tds locale, + il a donc déjà été déclaré dans le bloc courant *) + raise (DoubleDeclaration n) + end + (* analyse_tds_instruction : AstSyntax.instruction -> tds -> AstTds.instruction *) (* Paramètre tds : la table des symboles courante *) (* Paramètre i : l'instruction à analyser *) @@ -120,7 +151,9 @@ let rec analyse_tds_instruction tds i = ajouter tds n ia; (* Renvoie de la nouvelle déclaration où le nom a été remplacé par l'information et l'expression remplacée par l'expression issue de l'analyse *) - Declaration (t, ia, ne) + + let nt = recherche_type tds t in + Declaration (nt, ia, ne) | Some _ -> (* L'identifiant est trouvé dans la tds locale, il a donc déjà été déclaré dans le bloc courant *) @@ -196,6 +229,8 @@ let rec analyse_tds_instruction tds i = (* Analyse de l'expression *) let ne = analyse_tds_expression tds e in Retour (ne) + | AstSyntax.LocalTypeDef(td) -> + analyse_tds_typedef tds td (* analyse_tds_bloc : AstSyntax.bloc -> AstTds.bloc *) @@ -241,17 +276,20 @@ let analyse_tds_fonction maintds (AstSyntax.Fonction(t, str, l_typstr, bloc)) = (* Ajouter les arguments de la fonction dans la tds locale *) let nl_typinfo = (List.map ( fun (t, nom) -> + let nt = recherche_type maintds t in match chercherLocalement tds_bloc nom with | None -> - let i_ast_var = info_to_info_ast (Tds.InfoVar(nom, t, 0, "")) in + let i_ast_var = info_to_info_ast (Tds.InfoVar(nom, nt, 0, "")) in ajouter tds_bloc nom i_ast_var; - (t, i_ast_var) + (nt, i_ast_var) (* Si un argument est en double, on lève une exception *) | Some _ -> raise (DoubleDeclaration nom) ) l_typstr) in + let nt = recherche_type maintds t in + (* On crée l'info de la fonction *) - let info_fun = InfoFun(str, t, (List.map (fun (t, _) -> t) l_typstr)) in + let info_fun = InfoFun(str, nt, (List.map (fun (t, _) -> recherche_type maintds t) l_typstr)) in (* On ajoute a la tds locale la fonction pour qu'il puisse y avoir des appels récursifs *) let _ = ajouter tds_bloc str (info_to_info_ast info_fun) in @@ -263,7 +301,7 @@ let analyse_tds_fonction maintds (AstSyntax.Fonction(t, str, l_typstr, bloc)) = ajouter maintds str (info_to_info_ast info_fun); (* On retourne la AstTds fonction *) - AstTds.Fonction(t, (info_to_info_ast info_fun), nl_typinfo, new_bloc) + AstTds.Fonction(nt, (info_to_info_ast info_fun), nl_typinfo, new_bloc) end end @@ -272,10 +310,11 @@ let analyse_tds_fonction maintds (AstSyntax.Fonction(t, str, l_typstr, bloc)) = (* Vérifie la bonne utilisation des identifiants et tranforme le programme en un programme de type AstTds.ast *) (* Erreur si mauvaise utilisation des identifiants *) -let analyser (AstSyntax.Programme (fonctions,prog)) = +let analyser (AstSyntax.Programme (typedefs,fonctions,prog)) = let tds = creerTDSMere () in + let _ = List.map (analyse_tds_typedef tds) typedefs in let nf = List.map (analyse_tds_fonction tds) fonctions in let nb = analyse_tds_bloc tds prog in - Programme (nf,nb) + AstTds.Programme (nf,nb) end diff --git a/src/printerAst.ml b/src/printerAst.ml index e51a7a4..c6d4ecc 100644 --- a/src/printerAst.ml +++ b/src/printerAst.ml @@ -69,6 +69,8 @@ struct | Fraction -> "["^(string_of_expression e1)^"/"^(string_of_expression e2)^"] " | _ -> (string_of_expression e1)^(string_of_binaire b)^(string_of_expression e2)^" " end + + let string_of_typedef (TypeDef(n, t)) = n ^ "->" ^ (string_of_type t) ^ "\n" (* Conversion des instructions *) let rec string_of_instruction i = @@ -83,13 +85,15 @@ struct | TantQue (c,b) -> "TantQue : TQ "^(string_of_expression c)^"\n"^ "FAIRE \n"^((List.fold_right (fun i tq -> (string_of_instruction i)^tq) b ""))^"\n" | Retour (e) -> "Retour : RETURN "^(string_of_expression e)^"\n" + | LocalTypeDef(td) -> (string_of_typedef td) ^ "\n" (* Conversion des fonctions *) let string_of_fonction (Fonction(t,n,lp,li)) = (string_of_type t)^" "^n^" ("^((List.fold_right (fun (t,n) tq -> (string_of_type t)^" "^n^" "^tq) lp ""))^") = \n"^ ((List.fold_right (fun i tq -> (string_of_instruction i)^tq) li ""))^"\n" (* Conversion d'un programme Rat *) - let string_of_programme (Programme (fonctions, instruction)) = + let string_of_programme (Programme (typedefs, fonctions, instruction)) = + (List.fold_right (fun t tq -> (string_of_typedef t)^tq) typedefs "")^ (List.fold_right (fun f tq -> (string_of_fonction f)^tq) fonctions "")^ (List.fold_right (fun i tq -> (string_of_instruction i)^tq) instruction "") diff --git a/src/tds.ml b/src/tds.ml index 919d00e..757744b 100644 --- a/src/tds.ml +++ b/src/tds.ml @@ -6,6 +6,7 @@ type info = | InfoConst of string * int | InfoVar of string * typ * int * string | InfoFun of string * typ * typ list + | InfoType of string * typ (* Données stockées dans la tds et dans les AST : pointeur sur une information *) type info_ast = info ref diff --git a/src/tds.mli b/src/tds.mli index a1b317a..a5d9fe1 100644 --- a/src/tds.mli +++ b/src/tds.mli @@ -9,6 +9,8 @@ type info = | InfoVar of string * typ * int * string (* Information associée à une fonction : son nom (utile pour l'appel), son type de retour et la liste des types des paramètres *) | InfoFun of string * typ * typ list + (* Information associée à un type: son nom, son type associé *) + | InfoType of string * typ (* Table des symboles *) type tds diff --git a/src/testTam.ml b/src/testTam.ml index 3ca7a8c..a0f2437 100644 --- a/src/testTam.ml +++ b/src/testTam.ml @@ -109,10 +109,12 @@ let%expect_test "factrec" = runtam "../../fichiersRat/src-rat-tam-test/factrec.rat"; [%expect{| 120 |}] +(* Tests pointeurs *) let%expect_test "pointeur1" = runtam "../../fichiersRat/src-rat-tam-test/pointeur1.rat"; [%expect{| 3 |}] +(* Tests assignation addition *) let%expect_test "assadd1" = runtam "../../fichiersRat/src-rat-tam-test/assadd1.rat"; [%expect{| 3 |}] @@ -124,3 +126,12 @@ let%expect_test "assadd2" = let%expect_test "assadd3" = runtam "../../fichiersRat/src-rat-tam-test/assadd3.rat"; [%expect{| 3 |}] + +(* Tests typedef *) +let%expect_test "typedef1" = + runtam "../../fichiersRat/src-rat-tam-test/typedef1.rat"; + [%expect{| 2 |}] + +let%expect_test "typedef2" = + runtam "../../fichiersRat/src-rat-tam-test/typedef2.rat"; + [%expect{| 2 |}] \ No newline at end of file diff --git a/src/type.ml b/src/type.ml index 95190a2..2bd7634 100644 --- a/src/type.ml +++ b/src/type.ml @@ -1,4 +1,4 @@ -type typ = Bool | Int | Rat | Pointeur of typ | Undefined +type typ = Bool | Int | Rat | Pointeur of typ | TIdent of string | Undefined let rec string_of_type t = match t with diff --git a/src/type.mli b/src/type.mli index 2c30e5c..05ec110 100644 --- a/src/type.mli +++ b/src/type.mli @@ -1,5 +1,5 @@ (* Types manipulés dans Rat *) -type typ = Bool | Int | Rat | Pointeur of typ | Undefined +type typ = Bool | Int | Rat | Pointeur of typ | TIdent of string | Undefined (* string_of_type : typ -> string *) (* transforme un typ en chaîne de caractère *)