Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Wykład 9 Metoda pierwszeństwa operatorów. Dla ważnej klasy gramatyk (gramatyka operatorowa) możemy łatwo ręcznie budować wydajne analizatory redukujące.

Podobne prezentacje


Prezentacja na temat: "Wykład 9 Metoda pierwszeństwa operatorów. Dla ważnej klasy gramatyk (gramatyka operatorowa) możemy łatwo ręcznie budować wydajne analizatory redukujące."— Zapis prezentacji:

1 Wykład 9 Metoda pierwszeństwa operatorów

2 Dla ważnej klasy gramatyk (gramatyka operatorowa) możemy łatwo ręcznie budować wydajne analizatory redukujące. Cecha charakterystyczną tej ważnej, lecz wąskiej grupy gramatyk jest to, że: -prawa strona jakiejkolwiek produkcji nie jest, -nie zawiera dwóch sąsiadujących nieterminali

3 Gramatyka operatorowa Gramatyka E->EAE | (E) | -E | id, A-> + | - | * | / | E->EAE | (E) | -E | id, A-> + | - | * | / | nie jest gramatyką operatorową. Gramatyka E->E+E | E-E | E*E | E/E | EE | (E) | -E | id Jest gramatyką operatorową.

4 Technika pierwszeństwa operatorów Metoda pierwszeństwa operatorów została najpierw opisana jako manipulacje na symbolach, bez żadnych odwołań do ukrytej gramatyki. Gdy skończymy budować analizator dla gramatyki pisany metodą pierwszeństwa operatorów, możemy ignorować gramatykę, używając nieterminali na stosie tylko do zajmowania miejsca dla atrybutów związanych z nieterminalami.

5 Technika pierwszeństwa operatorów Wady metody pierwszeństwa operatorów: Niektóre symbole są trudne do obsłużenia., np. znak minus (-), który ma dwa różne priorytety w zależności od tego czy ma jeden czy dwa argumenty; Związek pomiędzy analizowaną gramatyką a analizatorem napisanym metoda pierwszeństwa jest słaby; Metodą pierwszeństwa operatorów można analizować tylko małą klasę gramatyk.

6 Metoda pierwszeństwa operatorów W metodzie pierwszeństwa operatorów między pewnymi parami terminali definiujemy trzy rozłączne relacje priorytetów: W metodzie pierwszeństwa operatorów między pewnymi parami terminali definiujemy trzy rozłączne relacje priorytetów: Kierują one wyborem uchwytów i mają następujące znaczenie: a<·b - a ma mniejszy priorytet niż b; a=b – a ma taki sam priorytet jak b; a·>b – a ma większy priorytet niż b.

7 Metoda pierwszeństwa operatorów Uwaga. Podobieństwo do relacji arytmetycznych jest iluzoryczne. Relacje priorytetów mają całkiem inne własności. Przykład: dla tego samego języka może zachodzić a b. dla pewnej pary terminali a i b może nie zachodzić ani a b. a b.

8 Metoda pierwszeństwa operatorów Istnieją dwie metody sprawdzania, jakie relacje priorytetów zachodzą miedzy parami terminali: Metoda intuicyjna – opiera się na tradycyjnych pojęciach łączności i priorytetów operatorów; Metoda wyboru relacji priorytetów.

9 Metoda intuicyjna Metoda intuicyjna – opiera się na tradycyjnych pojęciach łączności i priorytetów operatorów. Przykład: Jeśli * ma wyższy priorytet niż +, to ustalamy + +. Podejście takie usuwa niejednoznaczność z gramatyki E->E+E | E-E | E*E | E/E | EE | (E) | -E | id E->E+E | E-E | E*E | E/E | EE | (E) | -E | id oraz pozwala nam napisać dla niej analizator metodą pierwszeństwa operatorów (pomimo iż jednoargumentowy minus stwarza problemy).

10 Metoda wyboru relacji priorytetów Metoda wyboru relacji priorytetów polega na zbudowaniu jednoznacznej gramatyki dla języka, takiej, że drzewa wyprowadzenia budowane przy jej użyciu będą oddawać właściwą łączność i priorytety operatorów. Przykładowo dla często spotykanego źródła niejednoznaczności wiszącego else modelem może być gramatyka:

11 Metoda wyboru relacji priorytetów instr -> dopas_instr instr -> dopas_instr | niedopas_instr | niedopas_instr dopas_instr -> if wyr then dopas_instr else dopas_instr | inna | inna niedopas_instr -> if wyr then instr | if wyr then dopas_instr else niedopas_instr | if wyr then dopas_instr else niedopas_instr

12 Metoda wyboru relacji priorytetów Gdy dysponujemy już jednoznaczną gramatyką, korzystamy z mechanicznego sposobu, aby używając jej, skonstruować relacje priorytetów. Relacje te mogą nie być rozłączne i mogą pozwalać na analizowanie innych języków niż generowane przez początkową gramatykę, ale przy standardowych wyrażeniach arytmetycznych w praktyce nie spotyka się wielu problemów.

13 Relacje priorytetów operatorów Zadaniem relacji priorytetów jest oddzielenie uchwytów prawostronnych form zdanio- wych, z na prawym krańcu.

14 Relacje priorytetów operatorów Przyjmijmy, że mamy prawostronną formę zdaniową gramatyki operatorowej. Możemy prawostronną formę zdaniową zapisać jako : β 0 a 1 β 1 a 2 β 2... a n β n gdzie każde z β i jest albo Ɛ (pustym ciągiem) albo nieterminalem, zaś a i jest pojedynczym terminalnym, i=1,...,n. Załóżmy, że między a i i a i+1 zachodzi dokladnie jedna z relacji:.

15 Relacje priorytetów operatorów Do ustalenia końca ciągu będziemy używali symbolu $ oraz ustalimy, że dla wszystkich symboli terminalnych $ $. Przypuśćmy teraz, że usuwamy nieterminale z ciągu i umieszczamy symbol właściwej relacji. Symbol ten umieszczamy między każdą parą terminali i między krańcowymi terminalami i znakami $ oznaczającymi krańce ciągu. Przykładowo dla ciągu: id + id * id Otrzymujemy: $ + * $.

16 Relacje priorytetów operatorów Ustalamy relację priorytetów operatorów id+*$ id ·>·>·>·> ·>·>·>·> ·>·>·>·> + <·<·<·<· ·>·>·>·> <·<·<·<· ·>·>·>·> * <·<·<·<· ·>·>·>·> ·>·>·>·> ·>·>·>·> $ <·<·<·<· <·<·<·<· <·<·<·<·

17 Relacje priorytetów operatorów Metoda znalezienia uchwytu. - Przeglądamy ciąg od lewej strony aż do napotkania pierwszego ·>. $ + * $. - Następnie przechodzimy do tyłu (w prawo) po kolejnych =, aż napotkamy <·. $ + * $. - Uchwyt składa się ze wszystkich symboli leżących między pierwszym ·> z prawej strony a z prawej strony a <· z lewej strony, włączając wszystkie zawarte lub otaczające nieterminale. UWAGA: Dołączenie otaczających nieterminali jest konieczne, aby nie spowodować sąsiadowania dwóch nieterminali w prawostronnej formie zdaniowej.

18 Relacje priorytetów operatorów Zatem uchwytem jest w tym przypadku id. Przypomnijmy gramatykę: E->E+E | E-E | E*E | E/E | EE | (E) | -E | id Po dokonaniu redukcji względem produkcji E->id dostajemy prawostronną formę zdaniową E + id * id. E + id * id. Następnie po eliminacji w ciągu nieterminali i zastosowaniu symbolu właściwej relacji dostajemy $ * $. Po analogicznym zredukowaniu dwóch pozostałych id do E otrzymamy prawostronną formę zdaniową E + E * E E + E * E Następnie po eliminacji w ciągu nieterminali i zastosowaniu symbolu właściwej relacji dostajemy $ $. Oznacza to, że lewy koniec uchwytu jest między + oraz *, zaś prawy między * a $. Takie relacje priorytetów wskazują, że w prawostronnej formie zdaniowej uchwytem jest E * E.

19 Relacje priorytetów operatorów Aby uniknąć sytuacji, gdy w każdym kroku aby znaleźć uchwyt przeglądamy całą prawostronną formę zdaniową, używamy stosu do przechowywania już obejrzanych symboli wejściowych i korzystamy z relacji priorytetów do sterowania działaniem analizatora redukującego. Jeśli między termnalem na wierzchołku stosu a kolejnym symbolem z wyjścia zachodzi <· lub =, analizator wykonuje przesunięcie (oznacza to że nie znalazł jeszcze uchwytu); Jeżeli zachodzi ·>, to wykonywana jest redukcja (w tym momencie analizator znalazł prawy koniec uchwytu, a relacji priorytetów można użyć do znalezienia na stosie lewego krańca). Jeśli między parą terminali nie zachodzi żadna z relacji (id id), to wykryto błąd składniowy i należy wywołać procedurę obsługi błędu.

20 Algorytm analizy metodą pierwszeństwa operatorów Wejście: Tekst wejściowy ω i tablica relacji priorytetów. Wyjście: Jeśli ω jest poprawny – szkieletowe drzewo wyprowadzenia, z zajmującym miejsce nieterminalem E etykietującym wszystkie węzły wewnętrzne, w prze- ciwnym wypadku informacja o błędzie;

21 Algorytm analizy metodą pierwszeństwa operatorów Metoda: Początkowo stos zawiera $, a bufor ω$. 1)Zainicjuj ip tak, aby wskazywał pierwszy symbol ω$. 2)Repeat forever 3) if $ jest na wierzcholku stosu oraz ip wskazuje $ then 4) return else begin else begin 5) niech a będzie symbolem z wierzcholku stosu a b – symbolem wskazanym przez ip; wskazanym przez ip; 6) if a<·b lub a=b then begin 7) odloz b na stos; 8) przesun ip do nastepnego symbolu wejsciowego; end; end; 9) else if a·>b then /*redukcja*/ 10) repeat 11) zdejmi element ze stosu 12) until szczytowy element ze stosu jest w relacji <· z poprzednio zdjetym terminalem 13) else blad(); end end

22 Wyznaczanie relacji priorytetów z łączności i priorytetów operatorów 1) Jeśli operator θ 1 ma wyższy priorytet niż θ 2, przyjmujemy, że θ 1 ·> θ 2 oraz θ 2 θ 2 oraz θ 2 <· θ 1 Jeśli przykładowo, priorytet * jest większy niż +, przyjmujemy, że * ·> + oraz + + oraz + <· * (relacje te gwarantują, że, w wyrażeniach E+E*E+E, centralne E*E jest uchwytem, który będzie zredukowany jako pierwszy); (relacje te gwarantują, że, w wyrażeniach E+E*E+E, centralne E*E jest uchwytem, który będzie zredukowany jako pierwszy); 2) Jeśli θ 1 i θ 2 są operatorami o tym samym priorytecie (lub jest to jeden operator) przyjmijmy, że: θ 1 ·> θ 2 oraz θ 2 ·> θ 1 – jeśli te operatory są łączne lewostronnnie, θ 1 ·> θ 2 oraz θ 2 ·> θ 1 – jeśli te operatory są łączne lewostronnnie, θ 1 <· θ 2 oraz θ 2 <· θ 1 – jeśli te operatory są łączne lewostronnnie. θ 1 <· θ 2 oraz θ 2 <· θ 1 – jeśli te operatory są łączne lewostronnnie. Jeśli przykładowo, + i – są lewostronnie łączne, to przyjmijmy: Jeśli przykładowo, + i – są lewostronnie łączne, to przyjmijmy: + ·> +, + ·> -, - ·> -, - ·> + + ·> +, + ·> -, - ·> -, - ·> + Jeśli natomiast operator jest łączny prawostronnie, to przyjmujemy <· Jeśli natomiast operator jest łączny prawostronnie, to przyjmujemy <· (relacje te dają pewność, że w E-E+E wybranym uchwytem będzie E-E, a w E E E wybrane zostanie drugie E E. (relacje te dają pewność, że w E-E+E wybranym uchwytem będzie E-E, a w E E E wybrane zostanie drugie E E.

23 Wyznaczanie relacji priorytetów z łączności i priorytetów operatorów 3) Przyjmijmy, że θ θ, θ θ, θ ·> ), θ ·> $ θ, θ θ, θ ·> ), θ ·> $ <· θ dla wszystkich operatorów θ. Ponad to niech dla wszystkich operatorów θ. Ponad to niech ( = ) $ <· ( $ <· id ( $ ) $ ) <· id ( ) ) ·> ) ( ) ) ·> ) (reguły te zapewniają zredukowanie id i () do E. Ponadto, $ będący znakiem zarówno lewego, jaki i prawego krańca, powoduje - tak długo jak to możliwe – wyszukiwanie kolejnych uchwytów $. (reguły te zapewniają zredukowanie id i () do E. Ponadto, $ będący znakiem zarówno lewego, jaki i prawego krańca, powoduje - tak długo jak to możliwe – wyszukiwanie kolejnych uchwytów $.

24 Relacje priorytetów operatorów Przyjmujemy, że: -Operator ma najwyższy priorytet i jest prawostronnie łączny; -* oraz / mają drugi w kolejności priorytet i są lewostronnie łączne; -+ oraz - mają najniższy priorytet i są lewostronnie łączne. +-*/Id()$ + ·>·>·>·> ·>·>·>·> <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· ·>·>·>·> ·>·>·>·> - ·>·>·>·> ·>·>·>·> <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· ·>·>·>·> ·>·>·>·> * ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> <·<·<·<· <·<·<·<· <·<·<·<· ·>·>·>·> ·>·>·>·> / ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> <·<·<·<· <·<·<·<· <·<·<·<· ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> <·<·<·<· <·<·<·<· <·<·<·<· ·>·>·>·> ·>·>·>·> id ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ( <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<·= ) ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> $ <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<·

25 Obsługa operatorów jednoargumentowych Mamy dwa rodzaje operatorów jednoargumento- wych: 1)¬ (negacja logiczna) - nie jest on jednocześnie operatorem dwuargumentowym; 2)Znak -, który jest zarówno prefiksowym operatorem jednoargumentowym (np. -6), jaki i infiksowanym operatorem dwuargumentowym.

26 Obsługa operatorów jednoargumentowych ¬ (negacja logiczna) – operator ten możemy dołączyć do schematu tworzenia relacji priorytetów operatorów. A. Zakładając, że ¬ jest prefiksowym operatorem jedno- argumentowym, przyjmujemy θ <· ¬ θ <· ¬ dla wszystkich operatorów θ, zarówno jedno-, jak i dwuargumentowych; dla wszystkich operatorów θ, zarówno jedno-, jak i dwuargumentowych; Ponadto, jeśli ¬ ma wyższy priorytet niż θ, to przyjmujemy, że: ¬ ·> θ a jeśli nie, to przyjmujemy: ¬ <· θ B. Reguły dla postfiksowych operatorów jednoargumentowych są analogiczne.

27 Obsługa operatorów jednoargumentowych ¬ (negacja logiczna) – przykład Jeśli ¬ ma wyższy priorytet niż &, a & jest lewostronnie łączny, to według tych reguł formę: E&¬ E&E E&¬ E&E odczytalibyśmy jako: ( E & (¬ E) ) & E

28 Obsługa operatorów jednoargumentowych Znak - jest zarówno prefiksowym operatorem jednoargumentowym (np. -6), jaki i infiksowanym operatorem dwuargumentowym. Nawet jeśli jedno- i dwuargumentowemu minusowi nadamy ten sam priorytet, relacje opisane wyżej nie pozwolą poprawnie przeanalizować wejścia, takiego jak np. id*-id. Najlepszym podejściem jest w takim przypadku zmiana analizatora leksykalnego tak aby rozróżniał minus jednoargumentowy od dwuargumentowego i zwracał dla nich różne symbole. Niestety analizator leksykalny nie może podglądać symboli w celu ich odróżnienia (musi on pamiętać poprzedni symbol). Można to zrobić na przykład: minus jest jednoargumentowy, jeśli poprzednim symbolem był operator, lewy nawias, przecinek, albo symbol przypisania.

29 Funkcje priorytetów Kompilatory używające analizatorów działających metoda pierwszeństwa operatorów nie muszą przechowywać tablic opisujących relację priorytetów. W większości przypadków tablice te można zakodować przy użyciu dwóch funkcji priorytetów f: T->Z i g: T->Z (odwzorowujące symbole terminalne w liczby całkowite). Można więc odczytać relację priorytetów a i b, porównując ze sobą funkcje. Próbujemy dobrać f i g tak aby dla symboli a i b zachodziło: f(a) < f(b), gdy a<·b f(a) = f(b), gdy a=b f(a) > f(b), gdy a·>b

30 Funkcje priorytetów UWAGI. Przy wykorzystaniu funkcji priorytetów tracimy informacje o błędach zapisane w tablicy priorytetów (id i id były nieporównywalne), gdyż niezależnie od wartości f(a) i f(b) – jeden z powyższych warunków zawsze będzie zachodzić. Zazwyczaj utrata możliwości wykrywania błędów nie jest na tyle ważna, żeby rezygnować z użycia funkcji priorytetów jeśli tylko jest to możliwe ( błędy mogą być wykrywane, gdy chcemy wykonać redukcję, a nie możemy znaleźć uchwytu). Nie wszystkie tablice dla relacji priorytetów mają odpowiadające im funkcje priorytetów, ale w praktyce zazwyczaj takie funkcje daje się znaleźć.

31 Tablica priorytetów... +-*/Id()$ + ·>·>·>·> ·>·>·>·> <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· ·>·>·>·> ·>·>·>·> - ·>·>·>·> ·>·>·>·> <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· ·>·>·>·> ·>·>·>·> * ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> <·<·<·<· <·<·<·<· <·<·<·<· ·>·>·>·> ·>·>·>·> / ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> <·<·<·<· <·<·<·<· <·<·<·<· ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> <·<·<·<· <·<·<·<· <·<·<·<· ·>·>·>·> ·>·>·>·> id ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ( <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<·= ) ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> ·>·>·>·> $ <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<· <·<·<·<·

32 Tablica priorytetów +-*/()id$ f g Mamy, na przykład, * <· id oraz f(*)=4 < 5=g(id) Zauważmy, że chociaż f(id) >g(id), sugeruje, że id ·> id, to id nie jest w żadnej relacji z id.

33 Algorytm wyznaczania funkcji priorytetów Wejście: Tablica priorytetów operatorów. Wyjście: Funkcje priorytetów reprezentujące wejściową tablicę albo informacja, że one nie istnieją. Metoda:

34 Algorytm wyznaczania funkcji priorytetów KROK I. Dla każdego a, będącego terminalem lub symbolem $, stwórz symbole f a i g a. KROK II. Podziel uzyskane symbole na tak wiele grup, jak jest to możliwe i w taki sposób, aby f a i f b były w tej samej grupie, jeśli a=b. (Zauważmy, że możemy umieścić symbole w tej samej grupie, nawet jeśli nie są one w relacji =. Istotnie, jeśli na przykład a=b oraz c=b, to f a i f c będą w tej samej grupie, co g b. Jeśli dodatkowo c=d to f a i g d będą w tej samej grupie, mimo, że wcale nie musi zachodzić a=d).

35 Algorytm wyznaczania funkcji priorytetów KROK III. Stwórz graf skierowany, którego wierzchołkami są grupy znalezione w kroku II. Dla dowolnego a i b, - jeśli a <· b, dodaj do grafu krawędź z grupy, w której jest g b, do grupy z f a. - jeśli a <· b, dodaj do grafu krawędź z grupy, w której jest g b, do grupy z f a. - jeśli a ·> b, dodaj krawędź od grupy z f a do grupy z g b - jeśli a ·> b, dodaj krawędź od grupy z f a do grupy z g b Krawędź będąca ścieżką z f a do g b oznacza, że f(a) musi być większe od g(b), itd. KROK IV. Jeśli w grafie uzyskanym w kroku III są cykle, to funkcje priorytetów nie istnieją. Jeśli cykli nie ma, to niech f(a) będzie długością najdłuższej ścieżki zaczynającej się w grupie z f a ; niech g(b) będzie długością najdłuższej ścieżki o początku w grupie z g b.

36 Relacje priorytetów operatorów Ustalamy relację priorytetów operatorów id+*$ id ·>·>·>·> ·>·>·>·> ·>·>·>·> + <·<·<·<· ·>·>·>·> <·<·<·<· ·>·>·>·> * <·<·<·<· ·>·>·>·> ·>·>·>·> ·>·>·>·> $ <·<·<·<· <·<·<·<· <·<·<·<·

37 Relacje priorytetów operatorów W grafie nie ma cykli, więc funkcje priorytetów Istnieją; Ponieważ z f $ i g $ nie wychodzą żadne krawę- dzie, to f($)=g($)=0; Najdłuższa ścieżka z g + ma długość 1, więc g(+)=1; Istnieje ścieżka z g id do f * do g * do f + do g + do f $, więc g(id)=5.+*Id$f2440 g1350

38 Obsługa błędów w analizatorach Istnieją dwa miejsca, w których analizator działający metodą pierwszeństwa operatorów może wykryć błędy: 1.Jeśli terminal na wierzchołku stosu i aktualny symbol wejściowy nie są ze sobą w żadnej relacji priorytetów; 2.Jeśli znaleziono uchwyt, ale nie ma produkcji, dla której ten uchwyt byłby prawą stroną.

39 Obsługa błędów w analizatorach UWAGI. 1.Algorytm analizy metodą pierwszeństwa operatorów zdaje się redukować uchwyty złożone tylko z terminali. Jednakże, mimo że nieterminale są traktowane anonimowo, to na stosie analizatora dla każdego z niech jest zajęte miejsce. Czyli, gdy w powyższym błędzie 2. mówimy o uchwycie pasującym do prawej strony produkcji, oznacza to, że terminale do siebie pasują i pozycje zajmowane przez nieterminale są takie same.

40 Obsługa błędów w analizatorach UWAGI. 2.Sam fakt, że znaleźliśmy na stosie ciąg symboli a <· b 1 = b 2 =... =b k, nie oznacza, że b 1 b 2...b k jest ciągiem terminali po prawej stronie jakiejś produkcji. Nie sprawdzaliśmy tego warunku w algorytmie, ale możemy to zrobić, a nawet musimy, jeśli chcemy z redukcjami związać akcje semantyczne. Mamy więc możliwość wykrywania błędów w algorytmie z krokami (10)-(12) zmodyfikowanymi tak, aby sprawdzać, która z produkcji jest uchwytem podczas redukcji.

41 Obsługa błędów podczas redukcji Procedurę wykrywania i obsługi błędów możemy podzielić na kilka części. Pierwsza z nich obsługuje błędy typu 2. Procedura ta może, na przykład, zdejmować symbole ze stosu, tak jak korki (10)-(12) algorytmu. Ponieważ nie ma produkcji, zgodnie z którą można by wykonać redukcję, więc nie jest wykonywana żadna akcja semantyczna. Zamiast tego wypisywany jest komunikat diagnostyczny. Aby stwierdzić jak ma wyglądać ten komunikat, procedura obsługująca przypadek 2. musi zdecydować, do której produkcji jest podobna prawa strona zdejmowana ze stosu. Aby stwierdzić jak ma wyglądać ten komunikat, procedura obsługująca przypadek 2. musi zdecydować, do której produkcji jest podobna prawa strona zdejmowana ze stosu.

42 Obsługa błędów podczas redukcji Przykład: Zdejmujemy abc i nie ma prawej strony produkcji składającej się z a,b,c oraz zera lub więcej nieterminali. Możemy wówczas sprawdzić, czy usuniecie któregoś z a, b lub c daje popraną prawą stronę (z pominiętymi terminalami). Przykładowo jeśli prawa strona jest: aEcE to możemy wypisać komunikat: nieprawidlowy symbol b w wierszu (wiersz zawierajacy b)

43 Obsługa błędów podczas redukcji Przykład: Zdejmujemy abc i nie ma prawej strony produkcji składającej się z a,b,c oraz zera lub więcej nieterminali. Możemy również rozważać zmianę bądź wstawienie terminala. Jeśli prawą stroną byłyby napis abEdc, to moglibyśmy wypisać komunikat: pominiete d w wierszu (wiersz zawierajacy c) Może się również okazać, że prawa strona jest właściwym ciągiem terminali, ale z inaczej położonymi nieterinalami. Jeśli abc jest zdejmowane ze stosu bez zawartych lub otaczających nieterminali i abc nie jest prawą stroną, ale aEbc jest, możemy wypisać komunikat: pominiete E w wierszu (wiersz zawierajacy b) gdzie E oznacza odpowiednią kategorię składniową reprezsentowaną przez nieterminal E.

44 Obsługa błędów podczas redukcji Trudność znalezienia właściwego komunikatu, gdy nie znaleziono odpowiedniej prawej strony, zależy od tego, czy istnieje skończenie, czy nieskończenie wiele ciągów, które mogą być zdejmowane ze stosu w wierszach (10)-(12). W każdym takim ciągu b 1 b 2...b k, sąsiednie symbole muszą być w relacji =, czyli b 1 = b 2 =... =b k. Jeśli z tablicy priorytetów operatorów wynika, że istnieje tylko skończona liczba ciągów terminali powiązanych ze sobą relacją =, to możemy rozpatrywać te ciągi indywidualnie. Dla każdego takiego ciągu x możemy wcześniej wyznaczyć najbliższą mu prawą stronę y i wypisywać komunikat mówiący, że znaleziono x a oczekiwano y.

45 Obsługa błędów podczas redukcji Łatwo jest wyznaczyć wszystkie ciągi, które mogą być zdejmowane ze stosu w krokach (10)-(12), gdyż są one widoczne w grafie skierowanym, którego wierzchołki reprezentują terminale, a krawędź od a do b istnieje wtedy i tylko wtedy gdy a=b. Możliwe ciągi składają się wówczas z etykiet wierzchołków leżących na ścieżkach w tym grafie. Ścieżki mogą składać się z jednego wierzchołka Aby ścieżkę b 1 b 2...b k można było zdjąć przy jakimś wejściu, musi: istnieć symbol a (może nim być $), taki że a<· b 1 = b 2 =... =b k (b 1 nazwijmy początkowy) istnieć symbol a (może nim być $), taki że a<· b 1 = b 2 =... =b k (b 1 nazwijmy początkowy) istnieć symbol c (może nim być $) taki, że b k ·>c (b k nazwijmy końcowym). Tylko jeśli takie symbole istnieją może wystąpić redukcja, w wyniku której ze stosu zdejmiemy b 1 b 2...b k. Jeśli w grafie istnieje ścieżka od wierzchołka początkowego do końcowego zawierająca cykl, to istnieje nieskończenie wiele ciągów, które mogą zostać zdjęte ze stosu. W przeciwnym razie ciągów jest skończona liczba.

46 Obsługa błędów podczas redukcji Przypomnijmy gramatykę: E->E+E | E-E | E*E | E/E | EE | (E) | -E | id Tablica priorytetów Tablica priorytetów Graf tablicy priorytetów

47 Obsługa błędów podczas redukcji Procedura wyszukująca błędy: 1.Jeśli redukowany jest +,-,*,/ lub, sprawdza, że nieterminale są po obu stronach. Jeśli nie to wypisuje komunikat:.. brakuje oczekiwanych argumentow brakuje oczekiwanych argumentow 2.Jeśli redukowany jest id sprawdza, czy po obu stronach nie ma nieterminali. Jeśli jakiś jest, to ostrzega: brakuje oczekiwanego operatora 3.Jeśli redukowane są ( ) to sprawdza, czy między nawiasami jest nieteriminal. Jeśli nie to może poinformować nie ma wyrażenia pomiędzy nawiasami 4.Procedura musi ponadto sprawdzić, że nie ma nieterminala po lewej lub prawej stronie nawiasów. Jeśli jest, to procedura wypisuje komunikat: brakuje oczekiwanego operatora

48 Obsługa błędów przesunięcie/redukcja Gdy zaglądamy do tablicy priorytetów, aby zdecydować, czy wykonujemy przesunięcie czy redukcję (wiersze (6) i (9), może okazać się, że symbole z wierzchołka stosu i pierwszy symbol z wejścia nie są ze sobą w żadnej relacji. Przypuśćmy że a i b to dwa symbole z wierzchołka stosu ( b jest na wierzchu), c i d to dwa kolejne symbole wejściowe oraz, że b i c nie są w żadnej relacji priorytetów. b a $ cd$ stos wejście

49 Obsługa błędów przesunięcie/redukcja Aby odzyskać kontrolę, musimy zmodyfikować stos, wejście albo jedno i drugie. Możemy wówczas: zmieniać symbole; wstawiać symbole na stos i do wejścia kasować symbole z wejścia i stosu. Jeśli wstawiamy lub zmieniamy symbole, musimy uważać, żeby nie wpaść w pętlę nieskończoną, w której na przykład ciągle wstawialibyśmy symbole na początek wejścia, nie mogąc zredukować ani przesunąć żadnego z wstawionych symboli.

50 Obsługa błędów przesunięcie/redukcja Nie stworzymy pętli nieskończonych jeśli zapewnimy, aby po odzyskaniu kontroli aktualny symbol z wejścia mógł być przesunięty ( jeśli aktualnym symbolem jest $, mamy pewność, że nie dodamy symboli do wejścia, a stos w końcu się zmniejszy). Przykład. gdy ab jest na stosie a cd jest na wejściu, to jeśli a<·=c, to możemy zdjąć b ze stosu; Jeśli b<·=d, to możliwe jest usunięcie c ze stosu; Jeśli uda się znaleźć taki symbol e, że b<·=e <·=c, to możliwe jest wstawienie e przed c na wejściu. Ogólniej możemy wstawić taki ciąg symboli, że b<·=e 1 <·=... <·=e n <·=c (jeśli nie możemy znaleźć pojedynczego symbolu do wstawienia). Dla każdego pustego miejsca w tablicy priorytetów musimy podać procedurę obsługi błędów (ta sama procedura może być używana w kilku miejscach). Gdy analizator sprawdza wpis dla a i b w kroku (6) a a i b nie są w żadnej z relacji priorytetów – znajduje on wskaźnik procedury obsługi dla tego błędu.

51 Obsługa błędów przesunięcie/redukcja Przypomnijmy gramatykę: E->E+E | E-E | E*E | E/E | EE | (E) | -E | id Tablica priorytetów Tablica priorytetów Wiersze i kolumny, w których było co najmniej jedno puste miejsce wypełniliśmy nazwami procedur obsługi błędów:

52 Obsługa błędów przesunięcie/redukcja Najważniejsze części procedur obsługi błędów: e1: /* wywoływana gdy nie ma całego wyrażenia */ e1: /* wywoływana gdy nie ma całego wyrażenia */ wstaw id na wejście; wypisz komunikat: nie ma oczekiwanego argumentu ; wypisz komunikat: nie ma oczekiwanego argumentu ; e2: /* wywoływana gdy wyrażenia zaczyna się od prawego nawiasu */. e2: /* wywoływana gdy wyrażenia zaczyna się od prawego nawiasu */.. usuń ) z wejścia wypisz komunikat: nieoczekiwany prawy nawias ; e3: /* wywoływana gdy po id lub ) jest id lub ( */ e3: /* wywoływana gdy po id lub ) jest id lub ( */ wstaw + na wejście; wypisz komunikat: nie ma oczekiwanego operatora ; wypisz komunikat: nie ma oczekiwanego operatora ; e4: /* wywoływana gdy wyrażenia kończy się lewym nawiasem */ e4: /* wywoływana gdy wyrażenia kończy się lewym nawiasem */ zdejmij ze stosu ( wypisz komunikat: nie ma oczekiwanego prawego nawiasu ;

53 Obsługa błędów przesunięcie/redukcja Sprawdźmy jak ten mechanizm obsługi błędów obsłuży błędne wejście: id + ) $ id+)$ stos wejście

54 Obsługa błędów przesunięcie/redukcja Sprawdźmy jak ten mechanizm obsługi błędów obsłuży błędne wejście: id + ) E $ +)$ stos wejście

55 Obsługa błędów przesunięcie/redukcja Sprawdźmy jak ten mechanizm obsługi błędów obsłuży błędne wejście: id + ) + E $ )$ stos wejście brakuje oczekiwanych argumentow Ponieważ +·>), powinniśmy wyko- nać redukcję, uchwytem jest +. Procedura wyszukująca błędy sprawdza czy po lewej i prawej stronie plusa jest E. Nie ma więc wypisuje komunikat.

56 Obsługa błędów przesunięcie/redukcja Sprawdźmy jak ten mechanizm obsługi błędów obsłuży błędne wejście: id + ) E $ )$ stos wejście nieoczekiwany prawy nawias Ponieważ $ i ), nie są w żadnej relacji dla tej pary symboli mamy e2

57 Obsługa błędów przesunięcie/redukcja Sprawdźmy jak ten mechanizm obsługi błędów obsłuży błędne wejście: id + ) E $ $ stos wejście

58 Koniec wykładu dziewiątego


Pobierz ppt "Wykład 9 Metoda pierwszeństwa operatorów. Dla ważnej klasy gramatyk (gramatyka operatorowa) możemy łatwo ręcznie budować wydajne analizatory redukujące."

Podobne prezentacje


Reklamy Google