1 / 38

L E X

L E X. Generator analizatorów leksykalnych. GENERATOR L E X. Zadaniem generatora LEX jest wygenerowanie kodu źródłowego analizatora leksykalnego (domyślnie) w języku C; Kod źródłowy generowany jest przez LEX’a w oparciu o plik zawierający wszystkie reguły przetwarzania;

alain
Download Presentation

L E X

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. L E X Generator analizatorów leksykalnych

  2. GENERATOR L E X • Zadaniem generatora LEX jest wygenerowanie kodu źródłowego analizatora leksykalnego (domyślnie) w języku C; • Kod źródłowy generowany jest przez LEX’a w oparciu o plik zawierający wszystkie reguły przetwarzania; • Plik z regułami tworzony jest przez samego użytkownika; 2

  3. GENERATOR L E X • Schemat organizacji działania LEX’a: scan.l L E X scan.c G C C scane.exe plik.txt WYNIK 3

  4. GENERATOR L E X • flex –l scan.l (użycie generatora LEX) • gcc scan.c -o scan.exe (kompilacja C++) • scan.exe < plik.txt (analiza plik.txt) 4

  5. GENERATOR L E X • Ważną cechą analizatora jest możliwość wykorzystania go do większych aplikacji; • Każdy wygenerowany kod źródłowy zawiera bowiem funkcję, dzięki której można podłączyć analizator leksykalny do innych aplikacji. Funkcja o której mowa to yylex(); 5

  6. TWORZENIE PLIKU REGUŁ • Każdy plik ze specyfikacją dla programu LEX powinien składać się z trzech sekcji; • Pierwsza sekcja to sekcja definicji; • W sekcji definicji umieszczamy, jak sama nazwa wskazuje, definicje i deklaracje zmiennych, stałych, deklaracje stanów oraz makra procesora; 6

  7. TWORZENIE PLIKU REGUŁ • Sekcja definicji może zawierać fragment kodu, który system przepisze bezpośrednio do analizatora leksykalnego; • Kod ten musi być odpowiednio „opakowany”; • Otwarcie fragmentu bezpośrednio przepisywanego do analizatora powinno być poprzedzone znacznikiem %{, natomiast jej zamknięcie %}; 7

  8. TWORZENIE PLIKU REGUŁ • Przykład budowy sekcji definicji: %{ #include<iostream.h> int zmienna; int yylex(); int zmienna_druga=1; %} 8

  9. TWORZENIE PLIKU REGUŁ • Druga sekcja to sekcja przetwarzania; • W sekcji przetwarzania umieszczamy wszelkie reguły postępowania, zgodnie z którymi wygenerowany będzie analizator; • Reguły postępowania to inaczej przepisy na to co analizator ma zrobić gdy napotyka na określony „problem” (symbol); 9

  10. TWORZENIE PLIKU REGUŁ • Budowa reguły przetwarzania opiera się na dwóch zasadniczych częściach: wzorca i operacji; • Jej budowa wygląda więc: wzorzec operacja • Wzorzec jest zapisywany jako wyrażenie regularne; • Operacja jest blokiem instrukcji języka C; 10

  11. TWORZENIE PLIKU REGUŁ • Przykład budowy reguły przetwarzania: (a+b)*a(a+b)2 cout<<‘’W słowie A trzeci symbol od końca jest równy a’’; 11

  12. WYRAŻENIA REGULARNE • Podamy teraz kilka symboli używanych do zapisu wyrażeń regularnych występujących we wzorcach reguł przetwarzania: • Symbole linii: ^… - początek linii; …$ - koniec linii; 12

  13. WYRAŻENIA REGULARNE • Symbole operacji logicznych: ab - konkatenacja; a|b - alternatywa; a* - domknięcie zwrotne (domknięcie); a+ - domknięcie dodatnie (domknięcie po odjęciu słowa pustego); a? – opcjonalność (symbol „a” nie występuje lub występuje jeden raz); 13

  14. WYRAŻENIA REGULARNE • Powtarzanie symbolu: a{n} – powtórzenie symbolu „a” n – razy; a{n,m} – zakres powtarzania symbolu (czyli an,…,am); () – określają stopień ważności (c(a|d)|(e+) ); 14

  15. WYRAŻENIA REGULARNE • Klasy znaków: [a-z] - oznacza dowolny znak z zakresu od małej litery „a” do małej litery „z”; [^a-z] – oznacza dowolny znak spoza klasy [a-z] (jak gdyby „negacja” zakresu); [a-zXY] – oznacza dowolny znak z zakresu [a-z] lub wielką literę X lub Y; [0-9] – oznacza dowolną cyfrę od 0 do 9;

  16. WYRAŻENIA REGULARNE • Klasy znaków (c.d.): . - oznacza dowolny znak nie będący znakiem końca linii; \... – poprzedza sekwencje specjalne (podobnie jak w C) np.: \n – oznacza znak końca linii; \t – oznacza znak tabulatora; 16

  17. TWORZENIE PLIKU REGUŁ • Przykład budowy reguły przetwarzania: (a+b)*a(a+b)2 cout<<‘’W słowie A trzeci symbol od końca jest równy a’’; Powinniśmy wpisać: (a|b)*a(a|b){2} cout<<‘’W słowie A trzeci symbol od końca jest równy a’’; 17

  18. WYRAŻENIA REGULARNE Inne ważne zasady tworzenia wzorców: • Wzorce zawierające spacje ujmuje się w cudzysłów; • Komentarz wpisuje się między znaczniki /* a */; • Niedopasowane znaki są przepisywane na wyjście; 18

  19. Przykład Wyrażenie regularne akceptujące adres strony internetowej: [Ww]{3} \. [A-Za-z0-9._-]+ \. [A-Za-z]{3} \. [Pp] [Ll] 19

  20. Przykład Wyrażenie regularne akceptujące słowa kluczowe w Adzie begin i end: [A-Za-z]{3,5} [A-Za-z]{5} | [A-Za-z]{3} [Bb][Ee][Gg][Ii][Nn] | [Ee][Nn][Dd] 20

  21. Przykład Wyrażenie regularne akceptujące wszelkie identyfikatory (zmienne, stałe ) w C: [A-Za-z _ ] [A-Za-z0-9 _ ]* 21

  22. Przykład Wyrażenie regularne akceptujące datę: ([0-9]{2} \- [0-9]{2} \- [0-9]{4}) | ([0-9]{2} \. [0-9]{2} \. [0-9]{4}) | ([0-9]{4} \- [0-9]{2} \- [0-9]{2}) | ([0-9]{4} \. [0-9]{2} \. [0-9]{2}) ([0-9]{2} (\- | \.) [0-9]{2} (\- | \.) [0-9]{4}) | ([0-9]{4} (\- | \.) [0-9]{2} (\- | \.) [0-9]{2}) 22

  23. Przykład Wyrażenie regularne akceptujące wszelkie adresy poczty e-mail: [A-Za-z0-9 . _ -]+@[A-Za-z0-9 . _ ]+\.[A-Za-z]{2,4} 23

  24. TWORZENIE PLIKU REGUŁ • Trzecią sekcją składową pliku ze specyfikacją dla programu LEX jest sekcja podprogramów; • W skład sekcji podprogramów mogą, jak sama nazwa wskazuje, wchodzić definicje funkcje, które będą następnie wykorzystywane przez analizator leksykalny; 24

  25. TWORZENIE PLIKU REGUŁ • Deklaracja funkcji wchodzących w skład tej sekcji poddana jest regułą tworzenia funkcji w języku C; • Funkcja yywrap()–jest to funkcja o specjalnym znaczeniu. Gdy wywołujemy (uprzednio wygenerowany) analizator leksykalny, funkcja yywrap() jest wykonywana zawsze po przetworzeniu danych wejściowych; 25

  26. Przykład • Przykład funkcji znajdującej się w sekcji podprogramów: int main() { return yylex(); } • Wymaga ona oczywiście wcześniejszej deklaracji yylex’a w postaci zwrotu: int yylex(); 26

  27. TWORZENIE PLIKU REGUŁ • Przy tworzeniu pliku reguł przetwarzania można korzystać z zmiennych globalnych; • Deklaracja tego typu zmiennych znajduje się w pierwszej sekcji (sekcji definicji) pliku; • Zmienne globalne, mogą być oczywiście wykorzystywane w każdej następnej sekcji, np. inkrementowane, zmieniane, czy odczytywane; 27

  28. TWORZENIE PLIKU REGUŁ • Oprócz zmiennych globalnych można także korzystać ze zmiennych wbudowanych; • Mamy dwie szczególnie ważne zmienne wbudowane yyleng i yytext; • Zmienna yyleng jest typu int i okresla długość dopasowania; • Zmienna yytext jest znakiem (char) a dokładniej ciągiem znaków, wskazuje na leskem (odnajduje w strumieniu danych wejściowych, zapis który pasował do wzorca); 28

  29. TWORZENIE PLIKU REGUŁ • Pożyteczną rolę odgrywają także definicje regularne; • Tworzenie definicji regularnej to inaczej przypisanie wyrażeniu regularnemu pewnego identyfikatora; • Identyfikator ten może być wykorzystany później w polu wzorca; • Definicja regularna jest tworzona w sekcji definicji; 29

  30. Przykład • Definicje regularną umieszczamy co prawda w sekcji definicji, jednakże po bloku bezpośrednio przepisywanym do analizatora; • Zobaczmy następujący przykład, który pokazuje sposób korzystania z zadeklarowanego identyfikatora; 30

  31. Przykład %{ #include<iostream.h> int yylex(); %} identyfikator [Ii] [Ff] %% {identyfikator} {cout<<‘’ Wczytano leksem IF’’;} %% 31

  32. TWORZENIE PLIKU REGUŁ • Wszystkie trzy omówione sekcje składowe pliku ze specyfikacją dla programu LEX oddzielane są podwójnym znakiem procenta - %%; • Schemat pliku ze specyfikacją reguł dla programu LEX możemy więc zademonstrować w tabeli: 32

  33. TWORZENIE PLIKU REGUŁ SEKCJA DEFINICJI %% SEKCJA REGUŁ PRZETWARZANIA %% SEKCJA PODPROGRAMÓW ... 33

  34. NIEJEDNOZNACZNOŚĆ • Gdy przeanalizowaliśmy już zasadę działania generatora LEX, możemy przyjrzeć się istotnemu problemowi niejednoznaczności przy działaniu LEX; • Przykład: m* {cout<<‘’*’’;} mmm {cout<<‘’+’’;} Dostarczamy strumień danych postaci: mmmmmmmmmm;mmm 34

  35. NIEJEDNOZNACZNOŚĆ • ZASADA NAJDŁUŻSZEGO DOPASOWANIA – określa, iż jeśli mamy dwie lub więcej reguł dla których wzorce są spełnione, to wybierana jest ta reguła dla której dopasowanie wzorca jest najdłuższe; • ZASADA WCZEŚNIEJSZEGO DOPASOWANIA – mówi iż, gdy dopasowania maja identyczną długość, wybrana jest reguła, która została umieszczona pierwsza w pliku specyfikacji; 35

  36. NIEJEDNOZNACZNOŚĆ • Stosując zatem zasadę pierwszą w przykładzie, dane wyjściowe będą wyglądały: *;+ • Gdybyśmy zaś mieli dane wejściowe postaci mmm to stosując drugą zasadę dostaniemy na wyjściu + 36

  37. RETRAKCJA • Pojęcie retrakcji wiąże się ze sposobem działania analizatora; • Analizator przetwarza wiele wzorców równolegle w poszukiwaniu najlepszego (tzn. najdłuższego) . Porzuca on z czasem wzorce mniej „obiecujące” koncentrując się na wzorcach, które mogą dać dłuższe dopasowania; • W sytuacji niepowodzenia wraca do porzuconych wzorców;... 37

  38. KONIEC KONIEC WYKŁADU TRZECIEGO

More Related