/* Esame di Linguaggi di Programmazione Appello di laboratorio del 11 luglio 2005 Modificare il presente programma per risolvere il seguente quesito: Acquisita una grammatica, contare il numero di produzioni le cui parti sinistre non sono valide in quanto non contengono alcun simbolo non-terminale. */ /* GrammarReader v. 1.0 Corrado Mencar, Stefano Ferilli, Pasquale Lops */ #include #include #define MAX_WORD_LENGTH 100 #define MAX_PRODUCTIONS 100 // Definizione dei tipi ------------------------------------------------------*/ typedef char Symbol; typedef struct { Symbol word [MAX_WORD_LENGTH]; unsigned length; } Word; typedef struct { Word left; Word right; } Production; typedef struct { Production productions[MAX_PRODUCTIONS]; unsigned numprod; } Grammar; // Procedure di riconoscimento dei simboli -----------------------------------*/ int is_CFProduction(Production* p) { if (p->left.length==1 && isupper(p->left.word[0])) return 1; else return 0; } int is_CFGrammar(Grammar* g) { int i; for (i=0; inumprod; i++) if (!is_CFProduction(&g->productions[i])) return 0; return 1; } int is_terminal(Symbol s) { return (islower(s)); //return (s >= 'a') && (s <= 'z'); } int is_nonterminal(Symbol s) { return (isupper(s)); //return (s >= 'A') && (s <= 'Z'); } int is_prodsym(Symbol s) { return (s == '>'); } int is_prodsep(Symbol s) { return (s == '\n'); } /* Lettura di simboli da file ------------------------------------------------*/ Symbol read_sym(FILE* file) { Symbol s; // fscanf(file,"%c",&s); s = getc(file); return s; } // Procedura di acquisizione di una grammatica da un file --------------------*/ Grammar* load_grammar(FILE* file, Grammar* g) { enum States {START,LEFT,RIGHT,ERROR}; /* START = Scansione di una nuova produzione [F] LEFT = Scansione della parte sinistra RIGHT = Scansione della parte destra [F] ERROR = Errore di scansione */ enum States current_state = START; // Stato iniziale Symbol s; Production* p; //Word l; //Word r; g->numprod = 0; // Inizializza la grammatica while (current_state != ERROR && !feof(file)) { s = read_sym(file); if (feof(file)) break; switch(current_state) { case START: if (is_terminal(s) || is_nonterminal(s)) { current_state = LEFT; p = &(g->productions[g->numprod++]); p->left.length = 0; p->left.word[p->left.length++] = s; } else current_state = ERROR; break; case LEFT: if (is_terminal(s) || is_nonterminal(s)) { current_state = LEFT; p->left.word[p->left.length++] = s; } else if (is_prodsym(s)) { current_state = RIGHT; p->right.length = 0; } else current_state = ERROR; break; case RIGHT: if (is_terminal(s) || is_nonterminal(s)) { current_state = RIGHT; (*p).right.word[p->right.length++] = s; } else if (is_prodsep(s)) { current_state = START; } else current_state = ERROR; break; } } if (current_state == START || current_state == RIGHT) return g; else return NULL; } // Procedure di stampa void print_sym (Symbol s) { printf("%c ",s); } void print_word (Word* w) { int i; for (i=0; ilength; i++) print_sym(w->word[i]); } void print_production (Production* p) { print_word(&p->left); printf (" --> "); print_word(&p->right); } void print_grammar(Grammar* g) { int i; if (g == NULL) printf ("Errore! Grammatica non valida! \n"); else { printf ("Numero di produzioni: %d\n", g->numprod); for (i=0; inumprod; i++) { print_production(&g->productions[i]); printf ("\n"); } } } /* ESERCIZIO */ int esercizio (Grammar* g) { int i; /* indice delle produzioni */ int j; /* indice per la scansione della testa di una produzione*/ Symbol h; /* Simbolo della testa della produzione*/ int count = 0; /* contatore delle produzioni non valide*/ int flag; /* 1 se la produzione esaminata non è valida*/ for (i=0; i < g->numprod; i++) { flag = 0; for (j=0; j < g->productions[i].left.length; j++) /* per ogni simbolo della testa...*/ { h = g->productions[i].left.word[j]; /* h è il simbolo del corpo correntemente esaminato*/ if (is_nonterminal(h)) /* se h è non terminale, la produzione è valida*/ flag = 1; /* flag indica se la produzione deve essere conteggiata*/ } if (!flag) count++; } return count; /* restituzione del conteggio*/ } // MAIN ------------------------------------------------------------------------ int main(int argc, char *argv[]) { char* filename = argv[1]; FILE* gram_file; Grammar grammar; // controlla se è stato inserito il nome del file if (filename == 0) { printf("nome file non specificato \n"); return -1; } // apertura del file contenente la grammatica gram_file = fopen(filename,"r"); if (gram_file == NULL) { printf("nome di file errato\n"); return -1; } print_grammar(load_grammar(gram_file,&grammar)); fclose(gram_file); printf("Numero di produzioni non valide: %d\n", esercizio(&grammar)); system("PAUSE"); return 0; }