Files
compilateur-l/src/analyseur_lexical.c

250 lines
6.8 KiB
C

#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "symboles.h"
#include "analyseur_lexical.h"
#include "util.h"
#define YYTEXT_MAX 100
#define is_num(c)(('0' <= (c)) && ((c) <= '9'))
#define is_maj(c)(('A' <= (c)) && ((c) <= 'Z'))
#define is_min(c)(('a' <= (c)) && ((c) <= 'z'))
#define is_alpha(c)(is_maj(c) || is_min(c) || (c) == '_' || (c) == '$')
#define is_alphanum(c)(is_num((c)) || is_alpha((c)))
extern FILE *yyin;
char tableSymbole[] = {
';', ',', '(', ')', '[', ']', '{', '}', // Code
'+', '-', '*', '/', // Arithmetique
'<', '=', // Comparaison
'&','|', '!' , // Logique
'\0'
};
int codeSymbole[] = {
POINT_VIRGULE, VIRGULE, PARENTHESE_OUVRANTE, PARENTHESE_FERMANTE, CROCHET_OUVRANT, CROCHET_FERMANT, ACCOLADE_OUVRANTE, ACCOLADE_FERMANTE,
PLUS, MOINS, FOIS, DIVISE,
INFERIEUR, EGAL,
ET, OU, NON
};
char *tableMotsClefs[] = {
"si", "alors", "sinon", "tantque", "faire", "entier", "retour", "lire", "ecrire", '\0'
};
int codeMotClefs[] = {
SI, ALORS, SINON, TANTQUE, FAIRE, ENTIER, RETOUR, LIRE, ECRIRE
};
char yytext[YYTEXT_MAX];
int yyleng;
int nbMotsClefs = 9;
/* Compter les lignes pour afficher les messages d'erreur avec numero ligne */
int nb_ligne = 1;
/*******************************************************************************
* Fonction qui ignore les espaces et commentaires.
* Renvoie -1 si arrivé à la fin du fichier, 0 si tout va bien
******************************************************************************/
int mangeEspaces()
{
char c = fgetc(yyin);
int comment = 0;
while( comment || (c == ' ') || (c == '\n') || (c == '\t') || (c == '#' ) ) {
if( c == '#' ) {
comment = 1;
}
if( c == '\n' ) {
nb_ligne++;
comment = 0;
}
c = fgetc(yyin);
}
if ( feof(yyin) ) {
return -1;
}
ungetc(c, yyin);
return 0;
}
/*******************************************************************************
* Lit un caractère et le stocke dans le buffer yytext
******************************************************************************/
char lireCar(void)
{
yytext[yyleng++] = fgetc(yyin);
yytext[yyleng] = '\0';
return yytext[yyleng - 1];
}
/*******************************************************************************
* Remet le dernier caractère lu au buffer clavier et enlève du buffer yytext
******************************************************************************/
void delireCar()
{
char c;
c = yytext[yyleng - 1];
yytext[--yyleng] = '\0';
ungetc(c, yyin);
}
/*******************************************************************************
* Fonction principale de l'analyseur lexical, lit les caractères de yyin et
* renvoie les tokens sous forme d'entier. Le code de chaque unité est défini
* dans symboles.h sinon (mot clé, idententifiant, etc.). Pour les tokens de
* type ID_FCT, ID_VAR et NOMBRE la valeur du token est dans yytext, visible
* dans l'analyseur syntaxique.
******************************************************************************/
int yylex(void)
{
char c;
int i;
yytext[yyleng = 0] = '\0';
if (mangeEspaces() == -1)
return FIN;
c = lireCar();
// Symbole simple
for( int i = 0; tableSymbole[i] != '\0'; ++i ) {
if( c == tableSymbole[i] ) {
return codeSymbole[i];
}
}
// Nombre
if( is_num( c ) )
{
do {
lireCar();
} while( is_num( yytext[yyleng-1] ) );
delireCar();
return NOMBRE;
}
//id_var
if( c == '$' ) {
i = 1; // 1 pour $
do {
lireCar();
i++;
} while( is_alphanum( yytext[yyleng-1] ) );
i--;
delireCar();
if(i > 99) {
return -1;
}
return ID_VAR;
}
// Mot clefs
do {
lireCar();
} while( is_alphanum( yytext[yyleng-1] ) );
delireCar();
for( int i = 0; tableMotsClefs[i] != '\0'; ++i )
{
if( strcmp( tableMotsClefs[i], yytext ) == 0 ) {
return codeMotClefs[i];
}
}
for(; yyleng != 1; delireCar() );
//id_fct
if( is_alpha( c ) ) {
int i = 1; // 1 pour $
do {
lireCar();
i++;
} while( is_alphanum( yytext[yyleng-1] ) );
i--;
delireCar();
if(i > 99) {
return -1;
}
return ID_FCT;
}
erreur("Aucune Correspondance");
return -1;
}
/*******************************************************************************
* Fonction auxiliaire appelée par l'analyseur syntaxique tout simplement pour
* afficher des messages d'erreur et l'arbre XML
******************************************************************************/
void nom_token( int token, char *nom, char *valeur ) {
int i;
strcpy( nom, "symbole" );
if(token == POINT_VIRGULE) strcpy( valeur, "POINT_VIRGULE");
else if(token == PLUS) strcpy(valeur, "PLUS");
else if(token == MOINS) strcpy(valeur, "MOINS");
else if(token == FOIS) strcpy(valeur, "FOIS");
else if(token == DIVISE) strcpy(valeur, "DIVISE");
else if(token == PARENTHESE_OUVRANTE) strcpy(valeur, "PARENTHESE_OUVRANTE");
else if(token == PARENTHESE_FERMANTE) strcpy(valeur, "PARENTHESE_FERMANTE");
else if(token == CROCHET_OUVRANT) strcpy(valeur, "CROCHET_OUVRANT");
else if(token == CROCHET_FERMANT) strcpy(valeur, "CROCHET_FERMANT");
else if(token == ACCOLADE_OUVRANTE) strcpy(valeur, "ACCOLADE_OUVRANTE");
else if(token == ACCOLADE_FERMANTE) strcpy(valeur, "ACCOLADE_FERMANTE");
else if(token == EGAL) strcpy(valeur, "EGAL");
else if(token == INFERIEUR) strcpy(valeur, "INFERIEUR");
else if(token == ET) strcpy(valeur, "ET");
else if(token == OU) strcpy(valeur, "OU");
else if(token == NON) strcpy(valeur, "NON");
else if(token == FIN) strcpy(valeur, "FIN");
else if(token == VIRGULE) strcpy(valeur, "VIRGULE");
else if( token == ID_VAR ) {
strcpy( nom, "id_variable" );
strcpy( valeur, yytext );
}
else if( token == ID_FCT ) {
strcpy( nom, "id_fonction" );
strcpy( valeur, yytext );
}
else if( token == NOMBRE ) {
strcpy( nom, "nombre" );
strcpy( valeur, yytext );
}
else {
strcpy( nom, "mot_clef" );
for(i=0; i < nbMotsClefs; i++){
if( token == codeMotClefs[i] ){
strcpy( valeur, tableMotsClefs[i] );
break;
}
}
}
}
/*******************************************************************************
* Fonction auxiliaire appelée par le compilo en mode -l, pour tester l'analyseur
* lexical et, étant donné un programme en entrée, afficher la liste des tokens.
******************************************************************************/
void test_yylex_internal(FILE *yyin) {
int uniteCourante;
char nom[100];
char valeur[100];
do {
uniteCourante = yylex();
nom_token( uniteCourante, nom, valeur );
printf("%s\t%s\t%s\n", yytext, nom, valeur);
} while (uniteCourante != FIN);
}