170 likes | 395 Views
Using the LALR Parser Generator yacc. By J. H. Wang May 10, 2011. Parser Generators. LALR parser generator Yacc “Yet another compiler-compiler”, by S. C. Johnson Available on different platforms UNIX, Linux Other similar packages Bison. To generate the parser:
E N D
Using the LALR Parser Generator yacc By J. H. Wang May 10, 2011
Parser Generators • LALR parser generator Yacc • “Yet another compiler-compiler”, by S. C. Johnson • Available on different platforms • UNIX, Linux • Other similar packages • Bison
To generate the parser: • yacc <file>.ygcc -o <file> y.tab.c -ly
Creating an Input/Output Translator with Yacc Yacc compiler Yacc specification translate.y y.tab.c C compiler y.tab.c a.out a.out Input output
A Yacc source program has three parts • declarations%%translation rules%%supporting C functions • Ex: • EE+T|TTT*F|FF(E)|digit
Token declaration • %token tok1 tok2 … • Parser-controlled semantic stack • $$: LHS • $1, $2, …: RHS
%{#include <ctype.h>%}%token DIGIT%%line : expr ‘\n’ {printf(“%d\n”, $1); } ;expr : expr ‘+’ term { $$=$1+$3; } | term ;term : term ‘*’ factor { $$=$1*$3; } | factor ;factor : ‘(‘ expr ‘)’ { $$ = $2; } | DIGIT ;
%%yylex() { int c; c = getchar(); if (isdigit(c)) { yylval = c-’0’; return DIGIT; } return c;} • { $$ = $1; } is the default semantic action
Using Yacc with Ambiguous Grammars • EE+E|E-E|E*E|E/E|(E)|-E|number • %{#include <ctype.h>#include <stdio.h>#define YYSTYPE double%}%token NUMBER%left ‘+’ –’% left ‘*’ ‘/’% right UMINUS
%%line : lines expr ‘\n’ {printf(“%g\n”, $2); } | lines ‘\n’ | /* empty */ ;expr : expr ‘+’ expr { $$=$1+$3; } |expr ‘-’ expr { $$=$1-$3; } |expr ‘*’ expr { $$=$1*$3; } |expr ‘/’ expr { $$=$1/$3; } | ‘(‘ expr ‘)’ { $$ = $2; } | ‘-’ expr %prec UMINUS { $$ = -$2; } | NUMBER ;
%%yylex() { int c; while ((c = getchar()) == ‘ ‘); if ((c==‘.’)|| (isdigit(c))) { ungetc(c, stdin); scanf(“%lf”, &yylval); return NUMBER; } return c;}
yacc –v: general y.output that contains • Kernels of the set of items • A description of the parsing action conflicts • LR parsing table • yacc resolves all parsing action conflicts using the two rules • A reduce/reduce conflict is resolved by choosing the first production listed • A shift/reduce conflict is resolved in favor of shift
Associativity: %left, %right, %nonassoc • Precedences: according to the order, lowest first • By attaching a precedence and associativity to each production and terminal • To reduce, if the precedence of production is greater, or if the precedences are the same and the associativity of production is left • To shift, otherwise • The precedence of production: the precedence of its rightmost terminal • To force a precedence by: %prec <terminal>
Creating Yacc Lexical Analyzers with Lex • We replace yylex() by #include “lex.yy.c” • lex first.lyacc second.ycc y.tab.c –ly –ll • number [0-9]+\.?|[0-9]*\.[0-9]+%%[ ] { }{number} { sscanf(yytext, “%lf”, &yylval); return NUMBER; }\n|. { return yytext[0]; }
To Use Yacc with Lex • Steps in compilation: • yacc -d <file>.ylex <file>.l gcc -o <file> y.tab.c lex.yy.c -lfl –ly • yacc –d will generate the “y.tab.h” file • This can be included in <file>.l for token definition
Error Recovery in Yacc • Yacc uses a form of error productions • A error • %%line : lines expr ‘\n’ {printf(“%g\n”, $2); } | lines ‘\n’ | /* empty */ | error ‘\n’ {yyerror(“reenter previous line:”); yyerrok; } ; • yyerrok: resets the parser to normal mode of operation