Next: Simple Error Recovery, Previous: Reverse Polish Notation Calculator, Up: Examples [Contents][Index]

`calc`

We now modify rpcalc to handle infix operators instead of
postfix.^{3} Infix
notation involves the concept of operator precedence and the need for
parentheses nested to arbitrary depth. Here is the Bison code for
`calc.y`, an infix desk-top calculator.

/* Infix notation calculator. */

%{ #include <math.h> #include <stdio.h> int yylex (void); void yyerror (char const *); %}

/* Bison declarations. */ %define api.value.type {double} %token NUM %left '-' '+' %left '*' '/' %precedence NEG /* negation--unary minus */ %right '^' /* exponentiation */

%% /* The grammar follows. */

input: %empty | input line ;

line: '\n' | exp '\n' { printf ("\t%.10g\n", $1); } ;

exp: NUM | exp '+' exp { $$ = $1 + $3; } | exp '-' exp { $$ = $1 - $3; } | exp '*' exp { $$ = $1 * $3; } | exp '/' exp { $$ = $1 / $3; } | '-' exp %prec NEG { $$ = -$2; } | exp '^' exp { $$ = pow ($1, $3); } | '(' exp ')' { $$ = $2; } ;

%%

The functions `yylex`

, `yyerror`

and `main`

can be the
same as before.

There are two important new features shown in this code.

In the second section (Bison declarations), `%left`

declares token
kinds and says they are left-associative operators. The declarations
`%left`

and `%right`

(right associativity) take the place of
`%token`

which is used to declare a token kind name without
associativity/precedence. (These tokens are single-character literals,
which ordinarily don’t need to be declared. We declare them here to specify
the associativity/precedence.)

Operator precedence is determined by the line ordering of the
declarations; the higher the line number of the declaration (lower on
the page or screen), the higher the precedence. Hence, exponentiation
has the highest precedence, unary minus (`NEG`

) is next, followed
by ‘`*`’ and ‘`/`’, and so on. Unary minus is not associative,
only precedence matters (`%precedence`

. See Operator Precedence.

The other important new feature is the `%prec`

in the grammar
section for the unary minus operator. The `%prec`

simply instructs
Bison that the rule ‘`| '-' exp`’ has the same precedence as
`NEG`

—in this case the next-to-highest. See Context-Dependent Precedence.

Here is a sample run of `calc.y`:

$calc4 + 4.5 - (34/(8*3+-3))6.880952381-56 + 2-543 ^ 29

A similar example, but using an unambiguous grammar rather
than precedence and associativity annotations, is available as
`examples/c/calc`.