1*0c8de5b0SBaptiste Daroussin %IDENT "check variant syntax features" 2*0c8de5b0SBaptiste Daroussin %{ 3*0c8de5b0SBaptiste Daroussin 4*0c8de5b0SBaptiste Daroussin // http://dinosaur.compilertools.net/yacc/index.html */ 5*0c8de5b0SBaptiste Daroussin 6*0c8de5b0SBaptiste Daroussin #include <stdlib.h> 7*0c8de5b0SBaptiste Daroussin #include <stdio.h> 8*0c8de5b0SBaptiste Daroussin #include <ctype.h> 9*0c8de5b0SBaptiste Daroussin #include <math.h> 10*0c8de5b0SBaptiste Daroussin 11*0c8de5b0SBaptiste Daroussin typedef struct interval 12*0c8de5b0SBaptiste Daroussin { 13*0c8de5b0SBaptiste Daroussin double lo, hi; 14*0c8de5b0SBaptiste Daroussin } 15*0c8de5b0SBaptiste Daroussin INTERVAL; 16*0c8de5b0SBaptiste Daroussin 17*0c8de5b0SBaptiste Daroussin INTERVAL vmul(double, double, INTERVAL); 18*0c8de5b0SBaptiste Daroussin INTERVAL vdiv(double, double, INTERVAL); 19*0c8de5b0SBaptiste Daroussin 20*0c8de5b0SBaptiste Daroussin extern int yylex(void); 21*0c8de5b0SBaptiste Daroussin static void yyerror(const char *s); 22*0c8de5b0SBaptiste Daroussin 23*0c8de5b0SBaptiste Daroussin int dcheck(INTERVAL); 24*0c8de5b0SBaptiste Daroussin 25*0c8de5b0SBaptiste Daroussin double dreg[26]; 26*0c8de5b0SBaptiste Daroussin INTERVAL vreg[26]; 27*0c8de5b0SBaptiste Daroussin 28*0c8de5b0SBaptiste Daroussin %} 29*0c8de5b0SBaptiste Daroussin %expect 18 30*0c8de5b0SBaptiste Daroussin 31*0c8de5b0SBaptiste Daroussin %start line 32*0c8de5b0SBaptiste Daroussin %union 33*0c8de5b0SBaptiste Daroussin { 34*0c8de5b0SBaptiste Daroussin int ival; // dreg & vreg array index values 35*0c8de5b0SBaptiste Daroussin double dval; // floating point values 36*0c8de5b0SBaptiste Daroussin INTERVAL vval; // interval values 37*0c8de5b0SBaptiste Daroussin } 38*0c8de5b0SBaptiste Daroussin 39*0c8de5b0SBaptiste Daroussin %token <ival> DREG VREG // indices into dreg, vreg arrays */ 40*0c8de5b0SBaptiste Daroussin %token <dval> CONST // floating point constant */ 41*0c8de5b0SBaptiste Daroussin 42*0c8de5b0SBaptiste Daroussin %type <dval> dexp // expression */ 43*0c8de5b0SBaptiste Daroussin %type <vval> vexp // interval expression */ 44*0c8de5b0SBaptiste Daroussin 45*0c8de5b0SBaptiste Daroussin // precedence information about the operators */ 46*0c8de5b0SBaptiste Daroussin 47*0c8de5b0SBaptiste Daroussin %< '+' '-' // %< is an obsolete synonym for %left 48*0c8de5b0SBaptiste Daroussin %< '*' '/' 49*0c8de5b0SBaptiste Daroussin %> UMINUS // precedence for unary minus; 50*0c8de5b0SBaptiste Daroussin // %> is an obsolete synonym for %right 51*0c8de5b0SBaptiste Daroussin 52*0c8de5b0SBaptiste Daroussin \\ // beginning of rules section; \\ is an obsolete synonym for %% 53*0c8de5b0SBaptiste Daroussin 54*0c8de5b0SBaptiste Daroussin lines : // empty */ 55*0c8de5b0SBaptiste Daroussin | lines line 56*0c8de5b0SBaptiste Daroussin ; 57*0c8de5b0SBaptiste Daroussin 58*0c8de5b0SBaptiste Daroussin line : dexp '\n' 59*0c8de5b0SBaptiste Daroussin { 60*0c8de5b0SBaptiste Daroussin (void) printf("%15.8f\n", $1); 61*0c8de5b0SBaptiste Daroussin } 62*0c8de5b0SBaptiste Daroussin | vexp '\n' 63*0c8de5b0SBaptiste Daroussin { 64*0c8de5b0SBaptiste Daroussin (void) printf("(%15.8f, %15.8f)\n", $1.lo, $1.hi); 65*0c8de5b0SBaptiste Daroussin } 66*0c8de5b0SBaptiste Daroussin | DREG '=' dexp '\n' 67*0c8de5b0SBaptiste Daroussin { 68*0c8de5b0SBaptiste Daroussin dreg[$1] = $3; 69*0c8de5b0SBaptiste Daroussin } 70*0c8de5b0SBaptiste Daroussin | VREG '=' vexp '\n' 71*0c8de5b0SBaptiste Daroussin { 72*0c8de5b0SBaptiste Daroussin vreg[$1] = $3; 73*0c8de5b0SBaptiste Daroussin } 74*0c8de5b0SBaptiste Daroussin | error '\n' 75*0c8de5b0SBaptiste Daroussin { 76*0c8de5b0SBaptiste Daroussin yyerrok; 77*0c8de5b0SBaptiste Daroussin } 78*0c8de5b0SBaptiste Daroussin ; 79*0c8de5b0SBaptiste Daroussin 80*0c8de5b0SBaptiste Daroussin dexp : CONST 81*0c8de5b0SBaptiste Daroussin | DREG 82*0c8de5b0SBaptiste Daroussin { 83*0c8de5b0SBaptiste Daroussin $<dval>$ = dreg[$<ival>1]; // $$ & $1 are sufficient here 84*0c8de5b0SBaptiste Daroussin } 85*0c8de5b0SBaptiste Daroussin | dexp '+' dexp 86*0c8de5b0SBaptiste Daroussin { 87*0c8de5b0SBaptiste Daroussin $$ = $1 + $3; 88*0c8de5b0SBaptiste Daroussin } 89*0c8de5b0SBaptiste Daroussin | dexp '-' dexp 90*0c8de5b0SBaptiste Daroussin { 91*0c8de5b0SBaptiste Daroussin $$ = $1 - $3; 92*0c8de5b0SBaptiste Daroussin } 93*0c8de5b0SBaptiste Daroussin | dexp '*' dexp 94*0c8de5b0SBaptiste Daroussin { 95*0c8de5b0SBaptiste Daroussin $$ = $1 * $3; 96*0c8de5b0SBaptiste Daroussin } 97*0c8de5b0SBaptiste Daroussin | dexp '/' dexp 98*0c8de5b0SBaptiste Daroussin { 99*0c8de5b0SBaptiste Daroussin $$ = $1 / $3; 100*0c8de5b0SBaptiste Daroussin } 101*0c8de5b0SBaptiste Daroussin | '-' dexp %prec UMINUS 102*0c8de5b0SBaptiste Daroussin { 103*0c8de5b0SBaptiste Daroussin $$ = -$2; 104*0c8de5b0SBaptiste Daroussin } 105*0c8de5b0SBaptiste Daroussin | '(' dexp ')' 106*0c8de5b0SBaptiste Daroussin { 107*0c8de5b0SBaptiste Daroussin $$ = $2; 108*0c8de5b0SBaptiste Daroussin } 109*0c8de5b0SBaptiste Daroussin ; 110*0c8de5b0SBaptiste Daroussin 111*0c8de5b0SBaptiste Daroussin vexp : dexp 112*0c8de5b0SBaptiste Daroussin { 113*0c8de5b0SBaptiste Daroussin $$.hi = $$.lo = $1; 114*0c8de5b0SBaptiste Daroussin } 115*0c8de5b0SBaptiste Daroussin | '(' dexp ',' dexp ')' 116*0c8de5b0SBaptiste Daroussin { 117*0c8de5b0SBaptiste Daroussin $$.lo = $2; 118*0c8de5b0SBaptiste Daroussin $$.hi = $4; 119*0c8de5b0SBaptiste Daroussin if ( $$.lo > $$.hi ) 120*0c8de5b0SBaptiste Daroussin { 121*0c8de5b0SBaptiste Daroussin (void) printf("interval out of order\n"); 122*0c8de5b0SBaptiste Daroussin YYERROR; 123*0c8de5b0SBaptiste Daroussin } 124*0c8de5b0SBaptiste Daroussin } 125*0c8de5b0SBaptiste Daroussin | VREG 126*0c8de5b0SBaptiste Daroussin { 127*0c8de5b0SBaptiste Daroussin $$ = vreg[$1]; 128*0c8de5b0SBaptiste Daroussin } 129*0c8de5b0SBaptiste Daroussin | vexp '+' vexp 130*0c8de5b0SBaptiste Daroussin { 131*0c8de5b0SBaptiste Daroussin $$.hi = $1.hi + $3.hi; 132*0c8de5b0SBaptiste Daroussin $$.lo = $1.lo + $3.lo; 133*0c8de5b0SBaptiste Daroussin } 134*0c8de5b0SBaptiste Daroussin | dexp '+' vexp 135*0c8de5b0SBaptiste Daroussin { 136*0c8de5b0SBaptiste Daroussin $$.hi = $1 + $3.hi; 137*0c8de5b0SBaptiste Daroussin $$.lo = $1 + $3.lo; 138*0c8de5b0SBaptiste Daroussin } 139*0c8de5b0SBaptiste Daroussin | vexp '-' vexp 140*0c8de5b0SBaptiste Daroussin { 141*0c8de5b0SBaptiste Daroussin $$.hi = $1.hi - $3.lo; 142*0c8de5b0SBaptiste Daroussin $$.lo = $1.lo - $3.hi; 143*0c8de5b0SBaptiste Daroussin } 144*0c8de5b0SBaptiste Daroussin | dexp '-' vexp 145*0c8de5b0SBaptiste Daroussin { 146*0c8de5b0SBaptiste Daroussin $$.hi = $1 - $3.lo; 147*0c8de5b0SBaptiste Daroussin $$.lo = $1 - $3.hi; 148*0c8de5b0SBaptiste Daroussin } 149*0c8de5b0SBaptiste Daroussin | vexp '*' vexp 150*0c8de5b0SBaptiste Daroussin { 151*0c8de5b0SBaptiste Daroussin $$ = vmul( $1.lo, $1.hi, $3 ); 152*0c8de5b0SBaptiste Daroussin } 153*0c8de5b0SBaptiste Daroussin | dexp '*' vexp 154*0c8de5b0SBaptiste Daroussin { 155*0c8de5b0SBaptiste Daroussin $$ = vmul ($1, $1, $3 ); 156*0c8de5b0SBaptiste Daroussin } 157*0c8de5b0SBaptiste Daroussin | vexp '/' vexp 158*0c8de5b0SBaptiste Daroussin { 159*0c8de5b0SBaptiste Daroussin if (dcheck($3)) YYERROR; 160*0c8de5b0SBaptiste Daroussin $$ = vdiv ( $1.lo, $1.hi, $3 ); 161*0c8de5b0SBaptiste Daroussin } 162*0c8de5b0SBaptiste Daroussin | dexp '/' vexp 163*0c8de5b0SBaptiste Daroussin { 164*0c8de5b0SBaptiste Daroussin if (dcheck ( $3 )) YYERROR; 165*0c8de5b0SBaptiste Daroussin $$ = vdiv ($1, $1, $3 ); 166*0c8de5b0SBaptiste Daroussin } 167*0c8de5b0SBaptiste Daroussin | '-' vexp %prec UMINUS 168*0c8de5b0SBaptiste Daroussin { 169*0c8de5b0SBaptiste Daroussin $$.hi = -$2.lo; 170*0c8de5b0SBaptiste Daroussin $$.lo = -$2.hi; 171*0c8de5b0SBaptiste Daroussin } 172*0c8de5b0SBaptiste Daroussin | '(' vexp ')' 173*0c8de5b0SBaptiste Daroussin { 174*0c8de5b0SBaptiste Daroussin $$ = $2; 175*0c8de5b0SBaptiste Daroussin } 176*0c8de5b0SBaptiste Daroussin ; 177*0c8de5b0SBaptiste Daroussin 178*0c8de5b0SBaptiste Daroussin \\ /* beginning of subroutines section */ 179*0c8de5b0SBaptiste Daroussin 180*0c8de5b0SBaptiste Daroussin #define BSZ 50 /* buffer size for floating point numbers */ 181*0c8de5b0SBaptiste Daroussin 182*0c8de5b0SBaptiste Daroussin /* lexical analysis */ 183*0c8de5b0SBaptiste Daroussin 184*0c8de5b0SBaptiste Daroussin static void 185*0c8de5b0SBaptiste Daroussin yyerror(const char *s) 186*0c8de5b0SBaptiste Daroussin { 187*0c8de5b0SBaptiste Daroussin fprintf(stderr, "%s\n", s); 188*0c8de5b0SBaptiste Daroussin } 189*0c8de5b0SBaptiste Daroussin 190*0c8de5b0SBaptiste Daroussin int 191*0c8de5b0SBaptiste Daroussin yylex(void) 192*0c8de5b0SBaptiste Daroussin { 193*0c8de5b0SBaptiste Daroussin int c; 194*0c8de5b0SBaptiste Daroussin 195*0c8de5b0SBaptiste Daroussin while ((c = getchar()) == ' ') 196*0c8de5b0SBaptiste Daroussin { /* skip over blanks */ 197*0c8de5b0SBaptiste Daroussin } 198*0c8de5b0SBaptiste Daroussin 199*0c8de5b0SBaptiste Daroussin if (isupper(c)) 200*0c8de5b0SBaptiste Daroussin { 201*0c8de5b0SBaptiste Daroussin yylval.ival = c - 'A'; 202*0c8de5b0SBaptiste Daroussin return (VREG); 203*0c8de5b0SBaptiste Daroussin } 204*0c8de5b0SBaptiste Daroussin if (islower(c)) 205*0c8de5b0SBaptiste Daroussin { 206*0c8de5b0SBaptiste Daroussin yylval.ival = c - 'a'; 207*0c8de5b0SBaptiste Daroussin return (DREG); 208*0c8de5b0SBaptiste Daroussin } 209*0c8de5b0SBaptiste Daroussin 210*0c8de5b0SBaptiste Daroussin if (isdigit(c) || c == '.') 211*0c8de5b0SBaptiste Daroussin { 212*0c8de5b0SBaptiste Daroussin /* gobble up digits, points, exponents */ 213*0c8de5b0SBaptiste Daroussin char buf[BSZ + 1], *cp = buf; 214*0c8de5b0SBaptiste Daroussin int dot = 0, expr = 0; 215*0c8de5b0SBaptiste Daroussin 216*0c8de5b0SBaptiste Daroussin for (; (cp - buf) < BSZ; ++cp, c = getchar()) 217*0c8de5b0SBaptiste Daroussin { 218*0c8de5b0SBaptiste Daroussin 219*0c8de5b0SBaptiste Daroussin *cp = (char) c; 220*0c8de5b0SBaptiste Daroussin if (isdigit(c)) 221*0c8de5b0SBaptiste Daroussin continue; 222*0c8de5b0SBaptiste Daroussin if (c == '.') 223*0c8de5b0SBaptiste Daroussin { 224*0c8de5b0SBaptiste Daroussin if (dot++ || expr) 225*0c8de5b0SBaptiste Daroussin return ('.'); /* will cause syntax error */ 226*0c8de5b0SBaptiste Daroussin continue; 227*0c8de5b0SBaptiste Daroussin } 228*0c8de5b0SBaptiste Daroussin 229*0c8de5b0SBaptiste Daroussin if (c == 'e') 230*0c8de5b0SBaptiste Daroussin { 231*0c8de5b0SBaptiste Daroussin if (expr++) 232*0c8de5b0SBaptiste Daroussin return ('e'); /* will cause syntax error */ 233*0c8de5b0SBaptiste Daroussin continue; 234*0c8de5b0SBaptiste Daroussin } 235*0c8de5b0SBaptiste Daroussin 236*0c8de5b0SBaptiste Daroussin /* end of number */ 237*0c8de5b0SBaptiste Daroussin break; 238*0c8de5b0SBaptiste Daroussin } 239*0c8de5b0SBaptiste Daroussin *cp = '\0'; 240*0c8de5b0SBaptiste Daroussin 241*0c8de5b0SBaptiste Daroussin if ((cp - buf) >= BSZ) 242*0c8de5b0SBaptiste Daroussin printf("constant too long: truncated\n"); 243*0c8de5b0SBaptiste Daroussin else 244*0c8de5b0SBaptiste Daroussin ungetc(c, stdin); /* push back last char read */ 245*0c8de5b0SBaptiste Daroussin yylval.dval = atof(buf); 246*0c8de5b0SBaptiste Daroussin return (CONST); 247*0c8de5b0SBaptiste Daroussin } 248*0c8de5b0SBaptiste Daroussin return (c); 249*0c8de5b0SBaptiste Daroussin } 250*0c8de5b0SBaptiste Daroussin 251*0c8de5b0SBaptiste Daroussin static INTERVAL 252*0c8de5b0SBaptiste Daroussin hilo(double a, double b, double c, double d) 253*0c8de5b0SBaptiste Daroussin { 254*0c8de5b0SBaptiste Daroussin /* returns the smallest interval containing a, b, c, and d */ 255*0c8de5b0SBaptiste Daroussin /* used by *, / routines */ 256*0c8de5b0SBaptiste Daroussin INTERVAL v; 257*0c8de5b0SBaptiste Daroussin 258*0c8de5b0SBaptiste Daroussin if (a > b) 259*0c8de5b0SBaptiste Daroussin { 260*0c8de5b0SBaptiste Daroussin v.hi = a; 261*0c8de5b0SBaptiste Daroussin v.lo = b; 262*0c8de5b0SBaptiste Daroussin } 263*0c8de5b0SBaptiste Daroussin else 264*0c8de5b0SBaptiste Daroussin { 265*0c8de5b0SBaptiste Daroussin v.hi = b; 266*0c8de5b0SBaptiste Daroussin v.lo = a; 267*0c8de5b0SBaptiste Daroussin } 268*0c8de5b0SBaptiste Daroussin 269*0c8de5b0SBaptiste Daroussin if (c > d) 270*0c8de5b0SBaptiste Daroussin { 271*0c8de5b0SBaptiste Daroussin if (c > v.hi) 272*0c8de5b0SBaptiste Daroussin v.hi = c; 273*0c8de5b0SBaptiste Daroussin if (d < v.lo) 274*0c8de5b0SBaptiste Daroussin v.lo = d; 275*0c8de5b0SBaptiste Daroussin } 276*0c8de5b0SBaptiste Daroussin else 277*0c8de5b0SBaptiste Daroussin { 278*0c8de5b0SBaptiste Daroussin if (d > v.hi) 279*0c8de5b0SBaptiste Daroussin v.hi = d; 280*0c8de5b0SBaptiste Daroussin if (c < v.lo) 281*0c8de5b0SBaptiste Daroussin v.lo = c; 282*0c8de5b0SBaptiste Daroussin } 283*0c8de5b0SBaptiste Daroussin return (v); 284*0c8de5b0SBaptiste Daroussin } 285*0c8de5b0SBaptiste Daroussin 286*0c8de5b0SBaptiste Daroussin INTERVAL 287*0c8de5b0SBaptiste Daroussin vmul(double a, double b, INTERVAL v) 288*0c8de5b0SBaptiste Daroussin { 289*0c8de5b0SBaptiste Daroussin return (hilo(a * v.hi, a * v.lo, b * v.hi, b * v.lo)); 290*0c8de5b0SBaptiste Daroussin } 291*0c8de5b0SBaptiste Daroussin 292*0c8de5b0SBaptiste Daroussin int 293*0c8de5b0SBaptiste Daroussin dcheck(INTERVAL v) 294*0c8de5b0SBaptiste Daroussin { 295*0c8de5b0SBaptiste Daroussin if (v.hi >= 0. && v.lo <= 0.) 296*0c8de5b0SBaptiste Daroussin { 297*0c8de5b0SBaptiste Daroussin printf("divisor interval contains 0.\n"); 298*0c8de5b0SBaptiste Daroussin return (1); 299*0c8de5b0SBaptiste Daroussin } 300*0c8de5b0SBaptiste Daroussin return (0); 301*0c8de5b0SBaptiste Daroussin } 302*0c8de5b0SBaptiste Daroussin 303*0c8de5b0SBaptiste Daroussin INTERVAL 304*0c8de5b0SBaptiste Daroussin vdiv(double a, double b, INTERVAL v) 305*0c8de5b0SBaptiste Daroussin { 306*0c8de5b0SBaptiste Daroussin return (hilo(a / v.hi, a / v.lo, b / v.hi, b / v.lo)); 307*0c8de5b0SBaptiste Daroussin } 308