Jest to propozycja dla osób, które chciałyby zrealizować dodatkowe zadania wykraczające poza standardowy kurs.
Poniższy kod wydziela identyfikatory z tekstu. Jest to raczej zaczątek programu do dalszej rozbudowy.
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;
}