D’abord, quand on exécute mcc
, il va
commencer par exécuter le code qui se trouve dans le fichier
main.ml
.
Celui-ci lit les options de commande (-E
par
exemple), puis appelle l’analyseur syntaxique
Ctab.translation_unit
, auquel on passe
l’analyseur lexical Clex.ctoken
.
Le source de l’analyseur syntaxique, qui servira aussi de
documentation pour la grammaire du langage C--, est dans le fichier
ctab.mly
. La description des
tokens lexicaux est dans clex.mll
.
L’analyseur syntaxique fournit un programme sous forme d’une liste de
Cparse.var_declaration
. Les d’une liste de
var_declaration
sont déclarées au début du
fichier cparse.ml
, comme suit:
type mon_op = M_MINUS | M_NOT | M_POST_INC | M_POST_DEC | M_PRE_INC | M_PRE_DEC (* Les operations unaires: M_MINUS: calcule l'oppose -e de e; M_NOT: calcule la negation logique ~e de e; M_POST_INC: post-incrementation e++; M_POST_DEC: post-decrementation e--; M_PRE_INC: pre-incrementation ++e; M_PRE_DEC: pre-decrementation --e. *) type bin_op = S_MUL | S_DIV | S_MOD | S_ADD | S_SUB | S_INDEX (* Les operations binaires: S_MUL: multiplication entiere; S_DIV: division entiere (quotient); S_MOD: division entiere (reste); S_ADD: addition entiere; S_SUB: soustraction entiere; S_INDEX: acces \`a un element de tableau a[i]. *) type cmp_op = C_LT | C_LE | C_EQ (* Les operations de comparaison: C_LT (less than): <; C_LE (less than or equal to): <=; C_EQ (equal): ==. *) type loc_expr = locator * expr and expr = VAR of string (* une variable --- toujours de type int. *) | CST of int (* une constante entiere. *) | STRING of string (* une constante chaine. *) | SET_VAR of string * loc_expr (* affectation x=e. *) | SET_ARRAY of string * loc_expr * loc_expr (* affectation x[e]=e'. *) | CALL of string * loc_expr list (* appel de fonction f(e1,...,en) *) (* operations arithmetiques: *) | OP1 of mon_op * loc_expr (* OP1(mop, e) denote -e, ~e, e++, e--, ++e, ou --e. *) | OP2 of bin_op * loc_expr * loc_expr (* OP2(bop,e,e') denote e*e', e/e', e%e', e+e', e-e', ou e[e']. *) | CMP of cmp_op * loc_expr * loc_expr (* CMP(cop,e,e') vaut e<e', e<=e', ou e==e' *) | EIF of loc_expr * loc_expr * loc_expr (* EIF(e1,e2,e3) est e1?e2:e3 *) | ESEQ of loc_expr list (* e1, ..., en [sequence, analogue a e1;e2 au niveau code]; si n=0, represente skip. *) type var_declaration = CDECL of locator * string (* declaration de variable de type int. *) | CFUN of locator * string * var_declaration list * loc_code (* fonction avec ses arguments, et son code. *) and loc_code = locator * code and code = CBLOCK of var_declaration list * loc_code list (* { declarations; code; } *) | CEXPR of loc_expr (* une expression e; vue comme instruction. *) | CIF of loc_expr * loc_code * loc_code (* if (e) c1; else c2; *) | CWHILE of loc_expr * loc_code (* while (e) c1; *) | CRETURN of loc_expr option (* return; ou return (e); *) |
Le type locator
est juste un pointeur sur des
informations permettant aux fonctions
Error.error
et
Error.warning
d’afficher des message d’erreur
sensés.
Le fichier cparse.ml
contient aussi des
fonctions utiles, comme string_of_loc_expr
,
qui vous permettent d’obtenir une version imprimable d’une expression
C--, ce que vous pouvez utiliser en phase de débogage.
Le fichier genlab.ml
contient une fonction
genlab
qui vous permettra de fabriquer des labels uniques,
ce qui devrait être bien pratique lorsque vous émettrez des
instructions de saut dans votre code assembleur.
Le fichier verbose.ml
déclare une variable
verbose
que vous pourrez tester pour régler
le niveau d’informations de débogage que vous voudrez afficher (elle
vaut 1 si vous appelez mcc
avec l’option
-v1
, 2 si avec l’option
-v2
, et 0 par défaut).