|
|
1.1 ! root 1: .\" @(#)ssa 6.1 (Berkeley) 5/8/86 ! 2: .\" ! 3: .SH ! 4: Appendix A: A Simple Example ! 5: .PP ! 6: This example gives the complete Yacc specification for a small desk calculator; ! 7: the desk calculator has 26 registers, labeled ``a'' through ``z'', and accepts ! 8: arithmetic expressions made up of the operators +, \-, *, /, ! 9: % (mod operator), & (bitwise and), | (bitwise or), and assignment. ! 10: If an expression at the top level is an assignment, the value is not ! 11: printed; otherwise it is. ! 12: As in C, an integer that begins with 0 (zero) is assumed to be octal; ! 13: otherwise, it is assumed to be decimal. ! 14: .PP ! 15: As an example of a Yacc specification, the desk calculator ! 16: does a reasonable job of showing how precedences and ambiguities ! 17: are used, and demonstrating simple error recovery. ! 18: The major oversimplifications are that the ! 19: lexical analysis phase is much simpler than for most applications, and the ! 20: output is produced immediately, line by line. ! 21: Note the way that decimal and octal integers are read in by the grammar rules; ! 22: This job is probably better done by the lexical analyzer. ! 23: .sp ! 24: .nf ! 25: .ta .5i 1i 1.5i 2i 2.5i ! 26: ! 27: %{ ! 28: # include <stdio.h> ! 29: # include <ctype.h> ! 30: ! 31: int regs[26]; ! 32: int base; ! 33: ! 34: %} ! 35: ! 36: %start list ! 37: ! 38: %token DIGIT LETTER ! 39: ! 40: %left \'|\' ! 41: %left \'&\' ! 42: %left \'+\' \'\-\' ! 43: %left \'*\' \'/\' \'%\' ! 44: %left UMINUS /* supplies precedence for unary minus */ ! 45: ! 46: %% /* beginning of rules section */ ! 47: ! 48: list : /* empty */ ! 49: | list stat \'\en\' ! 50: | list error \'\en\' ! 51: { yyerrok; } ! 52: ; ! 53: ! 54: stat : expr ! 55: { printf( "%d\en", $1 ); } ! 56: | LETTER \'=\' expr ! 57: { regs[$1] = $3; } ! 58: ; ! 59: ! 60: expr : \'(\' expr \')\' ! 61: { $$ = $2; } ! 62: | expr \'+\' expr ! 63: { $$ = $1 + $3; } ! 64: | expr \'\-\' expr ! 65: { $$ = $1 \- $3; } ! 66: | expr \'*\' expr ! 67: { $$ = $1 * $3; } ! 68: | expr \'/\' expr ! 69: { $$ = $1 / $3; } ! 70: | expr \'%\' expr ! 71: { $$ = $1 % $3; } ! 72: | expr \'&\' expr ! 73: { $$ = $1 & $3; } ! 74: | expr \'|\' expr ! 75: { $$ = $1 | $3; } ! 76: | \'\-\' expr %prec UMINUS ! 77: { $$ = \- $2; } ! 78: | LETTER ! 79: { $$ = regs[$1]; } ! 80: | number ! 81: ; ! 82: ! 83: number : DIGIT ! 84: { $$ = $1; base = ($1==0) ? 8 : 10; } ! 85: | number DIGIT ! 86: { $$ = base * $1 + $2; } ! 87: ; ! 88: ! 89: %% /* start of programs */ ! 90: ! 91: yylex() { /* lexical analysis routine */ ! 92: /* returns LETTER for a lower case letter, yylval = 0 through 25 */ ! 93: /* return DIGIT for a digit, yylval = 0 through 9 */ ! 94: /* all other characters are returned immediately */ ! 95: ! 96: int c; ! 97: ! 98: while( (c=getchar()) == \' \' ) { /* skip blanks */ } ! 99: ! 100: /* c is now nonblank */ ! 101: ! 102: if( islower( c ) ) { ! 103: yylval = c \- \'a\'; ! 104: return ( LETTER ); ! 105: } ! 106: if( isdigit( c ) ) { ! 107: yylval = c \- \'0\'; ! 108: return( DIGIT ); ! 109: } ! 110: return( c ); ! 111: } ! 112: .fi ! 113: .bp
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.