- 1.1.1: Kompilator tworzy program wynikowy tłumacząc język źródłowy, natomiast interpreter wydaje się bezpośrednio wykonywać operacje wyspecyfikowane w programie źródłowym względem danych wejściowych dostarczanych przez użytkownika.
- 1.1.2:
- a) Program wynikowy w języku maszynowym tworzony przez kompilator jest zazwyczaj znacznie szybszy od interpretera przy przechodzeniu od wejścia do wyjścia.
- b) Interpreter zazwyczaj udostępnia lepszą diagnostykę błędów niż kompilator, gdyż wykonuje program źródłowy instrukcja po instrukcji.
- 1.1.3: Tworzenie kodu asemblera jest łatwiejsze do wykonania, a ponadto łatwiejsze do debugowania. Uzyskany kod asemblera jest następnie przetwarzany przez kolejny program nazywany po prostu asemblerem, który generuje relokowalny kod maszynowy jako swoje wyjście.
- 1.1.4: Język C często stanowi podstawę dla innych języków wysokiego poziomu, wobec czego transkompilator przetłumaczy dany kod o wiele szybciej.
- 1.1.5: Asembler generuje relokowalny kod maszynowy jako swoje wyjście, zyskane fragmenty kodu maszynowego mogą wymagać złączenia z innymi relokowalnymi plikami wynikowymi i plikami bibliotek w kod, który ostatecznie może zostać uruchomiony na komputerze.
- Ćwiczenie 1.1.1: Na czym polega różnica między kompilatorem a interpre-
- terem?
- Ćwiczenie 1.1.2: Jakie są zalety (a) kompilatora wobec interpretera oraz
- (b) interpretera wobec kompilatora?
- Ćwiczenie 1.1.3: Jakie korzyści zapewnia system przetwarzania języka, w któ-
- rym kompilator tworzy kod w języku asemblera, a nie w języku maszynowym?
- Ćwiczenie 1.1.4: Kompilator tłumaczący jeden język wysokiego poziomu na
- inny język wysokiego poziomu jest nazywany translatorem source-to-source
- lub transkompilatorem. Jakie mogą być korzyści użycia języka C jako języka
- wynikowego kompilatora?
- Ćwiczenie 1.1.5: Opisz kilka zadań, które musi wykonać asembler.
- 1.2.1 - 1.2.9
- - Analiza leksykalna: Pierwsza faza działania kompilatora. Analizator leksykalny (nazywany niekiedy skanerem lub lekserem) odczytuje strumień znaków budujących program źródłowy i grupuje te znaki w znaczące sekwencje nazywane leksemami. Dla każdego leksemu analizator leksykalny tworzy wyjście w postaci tokenu w formacie (nazwa-tokenu, wartość-atrybutu) który przekazywany jest do następnej fazy, czyli analizy składniowej.
- - Analiza składniowa: Analizator składniowy, nazywany też parserem, używa pierwszych komponentów tokenów utworzonych przez analizator leksykalny do zbudowania pośredniej reprezentacji przypominającej drzewo, odwzorowującej gramatyczną strukturę strumienia tokenów.
- - Analiza semantyczna: Analizator semantyczny wykorzystuje drzewo składniowe oraz informacje z tablicy symboli do sprawdzenia programu źródłowego pod kątem spójności semantycznej programu z definicją języka. Ponadto gromadzi on informacje o typach i zapisuje je albo w drzewie składniowym, albo w tablicy symboli do późniejszego użycia podczas generowania kodu pośredniego.
- - Generowanie kodu pośredniego: Po analizie składniowej i semantycznej programu źródłowego wiele kompilatorów generuje jawną niskopoziomową reprezentację pośrednią, zbliżoną do kodu maszynowego, o której możemy myśleć jako o programie dla maszyny abstrakcyjnej. Ta postać pośrednia powinna być łatwa do utworzenia i łatwa do przetłumaczenia na kod maszyny docelowej.
- - Optymalizacja kodu: Faza niezależnej od architektury maszynowej optymalizacji kodu ma na celu ulepszenie kodu pośredniego, dzięki czemu lepszy będzie również kod wynikowy.
- - Generowanie kodu: Generator kodu przyjmuje jako wejście reprezentację pośrednią programu źródłowego i odwzorowuje ją na język wynikowy.
- - Zarządzanie tablicą symboli: Tablica symboli jest strukturą danych zawierającą rekord dla wszystkich nazw zmiennych, z polami dla atrybutów tych nazw. Ta struktura danych powinna zostać tak zaprojektowana, aby umożliwić kompilatorowi szybkie odszukanie rekordu dla każdej nazwy, jak również szybkie zapisywanie i odczytywanie danych z tego rekordu.
- - Grupowanie faz w przebiegi: W konkretnej implementacji aktywność z wielu faz może zostać pogrupowana łącznie w przebieg (pass) odczytujący plik wejściowy i zapisujący plik wyjściowy.
- - Narzędzia do budowania kompilatorów: Narzędzia te używają specjalizowanych języków do specyfikowania i implementowania określonych komponentów i mogą używać naprawdę wyrafinowanych algorytmów. Większość udanych narzędzi to te, które ukrywają szczegóły algorytmu generującego i tworzą komponenty, które mogą być łatwo zintegrowane z pozostałymi częściami kompilatora.