OpenCores
URL https://opencores.org/ocsvn/minimips/minimips/trunk

Subversion Repositories minimips

[/] [minimips/] [trunk/] [gasm/] [src/] [analyseur.c] - Rev 15

Go to most recent revision | Compare with Previous | Blame | View Log

/*********************************************************************************************/
/* MODULE ANALYSEUR                                                                          */
/* Ce module a pour but de parcourir le fichier assembleur en effectuant la correspondance   */
/* du code source avec la syntaxe acceptée par le langage. La lecture se fait lexème par     */
/* lexème en utilisant le préprocesseur.                                                     */
/* Il se charge de générer la pile de précode qu sera utilisée par le syntéthiseur pour      */
/* générer le code final.                                                                    */
/*********************************************************************************************/
 
#include "analyseur.h"
 
/* Inclusion des autres modules du projet utilisés.                                          */
#include <debogueur.h>
#include <parametres.h>
#include <dialogue.h>
#include <formateur.h>
#include <preprocesseur.h>
#include <adaptateur.h>
 
type_precode * file_precode=NULL, * fin_file_precode=NULL;
 
int nprc_alloc=0; /* Compteur du nombre de précodes alloués.                                 */
 
/* fonctions de filtrage et de comparaison des lexèmes (sensibles ou non à la casse).        */
#define filtre(l, filtre)       filtre_lexeme(l, filtre, casse_sens)
#define compare_lexeme(l1, l2)  (casse_sens ? lexid(l1, l2) : lexcaseid(l1,l2))
 
/* Pointeur sur la file de lexèmes composant l'argument courant.                             */
static type_file_lexeme * ptr_arg=NULL;
 
/* ajoute le lexème sur la pile de lexèmes locale (instruction en cours).                    */
void push_local(type_lexeme * l)
{
        type_file_lexeme * nouv;
 
        nouv = (type_file_lexeme *) malloc(sizeof(type_file_lexeme));
        if (nouv==NULL) DIALOGUE("analyseur(push_local)", 0, F_ERR_MEM);
 
        nouv->suivant=ptr_arg;
        nouv->lexeme=l;
        ptr_arg=nouv;
}
 
/* Fonction récursive d'analyse du code assembleur.                                          */
type_feuille * analyse_rec(type_noeud * n_cour)
{
        type_lexeme * l_cour;
        type_noeud * fils_cour;
 
        l_cour=pop_lexeme();    /* Lecture d'un lexème par le préprocesseur.                 */
        fils_cour=n_cour->ptr_fils;
 
        while (fils_cour!=NULL && l_cour!=NULL)
        {
                if (filtre(l_cour, &(fils_cour->lexeme)))
                { /* Les lexèmes sont compatibles.                                           */
                        type_feuille * rescur;
                        rescur=analyse_rec(fils_cour);
                        if (rescur!=NULL) 
                        {  /* Validation de la transition.                                   */
                                push_local(l_cour);     /* Ajout dans la file locale.        */
                                return rescur;
                        }
                }
                /* La transition n'est pas validée.                                          */
                fils_cour=fils_cour->ptr_frere; /* On passe à la transition suivante.        */
        }
 
        push_lexeme(l_cour);            /* Le lexème est rendu au préprocesseur.             */
        return (n_cour->ptr_feuille);   /* Si la feuille est valide, l'instruction l'est.    */
}
 
/*********************************************************************************************/
/*                                                                                           */
/* Point d'entrée principal du module, fonction d'analyse. Les données analysées sont celles */
/* fournies par le préprocesseur qui doit être préalablement initialisé.                     */
/*                                                                                           */
/*********************************************************************************************/
 
/* Macro d'initialisation d'un nouveau précode.                                              */
#define INIT_PRECODE(precode)   \
{\
        ALLOC_PREC(precode)\
        precode->fichier_orig=f_orig;\
        precode->ligne_orig=l_orig;\
        precode->pco=pco;\
}
 
/* Macro d'ajout d'un précode en queue de la file.                                           */
#define EMPILE_PRECODE(precode) \
{\
        if (file_precode==NULL)\
        {\
                file_precode=precode;\
                fin_file_precode=precode;\
        }\
        else\
        {\
                fin_file_precode->suivant=precode;\
                fin_file_precode=precode;\
        }\
}
 
int analyse()
{
        int err=0;
        char * msg_orig = "analyseur(analyse)";
        type_lexeme * lex;
 
        pco = 0; /* Initialisation du pseudo compteur ordinal.                               */
 
        if (seplex == NULL)
        { /* Utilisation du séparateur par défaut.                                           */
                DIALOGUE(NULL, 0, W_SEPLEX_INIT);
                seplex=(type_lexeme *) malloc(sizeof(type_lexeme));
                if (seplex==NULL) DIALOGUE(msg_orig, 0, F_ERR_MEM);
                seplex->type = POS_MPV(OP);
                seplex->valeur.op = NL;
        }
 
        while ((lex = pop_lexeme())!=NULL) /* Analyse jusqu'à la fin du fichier.             */
        {
                int l_orig = ligne_courante();  /* On conserve la ligne de l'instruction.    */
                char * f_orig = gen_orig_msg(); /* On conserve le fichier d'origine.         */
                type_feuille * feuille;
 
                push_lexeme(lex);               /* On rend le lexème au prépreocesseur.      */
                feuille = analyse_rec(root);    /* Analyse de l'instruction suivante.        */
 
                if (feuille==NULL)
                { /* L'instruction n'a pas été reconnue.                                     */
                        type_lexeme * lex_depile;
                        type_precode * err_pcd;
                        INIT_PRECODE(err_pcd);
                        err++;                  /* Détection d'une erreur de syntaxe.        */
                        err_pcd->erreur=S_SYN_ERR; /* Mise à jour du code d'erreur.          */
                        EMPILE_PRECODE(err_pcd); /* Empilage du lexème erreur.               */
 
                        DIALOGUE(f_orig, l_orig, S_SYN_ERR);
 
                        while ((lex_depile=pop_lexeme())!=NULL
                                        && !compare_lexeme(lex_depile, seplex))
                        { /* On recherche le prochain lexème de séparation.                  */
                                FREE_LEX(lex_depile);
                        }
                        if (lex_depile!=NULL) FREE_LEX(lex_depile); /* Efface le "seplex".   */
                }
                else
                { /* L'instruction a été validée. Génération du précode.                     */
                        type_precode * pcd;
                        int p2f[MAX_FONCTIONS]; /* tableau des fonctions de seconde passe.   */
                        int i;
                        INIT_PRECODE(pcd);
 
                        /* Recopie de la file des lexèmes ayant validé l'instruction.        */
                        pcd->param = ptr_arg;
 
                        /* Recopie du masque de la feuille.                                  */
                        if (feuille->mask_primaire==NULL) pcd->mask=NULL;
                        else
                        {
                                ALLOC_MASK(pcd->mask);
                                if (pcd->mask==NULL)
                                        DIALOGUE(msg_orig, 0, F_ERR_MEM);
                                pcd->mask->valeur=feuille->mask_primaire->valeur;
                                pcd->mask->taille=feuille->mask_primaire->taille;
                        }
 
                        for (i=0 ; i<feuille->nbr_func ; i++)
                        { /* Tentative d'application des fonctions de l'adaptateur.          */
                                type_mask *  res = (feuille->ptr_func)[i](ptr_arg);
 
                                /* Différents cas de réponse de l'adaptateur.                */
                                switch (eval_code)
                                {
                                case EVAL_REUSSIE    :  /* Evalutation réussie.              */
                                        if (pcd->mask==NULL) 
                                        {
                                                pcd->mask=res; /* Pas encore de masque.      */
                                                res=NULL; /* Evite que le masque soit vidé.  */
                                                break;
                                        }
                                        if (res==NULL) break; /* Rien à faire.               */
                                        if (res->taille==pcd->mask->taille)
                                        { /* On ajoute le nouveau masque.                    */
                                                pcd->mask->valeur|=res->valeur;
                                                break;
                                        }
                                        /* Le masque retourné est incompatible.              */
                                        DIALOGUE(f_orig, l_orig, S_FUN_ERR);
                                        CLEAR_PRECODE(pcd); /* Le précode est une erreur.    */
                                        pcd->erreur=S_FUN_ERR;
                                        err++;
                                        break;
                                case EVAL_IMPOSSIBLE :  /* Fonction de seconde passe.        */
                                        p2f[(int)(pcd->nbr_func)++]=i;
                                        break;
                                case EVAL_ERREUR     :  /* Erreur de l'adaptateur/Syntaxe.   */
                                        affiche_message(f_orig, l_orig);
                                        err++;
                                        CLEAR_PRECODE(pcd); /* Le précode est une erreur.    */
                                        pcd->erreur=err_code;
                                        break;
                                default              :  /* Erreur de l'adaptateur.           */
                                        DIALOGUE(f_orig, l_orig, S_ADAP_ERR);
                                        CLEAR_PRECODE(pcd);
                                        pcd->erreur=S_ADAP_ERR;
                                        err++;
                                        break;
                                }
                                if (res!=NULL) FREE_MASK(res); /* Suppression du masque.     */
                        }
 
                        if (pcd->nbr_func!=0) /* Recopie des pointeurs vers les p2f.         */
                        { /* Il reste des fonctions de seconde passe.                        */
                                pcd->func=(type_ptr_fgm*) /* On crée le tableau.             */
                                        malloc((pcd->nbr_func)*sizeof(type_ptr_fgm));
                                for (i=0; i<pcd->nbr_func; i++)
                                { /* On recopie les fonctions de seconde passe.              */
                                        (pcd->func)[i]=(feuille->ptr_func)[p2f[i]];
                                }
                        }
                        else 
                        { /* Plus de fonctions de seconde passe, effacement des arguments.   */
                                pcd->func = NULL;
                                FREE_ARGS(pcd->param);
                        }
 
                        if ((pcd->mask==NULL || pcd->mask->taille==0) && pcd->func==NULL
                                        && pcd->erreur==NO_ERR)
                        { /* On supprime le précode s'il est vide.                           */
                                FREE_PRECODE(pcd);
                        }
                        else 
                        {
                                EMPILE_PRECODE(pcd);
                                if (pcd->mask!=NULL) pco+=pcd->mask->taille;
                        }
 
                        ptr_arg=NULL; /* Réinitialisation du pointeur de file de lexèmes.    */
                }
        }
        return err;
}
 
/* Cette fonction libère les structures de précode allouées lors de l'analyse. Les données   */
/* non écrites par le synthétiseur seront perdues.                                           */
void clear_analyseur()
{
        while (file_precode!=NULL)
        {
                type_precode * pcd=file_precode;
                file_precode=pcd->suivant;
                FREE_PRECODE(pcd);
        }
        fin_file_precode=NULL;
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.