You are on page 1of 44

Analizorul lexical

Program sursa

Analizor
lexical

Atomi lexicali

1
Analizorul lexical

Atom
Caracter lexical
curent Analizor Analizor
lexical sintactic
Plaseaza
inapoi in
buffer
ultimul eroare eroare
caracter

Tabela de
simboluri

2
Analizorul lexical

Descrierea atomilor lexicali: expresii regulate

Atom lexical exemplu


if if
const const
relatie <, <=, >, >=, ==, !=
numar 12, 12.34, 34.
sir ”text”
3
Atributele atomilor lexicali

a = b + 60 Analizor lexical
Atom lexical atribut
Pointer in tabela
de simboluri
<identificator, “a”>
<operator atribuire, -> <identificator, “b”>
<+,- > <numar, 60>

Analizor sintactic
4
Identificare atom lexical
Identificare atomi lexicali:
atomi lexicali specificati prin expresii regulate

Exemplu: atomi lexicali specificati prin expresiile regulate:


a | ab | abb
a
2 3
e

1
e
a b
4 5 6
e

a b b
7 8 9 10
5
FLEX

program
*.l FLEX lex.yy.c

lex.yy.c Compilator C a.out

6
Specificatia FLEX

• Partile componente ale unei specificatii flex:

%{
cod C
%}
%%
reguli
%%
cod C

7
Specificatia FLEX

• Reguli: Instructiuni C

ER1 { actiune1 }
ER2 { actiune2 }

ERn { actiunen }

8
Specificatia FLEX

• Reguli:

ERi { actiune1 ; … ; actiunen }

sau

ER1 | ER2 | … | ERn


{ actiune1 ; … ; actiune1 }

9
Exemplu FLEX
%{
#include <stdio.h>
%}

%%
reguli
”am” { printf(”Regula 1”);}
”3” { printf(”Regula 2”);}
”puncte” { printf(”Regula 3”);}
%%
Porneste
main() analizorul
lexical
{
yylex();
} 10
Determinarea potrivirilor in FLEX
%{
#include <stdio.h>
%}

%%
”ab” { printf(”Regula 1”);}
”abb” { printf(”Regula 2”);}
”abbc” { printf(”Regula 3”);}
%%

main()
{
yylex();
}
11
Expresii regulate in FLEX
“string” sirul “string”
. orice caracter diferit de '\n'
\. caracterul '.'

r* zero sau mai multe aparitii


r+ una sau mai multe aparitii
r{m, n} m <= numar de aparitii <= n
r{m, } numar de aparitii >= m
r{, n} numar de aparitii <= n
r{m} numar de aparitii == m
r? r+e

r 1r 2 concatenarea r1 cu r2
r1|r2 r1 + r2
(r) r 12
Expresii regulate in FLEX

[lista] orice caracter din lista


[a-z] orice caracter intre 'a' si 'z'
[^lista] orice caracter diferit de cel din lista

^r expresia regulata r la inceput de linie


$r expresia regulata r la sfarsit de linie

r1/r2 r1 daca este urmata de r2


{r} expresia regulata r

13
Determinarea potrivirilor in FLEX
%{
#include <stdio.h>
%}

%%
”ab” { printf(”Regula 1”);}
”abb” { printf(”Regula 2”);}
”abbc” { printf(”Regula 3”);}
[a-c]+ { printf(”Regula 4”);}
%%

main()
{
yylex();
14
}
Determinarea potrivirilor in FLEX
%{
#include <stdio.h>
%}

%%
”ab” { printf(”Regula 1”);}
”abb” { printf(”Regula 2”);}
”abbc”/”cdd” { printf(”Regula 3”);}
[a-d]+ { printf(”Regula 4”);}
%%

main()
{
yylex();
15
}
yytext

%{
#include <stdio.h>
%}

%%
[0-9]+ { printf(“%s\n”, yytext); }
.|\n { }
%%

main()
{ yylex();
}

16
Macrodefinitii

%{
#include <stdio.h>
int nc = 0;
%}
cifra [0-9]
%%
{cifra} { nc ++; }
.|\n { }
%%
main()
{
yylex();
printf(”numar cifre = %d”, nc);
}
17
yyleng
%{
#include <stdio.h>
int nc = 0;
%}
cifra [0-9]
%%
{cifra} { nc += yyleng; }
.|\n { }
%%
main()
{
yylex();
printf(”numar cifre = %d”, nc);
} 18
Exemplu
%{
#include <stdio.h>
int nc = 0, nl = 0;
%}
cifra [0-9]
litera [a-zA-Z]
%%
{cifra}+ { nc += yyleng; }
{litera}+ { nl += yyleng; }
.|\n { }
%%
main()
{
yylex();
printf(”numar cifre = %d”, nc);
printf(”numar litere = %d”, nl);
}
19
Oprirea analizorului lexical
%{
%}
cifra [0-9]
semn [+-]?
Natural {cifra}+
Intreg {semn}{Natural}
Real {semn}{Natural}\.{Natural}?
%%
{Real} { printf("real\n"); return 1;}
{Natural} { printf(“natural\n"); return 2;}
{Intreg} { printf("intreg\n"); return 3;}
. { return -1; }
\n { return -2; }
%%
main(){
printf(“numar = %i\n", yylex());
}
20
Stari
• Declarare

%s S1 S2 ... Sn

sau

%x S1 S2 ... Sn

• BEGIN(nume);

21
Exemplu1 - stari
%{ char * a;
int nr_aparitii = 0, nr_cifre = 0;
%}
litera [A-Za-z]
cifra [0-9]
%s URMATOR
%%<INITIAL>{litera}+ { a = malloc(yyleng+1);
strcpy(a, yytext);
nr_aparitii = 1;
BEGIN (URMATOR); }
<URMATOR>{litera}+ {
if (!strcmp(a, yytext)) nr_aparitii++; }
{cifra} {numar_cifre++;}
%%main()
{ yylex();
printf(„primul cuvant %s apare de %i ori\n au fost
%i cifre”, a, numar_aparitii, numar_cifre);
free(a);}
22
Exemplu2 - stari
%{ char * a;
int nr_aparitii = 0, nr_cifre = 0;
%}
litera [A-Za-z]
cifra [0-9]
%x URMATOR
%%<INITIAL>{litera}+ { a = malloc(yyleng);
strcpy(a, yytext);
nr_aparitii = 1;
BEGIN (URMATOR); }
<URMATOR>{litera}+ {
if (!strcmp(a, yytext)) nr_aparitii++; }
{cifra} {numar_cifre++;}
%%main()
{ yylex();
printf(„primul cuvant %s apare de %i ori\n au fost
%i cifre”, a, numar_aparitii, numar_cifre);
free(a);}
23
Exemplu2 - stari
%{ char * a;
int nr_aparitii = 0, nr_cifre = 0;
%}
litera [A-Za-z]
cifra [0-9]
%x URMATOR
%%<INITIAL>{litera}+ { a = malloc(yyleng+1);
strcpy(a, yytext);
nr_aparitii = 1;
BEGIN (URMATOR); }
<URMATOR>{litera}+ {
if (!strcmp(a, yytext)) nr_aparitii++; }
<INITIAL URMATOR>{cifra} {numar_cifre++;}
%%
main()
{ yylex();
printf(„primul cuvant %s apare de %i ori\n au fost
%i cifre”, a, numar_aparitii, numar_cifre);
free(a);}
24
Stiva de stari

• Starile sunt stocate sub forma variabilelor


intregi
– Starea initiala: INITIAL (0)
– Starea curenta:YY_START
– Stiva de stari
• void yy_push_state (int S)
• void yy_pop_state ()
• int yy_top_state ()

• %option stack
25
Exemplu – stiva de stari
%option stack
%x COMMENT
%%
"//" yy_push_state(COMMENT);
.|\n ;
<COMMENT>\n yy_pop_state();
<COMMENT>[^\n]+ printf("%s\n", yytext);
%%
int main ( int argc, char * argv[] )
{
yylex ();
return 0;
26
}
Determinarea potrivirilor in FLEX
%{
int n1 = 0, n2 = 0;
%}

%%
[a-c]+ {n1++;}
[a-d]+ {n2++;}
%%

main()
{
yylex();
printf(”n1 = %d, n2 = %d”, n1, n2);
}
27
REJECT
• Macroinstructiunea REJECT

• Folosita pentru modificarea algoritmului de


alegere a sirului care se potriveste

• Alte macroinstructiuni: BEGIN, ECHO

28
Determinarea potrivirilor in FLEX
%{
int n1 = 0, n2 = 0;
%}

%%
[a-c]+ {n1++; REJECT}
[a-d]+ {n2++;}
%%

main()
{
yylex();
printf(”n1 = %d, n2 = %d”, n1, n2);
}
29
Alt exemplu REJECT
%%
„acesta” |
„acesta este” |
„acesta este un” |
„acesta este un test” |
„acesta este un test ciudat”
{ ECHO; REJECT;}

%%

main(){
yylex();
}
30
Alt exemplu REJECT
%%
„acesta” |
„acesta este” |
„acesta este un” |
„acesta este un test” |
„acesta este un test ciudat”
{ ECHO; REJECT;}
.
%%

main(){
yylex();
}
31
Exemplu 1 - REJECT
%{ int NrCuvinte = 0;
%}
cuvant [A-Za-z][A-Za-z0-9]*
%%
bun | rau | urit |frumos
{ ECHO; printf("adjectiv\n"); REJECT;}

mananca | doarme | scrie |citeste


{ ECHO; printf("verb\n"); REJECT;}

{cuvant} { NrCuvinte++;}
. ;
%%
main ()
{ yylex();
printf("\n au fost %i cuvinte\n“, NrCuvinte);}
32
Exemplu 2 - REJECT
%{
int NrCuvinte = 0;
%}
cuvant [A-Za-z][A-Za-z0-9]*
%%
{cuvant} { NrCuvinte++; REJECT;}
bun | rau | urat |frumos
{ECHO; printf(" este adjectiv\n");}

maninca | doarme | scrie | citeste


{ ECHO; printf(" este verb\n");}
. ;
%%

main (){
yylex();
printf("\nau fost %i cuvinte\n", NrCuvinte);
}
33
yymore
0 1 yyleng-1

Potrivire pas i: Wi = yytext


intrare
yymore()

Sirul corespunzator
Wi potrivirii de la pasul i+1
intrare

yytext (la pasul i+1)


34
Exemplu yymore
%s DUPA
Cuvint [A-Za-z]*
CuvintSpecial {Cuvint}"$"
CuvintObisnuit {Cuvint}[\t \n]+
%%
<INITIAL>{CuvintSpecial}
{ BEGIN(DUPA); putchar('(');}
<INITIAL>{CuvintObisnuit} ;
<DUPA>{CuvintObisnuit} { yymore();}
<DUPA>{CuvintSpecial}
{ yytext[yyleng -1] = ')';
ECHO; BEGIN(INITIAL);
}
%%
main(){
yylex(); Intrare:
} a$a b$c
a $a b$c
aa$ a b$c
35
yyless

0 1 yyleng-1

yytext

intrare
yyless(int n)
0 1 n-1 n yyleng-1

yyleng-n caractere
n caractere
intrare 36
Exemplu yyless, yymore
%s DUPA
Cuvint [A-Za-z]*
CuvintSpecial {Cuvint}"$"
CuvintObisnuit {Cuvint}[\t \n]+

%%
<INITIAL>"$" { BEGIN(DUPA); putchar('('); }
<INITIAL>{CuvintObisnuit} ;
<INITIAL>{CuvintSpecial} { yyless(yyleng - 1); }
<DUPA>"$" { BEGIN(INITIAL);
yytext[yyleng -1] =')';
ECHO;
}
<DUPA>{CuvintObisnuit} { yymore(); }
%%
Intrare:
main(){ a$a b$c
yylex(); a $a b$c
} aa$ a b$c
37
Analiza unui fisier de intrare
%{

%}
%%

%%

main( int argc, char **argv ) {

yyin = fopen(argv+1, "r");


if (!yyin)
{ printf("!!!eroare!!!");exit(1);}
yylex();

} 38
Fisiere de intrare multiple
int yywrap();

Valori intoarse:
 1: nu mai exista fisiere de analizat la intrare
 0: mai exista fisiere de analizat la intrare

 1: valoarea implicita intoarsa de functie

39
Fisiere de intrare multiple
%{
#undef yywrap

%}
%%

%%
char **ListaFisiere;
unsigned int FisierCurent = 0;
unsigned int NumarFisiere;

main( int argc, char **argv ) {


FILE *fisier; ListaFisiere = argv + 1;
NumarFisiere = argc -1;
if (argc > 1) {
FisierCurent = 0;
fisier = fopen(ListaFisiere[FisierCurent], "r");
if (!fisier){ printf("!!!eroare!!!");exit(1);}
yyin = fisier;
yylex();
}
} 40
Fisiere de intrare multiple - yywrap
yywrap(){
FILE *fisier = NULL;

fclose(yyin);

FisierCurent++;
/* afisare info specifice fisierului current */

if (FisierCurent > NumarFisiere) return 1;


fisier = fopen(ListaFisiere[FisierCurent], "r");
if (!fisier){
printf("!!! eroare!!!");
exit(1);
}
yyin = fisier;
return(fisier ? 0:1);
}

41
Buffere de intrare multiple
YY_BUFFER_STATE yy_create_buffer
(FILE *file, int size)
void yy_switch_to_buffer
(YY_BUFFER_STATE new_buffer)
void yy_delete_buffer
(YY_BUFFER_STATE buffer)
void yypush_buffer_state
(YY_BUFFER_STATE buffer)
void yypop_buffer_state ( )
void yy_flush_buffer
(YY_BUFFER_STATE buffer)
42
Buffere de intrare multiple
/* buffer de intrare */
YY_BUFFER_STATE bp
FILE* f;

f = fopen(…, “r);
bp = yy_create_buffer(f, YY_BUF_SIZE);
yy_switch_to_buffer(bp);
….
….
yy_delete_buffer(bp);

43
Exemplu
%x incl
%%
include BEGIN(incl);
[a-z]+ ECHO;
[^a-z\n]*\n? ECHO;
<incl>[ \t]* ;
<incl>[^ \t\n]+ { /* preia nume fisier */
yyin = fopen( yytext, "r" );
if ( ! yyin ) error( ... );
yypush_buffer_state
(yy_create_buffer( yyin, YY_BUF_SIZE ));
BEGIN(INITIAL); }
<<EOF>> { yypop_buffer_state();
if ( !YY_CURRENT_BUFFER )
yyterminate(); 44
}