Lex jest skanerem potrafiącym analizować składnię języka (lexical analyzer generator). Yacc (Yet Another Compiler Compiler) potrafi budować z plików lex'a nowe programy (parser generator). W chwili obecnej lex jest zastąpiony przez flex, natomiast yacc przez bison. Skrypty dla obu można łączyć z kodem w C. ====================================================================== PRZYKŁAD 1 --> plik: 01-przyklad.lex ====================================================================== %{ #include %} %% stop printf("Stop command received\n"); start printf("Start command received\n"); %% --------- KOMPILACJA: lex 01-przyklad.lex cc lex.yy.c -o 01-przyklad.x -lfl --------- OPIS: analiza wejścia i przedrukownie każdego słowa, oprócz słów "stop" i "start". Koniec zabawy przez EOF (czyli ^D). ====================================================================== PRZYKŁAD 2 --> plik: 02-przyklad.lex ====================================================================== %{ #include %} %% [0123456789]+ printf("NUMBER\n"); [a-zA-Z][a-zA-Z0-9]* printf("WORD\n"); %% --------- KOMPILACJA: lex 02-przyklad.lex cc lex.yy.c -o 02-przyklad.x -lfl --------- OPIS: rozpoznawanie słów i liczb. Koniec ^D. ====================================================================== PRZYKŁAD 3 --> plik 03-rzymskie.lex ====================================================================== %% int total=0; I total += 1; IV total += 4; V total += 5; IX total += 9; X total += 10; XL total += 40; L total += 50; XC total += 90; C total += 100; CD total += 400; D total += 500; CM total += 900; M total += 1000; [ \t]+ return total; \n return total; %% int main (void) { int first, second; first = yylex (); second = yylex (); printf ("%d + %d = %d\n", first, second, first+second); return 0; } --------- KOMPILACJA: lex 03-rzymskie.lex cc lex.yy.c -o 03-rzymskie.x -lfl --------- OPIS: Dodawanie dwóch liczb podanych w systemie rzymskim. Liczby oddzielone mogą być spacjami i/lub tabulatorami. ====================================================================== PRZYKŁAD 4 --> pliki: 04-calculator.lex, 04-calculator.yacc ====================================================================== ------------- PLIK 04-calculator.lex ------------------------------------ %{ #include "y.tab.h" extern int yylval; %} %% [0-9]+ { yylval = atoi (yytext); printf ("scanned the number %d\n", yylval); return NUMBER; } [ \t] { printf ("skipped whitespace\n"); } \n { printf ("reached end of line\n"); return 0;} . { printf ("found other data \"%s\"\n", yytext); return yytext[0]; } %% ------------- PLIK 04-calculator.yacc ----------------------------------- %{ #include int yylex(); int yyerror (char *msg); %} %token NAME NUMBER %% statement: NAME '=' expression { printf("pretending to assign %s the value %d\n", $1, $3); } ; | expression { printf("= %d\n", $1); } ; expression: expression '+' NUMBER { $$ = $1 + $3; printf("Recognized '+' expression.\n"); } | expression '-' NUMBER { $$ = $1 - $3; printf("Recognized '-' expression.\n"); } | NUMBER { $$ = $1; printf ("Recognized a number.\n"); } ; %% int main (void) { return yyparse(); } /* Added because panther doesn't have liby.a installed. */ int yyerror (char *msg) { return fprintf (stderr, "YACC: %s\n", msg); } --------- KOMPILACJA: lex calculator.lex yacc -d calculator.yacc cc lex.yy.c y.tab.c -o calculator.x -lfl --------- OPIS: dodaje i odejmuje liczby. ====================================================================== PRZYKŁAD 5 --> pliki: 05-calculator2.lex, 05-calculator2.yacc ====================================================================== ------------- PLIK 05-calculator2.lex ------------------------------------ TAKI SAM JAK 04-calculator.lex ------------- PLIK 05-calculator2.yacc ----------------------------------- %{ #include int yylex(); int yyerror (char *msg); %} %token NAME NUMBER %left '-' '+' %left '*' '/' %nonassoc UMINUS %% statement: NAME '=' expression { printf("pretending to assign %s the value %d\n", $1, $3); } ; | expression { printf("= %d\n", $1); } ; expression: expression '+' expression { $$ = $1 + $3; printf ("Recognized '+' expression.\n"); } | expression '-' expression { $$ = $1 - $3; printf ("Recognized '-' expression.\n"); } | expression '*' expression { $$ = $1 * $3; printf ("Recognized '*' expression.\n"); } | expression '/' expression { if ($3 == 0) yyerror ("divide by zero"); else $$ = $1 / $3; printf ("Recognized '/' expression.\n"); } | '-' expression %prec UMINUS { $$ = - $2; printf ("Recognized negation.\n"); } | '(' expression ')' { $$ = $2; printf ("Recognized parenthesized expression.\n"); } | NUMBER { $$ = $1; printf ("Recognized a number.\n"); } ; %% int main (void) { return yyparse(); } /* Added because panther doesn't have liby.a installed. */ int yyerror (char *msg) { return fprintf (stderr, "YACC: %s\n", msg); } --------- KOMPILACJA: lex calculator2.lex yacc -d calculator2.yacc cc lex.yy.c y.tab.c -o calculator2.x -lfl --------- OPIS: dodaje, odejmuje, mnoży, dzieli liczby, rozpoznaje nawiasy ( ) i liczby ujemne. ====================================================================== ZAD.01. Korzystając z lex'a napisz program zliczający liczbę słów pliku. ZAD.02. Korzystając z lex'a napisz program zliczający liczbę wierszy pliku. ZAD.03. Napisz kalkulator działający w notacji polskiej (typu: 3 3 *).