/* * programme: lex.c * auteur: felipe@dift2030 * date: 10/09/2002 * * objet: illustrer le codage d'un analyseur lexical * par codage direct de l'automate associe (voir cours) * compilation: g++ -o lex lex.c * (pour pouvoir declarer localement une variable de for) */ #include #include // pour le strcmp #include // pour les fonctions isXXX /* * defines des classes */ #define LETTER 1 #define DIGIT 2 #define SPACE 3 /* * defines des tokens (les entiers retournes par lex) */ #define RESERVED 0 /* mots reserves */ #define IDENTIFICATEUR 1 /* un nom */ #define TYPE 2 /* ceux de la table types */ #define INT_LITERAL 3 /* ex: 12 */ #define FLOAT_LITERAL 4 /* ex: 12.5 */ #define BOOL_LITERAL 5 /* true ou false */ #define AFFECTATION 6 /* = */ #define SEP_INST 7 /* ; */ #define SEP_DECL 8 /* , */ #define OPEN_PAR 9 /* ( */ #define CLOSE_PAR 10 /* ) */ #define STRING 11 /* "une chaine" */ #define COMPARATOR 12 /* ceux de la table comparator */ #define OPERATOR 13 /* + - * / */ #define UNK -1 /* * les differentes tables */ #define MAX_RESERVED 9 char * (reserved[MAX_RESERVED]) = { "if", "then", "else", "read", "begin", "end", "write", "writeln", "while" }; #define MAX_TYPES 3 char * (types[MAX_TYPES]) = {"boolean","int","float"}; #define MAX_BOOLEAN_LITERAL 2 char * (booleen[MAX_BOOLEAN_LITERAL]) = {"true","false"}; /* * en pratique celle-ci est inutile * uniquement pour affichage a la fin */ char *(code[]) = { "RESERVED", "IDENTIFICATEUR", "TYPE", "INT_LITERAL", "FLOAT_LITERAL", "BOOL_LITERAL", "AFFECTATION", "SEP_INST", "SEP_DECL", "OPEN_PAR", "CLOSE_PAR", "STRING", "COMPARATOR", "OPERATOR" }; /* * autres variables globales */ #define MAXL 1000 // lg maximale d'un lexeme char lexeme[MAXL+1]; // contient le dernier lexeme analyse int L; // indice du dernier car dans lexeme int lastChar; // le dernier caractere lu (par getChar) int lastClass; // la deniere classe de lastChar /* * un peu de gestion d'erreur */ void error(char *message) { fprintf(stderr,"%s : %s\n",message,lexeme); exit(-1); } /* * lire un car depuis stdin et instancier les variables globales * lastChar et lastClass */ int getChar() { if (isspace(lastChar = getc(stdin))) lastClass = SPACE; else if (isdigit(lastChar)) lastClass = DIGIT; else if (isalpha(lastChar)) lastClass = LETTER; else lastClass = lastChar; return lastChar; } /* * ajout du dernier caractere lu dans lexeme */ void addChar() { if (L == MAXL) error("Debordement de la capacite de lexeme. Change le define MAXL dans lex.c et recompile ..."); lexeme[L++] = lastChar; lexeme[L] = 0; // le marqueur de fin de chaine } /* * recherche de mot dans la table (de max elts) * retourne l'indice de mot dans la table ou -1 */ int look(char *mot,char *(table[]),int max) { for (int i=0; i': case '=': addChar(); if (getChar() == '=') { addChar(); getChar(); } return COMPARATOR; break; case '"': // les chaines addChar(); while ((lastChar != EOF) && (getChar() != '"')) addChar(); if (lastChar == '"') {addChar(); getChar(); return STRING;} break; case SPACE: getChar(); return lex(); break; case EOF: return UNK; break; default: error("lexeme inconnu"); break; } // switch return UNK; // ne devrait jamais arriver } /* * lancement de l'analyseur lexical */ int main(int argc, char **argv) { int token; getChar(); while ((token=lex()) != UNK) { fprintf(stderr,"%s\t%d\t%s\n",lexeme,token,code[token]); } }