btyacc_calc1.y revision 264790
1264790Sbapt%PURE_PARSER 2264790Sbapt%{ 3264790Sbapt 4264790Sbapt/* http://dinosaur.compilertools.net/yacc/index.html */ 5264790Sbapt 6264790Sbapt#include <stdlib.h> 7264790Sbapt#include <stdio.h> 8264790Sbapt#include <ctype.h> 9264790Sbapt#include <math.h> 10264790Sbapt 11264790Sbapttypedef struct interval 12264790Sbapt{ 13264790Sbapt double lo, hi; 14264790Sbapt} 15264790SbaptINTERVAL; 16264790Sbapt 17264790SbaptINTERVAL vmul(double, double, INTERVAL); 18264790SbaptINTERVAL vdiv(double, double, INTERVAL); 19264790Sbapt 20264790Sbaptint dcheck(INTERVAL); 21264790Sbapt 22264790Sbaptdouble dreg[26]; 23264790SbaptINTERVAL vreg[26]; 24264790Sbapt 25264790Sbapt%} 26264790Sbapt%expect 17 27264790Sbapt 28264790Sbapt%start lines 29264790Sbapt%union 30264790Sbapt{ 31264790Sbapt int ival; 32264790Sbapt double dval; 33264790Sbapt INTERVAL vval; 34264790Sbapt} 35264790Sbapt 36264790Sbapt%token <ival> DREG VREG /* indices into dreg, vreg arrays */ 37264790Sbapt%token <dval> CONST /* floating point constant */ 38264790Sbapt 39264790Sbapt%type <dval> dexp /* expression */ 40264790Sbapt%type <vval> vexp /* interval expression */ 41264790Sbapt 42264790Sbapt /* precedence information about the operators */ 43264790Sbapt 44264790Sbapt%left '+' '-' 45264790Sbapt%left '*' '/' 46264790Sbapt%right UMINUS /* precedence for unary minus */ 47264790Sbapt 48264790Sbapt%% /* beginning of rules section */ 49264790Sbapt 50264790Sbaptlines : /* empty */ 51264790Sbapt | lines line '\n' [YYVALID;] 52264790Sbapt | lines error '\n' [YYVALID;] 53264790Sbapt { 54264790Sbapt yyerrok; 55264790Sbapt } 56264790Sbapt ; 57264790Sbapt 58264790Sbaptline : dexp 59264790Sbapt { 60264790Sbapt (void) printf("%15.8f\n", $1); 61264790Sbapt } 62264790Sbapt | vexp 63264790Sbapt { 64264790Sbapt (void) printf("(%15.8f, %15.8f)\n", $1.lo, $1.hi); 65264790Sbapt } 66264790Sbapt | DREG '=' dexp 67264790Sbapt { 68264790Sbapt dreg[$1] = $3; 69264790Sbapt } 70264790Sbapt | VREG '=' vexp 71264790Sbapt { 72264790Sbapt vreg[$1] = $3; 73264790Sbapt } 74264790Sbapt ; 75264790Sbapt 76264790Sbaptdexp : CONST 77264790Sbapt | DREG 78264790Sbapt { 79264790Sbapt $$ = dreg[$1]; 80264790Sbapt } 81264790Sbapt | dexp '+' dexp 82264790Sbapt { 83264790Sbapt $$ = $1 + $3; 84264790Sbapt } 85264790Sbapt | dexp '-' dexp 86264790Sbapt { 87264790Sbapt $$ = $1 - $3; 88264790Sbapt } 89264790Sbapt | dexp '*' dexp 90264790Sbapt { 91264790Sbapt $$ = $1 * $3; 92264790Sbapt } 93264790Sbapt | dexp '/' dexp 94264790Sbapt { 95264790Sbapt $$ = $1 / $3; 96264790Sbapt } 97264790Sbapt | '-' dexp %prec UMINUS 98264790Sbapt { 99264790Sbapt $$ = -$2; 100264790Sbapt } 101264790Sbapt | '(' dexp ')' 102264790Sbapt { 103264790Sbapt $$ = $2; 104264790Sbapt } 105264790Sbapt ; 106264790Sbapt 107264790Sbaptvexp : dexp 108264790Sbapt { 109264790Sbapt $$.hi = $$.lo = $1; 110264790Sbapt } 111264790Sbapt | '(' dexp ',' dexp ')' 112264790Sbapt { 113264790Sbapt $$.lo = $2; 114264790Sbapt $$.hi = $4; 115264790Sbapt if ( $$.lo > $$.hi ) 116264790Sbapt { 117264790Sbapt (void) printf("interval out of order\n"); 118264790Sbapt YYERROR; 119264790Sbapt } 120264790Sbapt } 121264790Sbapt | VREG 122264790Sbapt { 123264790Sbapt $$ = vreg[$1]; 124264790Sbapt } 125264790Sbapt | vexp '+' vexp 126264790Sbapt { 127264790Sbapt $$.hi = $1.hi + $3.hi; 128264790Sbapt $$.lo = $1.lo + $3.lo; 129264790Sbapt } 130264790Sbapt | dexp '+' vexp 131264790Sbapt { 132264790Sbapt $$.hi = $1 + $3.hi; 133264790Sbapt $$.lo = $1 + $3.lo; 134264790Sbapt } 135264790Sbapt | vexp '-' vexp 136264790Sbapt { 137264790Sbapt $$.hi = $1.hi - $3.lo; 138264790Sbapt $$.lo = $1.lo - $3.hi; 139264790Sbapt } 140264790Sbapt | dexp '-' vexp 141264790Sbapt { 142264790Sbapt $$.hi = $1 - $3.lo; 143264790Sbapt $$.lo = $1 - $3.hi; 144264790Sbapt } 145264790Sbapt | vexp '*' vexp 146264790Sbapt { 147264790Sbapt $$ = vmul( $1.lo, $1.hi, $3 ); 148264790Sbapt } 149264790Sbapt | dexp '*' vexp 150264790Sbapt { 151264790Sbapt $$ = vmul ($1, $1, $3 ); 152264790Sbapt } 153264790Sbapt | vexp '/' vexp 154264790Sbapt { 155264790Sbapt if (dcheck($3)) YYERROR; 156264790Sbapt $$ = vdiv ( $1.lo, $1.hi, $3 ); 157264790Sbapt } 158264790Sbapt | dexp '/' vexp 159264790Sbapt { 160264790Sbapt if (dcheck ( $3 )) YYERROR; 161264790Sbapt $$ = vdiv ($1, $1, $3 ); 162264790Sbapt } 163264790Sbapt | '-' vexp %prec UMINUS 164264790Sbapt { 165264790Sbapt $$.hi = -$2.lo; 166264790Sbapt $$.lo = -$2.hi; 167264790Sbapt } 168264790Sbapt | '(' vexp ')' 169264790Sbapt { 170264790Sbapt $$ = $2; 171264790Sbapt } 172264790Sbapt ; 173264790Sbapt 174264790Sbapt%% /* beginning of subroutines section */ 175264790Sbapt 176264790Sbaptint 177264790Sbaptmain (void) 178264790Sbapt{ 179264790Sbapt while(!feof(stdin)) { 180264790Sbapt yyparse(); 181264790Sbapt } 182264790Sbapt return 0; 183264790Sbapt} 184264790Sbapt 185264790Sbapt#define BSZ 50 /* buffer size for floating point numbers */ 186264790Sbapt 187264790Sbaptstatic void 188264790SbaptYYERROR_DECL() 189264790Sbapt{ 190264790Sbapt fprintf(stderr, "%s\n", s); 191264790Sbapt} 192264790Sbapt 193264790Sbapt /* lexical analysis */ 194264790Sbapt 195264790Sbaptstatic int 196264790SbaptYYLEX_DECL() 197264790Sbapt{ 198264790Sbapt int c; 199264790Sbapt 200264790Sbapt while ((c = getchar()) == ' ') 201264790Sbapt { /* skip over blanks */ 202264790Sbapt } 203264790Sbapt 204264790Sbapt if (isupper(c)) 205264790Sbapt { 206264790Sbapt#if YYPURE 207264790Sbapt (*yylval).ival = c - 'A'; 208264790Sbapt#else 209264790Sbapt yylval.ival = c - 'A'; 210264790Sbapt#endif 211264790Sbapt return (VREG); 212264790Sbapt } 213264790Sbapt if (islower(c)) 214264790Sbapt { 215264790Sbapt#if YYPURE 216264790Sbapt (*yylval).ival = c - 'a'; 217264790Sbapt#else 218264790Sbapt yylval.ival = c - 'a'; 219264790Sbapt#endif 220264790Sbapt return (DREG); 221264790Sbapt } 222264790Sbapt 223264790Sbapt if (isdigit(c) || c == '.') 224264790Sbapt { 225264790Sbapt /* gobble up digits, points, exponents */ 226264790Sbapt char buf[BSZ + 1], *cp = buf; 227264790Sbapt int dot = 0, expr = 0; 228264790Sbapt 229264790Sbapt for (; (cp - buf) < BSZ; ++cp, c = getchar()) 230264790Sbapt { 231264790Sbapt 232264790Sbapt *cp = (char) c; 233264790Sbapt if (isdigit(c)) 234264790Sbapt continue; 235264790Sbapt if (c == '.') 236264790Sbapt { 237264790Sbapt if (dot++ || expr) 238264790Sbapt return ('.'); /* will cause syntax error */ 239264790Sbapt continue; 240264790Sbapt } 241264790Sbapt 242264790Sbapt if (c == 'e') 243264790Sbapt { 244264790Sbapt if (expr++) 245264790Sbapt return ('e'); /* will cause syntax error */ 246264790Sbapt continue; 247264790Sbapt } 248264790Sbapt 249264790Sbapt /* end of number */ 250264790Sbapt break; 251264790Sbapt } 252264790Sbapt *cp = '\0'; 253264790Sbapt 254264790Sbapt if ((cp - buf) >= BSZ) 255264790Sbapt printf("constant too long: truncated\n"); 256264790Sbapt else 257264790Sbapt ungetc(c, stdin); /* push back last char read */ 258264790Sbapt#if YYPURE 259264790Sbapt (*yylval).dval = atof(buf); 260264790Sbapt#else 261264790Sbapt yylval.dval = atof(buf); 262264790Sbapt#endif 263264790Sbapt return (CONST); 264264790Sbapt } 265264790Sbapt return (c); 266264790Sbapt} 267264790Sbapt 268264790Sbaptstatic INTERVAL 269264790Sbapthilo(double a, double b, double c, double d) 270264790Sbapt{ 271264790Sbapt /* returns the smallest interval containing a, b, c, and d */ 272264790Sbapt /* used by *, / routines */ 273264790Sbapt INTERVAL v; 274264790Sbapt 275264790Sbapt if (a > b) 276264790Sbapt { 277264790Sbapt v.hi = a; 278264790Sbapt v.lo = b; 279264790Sbapt } 280264790Sbapt else 281264790Sbapt { 282264790Sbapt v.hi = b; 283264790Sbapt v.lo = a; 284264790Sbapt } 285264790Sbapt 286264790Sbapt if (c > d) 287264790Sbapt { 288264790Sbapt if (c > v.hi) 289264790Sbapt v.hi = c; 290264790Sbapt if (d < v.lo) 291264790Sbapt v.lo = d; 292264790Sbapt } 293264790Sbapt else 294264790Sbapt { 295264790Sbapt if (d > v.hi) 296264790Sbapt v.hi = d; 297264790Sbapt if (c < v.lo) 298264790Sbapt v.lo = c; 299264790Sbapt } 300264790Sbapt return (v); 301264790Sbapt} 302264790Sbapt 303264790SbaptINTERVAL 304264790Sbaptvmul(double a, double b, INTERVAL v) 305264790Sbapt{ 306264790Sbapt return (hilo(a * v.hi, a * v.lo, b * v.hi, b * v.lo)); 307264790Sbapt} 308264790Sbapt 309264790Sbaptint 310264790Sbaptdcheck(INTERVAL v) 311264790Sbapt{ 312264790Sbapt if (v.hi >= 0. && v.lo <= 0.) 313264790Sbapt { 314264790Sbapt printf("divisor interval contains 0.\n"); 315264790Sbapt return (1); 316264790Sbapt } 317264790Sbapt return (0); 318264790Sbapt} 319264790Sbapt 320264790SbaptINTERVAL 321264790Sbaptvdiv(double a, double b, INTERVAL v) 322264790Sbapt{ 323264790Sbapt return (hilo(a / v.hi, a / v.lo, b / v.hi, b / v.lo)); 324264790Sbapt} 325