Program We Kompilator Wy Źródłowy



Podobne dokumenty
Analiza leksykalna 1. Teoria kompilacji. Dr inż. Janusz Majewski Katedra Informatyki

Zadanie analizy leksykalnej

Analiza leksykalna 1. Języki formalne i automaty. Dr inż. Janusz Majewski Katedra Informatyki

Plan wykładu. Kompilatory. Literatura. Translatory. Literatura Translatory. Paweł J. Matuszyk

Translacja wprowadzenie

KONSTRUKCJA KOMPILATORÓW

Metody Kompilacji Wykład 1 Wstęp

Analizator syntaktyczny

Języki programowania zasady ich tworzenia

Metody Kompilacji Wykład 8 Analiza Syntaktyczna cd. Włodzimierz Bielecki WI ZUT

Generatory analizatorów

Analiza leksykalna i generator LEX

Matematyczne Podstawy Informatyki

Metody Kompilacji Wykład 7 Analiza Syntaktyczna

Wprowadzenie. Teoria automatów i języków formalnych. Literatura (1)

Uproszczony schemat działania kompilatora

Uproszczony schemat działania kompilatora

Gramatyki atrybutywne

Podstawy Informatyki Języki programowania c.d.

SYLABUS DOTYCZY CYKLU KSZTAŁCENIA Bieżący sylabus w semestrze zimowym roku 2016/17

Generator YACC: gramatyki niejednoznaczne

Metody kompilacji Wykłady 4-5

JIP. Analiza składni, gramatyki

Włączenie analizy leksykalnej do analizy składniowej jest nietrudne; po co więc jest wydzielona?

Paradygmaty i języki programowania. Analiza leksykalna Skaner, RE, DAS, NAS, ε- NAS

Semantyka i Weryfikacja Programów - Laboratorium 6

Wprowadzenie do analizy składniowej. Bartosz Bogacki.

Wydział Zarządzania AGH. Katedra Informatyki Stosowanej. Podstawy VBA cz. 1. Programowanie komputerowe

ForPascal Interpreter języka Pascal

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Programowanie komputerów

Wprowadzenie do kompilatorów

Programowanie w języku Python. Grażyna Koba

Wykład 5. Jan Pustelnik

Instrukcja do ćwiczenia P4 Analiza semantyczna i generowanie kodu Język: Ada

Wstęp do Programowania Obiektowego. Wykład 13 Paradygmaty. Składnia i semantyka.

10. Translacja sterowana składnią i YACC

Efektywna analiza składniowa GBK

Matematyczne Podstawy Informatyki

Algorytmy od problemu do wyniku

Analiza semantyczna. Gramatyka atrybutywna

0.1 Lewostronna rekurencja

Metody Kompilacji Wykład 13

Metody Kompilacji Wykład 3

2.2. Gramatyki, wyprowadzenia, hierarchia Chomsky'ego

Laboratorium 10: Maszyna stanów

Programowanie Strukturalne i Obiektowe Słownik podstawowych pojęć 1 z 5 Opracował Jan T. Biernat

Opis: Instrukcja warunkowa Składnia: IF [NOT] warunek [AND [NOT] warunek] [OR [NOT] warunek].

Wprowadzenie: języki, symbole, alfabety, łańcuchy Języki formalne i automaty. Literatura

Wprowadzenie. Wojciech Complak

Podstawy Kompilatorów

Algorytmika i Programowanie VBA 1 - podstawy

Gramatyki regularne i automaty skoczone

Gramatyki, wyprowadzenia, hierarchia Chomsky ego. Gramatyka

L E X. Generator analizatorów leksykalnych

Podstawy generatora YACC. Bartosz Bogacki.

Translacja sterowana składnią w metodzie zstępującej

DIAGRAMY SYNTAKTYCZNE JĘZYKA TURBO PASCAL 6.0

Podstawy Kompilatorów

JAO - Wprowadzenie do Gramatyk bezkontekstowych

Programowanie w Turbo Pascal

Generator skanerów Flex

Translacja sterowana składnią w generatorze YACC

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Wykład 10. Translacja sterowana składnią

Języki formalne i techniki translacji

Programowanie w języku C++ Grażyna Koba

Metodologie programowania

Administracja sieciowymi systemami operacyjnymi III Klasa - Linux

3.4. Przekształcenia gramatyk bezkontekstowych

Generator LLgen. Wojciech Complak Generator LLgen - charakterystyka. Generator LLgen -składnia specyfikacji

Programowanie strukturalne. Opis ogólny programu w Turbo Pascalu

Sprzęt komputera - zespół układów wykonujących programy wprowadzone do pamięci komputera (ang. hardware) Oprogramowanie komputera - zespół programów

JĘZYKIFORMALNE IMETODYKOMPILACJI

Definiowanie języka przez wyrażenie regularne(wr)

Języki formalne i gramatyki

Podstawy kompilatorów. Generator LLgen. Wojciech Complak.

Java EE produkcja oprogramowania

Obiektowa implementacja parsera klasy LL(1)

Przyczyny dwustopniowego tłumaczenia

Elementy języków programowania

Gramatyka operatorowa

1 Przygotował: mgr inż. Maciej Lasota

Języki formalne i automaty Ćwiczenia 1

TRANSLACJA I TRANSLATORY

Elżbieta Kula - wprowadzenie do Turbo Pascala i algorytmiki

Podstawy i języki programowania

Ryszard Myhan. Wykład 1: Języki programowania

Generator YACC: gramatyki niejednoznaczne

Dynamiczne przetwarzanie stron. dr Beata Kuźmińska-Sołśnia

Kompilator języka Basic można bezpłatnie pobrać ze strony z zakładki DOWNLOAD.

Bison - generator analizatorów składniowych

Bash - wprowadzenie. Bash - wprowadzenie 1/39

Matematyczne Podstawy Informatyki

Języki formalne i automaty Ćwiczenia 4

Algorytmy i struktury danych. wykład 2

Podstawy programowania Laboratorium. Ćwiczenie 2 Programowanie strukturalne podstawowe rodzaje instrukcji

Analiza metodą zstępującą. Bartosz Bogacki.

Programowanie w Logice Gramatyki metamorficzne. Przemysław Kobylański na podstawie [CM2003] i [SS1994]

Programowanie. Pascal - język programowania wysokiego poziomu. Klasa 2 Lekcja 9 PASCAL

Transkrypt:

1. Aho A.V., Ullman J.D. - The Theory of Parsing, Translation and Compiling.1972. 2. Foster J.M. - Automatyczna analiza składniowa. 1976 3. Gries D. - Konstrukcja translatorów dla maszyn cyfrowych, 1984 4. Hapgood F.R.A. - Metody kompilacji. 1982. 5. Waite W.M., Goos G. - Konstrukcja kompilatorów. 1989. 6. Aho A.V., Sethi R., Ullman J.D. - Compiler: Principles, Techniques and Tools. 1986. Wstęp: Translator - program, który umożliwia wykonanie programów napisanych w języku różnym od języka komputera. Rozróżnia się dwa rodzaje translatorów: a) kompilatory b) interpretery Ad. a). Kompilator - program, który tłumaczy program źródłowy na równoważny program wynikowy. Program źródłowy jest napisany w języku źródłowym, a program wynikowy należy do języka wynikowego. Wykonanie programu kompilatora następuje w czasie tłumaczenia. Cecha zasadnicza: program po przetłumaczeniu nie da się zmienić, jest statyczny. Kompilator jako dane wejściowe otrzymujemy "cały" program źródłowy i przekształca go na postać wynikowa. Program We Kompilator Wy Źródłowy Program wynikowy Ad. b). Interpreter można nazwać dynamicznym translatorem. Tłumaczy on na bieżąco i wykonuje program źródłowy. Działanie interpretera polega na wyodrębnieniu niewielkich jednostek programu źródłowego, tłumaczniu ich na pewna postać wynikowa i natychmiastowym ich wykonywaniu. Proces jest cykliczny. W czasie interpretacji przechowywany jest program źródłowy. Przykład: for i:=1 to 5 do s := s + i ; w przypadku intepretera ten fragment jest 5-krotnie tłumaczony Zalety: a)kompilatory -program wynikowy wykonuje się szybciej -do wykonania programu wynikowego nie jest potrzebny kompilator b)interpretery -łatwość zmian programu -mniejsza zajętość pamięci zewnętrznej (tylko tekst źródłowy) -możliwość pracy konwersacyjnej (zatrzymanie wykonania, zmiana wartości zmiennych, kontynuacja wykonania)

Struktura kompilatora. Kompilator Program źródłowy Analiza Leksykalna SKANER Analiza Analiza syntaktycz.. ( i semant.) PASER Kod pośredni Generacja kodu wynikow. GENERA- TOR Synteza Optymaliza cja kodu OPTYMA- LIZATOR Program wynikowy Tablice zmiennych, stałych, etykiet, itd... (A) Analiza leksykalna ciąg znaków ciąg tokenów SKANER Przykład: we : COST:= ( PRICE + TAX ) * 0.98 wy : id 1 := ( id 2 + id 3 ) * num 4 Tablica symboli. Adres Nazwa Charakter Dodatkowe informacje 1 2 3 4 COST PRICE TAX 0.98 Zmienna Zmienna Zmienna Stała Zmienna-pozycyjna Zmienna-pozycyjna Zmienna-pozycyjna Zmienna-pozycyjna Wyjście skanera : <= Wejście skanera: (id,1) COST (egu, ) := (left-par, ) ( (id,2) PRICE (plus, ) + (id,3) TAX (right-par, ) ) (mult, ) * (num,4) 0.98

Analizator leksykalny SKANER Program Źródłowy Analizator leksykalny SKANER token Daj następny token Analizator syntaktyczny PARSER postać pośrednia Tablica symboli a) Realizacja szeregowa Program źródłowy SKANER PARSER... program wynikowy -translator wieloprzebiegowy -translator nakładkowy -mniejsza zajętość PaO b)realizacja równoległa PARSER Program źródłowy SKANER Generator Optymal. Podprogram podprogram program wynikowy -translator jednoprzebiegowy -większa zajętość PaO -krótszy czas kompilacji

Zadania skanera: -wyodrębnianie tokenów -ignorowanie komentarzy -ignorowanie białych znaków (spacji, tabulacji, znaków nowej linii...) -korelowanie błędów zgłaszanych przez kompilator z numerami linii (skaner może liczyć \n) -tworzenie kopii zbioru wejściowego (źródłowego) łącznie z komunikatami o błędach -czasami realizacja funkcji preprocessingu, rozwijanie makrodefinicji Rozdzielenie etapu analizy na dwie odrębne funkcje: analizę leksykalna i analizę syntaktyczną sprawia, że jedna i druga mogą być wykonywane przy użyciu bardziej efektywnych algorytmów, gdyż algorytmy te istotnie się różnią, wykorzystując inne pryncypia formalne i realizacyjne. Podstawowe pojęcia: token, leksem, wzorzec (pattern) Przykład: const pi2 = 6.2832; token leksem wzorzec (pattern) const id num const pi2 = 6.2832 const - ( słowo kluczowe ) litera (litera cyfra )* < > <= >= = > <> cyfra + (.cyfra + )?(E(+ -)?cyfra + )? źródło : const pi2 = 6.2832 leksemy: const pi2 = 6.2832 tokeny : const id num Wzorce są opisami sposobu wyodrębniania tokenów. Wzorce pełnią role produkcji w gramatykach leksykalnych. Tokeny są symbolami nieterminalnymi w gramatykach leksykalnych. Tokeny są terminalami w gramatyce syntaktycznej. Podział gramatyki G opisującej dany język programowania mający na celu oddzielenie analizy leksykalnej od analizy syntaktycznej. Gramatyka G języka źródłowego (najczęściej bezkontekstowa) G = < N, T, P, Z > gdzie na ogól T = { A, B,..., Z, a, b,..., z, 0, 1,..., 9, +, -, *, /,, (, ),..} Przebudowujemy gramatykę G na rodzinę gramatyk:

G s = < N s, T s, P s, Z s > - gramatyka syntaktyczna T s = { Ts i Ts i jest tokenem } tokeny są terminalami w gramatyce syntaktycznej G i = < N i, T i, P i, Z i > - gramatyki leksykalne jedna dla każdego tokenu Z i =Ts i - i-ty token jest symbolem początkowym (nieterminalem) i-tej gramatyki leksykalnej Ts i N i, T i T N = N s! n T =! n i= 1 T i i= 1 N i Gramatyka języka źródłowego G jest więc efektem "podstawienia" gramatyk leksykalnych G i P = P s! n P i do gramatyki syntaktycznej G s i= 1 Z = Z s Przykład: Gramatyka języka analizowanego G: G = < N = { <program>, <nazwa>, <liczba>, <symbol>, <+>, <*>} T = { a, b, c, 0, 1, +, * }, P = { <program> ::= <nazwa> <liczba> <program><symbol><program> <nazwa> ::= a b c <nazwa> a <nazwa> b <nazwa> c <nazwa> 0 <nazwa> 1 <liczba> ::= 0 1 <liczba> 0 <liczba> 1 <symbol> ::= <+> <*> <+> ::= + <*> ::= * }, Z = <program> > tokeny: id num op_add op_mul Gramatyka syntaktyczna: <nazwa>, <liczba>, <+>, <*> G s = < N s = { <program>, <symbol> }, id num op_add op_mul T s = { }, <nazwa>, <liczba>, <+>, <*> P s = { <programy> ::= <nazwa> <liczba> <program><symbol><program> <symbol> ::= <+> <*> }, Z s = <program> >

Gramatyki leksykalne: 1) gramatyka nazw id G 1 = < N 1 = { <nazwa> }, T 1 = { a, b, c, 0, 1 }, P 1 = { <nazwa> ::= a b c <nazwa> a <nazwa> <nazwa> b <nazwa> c 0 <nazwa> 1 } Z 1 = <nazwa> > 2) gramatyka liczb num G 2 = < N 2 = { <liczba> }, T 2 = { 0, 1 }, P 2 = { <liczba> ::= 0 1 <liczba> 0 <liczba> 1 } Z 2 = < <liczba> > 3) gramatyka plusa op_add G 3 = < N 3 = { <+> }, T 3 = { + }, P 3 = { <+> : := + }, Z 3 = <+> > 4) gramatyka gwiazdki op_mult G 4 = < N 4 = { }, <*> T 4 = { * }, P 4 = { <*> ::= * }, Z 4 =< <*> >

Jeżeli do gramatyki G s "podstawimy gramatyki G 1, G 2, G 3 oraz G 4 - otrzymamy pełną gramatykę G. W gramatykach leksykalnych tokeny są traktowanie jako nieterminale. W gramatyce syntaktycznej tokeny pełnią role terminali. Gramatyki leksykalne G i należą na ogół do klasy gramatyk regularnych. Niekiedy jednak pojawiają się odstępstwa od regularności. Przykład: Uwzględnienie prawego kontekstu w FORTRANie Spacje (z wyjątkiem spacji wewnątrz łańcuchów) są zawsze ignorowane. Porównujemy: 1) DO 5 I = 1.25 równoznaczne DO5I = 1.25 (instrukcja podstawienia) 2) DO 5 I = 1,25 instrukcja pętli typu "for", odpowiednik: for i:=1 to 25 do begin...... etykieta... 5:end; 1) DO 5 I = 1.25 identyfikator operator podstawienia stała 2) stałe DO 5 I = 1, 25 przecinek słowo kluczowe etykieta operator podstawienia DO identyfikator zmiennej sterującej pętli DO. 5 I = 1 \n ' Po przeczytaniu znaków DO nie można dokonać uzgodnienia tokenu "Słowo kluczowe DO" dopóki nie zbada się prawego kontekstu i nie znajdzie się przecinka (wtedy rzeczywiście uzgadnia się "DO") lub kropki bądź znaku nowej linii (wtedy mamy instrukcje podstawienia).

Przykład: Słowa kluczowe nie są zastrzeżone (FORTRAN, PL/I). W języku PL/I poprawny jest zapis: IF THEN THEN THEN = ELSE ; ELSE ELSE = THEN; Jeśli więcej niż jeden wzorzec odpowiada danemu tokenowi, skaner musi zwrócić dodatkową informacje. Przykład: (FORTRAN) E.LE. M * C ** 2 ( E <= mc2 ) E <id, pointer do tablicy symboli >.LE. <oper_rel, <= > M <id, pointer do tablicy symboli > * <oper_mult, nic > C <id, pointer do tablicy symboli > ** <oper_exp, nic > 2 <num, pointer do tablicy lub wartość > Do opisu wzorców dla skanera stosujemy definicje regularne d 1 -> r 1 d 2 -> r 2... d n -> r n gdzie: d i - unikalna nazwa, r i - wyrażenie regularne nad symbolami alfabetu terminalnego T { d 1, d 2,..., d i-1 } Przykład: stale bez znaku w Pascalu digit --> 0 1 2 3 4 5 6 7 8 9 digit --> digit digit* {jest to zastąpienie klasycznego zapisu: digits --> digits digit digit } optional_fraction -->.digits ε optional_exponent --> E ( + - ε ) digits ε num --> digits optional_fraction optional_exponent Symbole metajęzyka : --> * ( ) Uproszczenia w notacji: w + - oznacza jedno lub więcej wystąpień wzorca w w + ww* w? - oznacza zero lub jedno wystąpienie wzorca w w? w ε

Przykład: stałe bez znaku w Pascalu digit --> 0 1 2 3 4 5 6 7 8 9 digits --> digit+ optional_fraction --> (.digits)? optional_exponent --> ( E (+ -)? digits)? num --> digits optional_fraction optional_exponent Symbole metajęzyka : --> + *? ( ) Jeżeli już wiemy, jak specyfikować tokeny, a właściwie jak tworzyć ich wzorce, to teraz musimy się nauczyć rozpoznawać tokeny na podstawie wzorców.

Rozpoznawanie tokenów. Przykładowa gramatyka syntaktyczna: stmt --> if expr then stmt if expr then stmt else stmt ε expr --> term term term term --> id num Definicje regularne: delim --> \t \n ws --> delim + letter --> a... z A... Z digit --> 0 1... 9 if --> if then --> then else --> else --> < <= <> = > >= id --> letter (letter digit) * num --> digit + (.digit + )?(E(+ -)?digit + )? Analizator leksykalny ma zwracać następujące informacje: wyr. regul. token atrybut tokenu ws if then else id num < <= <> = > >= - if then else id num - - - - wskaźnik do tablicy symboli wskaźnik do tablicy symboli LT LE NE EQ GT GE

Diagram rozpoznawania tokenu start < = 0 1 2 return(,le) > 3 return(,ne) = 5 other * unput() 4 return(,lt) return(,eq) > = return(,ge) 6 7 other * unput() return(,gt) 8 Rozpoznawanie identyfikatorów digit letter start 9 letter 10 other * unput() 11 return(gettoken(),install_id()) gettoken() - funkcja sprawdza, czy lexem jest słowem kluczowym. Jeśli tak, zwraca odpowiedni token skojarzony z tym słowem kluczowym, np. if, then czy else. Jeśli nie, funkcja zwraca id. install_id() - funkcja sprawdza, przeszukując odpowiednia tablice, czy lexem jest słowem kluczowym. Jeśli tak, zwraca 0. W przeciwnym przypadku bada, czy taki lexem już figuruje w tablicy symboli. Jeśli tak zwraca wskaźnik do niego. Jeśli nie, dokonuje instalacji nowego lexemu w tablicy symboli i zwraca odpowiedni wskaźnik. Nie zawsze stosuje się metodę umieszczania słów kluczowych w tablicy. Można budować dla nich odrębne wzorce i konstruować automaty rozpoznające. Wówczas jednak liczba stanów analizatora gwałtownie rośnie.

Rozpoznawanie tokenu num other * 20 digit + digit digit digit E digit other * 12 13 14 15 16 17 18 E - digit 19 other * 21 W stanach 19 20 21 { unput() return(num,install_num()) instal_num() - funkcja umieszcza leksem w tablicy i zwraca wskaźnik do niego Ignorowanie białych znaków delim delim other * 22 23 24 unput() żadna inna akcja analizatora nie jest podejmowana