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
%%register[[:blank:]]+ ;
^[[:blank:]]*long[[:blank:]]+int printf("long");
unsigned[[:blank:]]+int printf("unsigned int");
signed[[:blank:]]+int printf("int");
"\n"); NL++; }
\n { printf(
%%int yywrap() {
"---\n\%d\n",NL);
printf(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: