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

113 lines
3.7 KiB
OCaml

open Passe
(* Définition d'un compilateur comme l'enchaînement de
quatre passes (gestion des identifiants, typage, placement mémoire
génération de code). Chaque passe prend en entrée le type de
sortie de la passe précédente.
La dernière passe doit renvoyer une chaîne de caractères (le code généré)
*)
module Compilateur (Ptds:Passe)
(Ptype:Passe with type t1 = Ptds.t2)
(Pdep:Passe with type t1 = Ptype.t2)
(Pcode:Passe with type t1 = Pdep.t2 and type t2 = string) :
Passe with type t1 = Ptds.t1 and type t2 = string =
struct
type t1 = Ptds.t1
type t2 = string
(* analyse_semantique : ast -> string *)
(* Réalise l'analyse sémantique de l'arbre abstrait *)
(* en appliquant les passes les unes après les autres *)
(* retourne : le code issu de la dernière passe *)
let analyser ast =
let tast = Ptds.analyser ast in
let tyast = Ptype.analyser tast in
let past = Pdep.analyser tyast in
let code = Pcode.analyser past in
code
end
(* Compilateurs intermédiaires *)
(* Compilateur créant l'AST *)
(*
module CompilateurRat = Compilateur (PasseTdsNop) (PasseNop) (PasseNop) (PasseCodeNopNop)
*)
(* + passe de résolution des identifiants *)
open PasseTdsRat
module CompilateurRat = Compilateur (PasseTdsRat) (PasseTypeNop) (PasseNop) (PasseCodeNopNop)
(* + passe de typage *)
(*
open PasseTdsRat
open PasseTypeRat
module CompilateurRat = Compilateur (PasseTdsRat) (PasseTypeRat) (PassePlacementNop) (PasseCodeNopNop)
*)
(* + passe de placement mémoire *)
(*
open PasseTdsRat
open PasseTypeRat
open PassePlacementRat
module CompilateurRat = Compilateur (PasseTdsRat) (PasseTypeRat) (PassePlacementRat) (PasseCodeNop)
*)
(* + passe de génération de code -> compilateur complet *)
(*
open PasseTdsRat
open PasseTypeRat
open PassePlacementRat
open PasseCodeRatToTam
module CompilateurRat = Compilateur (PasseTdsRat) (PasseTypeRat) (PassePlacementRat) (PasseCodeRatToTam)
*)
open Lexing
(* report_error : string -> Lexing.lexbuf -> string -> unit *)
(* Affiche un message d'erreur lorsque le fichier n'est pas conforme à la grammaire *)
(* filename : le nom du fichier non conforme *)
(* lexbuf : l'analyser lexical *)
(* msg : le message d'erreur à afficher *)
let report_error filename lexbuf msg =
let (b,e) = (lexeme_start_p lexbuf, lexeme_end_p lexbuf) in
let fc = b.pos_cnum - b.pos_bol + 1 in
let lc = e.pos_cnum - b.pos_bol + 1 in
Printf.eprintf "File \"%s\", line %d, characters %d-%d: %s\n" filename b.pos_lnum fc lc msg
(* compiler : string -> string *)
(* Compilter un code rat en un code TAM *)
(* Paramètre ratfile : le nom du fichier rat à compiler *)
(* Utilise le compilateur "CompilateurRat" pour générer le code associé au fichier rat *)
(* Erreur si soucis lors de l'analyse lexicale, l'analyse syntaxique,
mauvaise utilisation des identifiants ou soucis de typage *)
let compiler ratfile =
let input = open_in ratfile in
let filebuf = Lexing.from_channel input in
try
let ast = Parser.main Lexer.token filebuf in
"; " ^ ratfile ^ "\n" ^ (CompilateurRat.analyser ast)
with
| Lexer.Error _ as e ->
report_error ratfile filebuf "lexical error (unexpected character).";
raise e
| Parser.Error as e->
report_error ratfile filebuf "syntax error.";
raise e
(* compilerVersFichier : string -> string -> () *)
(* Compiler un code rat en un code TAM et le sauve dans un fichier *)
(* ratfile : le nom du fichier rat à compiler *)
(* tamfile : le nom du fichier rat où sauver le résultat *)
let compilerVersFichier ratfile tamfile =
let tamcode = compiler ratfile in
let chan = open_out tamfile in
output_string chan tamcode;
close_out chan