# Yacc Practice, Part II

In this section we will extend the calculator from the previous section to incorporate some new functionality. New features include arithmetic operators multiply and divide. Parentheses may be used to over-ride operator precedence, and single-character variables may be specified in assignment statements. The following illustrates sample input and calculator output:

```user:  3 * (4 + 5)
calc:  27
user:  x = 3 * (4 + 5)
user:  y = 5
user:  x
calc:  27
user:  y
calc:  5
user:  x + 2*y
calc:  37
```

The lexical analyzer returns `VARIABLE` and `INTEGER` tokens. For variables `yylval` specifies an index to the symbol table `sym`. For this program `sym` merely holds the value of the associated variable. When `INTEGER` tokens are returned, `yylval` contains the number scanned. Here is the input specification for lex:

```%{
#include <stdlib.h>
#include "y.tab.h"
void yyerror(char *);
%}

%%

/* variables */
[a-z]       {
yylval = *yytext - 'a';
return VARIABLE;
}

/* integers */
[0-9]+      {
yylval = atoi(yytext);
return INTEGER;
}

/* operators */
[-+()=/*\n] { return *yytext; }

/* skip whitespace */
[ \t]        ;

/* anything else is an error */
.               yyerror("invalid character");

%%

int yywrap(void) {
return 1;
}
```

The input specification for yacc follows. The tokens for `INTEGER` and `VARIABLE` are utilized by yacc to create `#defines` in `y.tab.h` for use in lex. This is followed by definitions for the arithmetic operators. We may specify `%left`, for left-associative or `%right` for right associative. The last definition listed has the highest precedence. Consequently multiplication and division have higher precedence than addition and subtraction. All four operators are left-associative. Using this simple technique we are able to disambiguate our grammar.

```%token INTEGER VARIABLE
%left '+' '-'
%left '*' '/'

%{
void yyerror(char *);
int yylex(void);
int sym;
%}

%%

program:
program statement '\n'
|
;

statement:
expr                      { printf("%d\n", \$1); }
| VARIABLE '=' expr       { sym[\$1] = \$3; }
;

expr:
INTEGER
| VARIABLE                { \$\$ = sym[\$1]; }
| expr '+' expr           { \$\$ = \$1 + \$3; }
| expr '-' expr           { \$\$ = \$1 - \$3; }
| expr '*' expr           { \$\$ = \$1 * \$3; }
| expr '/' expr           { \$\$ = \$1 / \$3; }
| '(' expr ')'            { \$\$ = \$2; }
;

%%

void yyerror(char *s) {
fprintf(stderr, "%s\n", s);
}

int main(void) {
yyparse();
return 0;
}
```