Réaliser un compilateur pour le langage micrOCAML décrit
ci-dessous. Ce compilateur produira en sortie du code assembleur MIPS. Cet
assembleur très simple est proche du code 3 adresses vu en cours et en TD.
On donne ci-dessous la grammaire complète du langage micrOCAML.
Ce langage est un sous-ensemble impératif de OCAML. Dans
cette grammaire, les mots-clés et les terminaux apparaissent en fonte
courrier. Les constantes booléennes sont true
et false. Le terminal ident représente les
identificateurs qui sont formés d’une lettre minuscule suivi d’une suite
de caractères alphanumériques ou d’une apostrophe ou du caractère de
soulignement. Les commentaires débutent par les deux caractères (*
et se terminent par les deux caractères *). Ils peuvent être
imbriqués (pour implémenter l'imbrication de commentaires avec Lex, vous
pouvez utiliser les start conditions). Les tableaux sont
unidimensionnels et indicés à partir de 0. Par convention syntaxique, un
appel de procédure ne doit pas apparaître seul dans la
branche then d'un if. Par
exemple, if !x>0 then proc(x) else x := 0 est
syntaxiquement incorrect ! A la place, on peut par exemple écrire if
!x>0 then begin proc(x) end else x := 0.
program → decllist instr ;;
decllist → ε | decl in decllist
in vardecllistlet ident : type =
valcst // déclaration d'une constante
| let ident :
atomictype ref = ref atomiccst
// déclaration et initialisation d'une variablelet fundef | let rec fundefs
// groupe de fonctions ou procédures (mutuellement récursives) | fundef and fundefsident arglist = vardecllist instr
// déclaration d'une procédure
| ident arglist : atomictype
= vardecllist instr ; expr //
déclaration d'une fonction
| ident arglist : atomictype
= vardecllist expr // déclaration d'une
fonction pure
type →
atomictype | atomictype
array
atomictype → bool | intatomiccst | Array.make
integer atomiccst
atomiccst → integer | ( - integer ) | boolean
( ) | arglist1
arglist1 → ( arg )
| ( arg ) arglist1
arg → ident : type | ident
: atomictype ref
instr → if expr then instr
// conditionnelle
| if expr then instr else
instr // alternative
| while expr do sequence
done // itération
| begin sequence end |
begin end
// bloc d'instructions
| ident := expr
// affectation d'une variable
| ident . ( expr ) <-
expr // affectation d'un élément de
tableau
| ident exprlist | ident
( ) // appel de procédure
| print_int expr
// écriture d'un entier sur la sortie standard
| print_string string
// écriture d'une chaîne de caractères
sequence → instr | sequence ; instr
integer | boolean | ( expr
) | expr opb expr | opu expr
|
if expr then expr else expr
// alternative
|
ident exprlist | ident ( )
// appel de fonction
|
read_int ( ) // valeur
d'un entier lu sur l'entrée standard
| ident
// valeur d'une constante
| !
ident // valeur d'une
variable
|
ident . ( expr ) // valeur
d'un élément de tableau
exprlist → expr | exprlist expr
opb → + | − | ∗ | /
| < | <= | > | >=
| = | <> | && | ||
opu → − | not
micrOCAML
micrOCAML peuvent être exécutés en utilisant
l'interpréteur ou le compilateur OCAML (ces outils sont
installés sur la machine turing) : "essai.ml",
situé dans le répertoire courant, avec l'interpréteur, il suffit de taper la
commande ocaml essai.ml : $ cat essai.ml
(* Un simple Hello World ! *)
begin
print_string "Hello World !\n"
end
$ ocaml essai.ml
Hello World !
$
OCAML. La commande est ocamlc :$ ocamlc essai.ml
$ ./a.out
Hello World !
$ OCAML
comme modèle dans la mesure où le code exécutable généré par votre
compilateur doit se comporter comme le code exécutable généré par le
compilateur OCAML. Mais puisque micrOCAML est
seulement un sous-ensemble de OCAML, les erreurs détectées
par votre compilateur ne sont pas les mêmes que celles du compilateur OCAML.
D'autre part, comme votre langage source est uniquement impératif et que
le langage OCAML est avant tout fonctionnel, les techniques
de compilation utilisées ne sont pas les mêmes.
Le code généré devra être en assembleur MIPS R2000. L’assembleur est
décrit dans les documents mips.pdf et mips.ps.
Voici des exemples de codes MIPS :
Le code assembleur devra être exécuté à l’aide du
simulateur de processeur R2000 SPIM. Celui-ci est installé
sur la machine turing. Pour exécuter un code assembleur, il
suffit de faire : spim <nom_du_code>.s. Si vous
désirez installer SPIM sur votre propre machine :
tar xvfz spim.tar.gz cd spim-8.0/spim./Configure // Vérifier qu’il n’y a pas de messages
d’erreur (librairie ou logiciel manquant) Makefile la
ligne EXCEPTION_DIR = en y saisissant le chemin d’accès
au répertoire contenant le fichier exceptions.s. Il
s’agit du répertoire : /chemin_vers_votre_racine/spim-8.0/CPU make