Related articles |
---|
Yacc Learning Example #1 wolff@alpha.ces.cwru.edu (Francis Wolff) (1992-07-17) |
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--------------------------
--
Return to the
comp.compilers page.
Search the
comp.compilers archives again.