1 / 34

Y A C C

Y A C C. Generator analizatorów składniowych. GENERATOR YACC. Zadaniem generatora YACC jest wygenerowanie kodu źródłowego analizatora składniowego (domyślnie) w języku C; Pożyteczną rzeczą jest fakt, iż generator Yacc doskonale współpracuje z generatorem analizatorów leksykalnych Lex.

weston
Download Presentation

Y A C C

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. Y A C C Generator analizatorów składniowych

  2. GENERATOR YACC • Zadaniem generatora YACC jest wygenerowanie kodu źródłowego analizatora składniowego (domyślnie) w języku C; • Pożyteczną rzeczą jest fakt, iż generator Yacc doskonale współpracuje z generatorem analizatorów leksykalnych Lex. • Kod źródłowy generowany jest przez Yacc’a w oparciu o plik ze specyfikacją; • Plik z regułami tworzony jest przez samego użytkownika; 2

  3. GENERATOR YACC • Schemat organizacji działania Yacc’a: scan.l gram.y L E X YACC scan.c y.tab.c y.tab.h G C C scane.exe plik.txt 3 WYNIK

  4. GENERATOR YACC • Plik y.tab.c jest reprezentacją analizatora LALR napisaną w C, razem z innymi procedurami w języku C, które użytkownik mógł przygotować; • Opcja kompilacji "-d" powoduje zapisanie pliku nagłówkowego y.tab.h, w którym będą znajdować się definicje tokenów języka; 4

  5. GENERATOR YACC • flex –l scan.l (użycie generatora LEX) lex.yy.c • yacc -d gram.y (uzycie generatora Yacc dla pliku specyfikacji gram.y) y.tab.c i y.tab.h • gcc y.tab.c lex.yy.c (kompilacja C++) • ./a.out < plik.in (analiza pliku) 5 5

  6. GENERATOR YACC • 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 składniowy do innych aplikacji. Funkcja o której mowa to yyparse(); 6

  7. GENERATOR YACC • Zasady działania programu: • Wygenerowany przez program YACC analizator redukujący działa w oparciu o tablicę LALR; • Jako symbol startowy gramatyki, przyjmowany jest, przez domniemanie, nieterminal znajdujący się po lewej stronie pierwszej produkcji; 7

  8. GENERATOR YACC • Wygenerowany parser ma postać funkcji int yyparse(). Aby uruchomić parser zawarty w tej funkcji potrzebujemy dwóch innych funkcji: main() i yylex(); • Funkcja main(), która wywołuje funkcję yyparse(); • Parser wywołuje lexer (yylex()), kiedy tylko pobiera token z wejścia; • Yacc definiuje nazwy tokenów w parserze jako nazwy preprocesora C w y.tab.h, więc lexer może je użyć. 8

  9. GENERATOR YACC • Gdy lexer znajdzie token, który interesuje parser, zwraca do parsera jego numeryczną wartość, umieszczając ja w zmiennej yyval; • Funkcja yylex może być umieszczona w osobnym module (np. generowana programem lex); • Jeżeli korzystamy z zewnętrznego skanera, przy kompilacji dokładamy opcję "-d„ (y.tab.h, w którym będą zawarte definicje tokenów języka); 9

  10. TWORZENIE PLIKU SPECYFIKACJI • Każdy plik ze specyfikacją dla programu Yacc 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; 10

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

  12. TWORZENIE PLIKU SPECYFIKACJI • Przykład budowy sekcji definicji: %{ #include<iostream.h> int zmienna; int zmienna_druga=1; %} 12

  13. TWORZENIE PLIKU SPECYFIKACJI • 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 dokona redukcji zgodnie ze związaną z tą operacją produkcją; 13

  14. TWORZENIE PLIKU REGUŁ • Budowa reguły przetwarzania opiera się na dwóch zasadniczych częściach: produkcji i operacji; • Jej budowa wygląda więc: produkcja operacja • Produkcja jest zapisana w notacji programu Yacc. Strzałka w produkcji jest zastąpiona znakiem „ : ”; • Operacja jest blokiem instrukcji języka C; 14

  15. TWORZENIE PLIKU SPECYFIKACJI • Jeśli w gramatyce mamy produkcję S->T+T, to przykładowa reguła produkcji może wyglądać nastepująco: S : T ‘+’ T {printf(”liczba + liczba”);} ; • Podobnie jak w przypadku LLgen terminale, które nie są literałami (są nazwane) muszą być zadeklarowane za pomocą słowa kluczowego %token; 15

  16. NOTACJA YACC’a • Rozważmy gramatykę, w której zbiór produkcji jest następujący: E -> E + T; E -> T; T -> T * F; T -> F; F -> ( E ); F -> num; 16

  17. ANALIZA ZSTĘPUJĄCA Sprawdźmy, w jaki sposób można te produkcje przedstawić w notacji Yacc’a? %token num %% E : E ‘+’ T | T ; T : T ‘*’ F | F ; F : ‘(‘ E ’)’ | num ; 17

  18. NOTACJA YACC’a • Niech G będzie gramatyką z produkcjami T->(T) i T->. Wtedy pustą produkcję możemy zapisać w notacji Yacc następująco: %% T : ‘(‘ T ‘)’ | ; 18

  19. AKCJE SEMANTYCZNE • Akcja semantyczna Yacc’a jest sekwencją instrukcji w C; • Symbol $$ odwołuje się do wartości atrybutu skojarzonej z nieterminalem po lewej stronie; • Symbol $i odwołuje się do wartości skojarzonej z i-tym symbolem gramatyki po prawej stronie; • Akcja semantyczna wywoływana jest zawsze, gdy redukujemy według związanej z nią produkcji; 19

  20. AKCJE SEMANTYCZNE • Rozważmy dwie produkcje: E->E+T | T; wyr : wyr ‘+’ term {$$ = $1 +$3;} | term ; 20

  21. y.tab.h %token liczba %% E : E ‘+’ T | T ; T : T ‘-’ F | F ; F : ‘(‘ E ‘)’ | liczba ; #define liczba 257 %{ #include „y.tab.h” %} %% [+-()] return yytext[0]; [0-9]+ return liczba; [ \t] ; . Yy_fatal(”???”); 21+18 num+num wejście 21

  22. WSPÓŁPRACA Z LEX Aby powiązać Yacc z Lex’em musimy stworzyć analizator leksykalny, który będzie zwracał kolejny odnaleziony symbol; %{ #include ”y.tab.h” %} %% [+-() ] return yytext[0]; [0-9]+ return liczba; [ \t] ; . YY_FATAL(”???”); 22

  23. Współpraca z LEX Teraz możemy dopisać analizator składniowy: %token liczba %% S : S ’+’ T | T ; T : T ’-’ W | W ; W : ’(‘ S ’)’ | liczba ; 23

  24. %token liczba %% S : S ‘+’ T | T ; T : T ‘-’ W | W ; W : ‘(‘ S ‘)’ | liczba ; %{ #include ”y.tab.h” %} %% [+ - ()] return yytext[0]; [0-9]+ return liczba; [ \t] ; . YY_FATAL(”???”); 14+21+ -4 OK BŁĄD 24

  25. %token liczba %% S : S ‘+’ T | T ; T : T ‘-’ W | W ; W : ‘(‘ S ‘)’ | liczba ; %{ #include „y.tab.h” %} %% [+ - ()] return yytext[0]; [0-9]+ return liczba; [ \t] ; . Yy_fatal(”???”); 14*4 BŁĄD 25

  26. %token liczba %% S : S ‘+’ T | T ; T : T ‘*’ W | W ; W : ‘(‘ S ‘)’ | liczba ; %{ #include „y.tab.h” %} %% [+*()] return yytext[0]; [0-9]+ return liczba; [ \t] ; . Yy_fatal(”???”); 14+21+4 OK OK 26

  27. Współpraca z LEX Teraz możemy dopisać produkcję akceptującą: %token liczba %% S : S ’+’ T | T ; T : T ’-’ W | W ; Q : S {puts(”OK”);} ; W : ’(‘ S ’)’ | liczba ; 27

  28. PLIK SPECYFIKACJI • Generator Yacc pozwala na korzystanie ze zmiennych; • Oczywiście zmienna z której chcemy skorzystać, musi być uprzednio zadeklarowana w sekcji deklaracji; • Następnie może być przetwarzana, inkrementowana i zmieniana w sekcji reguł; • Sposób deklaracji: typ_zmiennej nazwa_zmiennej=wartość; 28

  29. PLIK SPECYFIKACJI • Oprócz zmiennych Yacc pozwala także na używanie funkcji; • Każda taka funkcja może być używana w regule przetwarzania; • Należy jednak pamiętać o zdefiniowaniu funkcji. Definicja ciała funkcji znajduje się w trzeciej części pliku specyfikacji – części definicji; • Funkcję definiuje się według standardów języka C; 29

  30. Przykład • Załóżmy, że mamy za zadanie napisać analizator dla języka, który składać się powinien, z tej samej liczby nawiasów otwierających co zamykających. Dodatkową trudnością niech będzie konieczność podania przez analizator liczby par nawiasów (otwierających i zamykających); • Produkcje gramatyki łatwo wyznaczyć: S -> ( S ), S ->;... 30

  31. SPECYFIKACJA YACC • W pliku specyfikacji dla generatora Yacc możemy również korzystać z nowych symboli leksykalnych; • Deklarację symbolu leksykalnego poprzedza słowo kluczowe %token np.. %token nazwa_symbolu; • Deklarację tę należy umieścić w sekcji pierwszej pliku specyfikacji;... 31

  32. SPECYFIKACJA YACC • W pliku specyfikacji dla generatora Yacc możemy również korzystać z wbudowanego w program Yacc nieterminala error; • Wbudowany nieterminal error jest bardzo przydatny przy wykrywaniu, eliminacji błędu; • Można go także zastosować przy powrocie po błędzie; 32

  33. Przykład • Zmodyfikujmy nieco rozważaną poprzednio gramatykę dla języka składającego się z jednakowej liczby nawiasów, i rozważmy gramatykę dla języka którym jest niepusty ciąg liczb w nawiasach; • Produkcjie tej gramatyki to: C ->(L); L->Liczba; L->L , Liczba...

  34. KONIEC KONIEC WYKŁADU ÓSMEGO

More Related