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.y gcc -o y.tab.c -ly
Creating an Input/Output Translator with Yacc Yacc compiler Yacc specification translate.y y.tab.c C compiler y.tab.ca.out Inputoutput
A Yacc source program has three parts –declarations % translation rules % supporting C functions Ex: –E E+T|T T T*F|F F (E)|digit
Token declaration –%token tok1 tok2 … Parser-controlled semantic stack –$$: LHS –$1, $2, …: RHS
%{ #include %} %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 E E+E|E-E|E*E|E/E|(E)|-E|number %{ #include #include #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
Creating Yacc Lexical Analyzers with Lex We replace yylex() by #include “lex.yy.c” lex first.l yacc second.y cc 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.y lex.l gcc -o y.tab.c lex.yy.c -lfl –ly –yacc –d will generate the “y.tab.h” file This can be included in.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
Thanks for Your Attention!