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

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:

   +, -, *, /, %  (mod operator), & (bitwise and),
   | (bitwise or), and assignments.
If an expression at the top level is an assignment, only the assignment is done; otherwise, the expression is printed. As in C, an integer that begins with 0 (zero) is assumed to be octal; otherwise, it is assumed to be decimal.

As an example of a yacc specification, the desk calculator shows 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;
             }
             |   expr ´%´ expr
             {
                    $$ = $1 % $3;
             }
             |   expr ´&´ expr
             {
                   $$ = $1 & $3;
             }
             |   expr ´|´ expr
             {
                   $$ = $1 | $3;
             }
             |  ´-´ expr  %prec UMINUS
             {
                   $$ = -$2;
             }
             |  LETTER
             {
                   $$ = regs[$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); }


Next topic: Advanced example
Previous topic: Examples of using yacc

© 2003 Caldera International, Inc. All rights reserved.
SCO OpenServer Release 5.0.7 -- 11 February 2003