|
|
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.