feat: typedef
This commit is contained in:
parent
0931e4a1c8
commit
8a4e107ecd
|
@ -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 *)
|
||||
|
|
8
src/fichiersRat/src-rat-tam-test/typedef1.rat
Normal file
8
src/fichiersRat/src-rat-tam-test/typedef1.rat
Normal file
|
@ -0,0 +1,8 @@
|
|||
main{
|
||||
typedef Int2 = int;
|
||||
Int2 a = 2;
|
||||
typedef PInt = int *;
|
||||
PInt px = &a;
|
||||
int y = (*px);
|
||||
print y;
|
||||
}
|
9
src/fichiersRat/src-rat-tam-test/typedef2.rat
Normal file
9
src/fichiersRat/src-rat-tam-test/typedef2.rat
Normal 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);
|
||||
}
|
|
@ -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 }
|
||||
|
|
|
@ -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)}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 "")
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 |}]
|
|
@ -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
|
||||
|
|
|
@ -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 *)
|
||||
|
|
Loading…
Reference in a new issue