#include #include // Macro à utiliser pour vérifier si il s'agit d'un symbole terminal ou non-term #define SYMBOLE(c) c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' int c; // unité lexicale courante : analyseur lexical simple > getc FILE *gramfile; // fichier à compiler contenant une descr. de grammaire HC //////////////////////////////////////////////////////////////////////////////// // STRUCTURES DE DONNEES - ARBRE ABSTRAIT // //////////////////////////////////////////////////////////////////////////////// typedef struct liste_sym_ { char sym; struct liste_sym_ *suivant; } liste_sym; typedef struct regle_ { char gauche; liste_sym *droite; } regle; typedef struct liste_regles_ { regle *regle; struct liste_regles_ *suivant; } liste_regles; //////////////////////////////////////////////////////////////////////////////// // CONSTRUCTEURS DES STRUCTURES DE DONNEES - ARBRE ABSTRAIT // //////////////////////////////////////////////////////////////////////////////// liste_sym *cree_liste_sym( char sym, liste_sym *suivant) { liste_sym *r = malloc( sizeof(liste_sym) ); r->sym = sym; r->suivant = suivant; return r; } //////////////////////////////////////////////////////////////////////////////// regle *cree_regle( char gauche, liste_sym *droite) { regle *r = malloc( sizeof(liste_regles) ); r->gauche = gauche; r->droite = droite; return r; } //////////////////////////////////////////////////////////////////////////////// liste_regles *cree_liste_regles( regle *regle, liste_regles *suivant) { liste_regles *r = malloc( sizeof(liste_regles) ); r->regle = regle; r->suivant = suivant; return r; } //////////////////////////////////////////////////////////////////////////////// // FONCTIONS UTILES QUI PEUVENT ETRE UTILISEES DANS LE COMPILATEUR // //////////////////////////////////////////////////////////////////////////////// void erreur( char attendu ) { fprintf( stderr, "ERREUR DE SYNTAXE : %c attendu, %c trouvé\n", attendu, c ); exit( -1 ); } //////////////////////////////////////////////////////////////////////////////// void consommer( char ctest ) { if( c == ctest ) { c = getc( gramfile ); } else { erreur( ctest ); } } //////////////////////////////////////////////////////////////////////////////// char consommerSymbole() { if( SYMBOLE(c) ) { char c_prev = c; c = getc( gramfile ); return c_prev; } else { erreur( 's' ); } } //////////////////////////////////////////////////////////////////////////////// // FONCTIONS D'ENSEMBLE DE CARACTÈRES - TRANSITIONS POUR LES TERMINAUX // //////////////////////////////////////////////////////////////////////////////// void alphabet_terminal( liste_regles *lr, char *sigma ) { int i; for( i = 0; i < 256; i++ ) { sigma[ i ] = 0; } liste_regles *lr_i = lr; if( lr_i != NULL ) { sigma[ lr_i->regle->gauche ] = 2; liste_sym *ls_i = lr_i->regle->droite; while( ls_i != NULL ) { if( sigma[ ls_i->sym ] != 2 ) { sigma[ ls_i->sym ] = 1; } ls_i = ls_i->suivant; } lr_i = lr_i->suivant; } for( i = 0; i < 256; i++ ) { if( sigma[ i ] == 2 ) { sigma[ i ] = 0; } } } //////////////////////////////////////////////////////////////////////////////// // GENERATION DE L'AUTOMATE PAR PARCOURS DE L'ARBRE ABSTRAIT - GEN. CODE // //////////////////////////////////////////////////////////////////////////////// int etat = 4; void parcours_symboles( int prec, char gauche, liste_sym *droite ) { if( droite != NULL ) { int new_etat = etat++; parcours_symboles( new_etat, gauche, droite->suivant ); printf( "%d\t%d\tEPS\tEPS\t%c\n", new_etat, prec, droite->sym ); } else { printf( "2\t%d\tEPS\t%c\tEPS\n", prec, gauche ); } } //////////////////////////////////////////////////////////////////////////////// void genere_automate( liste_regles *lr, char *sigma ) { int i; // EPS -> epsilon, BOT -> bottom (fin de pile/chaine d'entrée) printf( "0\t1\tEPS\tEPS\tBOT\n" ); printf( "1\t2\tEPS\tEPS\t%c\n", lr->regle->gauche ); printf( "2\t3\tBOT\tBOT\tBOT\n" ); for( i = 0; i < 256; i++ ) { if( sigma[i] == 1 ) { printf( "2\t2\t%c\t%c\tEPS\n", i, i ); } } liste_regles *lr_i = lr; while( lr_i != NULL ) { parcours_symboles( 2, lr_i->regle->gauche, lr_i->regle->droite ); lr_i = lr_i->suivant; } } //////////////////////////////////////////////////////////////////////////////// // 3 FONCTIONS POUR ANALYSE SYNTAXIQUE - GRAMMAIRE TRES SIMPLE gobjet.txt // //////////////////////////////////////////////////////////////////////////////// liste_sym *listeSymboles() { char S1; liste_sym *S2; if( SYMBOLE(c) ) { S1 = consommerSymbole(); S2 = listeSymboles(); return cree_liste_sym( S1, S2 ); } else if( c != ';' ) { erreur( ';' ); } return NULL; // prod vide } //////////////////////////////////////////////////////////////////////////////// regle *reg() { char S1 = consommerSymbole(); consommer( '>' ); liste_sym *S2 = listeSymboles(); return cree_regle( S1, S2 ); } //////////////////////////////////////////////////////////////////////////////// liste_regles *listeRegles() { if( SYMBOLE(c) ) { regle *S1 = reg(); consommer( ';' ); liste_regles *S2 = listeRegles(); return cree_liste_regles( S1, S2 ); } else if( c != '\n' ) { erreur( '.' ); } return NULL; // prod. vide } //////////////////////////////////////////////////////////////////////////////// // COMPILO // //////////////////////////////////////////////////////////////////////////////// int main( int argc, char *argv[] ) { gramfile = fopen( argv[1], "r" ); char sigma[ 256 ]; c = getc( gramfile ); liste_regles *abs = listeRegles(); alphabet_terminal( abs, sigma ); genere_automate( abs, sigma ); return 0; }