calc1.y revision 251143
1234949Sbapt%{ 2234949Sbapt 3234949Sbapt/* http://dinosaur.compilertools.net/yacc/index.html */ 4234949Sbapt 5234949Sbapt#include <stdlib.h> 6234949Sbapt#include <stdio.h> 7234949Sbapt#include <ctype.h> 8234949Sbapt#include <math.h> 9234949Sbapt 10234949Sbapttypedef struct interval 11234949Sbapt{ 12234949Sbapt double lo, hi; 13234949Sbapt} 14234949SbaptINTERVAL; 15234949Sbapt 16234949SbaptINTERVAL vmul(double, double, INTERVAL); 17234949SbaptINTERVAL vdiv(double, double, INTERVAL); 18234949Sbapt 19234949Sbaptextern int yylex(void); 20234949Sbaptstatic void yyerror(const char *s); 21234949Sbapt 22234949Sbaptint dcheck(INTERVAL); 23234949Sbapt 24234949Sbaptdouble dreg[26]; 25234949SbaptINTERVAL vreg[26]; 26234949Sbapt 27234949Sbapt%} 28234949Sbapt%expect 18 29234949Sbapt 30234949Sbapt%start line 31234949Sbapt%union 32234949Sbapt{ 33234949Sbapt int ival; 34234949Sbapt double dval; 35234949Sbapt INTERVAL vval; 36234949Sbapt} 37234949Sbapt 38234949Sbapt%token <ival> DREG VREG /* indices into dreg, vreg arrays */ 39234949Sbapt%token <dval> CONST /* floating point constant */ 40234949Sbapt 41234949Sbapt%type <dval> dexp /* expression */ 42234949Sbapt%type <vval> vexp /* interval expression */ 43234949Sbapt 44234949Sbapt /* precedence information about the operators */ 45234949Sbapt 46234949Sbapt%left '+' '-' 47234949Sbapt%left '*' '/' 48234949Sbapt%left UMINUS /* precedence for unary minus */ 49234949Sbapt 50234949Sbapt%% /* beginning of rules section */ 51234949Sbapt 52234949Sbaptlines : /* empty */ 53234949Sbapt | lines line 54234949Sbapt ; 55234949Sbapt 56234949Sbaptline : dexp '\n' 57234949Sbapt { 58234949Sbapt (void) printf("%15.8f\n", $1); 59234949Sbapt } 60234949Sbapt | vexp '\n' 61234949Sbapt { 62234949Sbapt (void) printf("(%15.8f, %15.8f)\n", $1.lo, $1.hi); 63234949Sbapt } 64234949Sbapt | DREG '=' dexp '\n' 65234949Sbapt { 66234949Sbapt dreg[$1] = $3; 67234949Sbapt } 68234949Sbapt | VREG '=' vexp '\n' 69234949Sbapt { 70234949Sbapt vreg[$1] = $3; 71234949Sbapt } 72234949Sbapt | error '\n' 73234949Sbapt { 74234949Sbapt yyerrok; 75234949Sbapt } 76234949Sbapt ; 77234949Sbapt 78234949Sbaptdexp : CONST 79234949Sbapt | DREG 80234949Sbapt { 81234949Sbapt $$ = dreg[$1]; 82234949Sbapt } 83234949Sbapt | dexp '+' dexp 84234949Sbapt { 85234949Sbapt $$ = $1 + $3; 86234949Sbapt } 87234949Sbapt | dexp '-' dexp 88234949Sbapt { 89234949Sbapt $$ = $1 - $3; 90234949Sbapt } 91234949Sbapt | dexp '*' dexp 92234949Sbapt { 93234949Sbapt $$ = $1 * $3; 94234949Sbapt } 95234949Sbapt | dexp '/' dexp 96234949Sbapt { 97234949Sbapt $$ = $1 / $3; 98234949Sbapt } 99234949Sbapt | '-' dexp %prec UMINUS 100234949Sbapt { 101234949Sbapt $$ = -$2; 102234949Sbapt } 103234949Sbapt | '(' dexp ')' 104234949Sbapt { 105234949Sbapt $$ = $2; 106234949Sbapt } 107234949Sbapt ; 108234949Sbapt 109234949Sbaptvexp : dexp 110234949Sbapt { 111234949Sbapt $$.hi = $$.lo = $1; 112234949Sbapt } 113234949Sbapt | '(' dexp ',' dexp ')' 114234949Sbapt { 115234949Sbapt $$.lo = $2; 116234949Sbapt $$.hi = $4; 117234949Sbapt if ( $$.lo > $$.hi ) 118234949Sbapt { 119234949Sbapt (void) printf("interval out of order\n"); 120234949Sbapt YYERROR; 121234949Sbapt } 122234949Sbapt } 123234949Sbapt | VREG 124234949Sbapt { 125234949Sbapt $$ = vreg[$1]; 126234949Sbapt } 127234949Sbapt | vexp '+' vexp 128234949Sbapt { 129234949Sbapt $$.hi = $1.hi + $3.hi; 130234949Sbapt $$.lo = $1.lo + $3.lo; 131234949Sbapt } 132234949Sbapt | dexp '+' vexp 133234949Sbapt { 134234949Sbapt $$.hi = $1 + $3.hi; 135234949Sbapt $$.lo = $1 + $3.lo; 136234949Sbapt } 137234949Sbapt | vexp '-' vexp 138234949Sbapt { 139234949Sbapt $$.hi = $1.hi - $3.lo; 140234949Sbapt $$.lo = $1.lo - $3.hi; 141234949Sbapt } 142234949Sbapt | dexp '-' vexp 143234949Sbapt { 144234949Sbapt $$.hi = $1 - $3.lo; 145234949Sbapt $$.lo = $1 - $3.hi; 146234949Sbapt } 147234949Sbapt | vexp '*' vexp 148234949Sbapt { 149234949Sbapt $$ = vmul( $1.lo, $1.hi, $3 ); 150234949Sbapt } 151234949Sbapt | dexp '*' vexp 152234949Sbapt { 153234949Sbapt $$ = vmul ($1, $1, $3 ); 154234949Sbapt } 155234949Sbapt | vexp '/' vexp 156234949Sbapt { 157234949Sbapt if (dcheck($3)) YYERROR; 158234949Sbapt $$ = vdiv ( $1.lo, $1.hi, $3 ); 159234949Sbapt } 160234949Sbapt | dexp '/' vexp 161234949Sbapt { 162234949Sbapt if (dcheck ( $3 )) YYERROR; 163234949Sbapt $$ = vdiv ($1, $1, $3 ); 164234949Sbapt } 165234949Sbapt | '-' vexp %prec UMINUS 166234949Sbapt { 167234949Sbapt $$.hi = -$2.lo; 168234949Sbapt $$.lo = -$2.hi; 169234949Sbapt } 170234949Sbapt | '(' vexp ')' 171234949Sbapt { 172234949Sbapt $$ = $2; 173234949Sbapt } 174234949Sbapt ; 175234949Sbapt 176234949Sbapt%% /* beginning of subroutines section */ 177234949Sbapt 178234949Sbapt#define BSZ 50 /* buffer size for floating point numbers */ 179234949Sbapt 180234949Sbapt /* lexical analysis */ 181234949Sbapt 182234949Sbaptstatic void 183234949Sbaptyyerror(const char *s) 184234949Sbapt{ 185234949Sbapt fprintf(stderr, "%s\n", s); 186234949Sbapt} 187234949Sbapt 188234949Sbaptint 189234949Sbaptyylex(void) 190234949Sbapt{ 191234949Sbapt int c; 192234949Sbapt 193234949Sbapt while ((c = getchar()) == ' ') 194234949Sbapt { /* skip over blanks */ 195234949Sbapt } 196234949Sbapt 197234949Sbapt if (isupper(c)) 198234949Sbapt { 199234949Sbapt yylval.ival = c - 'A'; 200234949Sbapt return (VREG); 201234949Sbapt } 202234949Sbapt if (islower(c)) 203234949Sbapt { 204234949Sbapt yylval.ival = c - 'a'; 205234949Sbapt return (DREG); 206234949Sbapt } 207234949Sbapt 208234949Sbapt if (isdigit(c) || c == '.') 209234949Sbapt { 210234949Sbapt /* gobble up digits, points, exponents */ 211234949Sbapt char buf[BSZ + 1], *cp = buf; 212234949Sbapt int dot = 0, expr = 0; 213234949Sbapt 214234949Sbapt for (; (cp - buf) < BSZ; ++cp, c = getchar()) 215234949Sbapt { 216234949Sbapt 217251143Sbapt *cp = (char) c; 218234949Sbapt if (isdigit(c)) 219234949Sbapt continue; 220234949Sbapt if (c == '.') 221234949Sbapt { 222234949Sbapt if (dot++ || expr) 223234949Sbapt return ('.'); /* will cause syntax error */ 224234949Sbapt continue; 225234949Sbapt } 226234949Sbapt 227234949Sbapt if (c == 'e') 228234949Sbapt { 229234949Sbapt if (expr++) 230234949Sbapt return ('e'); /* will cause syntax error */ 231234949Sbapt continue; 232234949Sbapt } 233234949Sbapt 234234949Sbapt /* end of number */ 235234949Sbapt break; 236234949Sbapt } 237234949Sbapt *cp = '\0'; 238234949Sbapt 239234949Sbapt if ((cp - buf) >= BSZ) 240234949Sbapt printf("constant too long: truncated\n"); 241234949Sbapt else 242234949Sbapt ungetc(c, stdin); /* push back last char read */ 243234949Sbapt yylval.dval = atof(buf); 244234949Sbapt return (CONST); 245234949Sbapt } 246234949Sbapt return (c); 247234949Sbapt} 248234949Sbapt 249234949Sbaptstatic INTERVAL 250234949Sbapthilo(double a, double b, double c, double d) 251234949Sbapt{ 252234949Sbapt /* returns the smallest interval containing a, b, c, and d */ 253234949Sbapt /* used by *, / routines */ 254234949Sbapt INTERVAL v; 255234949Sbapt 256234949Sbapt if (a > b) 257234949Sbapt { 258234949Sbapt v.hi = a; 259234949Sbapt v.lo = b; 260234949Sbapt } 261234949Sbapt else 262234949Sbapt { 263234949Sbapt v.hi = b; 264234949Sbapt v.lo = a; 265234949Sbapt } 266234949Sbapt 267234949Sbapt if (c > d) 268234949Sbapt { 269234949Sbapt if (c > v.hi) 270234949Sbapt v.hi = c; 271234949Sbapt if (d < v.lo) 272234949Sbapt v.lo = d; 273234949Sbapt } 274234949Sbapt else 275234949Sbapt { 276234949Sbapt if (d > v.hi) 277234949Sbapt v.hi = d; 278234949Sbapt if (c < v.lo) 279234949Sbapt v.lo = c; 280234949Sbapt } 281234949Sbapt return (v); 282234949Sbapt} 283234949Sbapt 284234949SbaptINTERVAL 285234949Sbaptvmul(double a, double b, INTERVAL v) 286234949Sbapt{ 287234949Sbapt return (hilo(a * v.hi, a * v.lo, b * v.hi, b * v.lo)); 288234949Sbapt} 289234949Sbapt 290234949Sbaptint 291234949Sbaptdcheck(INTERVAL v) 292234949Sbapt{ 293234949Sbapt if (v.hi >= 0. && v.lo <= 0.) 294234949Sbapt { 295234949Sbapt printf("divisor interval contains 0.\n"); 296234949Sbapt return (1); 297234949Sbapt } 298234949Sbapt return (0); 299234949Sbapt} 300234949Sbapt 301234949SbaptINTERVAL 302234949Sbaptvdiv(double a, double b, INTERVAL v) 303234949Sbapt{ 304234949Sbapt return (hilo(a / v.hi, a / v.lo, b / v.hi, b / v.lo)); 305234949Sbapt} 306