Jest to propozycja dla osób, które chciałyby zrealizować dodatkowe zadania wykraczające poza standardowy kurs.

Zadanie 1

Poniższy kod wydziela identyfikatory z tekstu. Jest to raczej zaczątek programu do dalszej rozbudowy.

Opis

Zadaniem parsera jest wydzielenie symboli z tekstu programu źródłowego. Struktura Parser zawiera bufor dla symbolu, informacje o liczbie znaków w buforze oraz pole stan (określające rodzaj symbolu i etap jego identyfikacji).

Centralną funkcją jest int akceptujZnak(Parser*p,int c). W zależności od stanu i rodzaju znaku podejmowana jest decyzja, czy znak należy wykorzystać  (i dopisać do bufora) czy też nie. Jeżeli znak zostanie wykorzystany, funkcja zwraca 1, w przeciwnym przypadku funkcja zwraca 0. Jest to informacja, że symbol jest gotowy do wykorzystania, można np.: go wypisać, czy w inny sposób przetworzyć.

Po przetworzeniu symbolu proces wydzielania symboli jest kontynuowany (wołamy init() i analizujemy kolejne znaki).

 Rozwijając parser najwygodniej jest wpierw utworzyć tabelę, która będzie opisywała przejścia między stanami. Przykład analizy komentarzy

Stan Typ znaku Następny stan Akcja
PUSTY / UKOSNIK return 1;
UKOSNIK * KOMENTARZ_WL return 1;
KOMENTARZ_WL * KOMENTARZ_GW return 1;
KOMENTARZ_GW / PUSTY return 1;
KOMENTARZ_WL NOT * KOMENTARZ_WL return 1
       
UKOSNIK / KOMENTARZ_1L return 1;
KOMENTARZ_1L \n PUSTY return 1;
KOMENTARZ_1L NOT \n KOMENTARZ_1L return 1;
       
PUSTY isdigit(c) STALA_LICZBOWA dopisz do bufora;return 1;

 


enum {	PUSTY,
		IDENT,	// wewnatrz identyfikatora
		STRING,	// tekst "zzzzzz"
		ZNAK,	// stala 'x'
		FP_CONST,		// itd
		DEC_CONST
};	

typedef struct _parser
{
	int stan;
	char bufor[256];
	int dlugosc;
}Parser;

void init(Parser*p)
{
	p->stan=PUSTY;
	p->dlugosc=0;
}

int akceptujZnak(Parser*p,int c)
{
	switch(p->stan){
		case PUSTY:
			if(isalpha(c) || c=='_'){
				p->stan=IDENT;
				p->bufor[p->dlugosc]=c;
				p->dlugosc++;
				return 1;
			}
			return 1;
		case IDENT:
			if(isalpha(c) || c=='_' || isdigit(c)){
				p->bufor[p->dlugosc]=c;
				p->dlugosc++;
				return 1;
			}
			else {
				return 0;
			}
		default:
			return 0;

	}
}

const char*symbol(Parser*p)
{
	p->bufor[p->dlugosc]=0;
	return p->bufor;
}

int main(int argc, char* argv[])
{
	char txt[]="123 ala _ma1 123x";
	int i=0;
	Parser p;
	init(&p);

	while(i<=strlen(txt)){
		if(akceptujZnak(&p,txt[i])){i++;continue;}
		printf("%s\n",symbol(&p));
		init(&p);
	}
	return 0;
}