DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
Parsing with yacc

# A simple example

This example gives the complete yacc applications for a small desk calculator; the calculator has 26 registers labeled a through z and accepts arithmetic expressions made up of the operators +, -, *, /, %,&, |, and the assignment operators.

If an expression at the top level is an assignment, only the assignment is done; otherwise, the expression is printed. As in the C language, an integer that begins with 0 is assumed to be octal; otherwise, it is assumed to be decimal.

As an example of a yacc specification, the desk calculator does a reasonable job of showing how precedence and ambiguities are used and demonstrates simple recovery. The major oversimplifications are that the lexical analyzer 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 grammar rules. This job is probably better done by the lexical analyzer.

```   %{
# 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 '\n'
|  list error '\n'
{
yyerrok;
}
;

stat      :  expr
{
(void) printf( "%d\n", \$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;
}
|   exp '%' expr
{
\$\$ = \$1 % \$3;
}
|   expr '&' expr
{
\$\$ = \$1 & \$3;
}
|   expr '|' expr
{
\$\$ = \$1 | \$3;
}
|  '-' expr  %prec UMINUS
{
\$\$ = -\$2;
}
|  LETTER
{
\$\$ = reg[\$1];
}
|  number
;

number    :   DIGIT
{
\$\$ = \$1; base = (\$1==0) ? 8 ; 10;
}
|   number DIGIT
{
\$\$ = base  \$1 + \$2;
}
;

%% 		/ beginning of subroutines section /

int yylex( )   / lexical analysis routine /
{              / return LETTER for lowercase letter, /
/ yylval = 0 through 25 /
/ returns DIGIT for digit, yylval = 0 through 9 /
/ all other characters are returned immediately /
int c;
/skip blanks/
while ((c = getchar()) == ' ')
;

/ c is now nonblank /

if (islower(c))
{
yylval = c - 'a';
return (LETTER);
}
if (isdigit(c))
}
yylval = c - '0';
return (DIGIT);

}
return (c);
}
```