Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Metoda pierwszeństwa operatorów

Podobne prezentacje


Prezentacja na temat: "Metoda pierwszeństwa operatorów"— Zapis prezentacji:

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

2 Metoda pierwszeństwa operatorów
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
E->EAE | (E) | -E | id, A-> + | - | * | / | ↑ nie jest gramatyką operatorową. E->E+E | E-E | E*E | E/E | E↑E | (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: <· , = , ·> 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 i a·>b. dla pewnej pary terminali a i b może nie zachodzić ani a<·b ani a=b ani 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 E->E+E | E-E | E*E | E/E | E↑E | (E) | -E | id
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 +<·* oraz *·>+. Podejście takie usuwa niejednoznaczność z gramatyki E->E+E | E-E | E*E | E/E | E↑E | (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 | niedopas_instr dopas_instr -> if wyr then dopas_instr else dopas_instr | inna niedopas_instr -> if wyr then 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 <· oznaczającym lewy kraniec, = występującym w środku uchwytu i ·> 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 a1 β1 a2 β2 ... an βn gdzie każde z βi jest albo Ɛ (pustym ciągiem) albo nieterminalem, zaś ai jest pojedynczym terminalnym, i=1,...,n. Załóżmy, że między ai i ai+1 zachodzi dokladnie jedna z relacji: <· , = lub ·> .

15 Relacje priorytetów operatorów
Do ustalenia końca ciągu będziemy używali symbolu $ oraz ustalimy, że dla wszystkich symboli terminalnych $ <· b oraz b ·> $. Przypuśćmy teraz, że usuwamy nieterminale z ciągu i umieszczamy symbol właściwej relacji <· = lub ·>. 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: $ <· id ·> + <· id ·> * <· id ·> $.

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

17 Relacje priorytetów operatorów
Metoda znalezienia uchwytu. - Przeglądamy ciąg od lewej strony aż do napotkania pierwszego ·>. $ <· id ·> + <· id ·> * <· id ·> $. - 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 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 | E↑E | (E) | -E | id Po dokonaniu redukcji względem produkcji E->id dostajemy prawostronną formę zdaniową E + id * id . Następnie po eliminacji w ciągu nieterminali i zastosowaniu symbolu właściwej relacji dostajemy $ <· + <· id ·> * <· id ·> $. Po analogicznym zredukowaniu dwóch pozostałych id do E otrzymamy prawostronną formę zdaniową E + E * E $ <· + <· * ·> $. 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 ω$. Zainicjuj ip tak, aby wskazywał pierwszy symbol ω$. Repeat forever if $ jest na wierzcholku stosu oraz ip wskazuje $ then return else begin niech a będzie symbolem z wierzcholku stosu a b – symbolem wskazanym przez ip; if a<·b lub a=b then begin odloz b na stos; przesun ip do nastepnego symbolu wejsciowego; end; else if a·>b then /*redukcja*/ repeat zdejmi element ze stosu until szczytowy element ze stosu jest w relacji <· z poprzednio zdjetym terminalem else blad(); 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 <· θ1 Jeśli przykładowo, priorytet * jest większy niż +, przyjmujemy, że * ·> + oraz + <· * (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. Jeśli przykładowo, + i – są lewostronnie łączne, to przyjmijmy: + ·> + , ·> - , ·> - , - ·> + 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 .

23 Wyznaczanie relacji priorytetów z łączności i priorytetów operatorów
3) Przyjmijmy, że θ <· id , id ·> θ , θ <· ( , (·> θ , θ ·> ) , θ ·> $ <· θ dla wszystkich operatorów θ. Ponad to niech ( = ) $ <· ( $ <· id ( <· ( id ·> $ ) <· id ( <· 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 $.

24 Relacje priorytetów operatorów
+ - * / Id ( ) $ ·> id = 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.

25 Obsługa operatorów jednoargumentowych
Mamy dwa rodzaje operatorów jednoargumento-wych: ¬ (negacja logiczna) - nie jest on jednocześnie operatorem dwuargumentowym; 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; 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 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
2 4 6 g 1 3 5 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 fa i ga. KROK II. Podziel uzyskane symbole na tak wiele grup, jak jest to możliwe i w taki sposób, aby fa i fb 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 fa i fc będą w tej samej grupie, co gb. Jeśli dodatkowo c=d to fa i gd 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 gb, do grupy z fa. - jeśli a ·> b, dodaj krawędź od grupy z fa do grupy z gb Krawędź będąca ścieżką z fa do gb 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 fa; niech g(b) będzie długością najdłuższej ścieżki o początku w grupie z gb.

36 Relacje priorytetów operatorów
Ustalamy relację priorytetów operatorów 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 gid do f* do g* do f+ do g+ do f$, więc g(id)=5. + * Id $ f 2 4 g 1 3 5

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: Jeśli terminal na wierzchołku stosu i aktualny symbol wejściowy nie są ze sobą w żadnej relacji priorytetów; 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. 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. Sam fakt, że znaleźliśmy na stosie ciąg symboli a <· b1 = b2 =... =bk, nie oznacza, że b1b2...bk 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.

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 b1b2...bk, sąsiednie symbole muszą być w relacji =, czyli b1 = b2 =... =bk. 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ę b1b2...bk można było zdjąć przy jakimś wejściu, musi: istnieć symbol a (może nim być $), taki że a<· b1 = b2 =... =bk (b1 nazwijmy początkowy) istnieć symbol c (może nim być $) taki, że bk·>c (bk nazwijmy końcowym). Tylko jeśli takie symbole istnieją może wystąpić redukcja, w wyniku której ze stosu zdejmiemy b1b2...bk. 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 | E↑E | (E) | -E | id Tablica priorytetów Graf tablicy priorytetów

47 Obsługa błędów podczas redukcji
Procedura wyszukująca błędy: Jeśli redukowany jest +,-,*,/ lub ↑, sprawdza, że nieterminale są po obu stronach. Jeśli nie to wypisuje komunikat: . brakuje oczekiwanych argumentow Jeśli redukowany jest id sprawdza, czy po obu stronach nie ma nieterminali. Jeśli jakiś jest, to ostrzega: brakuje oczekiwanego operatora 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 Procedura musi ponadto sprawdzić, że nie ma nieterminala po lewej lub prawej stronie nawiasów. Jeśli jest, to procedura wypisuje komunikat:

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 $ c d $ wejście stos

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<·=e1<·=... <·=en<·=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 | E↑E | (E) | -E | id 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 */ wstaw id na wejście; wypisz komunikat: „ nie ma oczekiwanego argumentu”; 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 ( */ wstaw + na wejście; wypisz komunikat: „ nie ma oczekiwanego operatora”; 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 + ) $ wejście stos

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 $ + ) $ wejście stos

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 $ ) $ wejście 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. stos brakuje oczekiwanych argumentow

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 $ ) $ wejście stos Ponieważ $ i ), nie są w żadnej relacji dla tej pary symboli mamy e2 nieoczekiwany prawy nawias

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 $ $ wejście stos

58 Koniec wykładu dziewiątego


Pobierz ppt "Metoda pierwszeństwa operatorów"

Podobne prezentacje


Reklamy Google