Generator YACC: gramatyki niejednoznaczne

Podobne dokumenty
Generator YACC: gramatyki niejednoznaczne

Podstawy generatora YACC. Bartosz Bogacki.

Metody Kompilacji Wykład 1 Wstęp

Bison - generator analizatorów składniowych

Translacja sterowana składnią w generatorze YACC

Wprowadzenie do analizy składniowej. Bartosz Bogacki.

10. Translacja sterowana składnią i YACC

Gramatyka operatorowa

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

Wykład 5. Jan Pustelnik

Wybrane narzędzia do tworzenia analizatorów leksykalnych i składniowych w C/C++ by Kapitol Team

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

Metody Kompilacji Wykład 3

Podstawy Kompilatorów

Generatory analizatorów

Metody Kompilacji Wykład 7 Analiza Syntaktyczna

Gramatyki atrybutywne

Wprowadzenie. Wojciech Complak

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

Języki programowania zasady ich tworzenia

Podstawy Kompilatorów

JIP. Analiza składni, gramatyki

Zadanie analizy leksykalnej

Analizator syntaktyczny

Program We Kompilator Wy Źródłowy

Metody Kompilacji Wykład 13

Języki programowania C i C++ Wykład: Typy zmiennych c.d. Operatory Funkcje. dr Artur Bartoszewski - Języki C i C++, sem.

Semantyka i Weryfikacja Programów - Laboratorium 6

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

KONSTRUKCJA KOMPILATORÓW

Operacje wykonywane są na operandach (argumentach operatorów). Przy operacji dodawania: argumentami operatora dodawania + są dwa operandy 2 i 5.

Podstawy kompilatorów. Generator LLgen. Wojciech Complak.

Translacja wprowadzenie

Matematyczne Podstawy Informatyki

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

Odczyt danych z klawiatury Operatory w Javie

Ćwiczenia nr 11. Translatory. Wprowadzenie teoretyczne

ForPascal Interpreter języka Pascal

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

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

Programowanie. programowania. Klasa 3 Lekcja 9 PASCAL & C++

Wprowadzania liczb. Aby uniknąć wprowadzania ułamka jako daty, należy poprzedzać ułamki cyfrą 0 (zero); np.: wpisać 0 1/2

Informatyka 1. Wyrażenia i instrukcje, złożoność obliczeniowa

Wykład 10. Translacja sterowana składnią

Matematyczne Podstawy Informatyki

Języki i paradygmaty programowania

Podstawy programowania w języku C i C++

Metody Realizacji Języków Programowania

Analiza leksykalna i generator LEX

Operatory. Operatory bitowe i uzupełnienie informacji o pozostałych operatorach. Programowanie Proceduralne 1

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

Instrukcje warunkowe i skoku. Spotkanie 2. Wyrażenia i operatory logiczne. Instrukcje warunkowe: if else, switch.

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

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

LABORATORIUM 3 ALGORYTMY OBLICZENIOWE W ELEKTRONICE I TELEKOMUNIKACJI. Wprowadzenie do środowiska Matlab

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

Wstęp do programowania

Wstęp do programowania INP003203L rok akademicki 2018/19 semestr zimowy. Laboratorium 4. Karol Tarnowski A-1 p.

0.1 Lewostronna rekurencja

Analiza zależności kontekstowych

Jerzy Nawrocki, Wprowadzenie do informatyki

Uproszczony schemat działania kompilatora

Operatory w C++ Operatory arytmetyczne. Operatory relacyjne (porównania) Operatory logiczne. + dodawanie - odejmowanie * mnożenie / dzielenie % modulo

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy WSKAŹNIKI KLASOWE

Podstawy programowania. 1. Operacje arytmetyczne Operacja arytmetyczna jest opisywana za pomocą znaku operacji i jednego lub dwóch wyrażeń.

Semantyka i Weryfikacja Programów - Laboratorium 3

Elżbieta Kula - wprowadzenie do Turbo Pascala i algorytmiki

ZYKI BEZKONTEKSTOWE (KLASA

Zajęcia P2AM. Analizator składniowy (Flex + Bison, Linux)

2.2. Gramatyki, wyprowadzenia, hierarchia Chomsky'ego

Dr inż. Grażyna KRUPIŃSKA. D-10 pokój 227 WYKŁAD 7 WSTĘP DO INFORMATYKI

Gramatyki (1-2) Definiowanie języków programowania. Piotr Chrząstowski-Wachjtel

Podstawy Kompilatorów

Języki formalne i gramatyki

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

JĘZYKIFORMALNE IMETODYKOMPILACJI

/* dołączenie pliku nagłówkowego zawierającego deklaracje symboli dla wykorzystywanego mikrokontrolera */ #include <aduc834.h>

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

JĘZYKI FORMALNE I METODY KOMPILACJI

Przeciążanie operatorów

Język ludzki kod maszynowy

INFORMATYKA, TECHNOLOGIA INFORMACYJNA ORAZ INFORMATYKA W LOGISTYCE

Podstawy Kompilatorów

Metodologie programowania

Algorytmika i Programowanie VBA 1 - podstawy

Programowanie strukturalne. Opis ogólny programu w Turbo Pascalu

Plan wynikowy z wymaganiami edukacyjnymi z matematyki w zakresie podstawowym dla klasy 1 zsz Katarzyna Szczygieł

Wykład 2 Składnia języka C# (cz. 1)

Analiza semantyczna. Gramatyka atrybutywna

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

Języki formalne i automaty Ćwiczenia 2

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

1 Przygotował: mgr inż. Maciej Lasota

operator zmiany znaku operatory mnożenia, dzielenia, dzielenia modulo operatory dodawania, odejmowania

Jerzy Nawrocki, Wprowadzenie do informatyki

ZAAWANSOWANE JĘZYKI PROGRAMOWANIA

Wprowadzenie do programowania w języku Visual Basic. Podstawowe instrukcje języka

5. JĘZYKI BEZKONTEKSTOWE (KLASA "2") GRAMATYKI BEZKONTEKSTOWE AUTOMATY ZE STOSEM DETERMINISTYCZNE JĘZYKI BEZKONTEKSTOWE I

JAO - Wprowadzenie do Gramatyk bezkontekstowych

Transkrypt:

Plan wykładu Generator YACC: gramatyki niejednoznaczne Wojciech Complak Wojciech.Complak@cs.put.poznan.pl gramatyki jednoznaczne i niejednoznaczne zalety gramatyk niejednoznacznych opisywanie łączności i priorytetów w generatorze YACC problem tzw. wiszącego else używanie przypadków specjalnych w gramatykach niejednoznacznych 1.03 Generator YACC: gramatyki niejednoznaczne (2/39) Gramatyki jednoznaczne i niejednoznaczne Gramatyki jednoznaczne i niejednoznaczne gramatyka jest jednoznaczna wtedy, gdy dla każdego zdania należącego do języka opisanego gramatyką istnieje tylko jedno drzewo składniowe drzewo składniowe opisuje składnię, a nie znaczenie (semantykę), nie odzwierciedla więc kolejności zastępowania symboli w formach zdaniowych każdemu drzewu składniowemu odpowiada jeden unikalny wywód prawostronny (YACC) rozważmy niejednoznaczną gramatykę dla ciągu liczb rozdzielonych znakami odejmowania: - sprawdźmy teraz: jak będzie wyglądać drzewo składniowe dla zdania jaki będzie wynik (i kolejność) obliczeń analizatora wygenerowanego przez YACCa Generator YACC: gramatyki niejednoznaczne (3/39) Generator YACC: gramatyki niejednoznaczne (4/39) Drzewa wywodu zdania - skaner dla zdania - - istnieją dwa drzewa składniowe lewostronna łączność operatora odejmowania prawostronna łączność operatora odejmowania Generator YACC: gramatyki niejednoznaczne (5/39) analizator leksykalny ma za zadanie: rozpoznać i zwrócić znak odejmowania ( - ) rozpoznać liczbę całkowitą, dokonać jej konwersji i zwrócić jako atrybut symbolu NUM %{ #include <stdlib.h> #include "y.tab.h" %} \- { return } [0-9]+ { yylval = atoi(yytext) return NUM } Generator YACC: gramatyki niejednoznaczne (6/39)

z nieterminalem wiążemy akcje semantyczne: dla produkcji rezultatem będzie różnica argumentów operatora odejmowania dla produkcji NUM rezultatem będzie wartość liczby S : { printf("%d",$1) } : { $$ = $1 - $3 } NUM { $$ = $1 } Generator YACC: gramatyki niejednoznaczne (7/39) w trakcie generowania analizatora przez YACCa (MKS) otrzymujemy informację o pojedynczym konflikcie przesuń/redukuj: State 5 :. (2) :. [ $end ] Shift/reduce conflict (4,2) on shift 4. reduce (2) Conflicts: State Token Action 5 shift 4 5 reduce (2) Generator YACC: gramatyki niejednoznaczne (8/39) po skompilowaniu analizatora testujemy jego działanie dla wejścia 1-2 - 3, zamiast odpowiedzi -4 otrzymujemy jednak 2 analiza wywodu: [2] [1]-[-1] [1]-[2]-[3] [1]-[2]-[3] [1]-[2]-[3] [1]-[2]-[3] wskazuje, że problem leży w kolejności redukcji symboli formy zdaniowej - - operator odejmowania jest lewostronnie łączny, powinniśmy więc wybrać interpretację (1-2) - 3 a została wybrana (zgodnie z domyślnymi regułami YACCa): 1 - (2-3) w trakcie generowania analizatora otrzymujemy komunikat o konflikcie przesunięcie/redukcja w pozycji - - sposób rozstrzygnięcia tego konfliktu decyduje o łączności operatora (przesunięcie łączność prawostronna, redukcja łączność lewostronna) Generator YACC: gramatyki niejednoznaczne (9/39) Generator YACC: gramatyki niejednoznaczne (10/39) domyślne reguły rozstrzygania konfliktów przez generator YACCa: konflikt przesunięcie/redukcja jest rozstrzygany na korzyść przesunięcia konflikt redukcja/redukcja - na korzyść redukcji zgodnie z wcześniejszą tekstową produkcją w specyfikacji w rozpatrywanym przykładzie domyślna reguła rozstrzygania konfliktów nie dała oczekiwanej łączności operatora odejmowania Generator YACC: gramatyki niejednoznaczne (11/39) czy jest w takim razie sens stosować gramatyki niejednoznaczne? gramatyki niejednoznaczne mają istotne zalety: są proste, łatwiej je modyfikować i rozbudowywać analizatory są efektywniejsze łatwo jest uwzględnić przypadki specjalne konieczne jest jedynie odpowiednie wskazanie sposobu rozstrzygnięcia konfliktów za pomocą słów kluczowych YACCa Generator YACC: gramatyki niejednoznaczne (12/39)

Porównanie złożoności gramatyk Porównanie złożoności gramatyk gramatyka jednoznaczna S : {printf("%d",$1)} : '+' T {$$=$1+$3} T {$$=$1-$3} T {$$=$1} T : T '*' F {$$=$1*$3} T '/' F {$$=$1/$3} F {$$=$1} F : '(' ')' {$$=$2} NUM {$$=$1} '+' F {$$=$2} F {$$=-$2} gramatyka niejednoznaczna %left '+' %left '*' '/' %left UMINUS L : {printf("%d",$1)} : '+' {$$=$1+$3} '+' %prec UMINUS {$$=$2} {$$=$1-$3} %prec UMINUS {$$=-$2 } '*' {$$=$1*$3} '/' {$$=$1/$3} '(' ')' {$$=$2} NUM {$$=$1} Generator YACC: gramatyki niejednoznaczne (13/39) gramatyka jednoznaczna /* 1 */ : '+' T /* 2 */ T /* 3 */ T /* 4 */ T : T '*' F /* 5 */ T '/' F /* 6 */ F /* 7 */ F : '(' ')' /* 8 */ NUM /* 9 */ '+' F /* 10 */ F gramatyka niejednoznaczna /* 1 */ : '+' /* 2 */ '+' /* 3 */ /* 4 */ /* 5 */ '*' /* 6 */ '/' /* 7 */ '(' ')' /* 8 */ NUM Generator YACC: gramatyki niejednoznaczne (14/39) gramatyka jednoznaczna S : {printf("%d",$1)} : '+' T {$$=$1+$3 printf("r1([%d]->[%d]+t[%d]) ",$$,$1,$3)} T {$$=$1-$3 printf("r2([%d]->[%d]-t[%d]) ",$$,$1,$3)} T {$$=$1 printf("r3([%d]->t[%d]) ",$$,$1)} T : T '*' F {$$=$1*$3 printf("r4(t[%d]->t[%d]*f[%d]) ",$$,$1,$3)} T '/' F {$$=$1/$3 printf("r5(t[%d]->t[%d]/f[%d]) ",$$,$1,$3)} F {$$=$1 printf("r6(t[%d]->f[%d]) ",$$,$1)} F : '(' ')' {$$=$2 printf("r7(f[%d]->([%d])) ",$$,$2)} NUM {$$=$1 printf("r8(f[%d]->num[%d]) ",$$,$1)} '+' F {$$=$2 printf("r9(f[%d]->+f[%d]) ",$$,$2)} F {$$=-$2 printf("r10(f[%d]->-f[%d]) ",$$,$2)} Generator YACC: gramatyki niejednoznaczne (15/39) gramatyka niejednoznaczna %left '+' %left '*' '/' %left UMINUS L : { printf("%d",$1) } : '+' {$$=$1+$3 printf("r1([%d]->[%d]+[%d]) ",$$,$1,$3)} '+' %prec UMINUS {$$=$2 printf("r2([%d]->+[%d]) ",$$,$2)} {$$=$1-$3 printf("r3([%d]->[%d]-[%d]) ",$$,$1,$3)} %prec UMINUS {$$=-$2 printf("r4([%d]->-[%d]) ",$$,$2)} '*' {$$=$1*$3 printf("r5([%d]->[%d]*[%d]) ",$$,$1,$3)} '/' {$$=$1/$3 printf("r6([%d]->[%d]/[%d]) ",$$,$1,$3)} '(' ')' {$$=$2 printf("r7([%d]->([%d])) ",$$,$2)} NUM {$$=$1 printf("r8([%d]->num[%d]) ",$$,$1)} Generator YACC: gramatyki niejednoznaczne (16/39) złożoność czasowa dla najprostszego poprawnego wejścia (pojedynczej liczby), np.: 2 gramatyka jednoznaczna 3 redukcje: r8(f[2]->num[2]),r6(t[2]->f[2]),r3([2]->t[2]) gramatyka niejednoznaczna 1 redukcja: r8([2]->num[2]) w tym prostym przypadku różnica wydajności jest bardzo duża (3-krotna) jak będzie wyglądać sytuacja dla większego rozmiaru wejścia? Generator YACC: gramatyki niejednoznaczne (17/39) złożoność czasowa dla wyrażenia: 2+3*4-1 jednoznaczna 11 redukcji: r8(f[2]->num[2]), r6(t[2]->f[2]), r3([2]->t[2]), r8(f[3]->num[3]), r6(t[3]->f[3]), r8(f[4]->num[4]), r4(t[12]->t[3]*f[4]), r1([14]->[2]+t[12]), r8(f[1]->num[1]), r6(t[1]->f[1]), r2([13]->[14]-t[1]) niejednoznaczna 7 redukcji: r8([2]->num[2]), r8([3]->num[3]), r8([4]->num[4]), r5([12]->[3]*[4]), r1([14]- >[2]+[12]), r8([1]->num[1]), r3([13]->[14]- [1]) Generator YACC: gramatyki niejednoznaczne (18/39)

jak opisać łączność i priorytet operatorów w YACCu? większość operatorów arytmetycznych ma lewostronne wiązanie definiujemy ich wiązanie za pomocą słowa kluczowego %left %left S : { printf("%d",$1) } : { $$ = $1 - $3 } NUM { $$ = $1 } Generator YACC: gramatyki niejednoznaczne (19/39) priorytet instrukcji wynika z priorytetu najbardziej prawego tokenu niewielka (ale nieprzemyślana) modyfikacja gramatyki powoduje powstanie konfliktów %left S : { printf("%d",$1) } : ' ' ' ' { $$ = $1 - $5 } NUM { $$ = $1 } Generator YACC: gramatyki niejednoznaczne (20/39) operator dodawania operatory mogą mieć trzy typy wiązań dla każdego typu przewidziano w YACCu odpowiednie słowo kluczowe: %left wiązanie lewostronne %right wiązanie prawostronne %nonassoc brak wiązania Generator YACC: gramatyki niejednoznaczne (21/39) dodajmy teraz do gramatyki operator dodawania ( + ) o takim samym priorytecie i wiązaniu jak operator odejmowania ( - ) %left '+' S : { printf("%d",$1) } : '+' { $$ = $1 + $3 } { $$ = $1 - $3 } NUM { $$ = $1 } Generator YACC: gramatyki niejednoznaczne (22/39) operatory multiplikatywne operator potęgowania następnie uzupełnijmy gramatykę o operatory multiplikatywne (mnożenia i dzielenia) i definiujemy ich priorytet i łączność %left '+' %left '*' '/' : '+' { $$ = $1 + $3 } { $$ = $1 - $3 } '*' { $$ = $1 * $3 } '/' { $$ = $1 / $3 } NUM { $$ = $1 } Generator YACC: gramatyki niejednoznaczne (23/39) w celu przypisania operatorowi prawostronnego wiązania należy użyć słowa kluczowego %right w językach programowania stosunkowo niewiele operatorów ma prawostronne wiązanie, np.: potęgowanie (operator ** albo ^) przypisanie (=) w języku C prawostronne wiązanie operatora potęgowania (np. ^) oznacza, że wyrażenie 2 ^ 3 ^ 2 jest interpretowane jako 2 ^ (3 ^ 2) Generator YACC: gramatyki niejednoznaczne (24/39)

operator potęgowania operatory bez wiązania dodanie do kalkulatora operatora potęgowania np. w postaci takiej jak w języku AWK (prawostronnie wiążący ^ ), wymaga: rozbudowania skanera o regułę: \^ { return '^' } oraz parsera o: deklarację: %right '^ produkcję: : '^' z akcją: {$$=(int)pow($1,$3)} Generator YACC: gramatyki niejednoznaczne (25/39) w celu określenia, że operator nie ma wiązania używamy słowa kluczowego %nonassoc przykładem takiego operatora jest porównanie (=) w Pascalu, w którym poprawne jest wyrażenie: a = b ale nie: a = b = c które należy zapisać np. jako: (a = b) = c modyfikujemy gramatykę dodając: deklarację %nonassoc '=' produkcję : '=' (z odpowiednimi akcjami) Generator YACC: gramatyki niejednoznaczne (26/39) unarny minus unarny minus poprawne rozbudowanie gramatyki o unarny minus wymaga specjalnych zabiegów wydaje się, że wystarczy dodanie produkcji : - z akcją semantyczną { $$ = -$2 } czy jest to jednak dobre podejście? generacja analizatora brak konfliktów ( ) testy: - 2-3 => -5 ( ) - 4 * - 2 => 8 ( ) - 8 / - 4 / - 2 => -4 (, powinno być -1) błąd wynika z faktu, że produkcja - ma taki priorytet jak operator -, niższy od priorytetu operatora / (i produkcji / ) problem powstaje w pozycji - /, kiedy to powinna nastąpić redukcja, ale skoro operator / ma wyższy priorytet od - zostanie wykonane przesunięcie wyrażenie zostaje źle zinterpretowane jako: -8 / ( -4 / -2) Generator YACC: gramatyki niejednoznaczne (27/39) Generator YACC: gramatyki niejednoznaczne (28/39) unarny minus unarny plus należy więc przypisać produkcji - wyższy priorytet niż operatorom * i / modyfikowanie priorytetu operatora - jest bezcelowe (minus unarny i binarny można rozróżnić dopiero na poziomie produkcji) problem można rozwiązać definiując pomocniczy token, np.: %token UMINUS a następnie za pomocą słowa kluczowego %prec przypisując jego priorytet produkcji: : %prec UMINUS {$$=-$2} Generator YACC: gramatyki niejednoznaczne (29/39) w niektórych językach dostępny jest również unarny plus obsługa unarnego plusa wymaga takich samych zabiegów, jak w przypadku unarnego minusa (można wykorzystać ten sam pomocniczy token) jeżeli zignorujemy ten problem, to kalkulator potraktuje np. + 8 / + 4 / + 2 jak + 8 / (+ 4 / + 2) i poda błędną odpowiedź: 4 zamiast poprawnej: 1 Generator YACC: gramatyki niejednoznaczne (30/39)

wiszące else wiszące else problem tzw. wiszącego else występuje w tych językach (np.: C, C++, Pascal), w których: instrukcja warunkowa ma opcjonalną część else i jednocześnie nie ma słowa (słów) kluczowego kończącego instrukcję warunkową zamknięcie instrukcji warunkowej przewidziano m. in. w Algolu 68 (fi), języku powłoki systemu UNIX (fi), Adzie (end if) i Moduli-2 (end) Generator YACC: gramatyki niejednoznaczne (31/39) problem wiszącego else (na przykładzie składni języka Pascal) polega na tym, że instrukcja: if a then if b then writeln('b') else writeln('c') może być interpretowana na dwa sposoby: if a then begin if b then writeln('b') else writeln('c') end { a } if a then begin if b then writeln('b') end else writeln('c') { b } Generator YACC: gramatyki niejednoznaczne (32/39) wiszące else wiszące else poprawna jest oczywiście interpretacja {a} wiążąca część else z bezpośrednio poprzedzającą ją instrukcją if-then zapiszmy instrukcję warunkową w YACCu: S : IF THN S IF THN S LS S nieterminale S i, to odpowiednio instrukcja i wyrażenie terminale IF, THN, LS reprezentują słowa kluczowe języka Pascal Generator YACC: gramatyki niejednoznaczne (33/39) w typowej gramatyce instrukcje nie mają priorytetów w wyniku czego powstaje konflikt przesunięcie/redukcja w pozycji: IF THN S LS S czy po przeczytaniu części if-then, widząc na wejściu else należy wykonać redukcję czy przesunięcie? konflikt zostanie rozstrzygnięty zgodnie z domyślnymi regułami na korzyść przesunięcia (i właściwej interpretacji instrukcji if-then-else) Generator YACC: gramatyki niejednoznaczne (34/39) wiszące else przypadki specjalne rozwiązanie tego konfliktu wymaga: przypisania terminalowi LS prawostronnego wiązania oraz przypisania części if-then takiego samego priorytetu jaki ma terminal LS: %right LS S : IF THN S IF THN S LS S %prec LS Generator YACC: gramatyki niejednoznaczne (35/39) fragment gramatyki preprocesora QN do składania równań (Kernighan & Cherry): %token sub sup : sub sup /* */ sub /* */ sup /* */... konflikty przesunięcie/redukcja można usunąć definiując łączność terminali sub i sup: %right sub sup Generator YACC: gramatyki niejednoznaczne (36/39)

przypadki specjalne przypadki specjalne konflikt redukcja/redukcja jest związany z produkcjami: sub sup sup w pozycji: sub sup sup YACC wykrywa konflikt redukcja/redukcja zgodnie z którą produkcją ma wykonać redukcję i jak wskazać generatorowi właściwy wybór? Generator YACC: gramatyki niejednoznaczne (37/39) obsłużenie przypadku specjalnego wymaga wybrania redukcji zgodnie z produkcją: sub sup a więc należy nadać jej wyższy priorytet modyfikowanie priorytetu tokenu sup jest bezcelowe (priorytet obu produkcji pochodzi właśnie od niego) wystarczy użyć domyślnych reguł produkcja, która ma mieć wyższy priorytet musi być tekstowo pierwsza w specyfikacji Generator YACC: gramatyki niejednoznaczne (38/39) Dalsza lektura podręczniki YACCa: Bison (klon YACCa): http://www.gnu.org/software/bison/manual/ Johnson S. C., YACC: Yet Another Compiler-Compiler, Unix Programmer's Manual Vol 2b, 1979 Levine J., Mason T., Brown D., lex & yacc, 2nd edition, O'Reilly, 1992 MKS LX & YACC, Reference Manual, MKS Software Inc., 2004 gramatyki niejednoznaczne Aho A. V., Sethi R., Ullman J. D., Compilers: Principles, Techniques, and Tools, Addison-Wesley, 1986 Generator YACC: gramatyki niejednoznaczne (39/39)