Generator analizatorów składniowych

Slides:



Advertisements
Podobne prezentacje
Tablice 1. Deklaracja tablicy
Advertisements

C++ wykład 2 ( ) Klasy i obiekty.
Język C/C++ Funkcje.
Programowanie obiektowe
Mgr inż.Marcin Borkowski Podstawy Java Krótkie wprowadzenie dla studentów Wyższej Szkoły Ekologii i Zarządzania
Deklaracje i definicje klas w C++ Składowe, pola, metody Konstruktory
Język ANSI C Funkcje Wykład: Programowanie komputerów
Prowadzący: mgr inż. Elżbieta Majka
Programowanie I Rekurencja.
Wprowadzenie do języka skryptowego PHP
Języki programowania C++
PROGRAMOWANIE STRUKTURALNE
formatowanie kodu źródłowego
Generator analizatorów składniowych
Metoda pierwszeństwa operatorów
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 8: Wykorzystanie procedur i funkcji © Jan Kaczmarek.
Przetwarzanie tekstów i AWK Copyright, 2000 © Jerzy R. Nawrocki Wprowadzenie do.
Programowanie imperatywne i język C Copyright, 2004 © Jerzy R. Nawrocki Wprowadzenie.
Programowanie imperatywne i język C
Języki formalne i gramatyki
Programowanie imperatywne i język C Copyright, 2004 © Jerzy R. Nawrocki Wprowadzenie.
Kurs Pascala – spis treści
1 Dygresja: cztery płyty główne…. 2 Dygresja: osobliwości C /* cos o nieistniejacym typie Boolean */ /* oraz o operatorze przecinkowym */ #include int.
Wykład 2 struktura programu elementy języka typy zmienne
Transformacja Z (13.6).
Programowanie w języku Fortran 95
AWK Zastosowania Informatyki Wykład 1 Copyright, 2003 © Adam Czajka.
Podstawy programowania
Podstawy programowania II Wykład 2: Biblioteka stdio.h Zachodniopomorska Szkoła Biznesu.
Podstawy programowania
KONSTRUKCJA KOMPILATORÓW WYKŁAD WYKŁAD Robert Plebaniak Robert Plebaniak.
A ctive S erver P ages Technologia dostępu do danych.
Podstawy programowania. Język C i C++– podstawy Temat: 1
© A. Jędryczkowski – 2006 r. © A. Jędryczkowski – 2006 r.
Wyrażenia algebraiczne
TABLICE C++.
Generator analizatorów leksykalnych
1 Wykład 8 Podprogramy. 2 Pojęcie i istota stosowania dzielenie programu na części (logicznie spójne) - nazwane - niezależne od pozostałych części - z.
Technologie internetowe II
Podstawy działania wybranych usług sieciowych
ŻYWE JĘZYKI PROGRAMOWANIA LIVING IT UP WITH A LIVE PROGRAMMING LANGUAGE Sean McDirmid Ecole Polytechnique Fédérale de Lausanne (EPFL)
Programowanie obiektowe – zastosowanie języka Java SE
Andrzej Repak Nr albumu
Elżbieta Fiedziukiewicz
Podstawy informatyki 2013/2014
Przekazywanie parametrów do funkcji oraz zmienne globalne i lokalne
Translatory Copyright, 2006 © Jerzy R. Nawrocki Wprowadzenie do informatyki Wykład 11.
Gramatyki i translatory
Podstawy języka Instrukcje - wprowadzenie
Podstawy programowania
ZAPIS BLOKOWY ALGORYTMÓW
Gramatyki Lindenmayera
Kurs języka C++ – wykład 4 ( )
Języki formalne i gramatyki Copyright, 2005 © Jerzy R. Nawrocki Teoretyczne podstawy.
Programowanie proceduralne Podstawy Programowania dla geoinformatyków Wykład 3 Rafał Witkowski, 2015.
Języki formalne Copyright, 2006 © Jerzy R. Nawrocki Wprowadzenie do informatyki Wykład.
ANALIZA SKŁADNIOWA.
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)
Systemy wspomagające dowodzenie twierdzeń
Seminarium Dyplomowe: Metodyka i Techniki Programowania Autor: Bartłomiej Fornal.
Wstęp do programowania Wykład 9
PHP jest językiem skryptowym służącym do rozszerzania możliwości stron internetowych. Jego składnia jest bardzo podobna do popularnych języków programowania.
Wstęp do programowania Wykład 2 Dane, instrukcje, program.
Podstawy informatyki Funkcje Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
Pakiety numeryczne Skrypty, funkcje Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania.
K URS JĘZYKA C++ – WYKŁAD 3 ( ) Przenoszenie Składowe statyczne Funkcje wbudowane Argumenty domyślne.
Zmienne typy danych w VBA. MS Excel – typy danych w języku programowania VBA.
Programowanie obiektowe – zastosowanie języka Java SE
Haskell Składnia funkcji.
Zapis prezentacji:

Generator analizatorów składniowych L L G E N Generator analizatorów składniowych

GENERATOR L LGEN Zadaniem generatora LLgen jest wygenerowanie analizatora składniowego, inaczej parsera (w języku C) metodą zejść rekurencyjnych, bez nawrotów; Kod źródłowy generowany jest przez LLgen’a w oparciu o plik zawierający specyfikację; W specyfikacji można korzystać z rozszerzonych specyfikacji gramatyk LL(1). Ponieważ LLgen zawiera wbudowane mechanizmy statycznego i dynamicznego rozstrzygania konfliktów, pozwala on na korzystanie z gramatyk niejednoznacznych; 2

GENERATOR LLGEN Schemat organizacji działania LLgen’a: scan.l gram.g L E X LLgen scan.c gram.c Lpars.c Lpars.h G C C scane.exe plik.txt 3 WYNIK

GENERATOR LLGEN flex –l scan.l (użycie generatora LEX) lex.yy.c LLgen gram.g (uzycie generatora LLgen dla pliku specyfikacji gram.g) Lpars.c i Lparse.h gcc lex.yy.c Lpars.c gram.c (kompilacja C++) ./a.out < plik.in (analiza pliku) 4 4

GENERATOR LLGEN Generator LLgen domyślnie korzysta z zewnętrznego analizatora leksykalnego, (wygenerowanego za pomocą LEX’a). W tym celu wywoływana jest funkcja yylex(); Plik Lpars.h, który powstaje podczas pracy generatora LLgen, zawiera definicje przypisujące stałe liczbowe nazwom zadeklarowanych token-ów; 5

GNENRATOR LLGEN Sposoby na wykorzystanie innego analizatora są następujące: umieścić implementację skanera bezpośrednio w specyfikacji gramatyki (w bloku ’{’ ’}’ lub w zewnętrznym pliku; W specyfikacji wskazać nazwę funkcji, którą Llgen ma wywołać; %lexical nazwa_funkcji; w razie potrzeby włączyć do analizatora leksykalnego plik Lpars.h; 6

GENERATOR LLGEN LLgen jest narzędziem wierszowym, do którego plik specyfikacji przygotowujemy w zwykłym pliku tekstowym, czasem w kilku plikach; Każdy wygenerowany kod źródłowy zawiera produkcje, dyrektywy generatora LLgen i deklaracje i kod w języku C 7

TWORZENIE SPECYFIKACJI Każdy produkcja ze specyfikacji dla programu LLgen składa się z: nieterminalu, znaku „ : ” i prawej strony produkcji. Zakończona jest średnikiem; Alternatywne prawe strony produkcji rozdzielane są znakiem „|”; Prawa strona produkcji może składać się z terminali, nieterminali i akcji semantycznych; nieterminal : prawa strona produkcji ; 8

TWORZENIE SPECYFIKACJI Reguły tworzenia specyfikacji: białe spacje są ignorowane, jednak nie mogą występować w obrębie nazwy; Komentarze wprowadzamy po znaku „/*” a zamykamy „*/”; Komentarze nie mogą być zagnieżdżone; Komentarze mogą wystąpić w każdym miejscu, gdzie dozwolone jest wystąpienie nazwy; 9

TWORZENIE SPECYFIKACJI Reguły tworzenia specyfikacji c.d. : Nazwy symboli terminalnych i nieterminalnych mogą być dowolnej długości. Maja one składnię taką, jak identyfikatory języka C; Nazwy symboli nie mogą kolidować ze słowami kluczowymi języka C; Wielkość liter w nazwie jest rozróżnialna; 10

TWORZENIE SPECYFIKACJI Reguły tworzenia specyfikacji c.d. : Nazwy symboli mogą być dowolnej długości, jednak w LLgen znaczących jest 50 pierwszych znaków; Wszystkie nazwy generowane i wykorzystywane przez LLgen rozpoczynają się prefiksem LL; 11

DEKLARACJA TERMINALI Terminale, które nie są literałami deklarujemy: %token ken; Jeśli mamy kilka terminali do deklaracji możemy to zrobić tak: %token nazwa1, nazwa2, nazwa3; Każde użycie terminala musi być poprzedzone jego deklaracją; 12

DEKLRACJE TERMINALI Terminale, które są literałami są ujmowane w apostrofy; LLgen rozpoznaje także (podobnie jak C) zestaw literałów specjalnych, tzn.: nowa linia ‘\n’ tabulator ‘\t’ powrót karetki ‘\r’ apostrof ‘\’’ wycofanie znaku ‘\b’ odwrotny ukośnik ‘\\’ liczba oktalna ‘\xxx’ 13

DEKLRACJE TERMINALI ZAPAMIETAJ!!! Napotkana w pliku specyfikacji nazwa, która nie była zadeklarowana jako token, będzie traktowana przez LLgen jako symbol nieterminalny; 14

DEKLRACJE TERMINALI Nieterminal jest implementowany jako funkcja języka C; W LLgenie możemy korzystać ze zmiennych lokalnych funkcji. Generator pozwala je deklarować, w nawiasach klamrowych, jedynie po lewej stronie produkcji za symbolem nieterminalnym, np.: A {int zmienna;} : S ken T ; 15

DEKLRACJE TERMINALI Przez akcję semantyczną rozumiemy dowolną pojedynczą instrukcję (grupę instrukcji) napisaną w języku C, które są ujęte w nawiasy klamrowe; W LLgenie akcje semantyczne możemy wstawić jedynie po prawej stronie produkcji, np.: A {int zmienna} : S ken {licznik=1;} T ; 16

NIETERMINAL STARTOWY Analizatory generowane przez LLgen mogą posiadać wiele nieterminali startowych; Deklaracja nieterminalu startowego inaczej aksjomatu wygląda następująco: %start funkcja , nazwa_nieterminala; np.: %start parse, S; 17

KOMPILACJA Polecenie, które służy do uruchomienia generatora to LLgen. Polecenie to jest wywoływane dla pilku specyfikacji (rozszerzenie g), np.: LLgen gram.g Generator Llgen na wyjściu produkuje trzy pliki: gram.c – plik w C zwierający implementację parsera; Lpars.h – plik zawierający interfejs analizatora leksykalnego; Lpars.c – szkielet parsera i tablica sterująca; 18

OPCJA -V Czasem warto jest przy uruchamianiu i testowaniu parsera korzystać z opcji –v; Dzięki opcji –v wygenerowany zostanie plik LL.output, który będzie zwierał informacje o nierozwiązanych konfliktach, które pojawiły się w gramatyce; 19

ROZSZERZENIE SKŁADNI GRAMATRYK Rozszerzenia standardowej składni gramatyk bezkontekstowych: * (*liczba) – domknięcie zwrotne + (+liczba) – domknięcie dodatnie ; ? – operator opcjonalności; [...] – możliwość grupowania symboli; 20

Przykład Niech ={a,b}. Rozważmy język regularny L=L(b*a). Wówczas: S : B A ; B : ‘b’ * A : ‘a’ S : B A ; B : | ‘b’ B A : ‘a’ 21

Przykład Niech ={a,b}. Rozważmy język L={b, ab, aab, aaab}. Wówczas: S : A B ; A : | ‘a’ C C : | ‘a’ B : ‘b’ S : A B ; A : ‘a’ *3 B : ‘b’ 22

Przykład Niech ={a,b}. Rozważmy język L={ab, aab, aaab}. Wówczas: S : A B ; A : ‘a’ C C : | ‘a’ B : ‘b’ S : A B ; A : ‘a’ +3 B : ‘b’ 23

Przykład Niech ={a,b}. Rozważmy język L={b, ab}. Wówczas: S : A B ; A : | ‘a’ B : ‘b’ S : A B ; A : ‘a’ ? B : ‘b’ 24

Przykład Niech ={a,b}. Rozważmy język L={A * : |A|=2}. Wówczas: S : ‘a’ B | ‘b’ B ; B : ‘a’ | ‘b’ S : [ ‘a’ | ‘b’ ] +2 ; 25

PORÓWNANIE Rozważmy gramatykę, która nie jest gramatyką LL(1). Porównajmy pracochłonność procedury dostosowania gramatyki a bezpośrednią implemantacją gramatyki w generatorze LLgen’; Niech =[a,b}. Napiszmy program akceptujący język bezkontekstowy L={A* : A=an bn ; n }; 26

PORÓWNANIE { int ilosc_a, ilosc_b; } %start parse , S; S : A B { if (ilosc_a= = ilosc_b) puts(’’OK.’’); else puts(’’Blad’’); } ; 27

PORÓWNANIE Usuwamy lewostronną rekurencję; A : ’a’ { ilosc_a=1; } B : ‘b’ { ilosc_b=1; } | B ‘b’ { ilosc_b++; } A : ’a’ { ilosc_a=1; } | ’a’ A { ilosc_a++; } ; B : ‘b’ { ilosc_b=1; } | ‘b’ B { ilosc_b++; } 28

PORÓWNANIE A : ’a’ C { ilosc_a++; } ; C : { ilosc_a=0; } B : ’b’ D { ilosc_b++; } D : { ilosc_b=0; } | ’b’ D { ilosc_b++; } 29

PORÓWNANIE S : {ilosc_a=ilosc_b=0} A B { if (ilosc_a= = ilosc_b) puts(’’OK.’’); else puts(’’Blad’’); } ; A : [ ’a’ {ilosc_a++} ] + B : [ ’b’ {ilosc_b++} ] + 30

LLSYMB LLsymb jest globalną zmienną całkowitą, która może przyjmować różne wartości. To jaka wartość będzie przyjęta, zależy od położenia głowicy czytającej po prawej stronie produkcji: Możliwe wartości: Jeśli przeczytany został token, to LLsymb przechowuje token; Po grupowaniu i alternatywie w zmiennej znajduje się podglądany token; 31

TWORZENIE SPECYFIKACJI W pliku ze specyfikacją do generatora LLgen obowiązkowo powinna znaleźć się implementacja funkcji main; %start parse, S ; int main(){ parse(); return 0; } 32

TWORZENIE SPECYFIKACJI W pliku ze specyfikacją do generatora LLgen powinna także znaleźć się implementacja funkcji LLmessage; Funkcja ta jest automatycznie wywoływana przez parser, gdy wystąpi bład składniowy; void LLmessage ( int tk ); Nie zwraca żadnej wartości Ma jeden parametr typu całkowitego 33

TWORZENIE SPECYFIKACJI Zmienna tk przyjmuje następujące wartości: gdy oczekiwany był token „tk” – tk > 0; gdy wczytany został nieoczekiwany token i został on usunięty – tk = 0; gdy nie został napotkany oczekiwany koniec pliku i pozostałe wejście będzie pominięte – tk = - 1; 34

Przykład Działanie generatora LLgen najlepiej zobaczyć na przykładzie. Na wejściu znajduje się ciąg słów złożonych z alfabetu naturalnego, słowa kończą się znakiem dwukropka i są rozdzielane przecinkiem. Dany na wejście ciąg zawiera co najmniej jedno słowo.... 35

KONFLIKTY W trakcie pracy generatora składniowego może dojść do konfliktu polegającego na: nie jesteśmy w stanie określić, którą z prawych stron należy rozwijać – konflikt alternatyw; Konstrukcja która jest aktualnie przetwarzana zawiera domkniecie i trudno określić, czy wejście jest jej dalszym ciągiem, czy też rozpoczyna inną konstrukcję – konflikt powtórzeń; 36

KONFLIKTY Konflikt alternatyw można rozstrzygnąć na dwa sposoby: dynamiczne rozstrzyganie konfliktu alternatywy: %if (warunek) statyczne rozstrzyganie konfliktu alternatyw: %prefer  %if(1) %aviod  %if(0) 37

Przykład Rozważmy zadanie badania parzystości liczby binarnej; Analizator leksykalny rozpoznaje i zwraca liczby binarne; %% [01] { return yytext[0]; } 38

Przykład { int wczytcyfra; } %start parse, S; S : ’0’ { wczytcyfra = 0; } R | ’1’ { wczytcyfra = 1; } R ; R : %if (wczytcyfra ==0 ) {puts(”parzysta”);} | {puts(”nieparzysta”);} | S 39

ROZWIĄZYWANIE KONFLIKTÓW Przykład użycia mechanizmu statycznego rozwiązywania konfliktów alternatyw jest problemem tzw. „wiszącego else”; Problem ten omówimy szczegółowo na wykładzie poświęconym generatorowi YACC; 40

ROZWIĄZYWANIE KONFLIKTÓW Konflikt powtórzeń jest rozstrzygany przy pomocy słowa kluczowego %while; %while ( warunek ) W ewaluacji warunku bardzo przydatne może być makro języka C, które jest generowane przez Llgen na podstawie słowa kluczowego %first; %first fmac, nonterm ; 41

KONIEC KONIEC WYKŁADU SZÓSTEGO