Professional Documents
Culture Documents
Yacc Example
"Yet Another Compiler Compiler"
Kanat Bolazar
Lex creates programs that scan your tokens one by one. Yacc takes a grammar (sentence structure) and generates a parser.
Lexical Rules Lex Input yylex() Grammar Rules Yacc yyparse() Parsed Input 2
Grammar Rules
C code
Lex
Input
char stream
yylex()
C code
Lexical Analyzer (Tokenizer)
token stream
yyparse()
C code Parser
Byacc is Berkeley implementation of Yacc (so it is Yacc). Resources: http://en.wikipedia.org/wiki/Flex_lexical_analyser http://en.wikipedia.org/wiki/GNU_Bison The Lex & Yacc Page (manuals, links): http://dinosaur.compilertools.net/ 4
A standard Yacc example is the int-valued calculator. Appendix A of Yacc manual at Lex and Yacc Page shows such a calculator. We'll examine this example in parts. Let's start with four operations:
E -> E + E |EE |E*E |E/E
Note that this grammar is ambiguous because 2 + 5 * 7 could be parsed 2 + 5 first or 5 * 7 first. 6
Directly included C code list is our start symbol; a list of one-line statements / expressions. DIGIT & LETTER are tokens; (other tokens use ASCII codes, as in '+', '=', etc)
%start list
/*
Precedence and associativity (left) of precedence for unary minus */ operators: +, - have lowest precedence 7 *, / have higher precedence
list: a list of one-line statements / expressions. Error handling allows a statement to be corrupt, but list continues with next statement. statement: expression to calculate, or assignment
number: made up of digits (tokenizer should handle this, but this is a simple example).
number: DIGIT { $$ = $1; base = ($1==0) ? 8 : 10; } | number DIGIT { $$ = base * $1 + $2; } ;
/* lexical analysis routine */ /* returns LETTER for a lower case letter, yylval = 0 through 25 */ /* return DIGIT for a digit, yylval = 0 through 9 */ /* all other characters are returned immediately */
int c; while( (c=getchar()) == ' ' ) {/* skip blanks */ } /* c is now nonblank */ if( islower( c ) ) { yylval = c - 'a'; return ( LETTER ); } if( isdigit( c ) ) { yylval = c - '0'; return( DIGIT ); } return( c ); }
10