J.Nawrocki, M. Antczak, A. Hoffa, S. Wąsik Plik źródłowy: 08cw11-tr.doc; Data: 2009-01-15 09:47:00 Ćwiczenia nr 11 Translatory Wprowadzenie teoretyczne Wiele dokumentów wprowadzających do języków Lex oraz Yacc można znaleźć za pomocą wyszukiwarki Google. Przykładowo dość zwięzłe wprowadzenie w języku angielskim znajduje się na stronie http://ds9a.nl/lex-yacc/cvs/lex-yacc-howto.html. Obszerny opis generatora Lex w języku polskim znajduje się na stronie http://www.cs.put.poznan.pl/wcomplak/lexman/lexman.htm. Poniżej znajduje się przykładowy program w Lexie i Yaccu, które mogą służyć jako ściąga wymaganego formatu pliku. Ich dokładny opis znajduje się w materiale do poprzednich ćwiczeń. Plik scan.l: %% [0-7] {return yytext[0];} // gdy na wejściu znajduje się // cyfra [0-7] przekaż ją do // dalszego etapu analizy " " {return ' ';} // gdy na wejściu znajduje się // znak przekaż go do dalszego // etapu analizy. {YY_FATAL("ERR!");} // jeżeli na wejściu pojawi się // dowolny znak (. ), który nie // został obsłużony przez żadną z // powyższych reguł bazujących na // wzorcach to przerwij analizę // leksykalną z błędem // sygnalizujących błędnie // przygotowaną zawartość pliku // wejściowego Plik scan.y: %{ #include <stdio.h> // pliki nagłówkowe zawierające #include <dos.h> // funkcje, które będą używane #include <stdlib.h> // w dalszych sekcjach kodu #include <process.h> // źródłowego %} %start E // symbol startowy %% // rozpoczyna się sekcja gramatyki E : S {puts("syntax OK\n");} // potwierdź na wyjściu popr. skł. S error {yyerror();} // jeżeli są jakieś śmieci to źle ; S : '0' S '0' // kolejne reguły, które definiują '1' S '1' // poprawną składnię języka '2' S '2' // zdefiniowanego w treści zadania '3' S '3' '4' S '4' '5' S '5' '6' S '6' '7' S '7' ' '
; %% // impl. pokrywanych funkcji yacca void yyerror(char* msg) // kod funkcji, który zostanie { // wywołany w momencie, gdy printf("syntax error!\n"); // wyrażenia w pliku wejściowym exit(1); // nie będą się zgadzać składniowo } // z językiem z treści zadania Zadania Zad. 1. Napisz w LEX-ie program, który pominie w tekście wejściowym wszystkie identyfikatory języka Pascal nie zawierające się w zbiorze begin end procedure. Identyfikator to ciąg dużych i małych liter, cyfr oraz znaków podkreślenia nie zaczynający się od cyfry. procedurs: begin+ eno. : begin+. Zad. 2(*). Napisz w LEX-ie program, który pominie w tekście wejściowym wszystkie słowa zawierające samogłoski. Ala mm kota. mm. Zad. 3(*). Napisz w LEX-ie program który zastąpi wszystkie znaki nie będące literami kropką. Ala ma kota 1111 Osy lubia miod 2222 3333 Ala.ma.kota... Osy.lubia.miod...... Zad. 4. Napisz w LEX-ie program sumujący wartości w danym wierszu. 5 6 7 3 3 4 2 5 6 7 3 Suma = 23 3 4 Suma = 7 2 Suma = 2
Zad. 5(*). W pliku wejściowym znajdują się liczby całkowite ze znakiem oraz bez znaku. Należy podać ilość liczb zapisanych w tym pliku, a każdą liczbę dodatnią poprzedzić znakiem +. Program powinien być napisany w LEX-ie. -31 4 54 6-4 -665 Plik wyjściowy -31 +4 +54 +6-4 -665 Plik sklada sie z 6 liczb Zad. 6. Napisz w LEX-ie program który sprawdza czy ciąg znajdujący się w pliku wejściowym jest postaci a n b n. Wykorzystaj makro BEGIN i dwa stany. aaabbb aabbb aaabbb T T aabbb F Zad. 7(*). Napisz w LEX-ie program który sprawdza czy ciąg znajdujący się w pliku wejściowym zawiera na zmianę 0 i 1. Wykorzystaj makro BEGIN i dwa stany. 010101 10101 1100 010101 T T 10101 T 1100 F Zad. 8. Napisać w YACC-u program, który sprawdzi, czy plik wejściowy zawiera napis w postaci 1+2*1+ i jeżeli tak, to wypisze "Syntax OK!!!", a w przeciwnym wypadku "Syntax Error. 111221 121 11 1 21 12 12121
Zad. 9(*). Napisać w YACC-u program, który sprawdzi, czy plik wejściowy zawiera napis w postaci 1*2+3+1* i jeżeli tak, to wypisze "Syntax OK!!!", a w przeciwnym wypadku "Syntax Error. 1231 22333 12333311 121 131 1321 12131 Zad. 10. Mając dany przedstawiony poniżej parser napisany w LEX-ie napisać w YACC-u program, który sprawdzi, czy w pliku wejściowy znajduje się ciąg cyfr, w którym na zmianę występuje cyfra parzysta i nieparzysta, przy czym pierwsza powinna być cyfra parzysta. %{ #include "y.tab.h" %} %% [02468] {yylval=atoi(yytext);return pp;} [13579] {yylval=atoi(yytext);return nn;} \n ;. {YY_FATAL("Unexpected character!!!");} 21074 6 012 1234 22 11 1 Zad. 11. Mając dany parser z zadania 10 napisać w YACC-u program, który mając dany plik złożony z ciągu cyfr wypisze sumę wszystkich cyfr nieparzystych. 017891 Suma: 18 Zad. 12(*). Mając dany parser z zadania 10 napisać w YACC-u program, który mając dany plik złożony z ciągu cyfr wypisze czy w pliku znajduje się więcej cyfr parzystych, czy nieparzystych.
017891 Wiecej nieparzystych Zad. 13. Mając dany parser z zadania 10 napisać w YACC-u program, który mając dany plik złożony z ciągu cyfr wypisze ten ciąg dodając nawiasy. Nawias powinien być dodany przed i za każdym podciągiem złożonym z cyfr nieparzystych. Możesz założyć, że zawsze pierwszy będzie podciąg złożony z cyfr parzystych, a ostatni podciąg złożony z cyfr nieparzystych. 01789134609 0(17)8(913)460(9) Zad. 14(*). Mając dany parser z zadania 10 napisać w YACC-u program, który mając dany plik złożony z ciągu cyfr wypisze ten ciąg dodając nawiasy. Nawias powinien być dodany przed i za każdym podciągiem złożonym z cyfr nieparzystych. Możesz założyć, że zawsze pierwszy będzie podciąg złożony z cyfr nieparzystych, a ostatni podciąg złożony z cyfr parzystych. 17891346090 (17)8(913)460(9)0