projet-traduction-langage/passeTdsRat.ml
2021-11-24 14:13:45 +01:00

158 lines
6.7 KiB
OCaml

(* Module de la passe de gestion des identifiants *)
module PasseTdsRat : Passe.Passe with type t1 = Ast.AstSyntax.programme and type t2 = Ast.AstTds.programme =
struct
open Tds
open Exceptions
open Ast
open AstTds
type t1 = Ast.AstSyntax.programme
type t2 = Ast.AstTds.programme
(* analyse_tds_expression : AstSyntax.expression -> AstTds.expression *)
(* Paramètre tds : la table des symboles courante *)
(* Paramètre e : l'expression à analyser *)
(* Vérifie la bonne utilisation des identifiants et tranforme l'expression
en une expression de type AstTds.expression *)
(* Erreur si mauvaise utilisation des identifiants *)
let analyse_tds_expression tds e = (AstTds.Booleen true) (* failwith "todo"*)
(* analyse_tds_instruction : AstSyntax.instruction -> tds -> AstTds.instruction *)
(* Paramètre tds : la table des symboles courante *)
(* Paramètre i : l'instruction à analyser *)
(* Vérifie la bonne utilisation des identifiants et tranforme l'instruction
en une instruction de type AstTds.instruction *)
(* Erreur si mauvaise utilisation des identifiants *)
let rec analyse_tds_instruction tds i =
match i with
| AstSyntax.Declaration (t, n, e) ->
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 *)
(* Vérification de la bonne utilisation des identifiants dans l'expression *)
(* et obtention de l'expression transformée *)
let ne = analyse_tds_expression tds e in
(* Création de l'information associée à l'identfiant *)
let info = InfoVar (n,Undefined, 0, "") in
(* Création du pointeur sur l'information *)
let ia = info_to_info_ast info in
(* Ajout de l'information (pointeur) dans la tds *)
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)
| 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
| AstSyntax.Affectation (n,e) ->
begin
match chercherGlobalement tds n with
| None ->
(* L'identifiant n'est pas trouvé dans la tds globale. *)
raise (IdentifiantNonDeclare n)
| Some info ->
(* L'identifiant est trouvé dans la tds globale,
il a donc déjà été déclaré. L'information associée est récupérée. *)
begin
match info_ast_to_info info with
| InfoVar _ ->
(* Vérification de la bonne utilisation des identifiants dans l'expression *)
(* et obtention de l'expression transformée *)
let ne = analyse_tds_expression tds e in
(* Renvoie de la nouvelle affectation où le nom a été remplacé par l'information
et l'expression remplacée par l'expression issue de l'analyse *)
Affectation (info, ne)
| _ ->
(* Modification d'une constante ou d'une fonction *)
raise (MauvaiseUtilisationIdentifiant n)
end
end
| AstSyntax.Constante (n,v) ->
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 (InfoConst (n,v)));
(* Suppression du noeud de déclaration des constantes devenu inutile *)
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
| AstSyntax.Affichage e ->
(* Vérification de la bonne utilisation des identifiants dans l'expression *)
(* et obtention de l'expression transformée *)
let ne = analyse_tds_expression tds e in
(* Renvoie du nouvel affichage où l'expression remplacée par l'expression issue de l'analyse *)
Affichage (ne)
| AstSyntax.Conditionnelle (c,t,e) ->
(* Analyse de la condition *)
let nc = analyse_tds_expression tds c in
(* Analyse du bloc then *)
let tast = analyse_tds_bloc tds t in
(* Analyse du bloc else *)
let east = analyse_tds_bloc tds e in
(* Renvoie la nouvelle structure de la conditionnelle *)
Conditionnelle (nc, tast, east)
| AstSyntax.TantQue (c,b) ->
(* Analyse de la condition *)
let nc = analyse_tds_expression tds c in
(* Analyse du bloc *)
let bast = analyse_tds_bloc tds b in
(* Renvoie la nouvelle structure de la boucle *)
TantQue (nc, bast)
| AstSyntax.Retour (e) ->
(* Analyse de l'expression *)
let ne = analyse_tds_expression tds e in
Retour (ne)
(* analyse_tds_bloc : AstSyntax.bloc -> AstTds.bloc *)
(* Paramètre tds : la table des symboles courante *)
(* Paramètre li : liste d'instructions à analyser *)
(* Vérifie la bonne utilisation des identifiants et tranforme le bloc
en un bloc de type AstTds.bloc *)
(* Erreur si mauvaise utilisation des identifiants *)
and analyse_tds_bloc tds li =
(* Entrée dans un nouveau bloc, donc création d'une nouvelle tds locale
pointant sur la table du bloc parent *)
let tdsbloc = creerTDSFille tds in
(* Analyse des instructions du bloc avec la tds du nouveau bloc
Cette tds est modifiée par effet de bord *)
let nli = List.map (analyse_tds_instruction tdsbloc) li in
(* afficher_locale tdsbloc ; *) (* décommenter pour afficher la table locale *)
nli
(* analyse_tds_fonction : AstSyntax.fonction -> AstTds.fonction *)
(* Paramètre tds : la table des symboles courante *)
(* Paramètre : la fonction à analyser *)
(* Vérifie la bonne utilisation des identifiants et tranforme la fonction
en une fonction de type AstTds.fonction *)
(* Erreur si mauvaise utilisation des identifiants *)
let analyse_tds_fonction maintds (AstSyntax.Fonction(t,n,lp,li)) =
failwith "TO DO"
(* analyser : AstSyntax.ast -> AstTds.ast *)
(* Paramètre : le programme à analyser *)
(* 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 tds = creerTDSMere () in
let nf = List.map (analyse_tds_fonction tds) fonctions in
let nb = analyse_tds_bloc tds prog in
Programme (nf,nb)
end