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