2020-10-22
Rozbicie ciągu znaków wejściowych na symbole leksykalne (wyrazy posiadające określone znaczenie). Ciąg symboli leksykalnych stanowi wejście dla analizatora składniowego.
Weźmy kawałek kodu w C:
double sqr(double x)
{
return x*x;
}| Token | Leksem |
|---|---|
Identyfikator_typu |
double |
Identyfikator |
sqr |
«(» |
( |
Identyfikator |
x |
«)» |
) |
«{» |
{ |
KW_return |
return |
Operator_binarny |
* |
«;» |
; |
«}» |
} |
| Symbol leksykalny | Wyrażenie regularne |
|---|---|
Identyfikator |
[a-zA-Z][a-zA-Z0-9]* |
«(» |
\( |
«{» |
\{ |
Operator_binarny |
\* |
KW_return |
return |
| Automat | Pamięć | Czas |
|---|---|---|
| DFA | ||
| NFA |
gdzie:
Jednak implementacja DFA jest duża łatwiejsza, a wielkość zmniejsza się w trakcie minimalizacji.
yylex() — funkcja wygenerowana przez LEX-a odpowiedzialna za działanie leksera (można ją wykorzystać w innej aplikacji)scan.l flex scan.c gcc scan[.exe]
\""%{// sekcja — biblioteki i inne ustawienia w normalnym C
#include<stdio.h>
int yywrap();
int yylex();
int NL=0;
%}
%%// tutaj określamy definicje znaków
^[[:blank:]]*register[[:blank:]]+ ;
long[[:blank:]]+int printf("long");
unsigned[[:blank:]]+int printf("unsigned int");
signed[[:blank:]]+int printf("int");
\n { printf("\n"); NL++; }
%%
int yywrap() {
printf("---\n\%d\n",NL);
return 1;
}
int main() {
return yylex();
}| Wyrażenie | Opis |
|---|---|
^x |
wzorzec od początku linii |
x$ |
wzorzec do końca linii |
xy |
konkatenacja wzorców |
x|y |
alternatywa wzorców |
x* |
domknięcie zwrotne |
x+ |
domknięcie dodatnie |
x? |
opcjonalność (występuje 0 lub 1 raz) |
x{3} |
występuje dokładnie trzy razy |
x{2,4} |
występuje 2, 3, lub 4 razy |
x{2,} |
występuje co najmniej dwa razy |
(x|y)z |
nawiasy wyrażają priorytet |
[a-z] |
klasa znaków, tu: jeden znak ze zbiour od a do z |
[^a-z] |
dowolny znak spoza klasy |
. |
dowolny znak (poza znakiem \n) |
yytext — wskaźnik na ostatnio rozpoznany (dopasowany)yyleng — długość dopasowanego leksemaCo zrobi LEX jeśli tekst może się dopasować do kilku wzorców?
Stosujemy zasady: