#include #include #include #include #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", "pour", '\0' }; int codeMotClefs[] = { SI, ALORS, SINON, TANTQUE, FAIRE, ENTIER, RETOUR, LIRE, ECRIRE, POUR }; char yytext[YYTEXT_MAX]; int yyleng; int nbMotsClefs = 10; /* 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); }