Program ma za zadanie rozpoznawać funkcje i wypisywać gdzie jest prototyp definicja i wywołania.
To są dwa moduły :
Idzie mi dość średnio bo jeśli podam kod źródłowy alex.c do analizowania to nie widzi pierwszego nawiasu otwierającego i próbuje sie odwołać do pustego stosu.
W innych plikach sytuacja wygląda lepiej ale też nie zawsze wypisuje wszystkie.
Jeśli ktoś mógł by pomóc w znalezieniu błędu był bym wdzięczny.
alex.c
#include "alex.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
static int ln= 0;
static char ident[256];
static FILE *ci= NULL;
void alex_init4file( FILE *in ) {
ln= 0;
ci= in;
}
lexem_t alex_nextLexem( void ) {
int c;
while( (c = fgetc(ci)) != EOF ) {
if( isspace( c ) )
continue;
else if( c == '\n' ){
ln++;
continue;
}
else if( c == '(' )
return OPEPAR;
else if( c == ')' )
return CLOPAR;
else if( c == '{' )
return OPEBRA;
else if( c == '}' )
return CLOBRA;
else if( isalpha( c ) ) {
int i= 1;
ident[0] = c;
while( isalnum( c = fgetc(ci) ) || c == '_' )
ident[i++] = c;
ident[i] = '\0';
return isKeyword(ident) ? OTHER : IDENT; }
else if( c == '"' ) {
while( (c = fgetc(ci)) != EOF && c != '"' )
return c==EOF ? EOFILE : OTHER;
}
else if( c == '\'' ) {
while( (c = fgetc(ci)) != EOF && c != '\'' )
return c==EOF ? EOFILE : OTHER;
}
else if( c == '/' ) {
if ( (c = fgetc(ci)) == '*' ) {
while ((c = fgetc(ci)) != '*');
while ((c = fgetc(ci)) != '/');
continue;
}
continue;
}
if( isdigit( c ) || c == '.' ) {
continue;
}
else {
return OTHER;
}
}
return EOFILE;
}
char * alex_ident( void ) {
return ident;
}
int alex_getLN() {
return ln;
}
int isKeyword(char * napis)
{
char buf[BUFSIZE];
FILE *in = fopen(FKEYWORD,"r");
if (in == NULL)
{
fprintf(stderr,"Nie można otworzyć pliku");
exit(EXIT_FAILURE);
}
while( fgets( buf, BUFSIZE, in ) != NULL ) {
char *wskaznik;
if( (wskaznik = strstr( buf, napis )) != NULL ) {
char * wk = wskaznik + strlen(napis);
char * wp = buf == wskaznik ? wk : wskaznik - 1;
if(isalpha(*wp) == 0 && isalpha(*wk) == 0){
fclose(in);
return 1;
}
}
}
fclose(in);
return 0;
}
paser.c
#include <stdio.h>
#include <stdlib.h> /*exit - ale exit trzeba kiedyś usunąć i nie będzie to potrzebne*/
#include "alex.h" /*analizator leksykalny*/
#include "fun_stack.h" /*stos funkcji*/
#include "store.h"
#include "parser.h"
#define MAXINDENTLENGHT 256 /*maks długość identyfikatora*/
void
analizatorSkladni (char *inpname)
{ /*przetwarza plik inpname*/
FILE *in = fopen (inpname, "r");
int nbra = 0; /*bilans nawiasów klamrowych {}*/
int npar = 0; /*bilans nawiasów zwykłych ()*/
alex_init4file (in); /*ustaw analizator leksykalny, aby czytał in*/
lexem_t lex;
lex = alex_nextLexem (); /*pobierz następny leksem*/
while (lex != EOFILE) {
switch (lex) {
case IDENT:{
char *iname = alex_ident (); /*zapamiętaj identyfikator i patrz co dalej*/
lexem_t nlex = alex_nextLexem ();
if (nlex == OPEPAR) { /*nawias otwierający - to zapewne funkcja*/
npar++;
put_on_fun_stack (npar, iname); /*odłóż na stos funkcji*/
/*stos f. jest niezbędny, aby poprawnie obsłużyć sytuacje typu*/
/*f1( 5, f2( a ), f3( b ) )*/
}
else { /*nie nawias, czyli nie funkcja*/
lex = nlex;
continue;
}
}
break;
case OPEPAR:
npar++;
break;
case CLOPAR:{ /*zamykający nawias - to może być koniec prototypu, nagłówka albo wywołania*/
if (top_of_funstack () == npar) { /*sprawdzamy, czy liczba nawiasów bilansuje się z wierzchołkiem stosu funkcji*/
/*jeśli tak, to właśnie wczytany nawias jest domknięciem nawiasu otwartego*/
/*za identyfikatorem znajdującym się na wierzchołku stosu*/
lexem_t nlex = alex_nextLexem (); /*bierzemy nast leksem*/
if (nlex == OPEBRA) { /*nast. leksem to klamra a więc mamy do czynienia z def. funkcji*/
store_add_def (get_from_fun_stack (), alex_getLN (), inpname);
nbra++;
}
else if (nbra == 0) /*nast. leksem to nie { i jesteśmy poza blokami - to musi być prototyp*/
store_add_proto (get_from_fun_stack (), alex_getLN (), inpname);
else /*nast. leksem to nie { i jesteśmy wewnątrz bloku - to zapewne wywołanie*/
store_add_call (get_from_fun_stack (), alex_getLN (), inpname);
}
npar--;
}
break;
case OPEBRA:
nbra++;
break;
case CLOBRA:
nbra--;
break;
case ERROR:{
fprintf (stderr, "\nBUUUUUUUUUUUUUUUUUUUUUU!\n"
"W pliku %s (linia %d) są błędy składni.\n"
"Kończę!\n\n", inpname, alex_getLN ());
exit (1);
}
break;
default:
break;
}
lex = alex_nextLexem ();
}
}