1 |
13 |
louismarie |
/*********************************************************************************************/
|
2 |
|
|
/* MODULE ANALYSEUR */
|
3 |
|
|
/* Ce module a pour but de parcourir le fichier assembleur en effectuant la correspondance */
|
4 |
|
|
/* du code source avec la syntaxe acceptée par le langage. La lecture se fait lexème par */
|
5 |
|
|
/* lexème en utilisant le préprocesseur. */
|
6 |
|
|
/* Il se charge de générer la pile de précode qu sera utilisée par le syntéthiseur pour */
|
7 |
|
|
/* générer le code final. */
|
8 |
|
|
/*********************************************************************************************/
|
9 |
|
|
|
10 |
|
|
#include "analyseur.h"
|
11 |
|
|
|
12 |
|
|
/* Inclusion des autres modules du projet utilisés. */
|
13 |
|
|
#include <debogueur.h>
|
14 |
|
|
#include <parametres.h>
|
15 |
|
|
#include <dialogue.h>
|
16 |
|
|
#include <formateur.h>
|
17 |
|
|
#include <preprocesseur.h>
|
18 |
|
|
#include <adaptateur.h>
|
19 |
|
|
|
20 |
|
|
type_precode * file_precode=NULL, * fin_file_precode=NULL;
|
21 |
|
|
|
22 |
|
|
int nprc_alloc=0; /* Compteur du nombre de précodes alloués. */
|
23 |
|
|
|
24 |
|
|
/* fonctions de filtrage et de comparaison des lexèmes (sensibles ou non à la casse). */
|
25 |
|
|
#define filtre(l, filtre) filtre_lexeme(l, filtre, casse_sens)
|
26 |
|
|
#define compare_lexeme(l1, l2) (casse_sens ? lexid(l1, l2) : lexcaseid(l1,l2))
|
27 |
|
|
|
28 |
|
|
/* Pointeur sur la file de lexèmes composant l'argument courant. */
|
29 |
|
|
static type_file_lexeme * ptr_arg=NULL;
|
30 |
|
|
|
31 |
|
|
/* ajoute le lexème sur la pile de lexèmes locale (instruction en cours). */
|
32 |
|
|
void push_local(type_lexeme * l)
|
33 |
|
|
{
|
34 |
|
|
type_file_lexeme * nouv;
|
35 |
|
|
|
36 |
|
|
nouv = (type_file_lexeme *) malloc(sizeof(type_file_lexeme));
|
37 |
|
|
if (nouv==NULL) DIALOGUE("analyseur(push_local)", 0, F_ERR_MEM);
|
38 |
|
|
|
39 |
|
|
nouv->suivant=ptr_arg;
|
40 |
|
|
nouv->lexeme=l;
|
41 |
|
|
ptr_arg=nouv;
|
42 |
|
|
}
|
43 |
|
|
|
44 |
|
|
/* Fonction récursive d'analyse du code assembleur. */
|
45 |
|
|
type_feuille * analyse_rec(type_noeud * n_cour)
|
46 |
|
|
{
|
47 |
|
|
type_lexeme * l_cour;
|
48 |
|
|
type_noeud * fils_cour;
|
49 |
|
|
|
50 |
|
|
l_cour=pop_lexeme(); /* Lecture d'un lexème par le préprocesseur. */
|
51 |
|
|
fils_cour=n_cour->ptr_fils;
|
52 |
|
|
|
53 |
|
|
while (fils_cour!=NULL && l_cour!=NULL)
|
54 |
|
|
{
|
55 |
|
|
if (filtre(l_cour, &(fils_cour->lexeme)))
|
56 |
|
|
{ /* Les lexèmes sont compatibles. */
|
57 |
|
|
type_feuille * rescur;
|
58 |
|
|
rescur=analyse_rec(fils_cour);
|
59 |
|
|
if (rescur!=NULL)
|
60 |
|
|
{ /* Validation de la transition. */
|
61 |
|
|
push_local(l_cour); /* Ajout dans la file locale. */
|
62 |
|
|
return rescur;
|
63 |
|
|
}
|
64 |
|
|
}
|
65 |
|
|
/* La transition n'est pas validée. */
|
66 |
|
|
fils_cour=fils_cour->ptr_frere; /* On passe à la transition suivante. */
|
67 |
|
|
}
|
68 |
|
|
|
69 |
|
|
push_lexeme(l_cour); /* Le lexème est rendu au préprocesseur. */
|
70 |
|
|
return (n_cour->ptr_feuille); /* Si la feuille est valide, l'instruction l'est. */
|
71 |
|
|
}
|
72 |
|
|
|
73 |
|
|
/*********************************************************************************************/
|
74 |
|
|
/* */
|
75 |
|
|
/* Point d'entrée principal du module, fonction d'analyse. Les données analysées sont celles */
|
76 |
|
|
/* fournies par le préprocesseur qui doit être préalablement initialisé. */
|
77 |
|
|
/* */
|
78 |
|
|
/*********************************************************************************************/
|
79 |
|
|
|
80 |
|
|
/* Macro d'initialisation d'un nouveau précode. */
|
81 |
|
|
#define INIT_PRECODE(precode) \
|
82 |
|
|
{\
|
83 |
|
|
ALLOC_PREC(precode)\
|
84 |
|
|
precode->fichier_orig=f_orig;\
|
85 |
|
|
precode->ligne_orig=l_orig;\
|
86 |
|
|
precode->pco=pco;\
|
87 |
|
|
}
|
88 |
|
|
|
89 |
|
|
/* Macro d'ajout d'un précode en queue de la file. */
|
90 |
|
|
#define EMPILE_PRECODE(precode) \
|
91 |
|
|
{\
|
92 |
|
|
if (file_precode==NULL)\
|
93 |
|
|
{\
|
94 |
|
|
file_precode=precode;\
|
95 |
|
|
fin_file_precode=precode;\
|
96 |
|
|
}\
|
97 |
|
|
else\
|
98 |
|
|
{\
|
99 |
|
|
fin_file_precode->suivant=precode;\
|
100 |
|
|
fin_file_precode=precode;\
|
101 |
|
|
}\
|
102 |
|
|
}
|
103 |
|
|
|
104 |
|
|
int analyse()
|
105 |
|
|
{
|
106 |
|
|
int err=0;
|
107 |
|
|
char * msg_orig = "analyseur(analyse)";
|
108 |
|
|
type_lexeme * lex;
|
109 |
|
|
|
110 |
|
|
pco = 0; /* Initialisation du pseudo compteur ordinal. */
|
111 |
|
|
|
112 |
|
|
if (seplex == NULL)
|
113 |
|
|
{ /* Utilisation du séparateur par défaut. */
|
114 |
|
|
DIALOGUE(NULL, 0, W_SEPLEX_INIT);
|
115 |
|
|
seplex=(type_lexeme *) malloc(sizeof(type_lexeme));
|
116 |
|
|
if (seplex==NULL) DIALOGUE(msg_orig, 0, F_ERR_MEM);
|
117 |
|
|
seplex->type = POS_MPV(OP);
|
118 |
|
|
seplex->valeur.op = NL;
|
119 |
|
|
}
|
120 |
|
|
|
121 |
|
|
while ((lex = pop_lexeme())!=NULL) /* Analyse jusqu'à la fin du fichier. */
|
122 |
|
|
{
|
123 |
|
|
int l_orig = ligne_courante(); /* On conserve la ligne de l'instruction. */
|
124 |
|
|
char * f_orig = gen_orig_msg(); /* On conserve le fichier d'origine. */
|
125 |
|
|
type_feuille * feuille;
|
126 |
|
|
|
127 |
|
|
push_lexeme(lex); /* On rend le lexème au prépreocesseur. */
|
128 |
|
|
feuille = analyse_rec(root); /* Analyse de l'instruction suivante. */
|
129 |
|
|
|
130 |
|
|
if (feuille==NULL)
|
131 |
|
|
{ /* L'instruction n'a pas été reconnue. */
|
132 |
|
|
type_lexeme * lex_depile;
|
133 |
|
|
type_precode * err_pcd;
|
134 |
|
|
INIT_PRECODE(err_pcd);
|
135 |
|
|
err++; /* Détection d'une erreur de syntaxe. */
|
136 |
|
|
err_pcd->erreur=S_SYN_ERR; /* Mise à jour du code d'erreur. */
|
137 |
|
|
EMPILE_PRECODE(err_pcd); /* Empilage du lexème erreur. */
|
138 |
|
|
|
139 |
|
|
DIALOGUE(f_orig, l_orig, S_SYN_ERR);
|
140 |
|
|
|
141 |
|
|
while ((lex_depile=pop_lexeme())!=NULL
|
142 |
|
|
&& !compare_lexeme(lex_depile, seplex))
|
143 |
|
|
{ /* On recherche le prochain lexème de séparation. */
|
144 |
|
|
FREE_LEX(lex_depile);
|
145 |
|
|
}
|
146 |
|
|
if (lex_depile!=NULL) FREE_LEX(lex_depile); /* Efface le "seplex". */
|
147 |
|
|
}
|
148 |
|
|
else
|
149 |
|
|
{ /* L'instruction a été validée. Génération du précode. */
|
150 |
|
|
type_precode * pcd;
|
151 |
|
|
int p2f[MAX_FONCTIONS]; /* tableau des fonctions de seconde passe. */
|
152 |
|
|
int i;
|
153 |
|
|
INIT_PRECODE(pcd);
|
154 |
|
|
|
155 |
|
|
/* Recopie de la file des lexèmes ayant validé l'instruction. */
|
156 |
|
|
pcd->param = ptr_arg;
|
157 |
|
|
|
158 |
|
|
/* Recopie du masque de la feuille. */
|
159 |
|
|
if (feuille->mask_primaire==NULL) pcd->mask=NULL;
|
160 |
|
|
else
|
161 |
|
|
{
|
162 |
|
|
ALLOC_MASK(pcd->mask);
|
163 |
|
|
if (pcd->mask==NULL)
|
164 |
|
|
DIALOGUE(msg_orig, 0, F_ERR_MEM);
|
165 |
|
|
pcd->mask->valeur=feuille->mask_primaire->valeur;
|
166 |
|
|
pcd->mask->taille=feuille->mask_primaire->taille;
|
167 |
|
|
}
|
168 |
|
|
|
169 |
|
|
for (i=0 ; i<feuille->nbr_func ; i++)
|
170 |
|
|
{ /* Tentative d'application des fonctions de l'adaptateur. */
|
171 |
|
|
type_mask * res = (feuille->ptr_func)[i](ptr_arg);
|
172 |
|
|
|
173 |
|
|
/* Différents cas de réponse de l'adaptateur. */
|
174 |
|
|
switch (eval_code)
|
175 |
|
|
{
|
176 |
|
|
case EVAL_REUSSIE : /* Evalutation réussie. */
|
177 |
|
|
if (pcd->mask==NULL)
|
178 |
|
|
{
|
179 |
|
|
pcd->mask=res; /* Pas encore de masque. */
|
180 |
|
|
res=NULL; /* Evite que le masque soit vidé. */
|
181 |
|
|
break;
|
182 |
|
|
}
|
183 |
|
|
if (res==NULL) break; /* Rien à faire. */
|
184 |
|
|
if (res->taille==pcd->mask->taille)
|
185 |
|
|
{ /* On ajoute le nouveau masque. */
|
186 |
|
|
pcd->mask->valeur|=res->valeur;
|
187 |
|
|
break;
|
188 |
|
|
}
|
189 |
|
|
/* Le masque retourné est incompatible. */
|
190 |
|
|
DIALOGUE(f_orig, l_orig, S_FUN_ERR);
|
191 |
|
|
CLEAR_PRECODE(pcd); /* Le précode est une erreur. */
|
192 |
|
|
pcd->erreur=S_FUN_ERR;
|
193 |
|
|
err++;
|
194 |
|
|
break;
|
195 |
|
|
case EVAL_IMPOSSIBLE : /* Fonction de seconde passe. */
|
196 |
|
|
p2f[(int)(pcd->nbr_func)++]=i;
|
197 |
|
|
break;
|
198 |
|
|
case EVAL_ERREUR : /* Erreur de l'adaptateur/Syntaxe. */
|
199 |
|
|
affiche_message(f_orig, l_orig);
|
200 |
|
|
err++;
|
201 |
|
|
CLEAR_PRECODE(pcd); /* Le précode est une erreur. */
|
202 |
|
|
pcd->erreur=err_code;
|
203 |
|
|
break;
|
204 |
|
|
default : /* Erreur de l'adaptateur. */
|
205 |
|
|
DIALOGUE(f_orig, l_orig, S_ADAP_ERR);
|
206 |
|
|
CLEAR_PRECODE(pcd);
|
207 |
|
|
pcd->erreur=S_ADAP_ERR;
|
208 |
|
|
err++;
|
209 |
|
|
break;
|
210 |
|
|
}
|
211 |
|
|
if (res!=NULL) FREE_MASK(res); /* Suppression du masque. */
|
212 |
|
|
}
|
213 |
|
|
|
214 |
|
|
if (pcd->nbr_func!=0) /* Recopie des pointeurs vers les p2f. */
|
215 |
|
|
{ /* Il reste des fonctions de seconde passe. */
|
216 |
|
|
pcd->func=(type_ptr_fgm*) /* On crée le tableau. */
|
217 |
|
|
malloc((pcd->nbr_func)*sizeof(type_ptr_fgm));
|
218 |
|
|
for (i=0; i<pcd->nbr_func; i++)
|
219 |
|
|
{ /* On recopie les fonctions de seconde passe. */
|
220 |
|
|
(pcd->func)[i]=(feuille->ptr_func)[p2f[i]];
|
221 |
|
|
}
|
222 |
|
|
}
|
223 |
|
|
else
|
224 |
|
|
{ /* Plus de fonctions de seconde passe, effacement des arguments. */
|
225 |
|
|
pcd->func = NULL;
|
226 |
|
|
FREE_ARGS(pcd->param);
|
227 |
|
|
}
|
228 |
|
|
|
229 |
|
|
if ((pcd->mask==NULL || pcd->mask->taille==0) && pcd->func==NULL
|
230 |
|
|
&& pcd->erreur==NO_ERR)
|
231 |
|
|
{ /* On supprime le précode s'il est vide. */
|
232 |
|
|
FREE_PRECODE(pcd);
|
233 |
|
|
}
|
234 |
|
|
else
|
235 |
|
|
{
|
236 |
|
|
EMPILE_PRECODE(pcd);
|
237 |
|
|
if (pcd->mask!=NULL) pco+=pcd->mask->taille;
|
238 |
|
|
}
|
239 |
|
|
|
240 |
|
|
ptr_arg=NULL; /* Réinitialisation du pointeur de file de lexèmes. */
|
241 |
|
|
}
|
242 |
|
|
}
|
243 |
|
|
return err;
|
244 |
|
|
}
|
245 |
|
|
|
246 |
|
|
/* Cette fonction libère les structures de précode allouées lors de l'analyse. Les données */
|
247 |
|
|
/* non écrites par le synthétiseur seront perdues. */
|
248 |
|
|
void clear_analyseur()
|
249 |
|
|
{
|
250 |
|
|
while (file_precode!=NULL)
|
251 |
|
|
{
|
252 |
|
|
type_precode * pcd=file_precode;
|
253 |
|
|
file_precode=pcd->suivant;
|
254 |
|
|
FREE_PRECODE(pcd);
|
255 |
|
|
}
|
256 |
|
|
fin_file_precode=NULL;
|
257 |
|
|
}
|