feat: typedef

This commit is contained in:
Guillotin Damien 2021-12-12 18:25:08 +01:00
parent 0931e4a1c8
commit 8a4e107ecd
12 changed files with 112 additions and 16 deletions

View file

@ -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 *)

View file

@ -0,0 +1,8 @@
main{
typedef Int2 = int;
Int2 a = 2;
typedef PInt = int *;
PInt px = &a;
int y = (*px);
print y;
}

View file

@ -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);
}

View file

@ -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 }

View file

@ -7,6 +7,7 @@ open Ast.AstSyntax
%token <int> ENTIER
%token <string> ID
%token <string> 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 <programme> 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)}

View file

@ -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

View file

@ -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 "")

View file

@ -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

View file

@ -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

View file

@ -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 |}]

View file

@ -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

View file

@ -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 *)