Podstawy kompilatorów: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
 
(Nie pokazano 23 wersji utworzonych przez 2 użytkowników)
Linia 1: Linia 1:
== Forma zajęć ==
Wykład (30 godzin) + laboratorium (30 godzin)
== Opis ==
== Opis ==
Celem przedmiotu jest przedstawienie zasad i technik budowy kompilatorów.
Kompilator jest programem, który przetwarza kod napisany w jednym języku (tzw. języku źródłowym) na równoważny kod w drugim języku (tzw. języku wynikowym).
W ramach przedmiotu przedstawione zostaną zasady ich implementacji zarówno z wykorzystaniem specjalizowanych narzędzi takich jak LEX i YACC jak i z wykorzystaniem uniwersalnych języków programowania wysokiego poziomu, takich jak język C.
Na rynku funkcjonuje wiele typów kompilatorów dla różnych języków źródłowych i wynikowych oraz wiele narzędzi pokrewnych kompilatorom, takich jak statyczne analizatory i kontrolery kodu, formatery programów źródłowych, kompilatory krzemowe i interpretery zapytań.
Wraz z rozszerzaniem zakresu zastosowań informatyki oraz pojawianiem się nowych technologii, powstaje potrzeba rozwijania i tworzenia nowych narzędzi tego typu. Zasady i techniki pisania kompilatorów są na tyle ogólne, że obejmują wiedzę z zakresu języków programowania, architektury maszynowej, teorii języków oraz algorytmikę i inżynierię oprogramowania.
Pierwsze kompilatory powstały w latach 50. i powszechnie uważane były wówczas za programy trudne do napisania. Od tego czasu wytworzono jednak systematyczne techniki wykonywania poszczególnych zadań pojawiających się w trakcie kompilacji, stworzono odpowiednie języki implementacji, środowiska i narzędzia programistyczne istotnie upraszczające te zadania.<br>
Celem przedmiotu ''Podstawy kompilatorów'' jest przedstawienie zasad, technik i narzędzi wykorzystywanych współcześnie do budowy kompilatorów.<br>
W ramach przedmiotu przedstawione zostaną zasady implementacji kompilatorów, zarówno z wykorzystaniem specjalizowanych narzędzi takich jak LEX, YACC i LLgen, jak i z wykorzystaniem uniwersalnych języków programowania wysokiego poziomu, takich jak język C.
Omówione zostaną poszczególne fazy kompilacji poczynając od analizy leksykalnej, poprzez analizę składniową, semantyczną, generację kodu pośredniego i wynikowego po optymalizację kodu. Przedstawione zostaną także zagadnienia dotyczące budowy środowiska wykonawczego.
Omówione zostaną poszczególne fazy kompilacji poczynając od analizy leksykalnej, poprzez analizę składniową, semantyczną, generację kodu pośredniego i wynikowego po optymalizację kodu. Przedstawione zostaną także zagadnienia dotyczące budowy środowiska wykonawczego.
 
Przedmiot ''Podstawy kompilatorów'' koncentruje się na omówieniu etapu analizy kodu i przedstawieniu narzędzi wykorzystywanych w tworzeniu kompilatorów.Pozostałe zagadnienia omówione są szerzej w ramach przedmiotu ''Metody realizacji języków programowania''.
Oprócz wykładów będą prowadzone ćwiczenia laboratoryjne, w trakcie których rozwiązywane będą zadania ilustrujące zagadnienia omawiane na wykładach.


== Sylabus ==
== Sylabus ==


=== Autorzy ===
=== Autor sylabusa ===
* Wojciech Complak, wojciech.complak@cs.put.poznan.pl
* Wojciech Complak &mdash; Politechnika Poznańska
* Bartosz Bogacki, bartosz.bogacki@cs.put.poznan.pl


=== Zakres przedmiotu ===
=== Autorzy kursu ===
# Wstęp, organizacja procesu kompilacji (zakres przedmiotu, rodzaje translatorów, interpretacja a kompilacja, model kompilatora, podział na fazy)
Kurs został opracowany przez zespół pracowników Instytutu Informatyki Politechniki Poznańskiej w składzie:
# Analiza leksykalna (wprowadzenie do analizy leksykalnej, podstawowe pojęcia, implementacja analizatorów leksykalnych w językach imperatywnych na przykładzie języka C)
* dr inż. Wojciech Complak
# Implementacja analizatorów leksykalnych w Lexie (koncepcja i używanie generatora, konwencje notacyjne, wzorce, akcje, retrakcja, konteksty, odrzucenie dopasowania)
* mgr inż. Bartosz Bogacki
# Wstęp do analizy składniowej (podstawowe pojęcia analizy składniowej, klasyfikacja Chomsky'ego a implementacja analizatorów, gramatyki bezkontekstowe)
# Analiza metodą zstępującą (koncepcja metody top-down, ograniczenia metody : lewostronna rekurencja, faktoryzacja)
# Implementacja analizatora zstępującego analizatora składniowego w języku imperatywnym (na przykładzie języka C)
# Analiza metodą wstępującą (koncepcja metody bottom-up, LR-parsery, metody generowania tablic)
# Podstawy generatora YACC
# Generator YACC : gramatyki niejednoznaczne, konflikty, rozstrzyganie
# Translacja sterowana składnią w generatorze YACC (atrybuty i implementacja, akcje wielokrotne)
# Zależności kontekstowe (systemy typów, kontrola zgodności typów, konwersje)
# Generacja kodu pośredniego (koncepcja języka pośredniego, typy języków pośrednich, maszyny wirtualne)
# Generacja kodu wynikowego (architektury sprzętowe, przydział i wyznaczanie rejestrów, bloki podstawowe, grafy przepływu)
# Optymalizacja (cele optymalizacja, optymalizacja zależna i niezależna od maszyny docelowej,  analiza przepływu sterowania, analiza przepływu danych, optymalizacja a uruchamianie oprogramowania, superkompilatory)
# Zarządzanie pamięcią (strategie alokacji, alokacja stosowa, sterta, algorytmy przydziału ze sterty, arbitralne zarządzanie a usuwanie nieużytków, wykrywanie wiszących referencji, scalanie)
# Dostęp do nazw nielokalnych (widzialność, zasięg, zagnieżdżanie bloków, procedur i funkcji, widzialność statyczna, język C a Pascal i Ada, wiązania dostępu, wektory display, widzialność dynamiczna, płytki i głęboki dostęp)
# Obsługa wyjątków, kod wielowątkowy, przekazywanie parametrów (zarządzanie stosem, alokacja ze sterty, tryby i metody przekazywania parametrów)
# Systemy rozproszone, zdalne wywoływanie (translatory dla systemów rozproszonych, konwersje reprezentacji)


=== Wymagania wstępne ===
=== Wymagania wstępne ===
Linia 36: Linia 26:
* Umiejętność programowania w imperatywnych językach wysokiego poziomu
* Umiejętność programowania w imperatywnych językach wysokiego poziomu
* Podstawowa znajomość architektury procesora i języka asemblera
* Podstawowa znajomość architektury procesora i języka asemblera
=== Zawartość ===
* Pierwszy moduł poświęcony jest omówieniu modelu kompilatora, planu i zakresu przedmiotu oraz literatury i narzędzi potrzebnych do wykonywania ćwiczeń. W ramach modułu przedstawiono model kompilatora typu analiza-synteza i zadania wykonywane w fazach analizy leksykalnej, analizy składniowej i analizy semantycznej, wchodzących w skład etapu analizy, oraz fazach generacji kodu pośredniego, generacji i optymalizacji kodu wynikowego, wchodzących w skład etapu syntezy. Omówiono również zagadnienia dotyczące budowy środowiska wykonawczego, takie jak dostęp do nazw nielokalnych, dynamiczny przydział pamięci i przekazywanie parametrów do podprogramów.
* Kolejna część kursu składa się z dwóch modułów, w których omówiono fazę analizy leksykalnej. Pierwszy moduł tego cyklu jest ogólnym wprowadzeniem do analizy leksykalnej. Przedstawiono zadania, jakie ma do wykonania analizator leksykalny, podstawowe pojęcia związane z analizą leksykalną, konstruowanie niedeterministycznych i deterministycznych automatów skończonych oraz implementowanie na podstawie deterministycznych automatów skończonych prostych analizatorów leksykalnych w uniwersalnych językach programowania na przykładzie języka C. Drugi moduł tego cyklu poświęcony jest omówieniu specjalizowanego narzędzia do tworzenia analizatorów leksykalnych, jakim jest generator LEX. W module przedstawiono ogólną charakterystykę i filozofię działania generatora i wygenerowanych za jego pomocą analizatorów, składnię specyfikacji analizatorów leksykalnych, posługiwanie się definicjami regularnymi i wzorcami oraz prawym i lewym kontekstem.
* Kolejne osiem modułów tworzy cykl poświęcony analizie składniowej. Pierwszy moduł tego cyklu jest ogólnym wprowadzeniem do analizy składniowej. W ramach modułu omówiono pojęcia związane z posługiwaniem się gramatykami bezkontekstowymi, takie jak jednostki terminalne i nieterminalne, produkcje, wywody, rekurencję prawostronną i lewostronną, niejednoznaczność i równoważność gramatyk bezkontekstowych. W drugim module omówione jest prowadzenie analizy składniowej metodą zstępującą (LL). Przedstawiono ogólną charakterystykę metody zstępującej i metody konstruowania analizatorów działających zgodnie z tą metodą. Wskazano także na ograniczenia, jakie metoda zstępująca nakłada na postać gramatyki źródłowej, zademonstrowano metody dostosowywania gramatyk do odpowiedniej postaci oraz zasady implementacji analizatorów działających metodą zstępującą w uniwersalnym języku programowania na przykładzie języka C. Ważną zaletą metody zstępującej jest możliwość implementowania nawet stosunkowo złożonych analizatorów bezpośrednio w uniwersalnym języku programowania. W przypadku większych projektów korzystne jest jednak użycie specjalizowanego narzędzia, takiego jak generator analizatorów składniowych LLgen. Generator ten został przedstawiony w ramach kolejnego modułu, który zawiera jego ogólną charakterystykę, opis współpracy z analizatorem leksykalnym, omówienie rozszerzeń gramatyk bezkontekstowych wprowadzonych w tym generatorze oraz środowiska generatora i mechanizmów rozstrzygania konfliktów składniowych alternatyw i powtórzeń charakterystycznych dla analizy składniowej prowadzonej metodą zstępującą. W ramach kolejnego modułu przedstawiono translację sterowaną składnią &mdash; metodę translacji języków opartą o gramatyki bezkontekstowe. Przedstawiono pojęcia atrybutów syntetyzowanych i dziedziczonych, definicji sterowanych składnią, schematów translacji oraz definicji S-atrybutowych i L-atrybutowych. W drugiej części modułu omówiono zasady implementacji translacji sterowanej składnią w uniwersalnym języku programowania na przykładzie języka C oraz w generatorze LLgen. Kolejny moduł cyklu jest wprowadzeniem do silniejszej metody analizy składniowej – metody wstępującej (LR). W module przedstawiono ogólną charakterystykę metody, zasady konstruowania i działania analizatorów działających metodą LR i metody rozstrzygania konfliktów składniowych. W przypadku metody wstępującej, tworzenie analizatorów składniowych bezpośrednio w uniwersalnym języku programowania jest praktycznie nierealne. Dlatego w kolejnym module przedstawione jest najpopularniejsze specjalistyczne narzędzie wykorzystywane do tworzenia analizatorów składniowych działających metodą wstępującą &mdash; generator YACC. W ramach modułu przedstawiono ogólną charakterystykę generatora YACC, składnię specyfikacji analizatora składniowego, zasady współpracy z analizatorem leksykalnym oraz wykrywania i obsługi błędów składniowych. W kolejnym module omawiana jest translacja sterowana składnią w metodzie wstępującej z wykorzystaniem generatora YACC. Przedstawiono sposoby deklarowania i używania różnych typów atrybutów oraz zasady korzystania z atrybutów syntetyzowanych i dziedziczonych. Ostatni moduł z cyklu dotyczącego fazy analizy składniowej poświęcono posługiwaniu się gramatykami niejednoznacznymi w metodzie wstępującej w generatorze YACC. W ramach modułu najpierw pokazano, dlaczego warto posługiwać się gramatykami niejednoznacznymi, a następnie omówiono zasady wykorzystywania ich w generatorze YACC. Przedstawiono sposoby rozstrzygania konfliktów przesuń/redukuj i redukuj/redukuj charakterystycznych dla metody wstępującej przy pomocy opisywania łączności i priorytetów. Następnie omówiono przykłady typowych problemów spotykanych w implementacji translatorów dla popularnych języków programowania – problem tzw. ''wiszącego else'' i korzystanie z przypadków specjalnych.
* Kolejny moduł poświęcony jest analizie semantycznej. Przedstawiono różne typy kontroli zależności kontekstowych, takie jak sprawdzenie przepływu sterowania, sprawdzenie unikalności deklaracji nazw i sprawdzenie powtórzeń nazw. W ramach modułu szczególny nacisk położono na najtrudniejszą w implementacji kontrolę &mdash; sprawdzanie zgodności typów. Przedstawiono koncepcję nazwowej i strukturalnej zgodności typów oraz szkielet prostego kontrolera zgodności typów.
* Ostatni moduł poświęcony jest etapowi syntezy kodu i zagadnieniom dotyczącym budowy środowiska wykonawczego. Omówiono fazę generacji kodu pośredniego oraz różne typy języków pośrednich ze szczególnym naciskiem na kod trójadresowy. Zademonstrowano przykładowe optymalizacje kodu, wykonywane zarówno w fazie generacji kodu pośredniego, jak i w fazie generacji kodu wynikowego. Omówiono również niektóre zagadnienia dotyczące budowy środowiska wykonawczego, takie jak dostęp do nazw nielokalnych, dynamiczny przydział pamięci i przekazywanie parametrów do podprogramów.


=== Literatura ===
=== Literatura ===
* Aho A. V., Sethi R., Ullman J. D., Kompilatory Reguły, metody i narzędzia, WNT 2002.
* A.V. Aho, M.S. Lam, R. Sethi, J.D. Ullman, ''Compilers: Principles, Techniques, and Tools, 2/E'' (w języku polskim dostępne jest tłumaczenie poprzedniej wersji tej książki z 1986 roku: A.V. Aho, M.S. Lam, R. Sethi, J.D. Ullman, ''Kompilatory. Reguły, metody i narzędzia'', Wydawnictwa Naukowo-Techniczne, Warszawa 2002).
* Waite W. M., Goos G., Konstrukcja kompilatorów, WNT, 1989
* M. Foryś,W. Foryś, ''Teoria automatów i języków formalnych'', Akademicka Oficyna Wydawnicza Exit, 2005.
* J.P. Tremblay, P.G. Sorenson, ''The Theory and Practice of Compiler Writing'', McGraw-Hill, 1985.
* W.M. Waite,G. Goos, ''Konstrukcja kompilatorów'', Wydawnictwa Naukowo-Techniczne, Warszawa 1989.
* R. Wilhelm, D. Maurer, ''Compiler Design'', Addison-Wesley, 1995.
 
== Moduły ==
* [[pok-1-wyk-toc|Wykład 1: Podstawy kompilatorów. Wprowadzenie do przedmiotu]] ([http://osilek.mimuw.edu.pl/external/pok/pok-1-wyk/player.html Flash], [[media:pok-1-wyk.pdf|PDF]], [[media:pok-1-wyk-kolor.pdf|PDF kolor]]),[[media:pok-1-lab.pdf| Laboratorium (PDF)]]
* [[pok-2-wyk-toc|Wykład 2: Podstawy kompilatorów. Analiza leksykalna]] ([http://osilek.mimuw.edu.pl/external/pok/pok-2-wyk/player.html Flash], [[media:pok-2-wyk.pdf|PDF]], [[media:pok-2-wyk-kolor.pdf|PDF kolor]]),[[media:pok-2-lab.pdf| Laboratorium (PDF)]]
* [[pok-3-wyk-toc|Wykład 3: Podstawy kompilatorów. Implementacja analizatorów leksykalnych]] ([http://osilek.mimuw.edu.pl/external/pok/pok-3-wyk/player.html Flash], [[media:pok-3-wyk.pdf|PDF]], [[media:pok-3-wyk-kolor.pdf|PDF kolor]]),[[media:pok-3-lab.pdf| Laboratorium (PDF)]]
* [[pok-4-wyk-toc|Wykład 4: Podstawy kompilatorów. Wstęp do analizy składniowej]] ([http://osilek.mimuw.edu.pl/external/pok/pok-4-wyk/player.html Flash], [[media:pok-4-wyk.pdf|PDF]], [[media:pok-4-wyk-kolor.pdf|PDF kolor]]),[[media:pok-4-lab.pdf| Laboratorium (PDF)]]
* [[pok-5-wyk-toc|Wykład 5: Podstawy kompilatorów. Analiza metodą zstępującą]] ([http://osilek.mimuw.edu.pl/external/pok/pok-5-wyk/player.html Flash], [[media:pok-5-wyk.pdf|PDF]], [[media:pok-5-wyk-kolor.pdf|PDF kolor]]),[[media:pok-5-lab.pdf| Laboratorium (PDF)]]
* [[pok-6-wyk-toc|Wykład 6: Podstawy kompilatorów. Generowanie analizatorów działających metodą zstępującą]] ([http://osilek.mimuw.edu.pl/external/pok/pok-6-wyk/player.html Flash], [[media:pok-6-wyk.pdf|PDF]], [[media:pok-6-wyk-kolor.pdf|PDF kolor]]),[[media:pok-6-lab.pdf| Laboratorium (PDF)]]
* [[pok-7-wyk-toc|Wykład 7: Podstawy kompilatorów. Translacja sterowana składnią w metodzie zstępującej]] ([http://osilek.mimuw.edu.pl/external/pok/pok-7-wyk/player.html Flash], [[media:pok-7-wyk.pdf|PDF]], [[media:pok-7-wyk-kolor.pdf|PDF kolor]]),[[media:pok-7-lab.pdf| Laboratorium (PDF)]]
* [[pok-8-wyk-toc|Wykład 8: Podstawy kompilatorów. Analiza metodą wstępującą]] ([http://osilek.mimuw.edu.pl/external/pok/pok-8-wyk/player.html Flash], [[media:pok-8-wyk.pdf|PDF]], [[media:pok-8-wyk-kolor.pdf|PDF kolor]]),[[media:pok-8-lab.pdf| Laboratorium (PDF)]]
* [[pok-9-wyk-toc|Wykład 9: Podstawy kompilatorów. Podstawy generaratora YACC]] ([http://osilek.mimuw.edu.pl/external/pok/pok-9-wyk/player.html Flash], [[media:pok-9-wyk.pdf|PDF]], [[media:pok-9-wyk-kolor.pdf|PDF kolor]]),[[media:pok-9-lab.pdf| Laboratorium (PDF)]]
* [[pok-10-wyk-toc|Wykład 10: Podstawy kompilatorów. Translacja sterowana składnią w generatorze YACC]] ([http://osilek.mimuw.edu.pl/external/pok/pok-10-wyk/player.html Flash], [[media:pok-10-wyk.pdf|PDF]], [[media:pok-10-wyk-kolor.pdf|PDF kolor]]),[[media:pok-10-lab.pdf| Laboratorium (PDF)]]
* [[pok-11-wyk-toc|Wykład 11: Podstawy kompilatorów. Generator YACC : gramatyki niejednoznaczne]] ([http://osilek.mimuw.edu.pl/external/pok/pok-11-wyk/player.html Flash], [[media:pok-11-wyk.pdf|PDF]], [[media:pok-11-wyk-kolor.pdf|PDF kolor]]),[[media:pok-11-lab.pdf| Laboratorium (PDF)]]
* [[pok-12-wyk-toc|Wykład 12: Podstawy kompilatorów. Analiza zależności kontekstowych]] ([http://osilek.mimuw.edu.pl/external/pok/pok-12-wyk/player.html Flash], [[media:pok-12-wyk.pdf|PDF]], [[media:pok-12-wyk-kolor.pdf|PDF kolor]]),[[media:pok-12-lab.pdf| Laboratorium (PDF)]]
* [[pok-13-wyk-toc|Wykład 13: Podstawy kompilatorów. Synteza kodu i środowisko czasu wykonania]] ([http://osilek.mimuw.edu.pl/external/pok/pok-13-wyk/player.html Flash], [[media:pok-13-wyk.pdf|PDF]], [[media:pok-13-wyk-kolor.pdf|PDF kolor]]),[[media:pok-13-lab.pdf| Laboratorium (PDF)]]

Aktualna wersja na dzień 10:32, 28 wrz 2006

Forma zajęć

Wykład (30 godzin) + laboratorium (30 godzin)

Opis

Kompilator jest programem, który przetwarza kod napisany w jednym języku (tzw. języku źródłowym) na równoważny kod w drugim języku (tzw. języku wynikowym). Na rynku funkcjonuje wiele typów kompilatorów dla różnych języków źródłowych i wynikowych oraz wiele narzędzi pokrewnych kompilatorom, takich jak statyczne analizatory i kontrolery kodu, formatery programów źródłowych, kompilatory krzemowe i interpretery zapytań. Wraz z rozszerzaniem zakresu zastosowań informatyki oraz pojawianiem się nowych technologii, powstaje potrzeba rozwijania i tworzenia nowych narzędzi tego typu. Zasady i techniki pisania kompilatorów są na tyle ogólne, że obejmują wiedzę z zakresu języków programowania, architektury maszynowej, teorii języków oraz algorytmikę i inżynierię oprogramowania. Pierwsze kompilatory powstały w latach 50. i powszechnie uważane były wówczas za programy trudne do napisania. Od tego czasu wytworzono jednak systematyczne techniki wykonywania poszczególnych zadań pojawiających się w trakcie kompilacji, stworzono odpowiednie języki implementacji, środowiska i narzędzia programistyczne istotnie upraszczające te zadania.
Celem przedmiotu Podstawy kompilatorów jest przedstawienie zasad, technik i narzędzi wykorzystywanych współcześnie do budowy kompilatorów.
W ramach przedmiotu przedstawione zostaną zasady implementacji kompilatorów, zarówno z wykorzystaniem specjalizowanych narzędzi takich jak LEX, YACC i LLgen, jak i z wykorzystaniem uniwersalnych języków programowania wysokiego poziomu, takich jak język C. Omówione zostaną poszczególne fazy kompilacji poczynając od analizy leksykalnej, poprzez analizę składniową, semantyczną, generację kodu pośredniego i wynikowego po optymalizację kodu. Przedstawione zostaną także zagadnienia dotyczące budowy środowiska wykonawczego. Przedmiot Podstawy kompilatorów koncentruje się na omówieniu etapu analizy kodu i przedstawieniu narzędzi wykorzystywanych w tworzeniu kompilatorów.Pozostałe zagadnienia omówione są szerzej w ramach przedmiotu Metody realizacji języków programowania.

Sylabus

Autor sylabusa

  • Wojciech Complak — Politechnika Poznańska

Autorzy kursu

Kurs został opracowany przez zespół pracowników Instytutu Informatyki Politechniki Poznańskiej w składzie:

  • dr inż. Wojciech Complak
  • mgr inż. Bartosz Bogacki

Wymagania wstępne

  • Umiejętność konstruowania algorytmów iteracyjnych i rekurencyjnych
  • Umiejętność programowania w imperatywnych językach wysokiego poziomu
  • Podstawowa znajomość architektury procesora i języka asemblera

Zawartość

  • Pierwszy moduł poświęcony jest omówieniu modelu kompilatora, planu i zakresu przedmiotu oraz literatury i narzędzi potrzebnych do wykonywania ćwiczeń. W ramach modułu przedstawiono model kompilatora typu analiza-synteza i zadania wykonywane w fazach analizy leksykalnej, analizy składniowej i analizy semantycznej, wchodzących w skład etapu analizy, oraz fazach generacji kodu pośredniego, generacji i optymalizacji kodu wynikowego, wchodzących w skład etapu syntezy. Omówiono również zagadnienia dotyczące budowy środowiska wykonawczego, takie jak dostęp do nazw nielokalnych, dynamiczny przydział pamięci i przekazywanie parametrów do podprogramów.
  • Kolejna część kursu składa się z dwóch modułów, w których omówiono fazę analizy leksykalnej. Pierwszy moduł tego cyklu jest ogólnym wprowadzeniem do analizy leksykalnej. Przedstawiono zadania, jakie ma do wykonania analizator leksykalny, podstawowe pojęcia związane z analizą leksykalną, konstruowanie niedeterministycznych i deterministycznych automatów skończonych oraz implementowanie na podstawie deterministycznych automatów skończonych prostych analizatorów leksykalnych w uniwersalnych językach programowania na przykładzie języka C. Drugi moduł tego cyklu poświęcony jest omówieniu specjalizowanego narzędzia do tworzenia analizatorów leksykalnych, jakim jest generator LEX. W module przedstawiono ogólną charakterystykę i filozofię działania generatora i wygenerowanych za jego pomocą analizatorów, składnię specyfikacji analizatorów leksykalnych, posługiwanie się definicjami regularnymi i wzorcami oraz prawym i lewym kontekstem.
  • Kolejne osiem modułów tworzy cykl poświęcony analizie składniowej. Pierwszy moduł tego cyklu jest ogólnym wprowadzeniem do analizy składniowej. W ramach modułu omówiono pojęcia związane z posługiwaniem się gramatykami bezkontekstowymi, takie jak jednostki terminalne i nieterminalne, produkcje, wywody, rekurencję prawostronną i lewostronną, niejednoznaczność i równoważność gramatyk bezkontekstowych. W drugim module omówione jest prowadzenie analizy składniowej metodą zstępującą (LL). Przedstawiono ogólną charakterystykę metody zstępującej i metody konstruowania analizatorów działających zgodnie z tą metodą. Wskazano także na ograniczenia, jakie metoda zstępująca nakłada na postać gramatyki źródłowej, zademonstrowano metody dostosowywania gramatyk do odpowiedniej postaci oraz zasady implementacji analizatorów działających metodą zstępującą w uniwersalnym języku programowania na przykładzie języka C. Ważną zaletą metody zstępującej jest możliwość implementowania nawet stosunkowo złożonych analizatorów bezpośrednio w uniwersalnym języku programowania. W przypadku większych projektów korzystne jest jednak użycie specjalizowanego narzędzia, takiego jak generator analizatorów składniowych LLgen. Generator ten został przedstawiony w ramach kolejnego modułu, który zawiera jego ogólną charakterystykę, opis współpracy z analizatorem leksykalnym, omówienie rozszerzeń gramatyk bezkontekstowych wprowadzonych w tym generatorze oraz środowiska generatora i mechanizmów rozstrzygania konfliktów składniowych alternatyw i powtórzeń charakterystycznych dla analizy składniowej prowadzonej metodą zstępującą. W ramach kolejnego modułu przedstawiono translację sterowaną składnią — metodę translacji języków opartą o gramatyki bezkontekstowe. Przedstawiono pojęcia atrybutów syntetyzowanych i dziedziczonych, definicji sterowanych składnią, schematów translacji oraz definicji S-atrybutowych i L-atrybutowych. W drugiej części modułu omówiono zasady implementacji translacji sterowanej składnią w uniwersalnym języku programowania na przykładzie języka C oraz w generatorze LLgen. Kolejny moduł cyklu jest wprowadzeniem do silniejszej metody analizy składniowej – metody wstępującej (LR). W module przedstawiono ogólną charakterystykę metody, zasady konstruowania i działania analizatorów działających metodą LR i metody rozstrzygania konfliktów składniowych. W przypadku metody wstępującej, tworzenie analizatorów składniowych bezpośrednio w uniwersalnym języku programowania jest praktycznie nierealne. Dlatego w kolejnym module przedstawione jest najpopularniejsze specjalistyczne narzędzie wykorzystywane do tworzenia analizatorów składniowych działających metodą wstępującą — generator YACC. W ramach modułu przedstawiono ogólną charakterystykę generatora YACC, składnię specyfikacji analizatora składniowego, zasady współpracy z analizatorem leksykalnym oraz wykrywania i obsługi błędów składniowych. W kolejnym module omawiana jest translacja sterowana składnią w metodzie wstępującej z wykorzystaniem generatora YACC. Przedstawiono sposoby deklarowania i używania różnych typów atrybutów oraz zasady korzystania z atrybutów syntetyzowanych i dziedziczonych. Ostatni moduł z cyklu dotyczącego fazy analizy składniowej poświęcono posługiwaniu się gramatykami niejednoznacznymi w metodzie wstępującej w generatorze YACC. W ramach modułu najpierw pokazano, dlaczego warto posługiwać się gramatykami niejednoznacznymi, a następnie omówiono zasady wykorzystywania ich w generatorze YACC. Przedstawiono sposoby rozstrzygania konfliktów przesuń/redukuj i redukuj/redukuj charakterystycznych dla metody wstępującej przy pomocy opisywania łączności i priorytetów. Następnie omówiono przykłady typowych problemów spotykanych w implementacji translatorów dla popularnych języków programowania – problem tzw. wiszącego else i korzystanie z przypadków specjalnych.
  • Kolejny moduł poświęcony jest analizie semantycznej. Przedstawiono różne typy kontroli zależności kontekstowych, takie jak sprawdzenie przepływu sterowania, sprawdzenie unikalności deklaracji nazw i sprawdzenie powtórzeń nazw. W ramach modułu szczególny nacisk położono na najtrudniejszą w implementacji kontrolę — sprawdzanie zgodności typów. Przedstawiono koncepcję nazwowej i strukturalnej zgodności typów oraz szkielet prostego kontrolera zgodności typów.
  • Ostatni moduł poświęcony jest etapowi syntezy kodu i zagadnieniom dotyczącym budowy środowiska wykonawczego. Omówiono fazę generacji kodu pośredniego oraz różne typy języków pośrednich ze szczególnym naciskiem na kod trójadresowy. Zademonstrowano przykładowe optymalizacje kodu, wykonywane zarówno w fazie generacji kodu pośredniego, jak i w fazie generacji kodu wynikowego. Omówiono również niektóre zagadnienia dotyczące budowy środowiska wykonawczego, takie jak dostęp do nazw nielokalnych, dynamiczny przydział pamięci i przekazywanie parametrów do podprogramów.

Literatura

  • A.V. Aho, M.S. Lam, R. Sethi, J.D. Ullman, Compilers: Principles, Techniques, and Tools, 2/E (w języku polskim dostępne jest tłumaczenie poprzedniej wersji tej książki z 1986 roku: A.V. Aho, M.S. Lam, R. Sethi, J.D. Ullman, Kompilatory. Reguły, metody i narzędzia, Wydawnictwa Naukowo-Techniczne, Warszawa 2002).
  • M. Foryś,W. Foryś, Teoria automatów i języków formalnych, Akademicka Oficyna Wydawnicza Exit, 2005.
  • J.P. Tremblay, P.G. Sorenson, The Theory and Practice of Compiler Writing, McGraw-Hill, 1985.
  • W.M. Waite,G. Goos, Konstrukcja kompilatorów, Wydawnictwa Naukowo-Techniczne, Warszawa 1989.
  • R. Wilhelm, D. Maurer, Compiler Design, Addison-Wesley, 1995.

Moduły