PARADYGMATY I JĘZYKI PROGRAMOWANIA. lex/flex i yacc/bison w- 4 (2014)

Podobne dokumenty
Generatory analizatorów

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

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

Zadanie analizy leksykalnej

Podstawy Kompilatorów

Bison - generator analizatorów składniowych

L E X. Generator analizatorów leksykalnych

10. Translacja sterowana składnią i YACC

Programy pomocnicze: diff, make, systemy rcs i cvs, debugger. Zarządzanie wersjami.

Podstawy generatora YACC. Bartosz Bogacki.

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

Flex - generator analizatorów leksykalnych

Metody Kompilacji Wykład 13

Podstawy Kompilatorów

Generator skanerów Flex

Ćwiczenia nr 11. Translatory. Wprowadzenie teoretyczne

Analiza leksykalna i generator LEX

Podstawy Kompilatorów

Laboratorium z użyciem analizatora leksykalnego FLEX

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

Metody Kompilacji Wykład 1 Wstęp

Wybrane narzędzia do tworzenia analizatorów leksykalnych i składniowych w C/C++ Narzędzia, zastosowanie oraz próby rankingu.

KONSTRUKCJA KOMPILATORÓW

Metody Kompilacji Wykład 7 Analiza Syntaktyczna

Translacja sterowana składnią w generatorze YACC

Podstawy programowania C. dr. Krystyna Łapin

Semantyka i Weryfikacja Programów - Laboratorium 6

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

Języki formalne i gramatyki

Generator YACC: gramatyki niejednoznaczne

Generator analizatorów leksykalnych - Lex. Bartosz Bogacki.

Program We Kompilator Wy Źródłowy

Wstęp do Informatyki i Programowania Laboratorium: Lista 0 Środowisko programowania

Metody Kompilacji Wykład 3

automatem skończonym niedeterministycznym (ang. nondeterministic finite automaton) M N nazywamy system:

Języki programowania zasady ich tworzenia

Wstęp do Programowania, laboratorium 02

Podstawy programowania. Wykład Pętle. Tablice. Krzysztof Banaś Podstawy programowania 1

Wstęp do programowania INP003203L rok akademicki 2016/17 semestr zimowy. Laboratorium 1. Karol Tarnowski A-1 p.

Podstawy Kompilatorów

Podstawy Kompilatorów

1. Wprowadzanie danych z klawiatury funkcja scanf

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

1. Pierwszy program. Kompilator ignoruje komentarze; zadaniem komentarza jest bowiem wyjaśnienie programu człowiekowi.

Programowanie Proceduralne

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

Podstawy Kompilatorów

Wstęp do programowania

Lab 10. Funkcje w argumentach funkcji metoda Newtona. Synonimy nazw typów danych. Struktury. Tablice struktur.

Metody kompilacji Wykłady 4-5

Wykład VII. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

Język C zajęcia nr 11. Funkcje

Programowanie proceduralne INP001210WL rok akademicki 2018/19 semestr letni. Wykład 6. Karol Tarnowski A-1 p.

Języki i metodyka programowania. Typy, operatory, wyrażenia. Wejście i wyjście.

JIP. Analiza składni, gramatyki

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

Wybrane narzędzia do tworzenia analizatorów leksykalnych i składniowych w Javie

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

Gramatyki atrybutywne

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Analizator syntaktyczny

Matematyczne Podstawy Informatyki

System operacyjny Linux

Paradygmaty i języki programowania. Analiza leksykalna Skaner, RE, DAS, NAS, ε- NAS

Wskaźniki. Przemysław Gawroński D-10, p marca Wykład 2. (Wykład 2) Wskaźniki 8 marca / 17

Zmienne, stałe i operatory

Make jest programem komputerowym automatyzującym proces kompilacji programów, na które składa się wiele zależnych od siebie plików.

2 Przygotował: mgr inż. Maciej Lasota

Podstawy Informatyki sem. I 2014/2015 studia zaoczne Elektronika i Telekomunikacja!

Laboratorium 1 Temat: Przygotowanie środowiska programistycznego. Poznanie edytora. Kompilacja i uruchomienie prostych programów przykładowych.

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 1. Karol Tarnowski A-1 p.

1. Wprowadzenie do C/C++

Wykład 10. Translacja sterowana składnią

Podstawy programowania w języku C++

Programowanie w języku C++ Grażyna Koba

Funkcja (podprogram) void

OPERACJE WEJŚCIA / WYJŚCIA. wysyła sformatowane dane do standardowego strumienia wyjściowego (stdout)

Temat 1: Podstawowe pojęcia: program, kompilacja, kod

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 12. Karol Tarnowski A-1 p.

Jerzy Nawrocki, Wprowadzenie do informatyki

Świat parserów. Krzysztof Leszczyński Polska Grupa Użytkowników Linuxa

Wyrażenia regularne. Wyrażenia regularne 1/41

Języki formalne i techniki translacji

Tablice, funkcje - wprowadzenie

Programowanie w C++ Wykład 3. Katarzyna Grzelak. 12 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 35

Wskaźniki w C. Anna Gogolińska

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

Algorytm. a programowanie -

Podstawy Informatyki. Inżynieria Ciepła, I rok. Wykład 10 Kurs C++

Programowanie w języku Python. Grażyna Koba

1. Wprowadzenie do C/C++

Wykład 15. Literatura. Kompilatory. Elementarne różnice. Preprocesor. Słowa kluczowe

Co nie powinno być umieszczane w plikach nagłówkowych:

Elżbieta Kula - wprowadzenie do Turbo Pascala i algorytmiki

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

Wykład 5. Jan Pustelnik

Metodyki i Techniki Programowania MECHANIZM POWSTAWANIA PROGRAMU W JĘZYKU C PODSTAWOWE POJĘCIA

Języki programowania obiektowego Nieobiektowe elementy języka C++

Matematyczne Podstawy Informatyki

wykład III uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - zarządzanie pamięcią, struktury,

Transkrypt:

PARADYGMATY I JĘZYKI PROGRAMOWANIA lex/flex i yacc/bison w- 4 (2014)

Kompilator 2 faza wstępna faza końcowa faza postkońcowa Skaner Parser Analizator semantyki Optymizator Generator kodu

lexer/scanner 3 Analiza leksykalna proces zamiany ciągów znaków na ciąg tokenów x = 4 3*2 LEKSEM TOKEN x ZMIENNA = PRZYPISANIE 4 LICZBA - O_MINUS 3 LICZBA * O_MUL 2 LICZBA

parser 4 Analiza syntaktyczna analiza ciągów tokenów (leksemów); ich struktura gramatyczna; błędy składni LEKSEM TOKEN x ZMIENNA = PRZYPISANIE 4 LICZBA - O_MINUS 3 LICZBA * O_MUL 2 LICZBA x = 4 3*2 = x - 4 * 3 2 ^ 4

Analizator semantyki 5 Analiza semantyczna znaczenie n np. sprawdzanie typów, wiązanie obiektów, etc. Kod: double a = "napis"; Błąd analizy semantycznej: error: incompatible types in initialization

Optymalizator 6 zmniejszenie/zwiększenie pewnych własności programu wynikowego np. przyspieszenie programu

Generator kodu 7 Generacja kodu proces, w którym kompilator zamienia program źródłowy na wykonywalny, maszynowy x = a + b * c load c! mul b! add a! store x!

8 lex/flex & yacc/bison

lex/flex 9 lex narzędzie do budowy analizatorów leksykalnych M.E. Lesk i E. Schmidt (Lex A Lexical Analyzer Generator) obecnie rzadko używany flex (fast lexical analyzer generator) Open source (darmowy)

yacc/bison 10 yacc narzędzie do tworzenia analizatorów syntaktycznych (S.C. Johnson. Yacc: Yet Another Compiler- Compiler) wygenerowany parser potrzebuje analizatroa leksykalnego obecnie rzadko używany bison Open source (darmowy)

...związek z kompilacją 11 faza wstępna faza końcowa faza postkońcowa Skaner Parser Analizator semantyki Optymizator Generator kodu Lex/Flex (*.l skrypt) Yacc/Bison (*.y skrypt)

Schemat działania 12 KOD ŹRODŁOWY a = b + c * d WZORCE GRAMATYKA = id1 + id2 * id3 id4 ^ lex/flex yylex() ANALIZA LEKSYKALNA yyparse() yacc/bison ANALIZA SYNTAKTYCZNA KOD ASEMB. ======== load id3 mul id4 add id2 store id1

Schemat działania 13 skrypt.l skrypt.y lex flex yacc bison kod skanera skrypt.lex.c skrypt.tab.c kod parsera wejście a.out wyjście

Jak działa flex? 14 Flex używa skryptu *.l do generowania skanera *.l skrypt lex lex.yy.c skaner: czyta plik wejściowy (input file) przetwarza plik na ciąg tokenów tokeny przekazuje do parsera

Jak działa flex? 15 Skrypt dla flex- a: %{ #include <stdio.h> %} %% begin printf("started\n"); hello printf("hello!\n"); thanks printf( Welcome\n"); end printf("stopped\n"); %% KOMPILACJA i WYKONANIE $ flex examplea.l! $ gcc -o examplea lex.yy.c lfl! $./examplea! begin! Started! hello! Hello!! end! Stopped! thanks! Welcome! hello thanks! Hello!! Welcome!

Tokenizacja 16 %{ #include <stdio.h> #include <y.tab.h> %} %% begin return BEGIN; hello return HELLO; thanks return THANKS; end return END; %% Zamiast drukowania (printf(...)) dokonujemy identyfikacji TOKENU i zwracamy jego nazwę. Nazwa ta będzie używana przez program yacc, do opisu gramatyki.

Wyrażenia regularne 17 /* sekcja definicji */ %{ #include <stdio.h> %} %% /* sekcja reguł */ [a-z] printf("lowercase_word\n"); [A-Z] printf("uppercase_word\n"); [a-za-z] printf("word\n"); [0-9] printf("integer\n"); [0-9.] printf("float\n"); ";" printf("semicolon\n"); "(" printf( Left_parentheses\n"); ")" printf( Right_parentheses\n"); %%

Format reguł flex- a 18 dopasuj tekst z wejścia do wzorców (REGEX) zwracaj typ tokenów (TOKEN_TYPE) Format:! REGEX!{ /* Kod */!!!return TOKEN_TYPE;!!}!!!

Reguły flex- a 19 Flex dopasowuje tokeny o największej długości Wejście: abc Reguła: [a- z]+ Token: abc(nie "a" i nie "ab ) Flex używa zasady: pierwsza dobra reguła wejście: jeden Reguła_1: "jeden { printf("hello,"); Reguła_2: [a- za- z]+ { printf ("World!"); } à Wyjście: Hello, (nie World! )

Wymiana danych 20 yytext - przechowuje wartość przeczytaną przez lex yyval - jest używana do wymiany wartości między lex a yacc Przykład [0-9] yyval = atoi(yytext); return NUMBER; Tutaj pod yyval została wstawiona wartość otrzymana z konwersji napisu wejściowego, dopasowanego do wyrażenia regularnego, która pierwotnie została zapisana w zmiennej yytext. Prócz tego zwrócony został typ wartości (NUMBER) w ten sposób yacc dowie o typie i może go używać we własnych definicjach.

Wymiana danych 21 definicje tokenów metoda podstawowa inne informacje YYSTYPE (lex i yacc: definicje) %{ #define YYSTYPE double %} lex: deklaracje extern YYSTYPE yyval; yacc: deklaracje YYSTYPE yyval;

Ogólny skrypt lex- a 22 plik skryptu dla lex- a: /** sekcja definicji **/!...! %%! /** sekcja reguł **/!...! %%! /** Sekcja kodu C kopiowanego dosłownie **/!...

calc1.l 23! /* sekcja definicji */! %{! #include <stdlib.h>! #include <stdio.h>! #include "calc1.h"! void yyerror(char*);! extern int yylval;! %}!

calc1.l 24! /* sekcja definicji */! %{! #include <stdlib.h>! #include <stdio.h>! #include "calc1.h"! void yyerror(char*);! extern int yylval;! %}! nagłówek calc1.h

calc1.l 25! /* sekcja definicji */! %{! #include <stdlib.h>! #include <stdio.h>! #include "calc1.h"! void yyerror(char*);! extern int yylval;! %}! nagłówek funkcji błędów

calc1.l 26! /* sekcja definicji */! %{! #include <stdlib.h>! #include <stdio.h>! #include "calc1.h"! void yyerror(char*);! extern int yylval;! %}! zmienna komunikacyjna, zewnętrzna

calc1.l 27 /* sekcja reguł */! %%! [ \t]+ ;! [0-9]+ {yylval = atoi(yytext); return INTEGER;}! [-+*/] {return *yytext;}! "(" {return *yytext;}! ")" {return *yytext;}! \n {return *yytext;}!. {char msg[25]; sprintf(msg,"%s <%s>",! "invalid character",yytext); yyerror(msg);}!!

calc1.l 28 /* sekcja reguł */! wyrażenia regularne, wzorce %%! [ \t]+ ;! [0-9]+ {yylval = atoi(yytext); return INTEGER;}! [-+*/] {return *yytext;}! "(" {return *yytext;}! ")" {return *yytext;}! \n {return *yytext;}!. {char msg[25]; sprintf(msg,"%s <%s>",! "invalid character",yytext); yyerror(msg);}!!

calc1.l 29 /* sekcja reguł */! puste znaki %%! [ \t]+ ;! [0-9]+ {yylval = atoi(yytext); return INTEGER;}! [-+*/] {return *yytext;}! "(" {return *yytext;}! ")" {return *yytext;}! \n {return *yytext;}!. {char msg[25]; sprintf(msg,"%s <%s>",! "invalid character",yytext); yyerror(msg);}!!

calc1.l 30 /* sekcja reguł */! cyfry; jedna lub więcej %%! [ \t]+ ;! [0-9]+ {yylval = atoi(yytext); return INTEGER;}! [-+*/] {return *yytext;}! "(" {return *yytext;}! ")" {return *yytext;}! \n {return *yytext;}!. {char msg[25]; sprintf(msg,"%s <%s>",! "invalid character",yytext); yyerror(msg);}!!

calc1.l 31 /* sekcja reguł */! zwracana nazwa tokenu %%! [ \t]+ ;! [0-9]+ {yylval = atoi(yytext); return INTEGER;}! [-+*/] {return *yytext;}! "(" {return *yytext;}! ")" {return *yytext;}! \n {return *yytext;}!. {char msg[25]; sprintf(msg,"%s <%s>",! "invalid character",yytext); yyerror(msg);}!!

calc1.l 32 /* sekcja reguł */! jeden znak; operator %%! [ \t]+ ;! [0-9]+ {yylval = atoi(yytext); return INTEGER;}! [-+*/] {return *yytext;}! "(" {return *yytext;}! ")" {return *yytext;}! \n {return *yytext;}!. {char msg[25]; sprintf(msg,"%s <%s>",! "invalid character",yytext); yyerror(msg);}!!

calc1.l 33 /* sekcja reguł */! kropka oznacza dowolny znak (nie \n) %%! [ \t]+ ;! [0-9]+ {yylval = atoi(yytext); return INTEGER;}! [-+*/] {return *yytext;}! "(" {return *yytext;}! ")" {return *yytext;}! \n {return *yytext;}!. {char msg[25]; sprintf(msg,"%s <%s>",! "invalid character",yytext); yyerror(msg);}!!

calc1.l 34 /* sekcja reguł */! reakcja na kropkę %%! [ \t]+ ;! [0-9]+ {yylval = atoi(yytext); return INTEGER;}! [-+*/] {return *yytext;}! "(" {return *yytext;}! ")" {return *yytext;}! \n {return *yytext;}!. {char msg[25]; sprintf(msg,"%s <%s>",! "invalid character",yytext); yyerror(msg);}!!

calc1.l 35 /* sekcja reguł */! przekazywana zmienna i jej zawartość %%! [ \t]+ ;! [0-9]+ {yylval = atoi(yytext); return INTEGER;}! [-+*/] {return *yytext;}! "(" {return *yytext;}! ")" {return *yytext;}! \n {return *yytext;}!. {char msg[25]; sprintf(msg,"%s <%s>",! "invalid character",yytext); yyerror(msg);}!!

calc1.l 36 /* sekcja reguł */! przekazywany typ tokenu %%! [ \t]+ ;! [0-9]+ {yylval = atoi(yytext); return INTEGER;}! [-+*/] {return *yytext;}! "(" {return *yytext;}! ")" {return *yytext;}! \n {return *yytext;}!. {char msg[25]; sprintf(msg,"%s <%s>",! "invalid character",yytext); yyerror(msg);}!!

calc1.l 37 /* sekcja reguł */! funkcja błędów %%! [ \t]+ ;! [0-9]+ {yylval = atoi(yytext); return INTEGER;}! [-+*/] {return *yytext;}! "(" {return *yytext;}! ")" {return *yytext;}! \n {return *yytext;}!. {char msg[25]; sprintf(msg,"%s <%s>",! "invalid character",yytext); yyerror(msg);}!!

38 yacc/bison

Jak działa bison? 39 Bison używa skryptu z pliku *.y nazwa.tab.c nazwa.y bison nazwa.parse.c Parser czyta ciąg tokenów i próbuje zidentyfikować struktury gramatyczne zgodnie ze specyfikacją

Gramatyka 40 Gramatyka zbiór reguł formalnych dla napisów z danego języka. Reguły opisują zasady tworzenia napisów (tokenów) ze znaków zgodnie z zadaną składnią

41 Prosty przykład Leksem Token 3 LICZBA + O_PLUS 2 LICZBA - O_MINUS 1 LICZBA WEJŚCIE: 3 + 2 1 E => E + E E E E * E E / E id Gramatyka

42 Prosty przykład Leksem Token 3 LICZBA + O_PLUS 2 LICZBA - O_MINUS 1 LICZBA WEJŚCIE: 3 + 2 1 E => E + E E E E * E E / E id Gramatyka

43 Prosty przykład Leksem Token 3 LICZBA + O_PLUS 2 LICZBA - O_MINUS 1 LICZBA Startujemy z lewej strony.widzimy, że mamy id. WEJŚCIE: 3 + 2 1 E => E + E E E E * E E / E id Gramatyka

44 Prosty przykład Leksem Token 3 LICZBA + O_PLUS 2 LICZBA - O_MINUS 1 LICZBA id jest wyrażeniem WEJŚCIE: 3 + 2 1 E => E + E E E E * E E / E id Gramatyka

45 Prosty przykład Leksem Token 3 LICZBA + O_PLUS 2 LICZBA - O_MINUS 1 LICZBA Parser wie, że 3 jest wyrażeniem. W dalszych próbach oprze się na następnym znaczniku. WEJŚCIE: 3 + 2 1 E => E + E E E E * E E / E id Gramatyka

46 Prosty przykład Leksem Token 3 LICZBA + O_PLUS 2 LICZBA - O_MINUS 1 LICZBA Produkcja z plus pasuje bo jest to następny token z wejścia. WEJŚCIE: 3 + 2 1 E => E + E E E E * E E / E id Gramatyka

47 Prosty przykład Leksem Token 3 LICZBA + O_PLUS 2 LICZBA - O_MINUS 1 LICZBA Przesuwamy się do następnego tokenu, który jest id, a więc jest wyrażeniem (E) WEJŚCIE: 3 + 2 1 E => E + E E E E * E E / E id Gramatyka

48 Prosty przykład Leksem Token 3 LICZBA + O_PLUS 2 LICZBA - O_MINUS 1 LICZBA Wiemy, że E + E to wyrażenie (E). Powtarzamy proces aż do wyczerpania możliwości... WEJŚCIE: 3 + 2 1 E => E + E E E E * E E / E id Gramatyka

Gramatyka i format yacc 49 Gramatyka G = {{E, I}, T, P, E} 1. E => I! 2. E => E + E! 3. E => E * E! 4. E => ( E )! 5. I => a! 6. I => b! 7. I => Ia! 8. I = Ib! 9. I = I0! 10. I => I1!! T = {+, *, (, ), a, b, 0, 1} = s. terminalne P = {produkcje: 1-10}, E start Format programu yacc! Exp : Id {...}! Exp + Exp {...}! Exp * Exp {...}! ( Exp ) {...}! ;! Id : a {...}! b {...}! Id a {...}! Id 0 {...}! Id 1 {...}! ;!

calc1.y 50!! /* sekcja definicji */! %{! #include <stdlib.h>! #include <stdio.h>! int yylex(void);! #include "calc1.h"! %}! %token INTEGER!

calc1.y 51 %% /* sekcja REGUŁ */! program:! line program! line:! expr:! mulex:! term:! line! expr \n { printf("%d\n",$1); }! n! expr + mulex { $$ = $1 + $3; }! expr - mulex { $$ = $1 - $3; }! mulex { $$ = $1; }! mulex * term { $$ = $1 * $3; }! mulex / term { $$ = $1 / $3; }! term { $$ = $1; }! ( expr ) { $$ = $2; }! INTEGER { $$ = $1; }!

calc1.y 52 %% /* sekcja REGUŁ */! program:! line program! line:! expr:! mulex:! term:! line! expr \n { printf("%d\n",$1); }! n! expr + mulex { $$ = $1 + $3; }! expr - mulex { $$ = $1 - $3; }! mulex { $$ = $1; }! mulex * term { $$ = $1 * $3; }! mulex / term { $$ = $1 / $3; }! term { $$ = $1; }! ( expr ) { $$ = $2; }! INTEGER { $$ = $1; }! reguły gramatyczne

calc1.y 53 %% /* sekcja REGUŁ */! program:! line program! line:! expr:! mulex:! term:! line! expr \n { printf("%d\n",$1); }! n! akcje expr + mulex { $$ = $1 + $3; }! expr - mulex { $$ = $1 - $3; }! mulex { $$ = $1; }! mulex * term { $$ = $1 * $3; }! mulex / term { $$ = $1 / $3; }! term { $$ = $1; }! ( expr ) { $$ = $2; }! INTEGER { $$ = $1; }!

calc1.y 54 %% /* sekcja REGUŁ */! program:! line program! line:! expr:! mulex:! term:! line! expr \n { printf("%d\n",$1); }! n! expr + mulex { $$ = $1 + $3; }! expr - mulex { $$ = $1 - $3; }! mulex { $$ = $1; }! mulex * term { $$ = $1 * $3; }! mulex / term { $$ = $1 / $3; }! term { $$ = $1; }! ( expr ) { $$ = $2; }! INTEGER { $$ = $1; }! Kolejność operacji zapewnia kolejność produkcji: najpierw plus/minus co oznacza, że mulex jest realizowane jako pierwsze. Można deklarować łączność działań: %left PLUS MINUS! %right NOT!! etc.

calc1.y 55 %% /* sekcja REGUŁ */! program:! line program! line:! expr:! mulex:! term:! line! expr \n { printf("%d\n",$1); }! n! expr + mulex { $$ = $1 + $3; }! expr - mulex { $$ = $1 - $3; }! mulex { $$ = $1; }! mulex * term { $$ = $1 * $3; }! mulex / term { $$ = $1 / $3; }! term { $$ = $1; }! ( expr ) { $$ = $2; }! INTEGER { $$ = $1; }! zwykły wydruk; informacja

calc1.y 56 %% /* sekcja REGUŁ */! program:! line program! line:! expr:! mulex:! term:! line! expr \n { printf("%d\n",$1); }! n! $1 $2 $3 expr + mulex { $$ = $1 + $3; }! expr - mulex { $$ = $1 - $3; }! mulex { $$ = $1; }! mulex * term { $$ = $1 * $3; }! mulex / term { $$ = $1 / $3; }! term { $$ = $1; }! ( expr ) { $$ = $2; }! INTEGER { $$ = $1; }! specjalne zmienne przechowujące dopasowane wyrażenia z prawej strony produkcji

calc1.y 57 %% /* sekcja REGUŁ */! program:! line program! line:! expr:! mulex:! term:! line! expr \n { printf("%d\n",$1); }! n! expr + mulex { $$ = $1 + $3; }! expr - mulex { $$ = $1 - $3; }! mulex { $$ = $1; }! mulex * term { $$ = $1 * $3; }! mulex / term { $$ = $1 / $3; }! term { $$ = $1; }! ( expr ) { $$ = $2; }! INTEGER { $$ = $1; }! obliczona lewa strona produkcji i umieszczana na stosie

calc1.y 58 /* sekcja kodu C */! %%! void yyerror(char *s)! {! fprintf(stderr,"%s\n",s);! return;! }! int main(void)! {! /*yydebug=1;*/! yyparse();! return 0;! }! wywołanie głównej funkcji parsera

calc1.y 59 /* sekcja kodu C */! %%! void yyerror(char *s)! {! fprintf(stderr,"%s\n",s);! return;! }! int main(void)! {! /*yydebug=1;*/! yyparse();! return 0;! }! definicja funkcji błędów

Praktyka 60 uruchomić yacc/bison na pliku skryptowym z definicjami uruchomić lex/flex na pliku definicji syntaktycznych skompilować żródło wygenerowane przez yacc skompilować plik wygenerowany przez lex/flex skompilować inne potrzebne pliki połączyć wszystkie wynikowe pliki w plik wykonywalny

Przykład: poprawianie tekstu 61 lex/flex: Usuwanie zbędnych pustych linii, wielokrotnych spacji, spacji przed znakami przestankowymi takimi jak.,?! itd. /** definicje **/ punct [,.;:!?] text [a- za- Z] %% /** reguły **/ ) +/{punct} {printf( ) );} ) /{text} {printf( ) );} {text}+ +/ ) {while (yytext[yyleng- 1]== ) yyleng- - ; ECHO;} ({punct} {text}+)/ ( {ECHO; printf( );} ( +/{text} {while (yytext[yyleng- 1]== ) yyleng- - ; ECHO;} {text}+" "+/{punct} {while (yytext[yyleng- 1]== ) yyleng- - ; ECHO;} ˆ + ; + {printf( );}. {ECHO;} \n/\n\n ; \n {ECHO;}

Kalkulator (flex)[3] 62 %{! #include <stdlib.h>! #include "calc.tab.h"! %}! NUMBER [0-9]+! OP![+-/*]! %%! {NUMBER}!{ yylval.value =!!strtol(yytext, 0, 10); return NUMBER; }! ({OP} \n)!{ return yytext[0]; }!.!!{ ; }!

Praktyka - makefile 63 YFLAGS!= -d # header files! PROGRAM = calc! OBJS!= $(PROGRAM).tab.o lex.yy.o # + inne! SRCS CC!= $(PROGRAM).tab.c lex.yy.c # + inne!!= gcc! all: $(PROGRAM)!.c.o: $(SRCS)!!$(CC) -c $*.c -o $@ -O! $(PROGRAM).tab.c: $(PROGRAM).y!!bison $(YFLAGS) $(PROGRAM).y! lex.yy.c: $(PROGRAM).l!!flex $(PROGRAM).l! calc: $(OBJS)!!$(CC) $(OBJS) -o $@ -ll -lm! clean:;!rm -f $(OBJS) core *~ \#* *.o $(PROGRAM) \!!y.* lex.yy.* $(PROGRAM).tab.*!

Literatura 64 1. Lesk, Schmidt. Lex A Lexical Analyzer Generator. 2. Johnson. Yacc Yet another compiler- compiler. 3. T. Niemann. LEX & YACC TUTORIAL (epaperpress.com) 4. M. Landwehr. Flex/bison tutorial. ( hgp://www.capsl.udel.edu/courses/cpeg421/2012/slides/) 5. www/developerworks/aix/tutorials/au_lexyacc 6. Flex/Bison Tutorial. Aaron Myles Landwehr <aron+ta@udel.edu>

Pytania i dyskusja 65?

66 Dodatki na wszelki wypadek...

Kalkulator 67 Zadanie 1. Używając programów lex/flex oraz yacc/bison napisać program prostego kalkulatora z odwróconą notacją polską, z działaniami +,-,*,/. Zadanie 2. Niech T={0, 1, (, ), +, *,!, e} oznacza zbiór symboli terminalnych. Zaprojektować CFG (context free grammar), która generuje wyrażenia regularne nad alfabetem {0,1}. (Patrz: HopcroR, Rozdział 5. G={V, T, P, S}, gdzie V jest zbiorem zmiennych, T oznacza symbole terminalne, P jest zbiorem produkcji, S jest symbolem startowym). Zadanie 3. Rozważyć CFG zdefiniowaną produkcjami: S => asbs bsas ε. Udowodnić, że język L(G) jest zbiorem wszystkich napisów o równej liczbie symboli a i b.

calc.l [4] 68 %{ #define YYSTYPE double #include "calc.tab.h" #include <math.h> extern double yylval; %} D [0-9.] %% [ \t] { ; } log return LOG; pi return PIVAL; sin return SIN; cos tan and return COS; return TAN; return AND; not xor or reg ans fix sci eng const return NOT; return XOR; return OR; return REGA; return ANS; return FIX; return SCI; return ENG; return CONST; bintodec return BINTODEC; dectobin return DECTOBIN; {D}+ { sscanf( yytext, "%lf", &yylval ); return NUMBER ; } [a- za- Z_]+ return IDENT; "[" return OPENREG; "]" return CLOSEREG;

calc.l [4] cd. 69 "<<"!return LEFTSHIFT;! ">>"!return RIGHTSHIFT;! "++"!return INC;! "--"!return DEC;! "+"!return PLUS;! "-"!return MINUS;! "~"!return UNARYMINUS;! "/"!return DIV;! "*"!return MUL;! "^"!return POW;! "!!return FACT;! ("!return OPENBRACKET;! ")"!return CLOSEBRACKET;! "%"!return MOD;!!! "^^"!return XOR;! "("!return OPENBRACKET;! ")"!return CLOSEBRACKET;! "%"!return MOD;! "^^"!return XOR;! "!!"!return NOT;! "="!return ASSIGN;! "&&"!return LAND;! " "!return OR;! " "!return IOR;! "&"!return AND;! "~~"!return COMPLEMENT;! "\n"!return EOLN;!!

Metaznaki wzorców 70 Metaznak Dopasowanie. dowolny znak oprócz nowej \n newline * zero lub więcej kopii poprzedniego wyrażenia + jedna lub więcej kopii poprzedniego wyrażenia? zero lub jedna kopia poprzedniego wyrażenia ^ początek linii $ koniec linii a b a lub b (ab)+ jedna lub więcej kopii ab (grupowanie) "a+b" literał "a+b [] klasa znaków

Przykłady regexp i dopasowań 71 Wzorzec Dopasowanie abc abc abc* ab abc abcc abccc... abc+ abc abcc... a(bc)+ abc abcbc abcbcbc... a(bc)? a abc abcbc... [a- z] dowolna litera a, b,...,z [- az] - lub a lub z [a- za- Z0-9]+ jeden lub więcej znaków alfanumerycznych [ \t\n]+ biały znak (odstęp, tabulator, nowa linia) [^ab] wszystko oprócz a, b [a^b] a lub ^ lub b [a b] a lub lub b a b a lub b

Redukcja produkcji 72 gramatyka operacje na stosie E => E * E (r2) => E * z (r3) => E + E * z (r1) => E + y * z (r3) => x + y * z (r3) 1. x + y * z shig 2 x. + y * z reduce(r3) 3 E. + y * z shig 4 E +. y * z shig 5 E + y. * z reduce(r3) 6 E + E. * z shig 7 E + E *. z shig 8 E + E * z. reduce(r3) 9 E + E * E. reduce(r2) emit mulhply 10 E + E. reduce(r1) emit add 11 E. accept

73 za tydzień...!?