Yacc Learning Example #1

Francis Wolff <wolff@alpha.ces.cwru.edu>
Fri, 17 Jul 1992 05:45:07 GMT

          From comp.compilers

Related articles
Yacc Learning Example #1 wolff@alpha.ces.cwru.edu (Francis Wolff) (1992-07-17)
| List of all articles for this month |

Newsgroups: comp.compilers
From: Francis Wolff <wolff@alpha.ces.cwru.edu>
Organization: Compilers Central
Date: Fri, 17 Jul 1992 05:45:07 GMT
Keywords: yacc, code

I have had requests for some examples on yacc and I made some up
with the purpose of learning yacc and grammars. All one needs is
a yacc and c compiler (no lex is needed).


BEGIN----------------------CUT HERE--------------------------
%{
/*------------------------------------------------------------------*/
/* Learning (or bootstrapping) Example #1: Using yacc without lex */
/* File: calc1.yac */
/* Date: July 16, 1992 */
/* From: Frank Wolff (wolff@alpha.ces.cwru.edu) */
/* */
/* This is a simple calculator which avoids the use of any lex */
/* At this time, I don't know how much much faster lex will */
/* improve this program in terms of speed/storage performance. */
/*------------------------------------------------------------------*/
/* Simple calculator with precedence: multiply is higher than add */
/* WARNING: no blanks between integers and operaters, see example 2 */
/* */
/* To make this for Unix Systems: */
/* yacc calc.yac */
/* cc y.tab.c -o calc */
/* calc */
/* To make this for PC Systems (Borland Turbo C) */
/* yacc calc.yac */
/* tcc ytab.c */
/* ytab */
/* Some sample input: */
/* 1+2*3 {stdin: input, result=6 not 9} */
/* (1+2)*3 {result=9} */
/* 2^3^2 {result=512 not 64 } */
/* (2^3)^2 {result=64} */
/* 2^(3^2) {result=512} */
/* q {quit} */
/* */
/* WARNING: Every time you change your grammar file (*.yac) */
/* DON'T FORGET TO RUN YACC AGAIN!!! RECOMPILING YTAB.C */
/* STILL CONTAINS THE OLD GRAMMAR and code !!! */
/*------------------------------------------------------------------*/
/* Some Grammar Terminology */
/* */
/* Left recursion: 1+2+3 is the same as (1+2)+3 */
/* */
/* Right recursion (also commonly called tail recursion): */
/* is useful in the x to the y power: 4^3^2 is the same as 4^(3^2) */
/* which should not be confused with (4^3)^2. */
/* */
/* Precedence, where the associativity is higher for one operator */
/* than another: 1+2*3 is the same as 1+(2*3) not (1+2)*3. */
/* Precedence has priority over the left recursion of the add op. */
/* The precedence from highest to lowest is: () ^ /* +- */
/*------------------------------------------------------------------*/
#include <stdio.h>


#define yyerror(X) printf(X)
int number;


int power(int x, int y) { /* return x to the power y */
    int z=1, p=x, signf;


    if (y<0) { signf=1; y=-y; } else { signf=0; }
    for(;;) {
        if (y & 1) { z = z * p; }
        y=y>>1; if (y==0) { break; }
        p=p*p; /* keep p*p here to minimize overflows: */
                      /* when using float for the last case */
    }
    if (signf) { z=1/z; }
    return z;
}
int yylex() { return getchar(); }
%}


%%
prog : stmt prog | stmt;


stmt : expr '\n' { printf("result=%d\n", $$); }
                  | 'q' { exit(0); }
                  ;


expr : expr '+' term { $$=$1 + $3; } /* This is called left recursion */
                  | expr '-' term { $$=$1 - $3; }
                  | term /* by default { $$=$1; } */
                  ;


term : term '*' factor { $$=$1 * $3; }
                  | term '/' factor { $$=$1 / $3; }
                  | factor /* by default { $$=$1; } */
                  ;


factor : primary '^' factor { $$=power($1,$3); } /* right recursion */
                                                                                                      /* or tail recursion */
                  | primary
                  ;


primary : '(' expr ')' { $$=$2; } /* This is called recursion */
                  | integer { $$=number; }
                  ;


integer : digit { number=$1-'0'; } integer1;


integer1 : digit { number=number*10 + ($1-'0'); } integer1
                  | /* null entry */
                  ;


digit : '0' {$$='0';} | '1' {$$='1';} | '2' {$$='2';} | '3' {$$='3';}
                  | '4' {$$='4';} | '5' {$$='5';} | '6' {$$='6';} | '7' {$$='7';}
                  | '8' {$$='8';} | '9' {$$='9';}
                  ;


%%
void main(int argc, char *argv[]) {
        yyparse();
}


END------------------------CUT HERE--------------------------
--


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.