Zadanie 1
Poniższa gramatyka opisuje strukturę instrukcji warunkowych
w wielu językach programowania ('i' jest skrótem dla 'if',
'e' jest skrótem dla 'else', 'x' oznacza inne instrukcje,
'w' oznacza warunek (wyrażenie logiczne).
instr : 'i' war instr elsei | 'x' ;
elsei : /* puste */ | 'e' instr ;
war : 'w' ;
'bison' dla tej gramatyki zgłasza jeden konflikt przesunięcie/redukcja.
Domyślny mechanizm rozstrzygania konfliktów 'bison'-a wybiera w tym
miejscu przesunięcie co wiąże część
'elsei' z najbliższą instrukcją 'i'. Dobrać deklaracje priorytetu
tak by 'bison' wykonał redukcję. Jaki będzie efekt tej modyfikacji
dla języka akceptowanego przez analizator syntaktyczny?
Czy można w ten sposób
spowodować by 'bison' związał część 'elsei' z najdalszą instukcją 'i'?
Uwaga: Polecenie `info bison' pozwala przeglądać instrukcję `bison'-a.
Jeśli w części `Grammar File' punkt `Declarations' wybierzemy
podpunkt `Precedence Decl' to dostaniemy podsumowanie informacji o
deklaracjach priorytetu (warto też odwiedzić podpunkt
`Operator Precedence' w części o algorytmie `bison'-a).
Zadanie 2
Rozważmy język składający się z poprawnie zagnieżdżonych nawiasów
dwu rodzajów (tzn. jedna para to '(' i ')' a druga to '[' i ']') ,
z tym że stopień zadnieżdżenia nie może przekroczyć ustalonego N.
Uzasadnić że język ten można opisać gramatyką bezkontekstową
wielkości proporcjonalnej do N. Pokazać że minimaly automat
deterministyczny akceptujący ten język musi mieć wykładniczą
względem N liczbę stanów. Porównać to z przypadkiem nawiasów
jednego rodzaju.
Zadanie 3
Na symbolach pomocniczych gramatyki bezkontektowej wprowadzamy
relację równoważności ~ zdefiniowaną następująco: A ~ B wtedy
i tylko wtedy gdy B pojawia się w pewnej frazie wyprowadzanej
z A i A pojawia się w pewnej frazie wyprowadzanej z B.
Klasy abstrakcj tej relacji nazywamy klasami wzajemnie
rekursywnych symboli pomocniczych. Rozważmy teraz relację
"B pojawia się w pewnej frazie wyprowadzanej z A". Pokazać
że ta relacja jest dobrze zdefiniowana na klasach abstrakcji ~
(tzn. wynik nie zależy od wyboru reprezentantów) i zadaje
porządek częściowy. Powiemy że gramatyka jest mocno regularna
jeśli dla każedej klasy wzajemnie rekursywnych symboli pomocniczych
nowa gramatyka w której pozostałe symbole traktujemy jako
symbole końcowe jest lewostronnie lib prawostronnie liniowa.
Gramatykę nazywamy lewostronnie liniową jeśli symbole
pomocnicze występują tylko jako pierwsze symbole po prawej
stronie reguł. Podobnie Gramatykę nazywamy prawostronnie liniową
jeśli symbole pomocnicze występują tylko jako ostatnie symbole
po prawej stronie reguł. W szczególności prawa strona dowolnej
reguły zawiera co najwyżej jeden symbol pomocniczy. Pokazać
że gramatyka mocno regularna definiuje język regularny.
Pokazać że minimalny automat skończony rozpoznający język
definiowany przez gramatykę mocno regularną może mieć rozmiar
wykładniczy względem rozmiaru gramatyki.
Zadanie 4
Niekiedy chcemy aproksymować gramatyki bezkontekstowe gramatykami
definującymi języki regularne. Poniżej podajemy jedną z takich
konstrukcji. Najpierw wyznaczamy klasy wzajemnie rekursywnych
symboli pomocniczych. Jeśli gramatyka otrzymana przez potraktowanie
pozostałych symboli gramatyki jako końcowe nie jest prawostronnie
liniowa to dla każdego symbolu danej klasy wprowadzamy nowy
dodatkowy symbol. Dalej oryginalne symbole klasy będę oznaczał
przez A_i (z odpowiednim i) a dodane przez B_i. Regułę
A_0 : a_0A_1a_1A_2...A_na_n ;
gdzie a_i są ciągami symboli traktowanych jako końcowe (tzn.
symboli końcowych oraz pomocniczych spoza naszej klasy),
zastępuję kolekcją reguł:
A_0 : a_0A_1 ;
B_1 : a_1A_2 ;
...
B_n : a_nB_0 ;
Ponadto dodaję reguły mówiące że dowolne B_i może wyprowadzać
ciąg pusty. Pokazać że tak otrzymana gramatyka jest mocno
regularna i że definowany przez nią język zawiera język
generowany przez oryginalną gramatykę. Jak wygląda gramatyka
otrzymana z następującej gramatyki dla wyrażeń:
E : E '+' T | T ;
T : T '*' F | F ;
F : '(' E ')' | 'x' ;
Komentarz1: Idea konstrukcji jest taka że w nowej gramatyce A_i wyprowadza
to co w starej plus ogon, tzn. pozostałą część słowa. B_i wyprowadza
ogon, czyli to co jest po A_i. Jeśli porównać wyprowadzenia w obu
gramtykach to w nowej A_i pojawia się na początku wyprowadzenia A_i
w starej a B_i na końcu wyprowadzenia A_i w starej.
Komentarz2: Ta konstrukcja pozwala aproksymować przekrój języków
bezkontekstowych: dla języków regularnych przekrój daje się
obliczać. Jeśli aproksymacje się nie przecinają to oryginalne
jezyki też sie nie przecinają. Jeśli aproksymacje się przecinają
to można znaleźć najkrótsze słowo w przekroju aproksymacji.
Jeśli to słowo należy do oryginalnych języków to przekrój
jest niepusty. W przeciwnym razie potrzebujemy lepszą aproksymację
(konstrukcję powyżej można zmodyfikować tak by otrzymać ciąg
coraz lepszych aproksymacji).