home *** CD-ROM | disk | FTP | other *** search
- .SH
- Appendix A: A Simple Example
- .PP
- This example gives the complete Yacc specification for a small desk calculator;
- the desk calculator has 26 registers, labeled ``a'' through ``z'', and accepts
- arithmetic expressions made up of the operators +, \-, *, /,
- % (mod operator), & (bitwise and), | (bitwise or), and assignment.
- If an expression at the top level is an assignment, the value is not
- printed; otherwise it is.
- As in C, an integer that begins with 0 (zero) is assumed to be octal;
- otherwise, it is assumed to be decimal.
- .PP
- As an example of a Yacc specification, the desk calculator
- does a reasonable job of showing how precedences and ambiguities
- are used, and demonstrating simple error recovery.
- The major oversimplifications are that the
- lexical analysis phase is much simpler than for most applications, and the
- output is produced immediately, line by line.
- Note the way that decimal and octal integers are read in by the grammar rules;
- This job is probably better done by the lexical analyzer.
- .sp
- .nf
- .ta .5i 1i 1.5i 2i 2.5i
-
- %{
- # include <stdio.h>
- # include <ctype.h>
-
- int regs[26];
- int base;
-
- %}
-
- %start list
-
- %token DIGIT LETTER
-
- %left \'|\'
- %left \'&\'
- %left \'+\' \'\-\'
- %left \'*\' \'/\' \'%\'
- %left UMINUS /* supplies precedence for unary minus */
-
- %% /* beginning of rules section */
-
- list : /* empty */
- | list stat \'\en\'
- | list error \'\en\'
- { yyerrok; }
- ;
-
- stat : expr
- { printf( "%d\en", $1 ); }
- | LETTER \'=\' expr
- { regs[$1] = $3; }
- ;
-
- expr : \'(\' expr \')\'
- { $$ = $2; }
- | expr \'+\' expr
- { $$ = $1 + $3; }
- | expr \'\-\' expr
- { $$ = $1 \- $3; }
- | expr \'*\' expr
- { $$ = $1 * $3; }
- | expr \'/\' expr
- { $$ = $1 / $3; }
- | expr \'%\' expr
- { $$ = $1 % $3; }
- | expr \'&\' expr
- { $$ = $1 & $3; }
- | expr \'|\' expr
- { $$ = $1 | $3; }
- | \'\-\' expr %prec UMINUS
- { $$ = \- $2; }
- | LETTER
- { $$ = regs[$1]; }
- | number
- ;
-
- number : DIGIT
- { $$ = $1; base = ($1==0) ? 8 : 10; }
- | number DIGIT
- { $$ = base * $1 + $2; }
- ;
-
- %% /* start of programs */
-
- yylex() { /* 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 );
- }
- .fi
- .bp
-