198e903e7SBaptiste Daroussin %{
298e903e7SBaptiste Daroussin
398e903e7SBaptiste Daroussin /* http://dinosaur.compilertools.net/yacc/index.html */
498e903e7SBaptiste Daroussin
598e903e7SBaptiste Daroussin #include <stdlib.h>
698e903e7SBaptiste Daroussin #include <stdio.h>
798e903e7SBaptiste Daroussin #include <ctype.h>
898e903e7SBaptiste Daroussin #include <math.h>
998e903e7SBaptiste Daroussin
1098e903e7SBaptiste Daroussin typedef struct interval
1198e903e7SBaptiste Daroussin {
1298e903e7SBaptiste Daroussin double lo, hi;
1398e903e7SBaptiste Daroussin }
1498e903e7SBaptiste Daroussin INTERVAL;
1598e903e7SBaptiste Daroussin
1698e903e7SBaptiste Daroussin INTERVAL vmul(double, double, INTERVAL);
1798e903e7SBaptiste Daroussin INTERVAL vdiv(double, double, INTERVAL);
1898e903e7SBaptiste Daroussin
1998e903e7SBaptiste Daroussin extern int yylex(void);
2098e903e7SBaptiste Daroussin static void yyerror(const char *s);
2198e903e7SBaptiste Daroussin
2298e903e7SBaptiste Daroussin int dcheck(INTERVAL);
2398e903e7SBaptiste Daroussin
2498e903e7SBaptiste Daroussin double dreg[26];
2598e903e7SBaptiste Daroussin INTERVAL vreg[26];
2698e903e7SBaptiste Daroussin
2798e903e7SBaptiste Daroussin %}
2898e903e7SBaptiste Daroussin %expect 18
2998e903e7SBaptiste Daroussin
3098e903e7SBaptiste Daroussin %start line
3198e903e7SBaptiste Daroussin %union
3298e903e7SBaptiste Daroussin {
3398e903e7SBaptiste Daroussin int ival;
3498e903e7SBaptiste Daroussin double dval;
3598e903e7SBaptiste Daroussin INTERVAL vval;
3698e903e7SBaptiste Daroussin }
3798e903e7SBaptiste Daroussin
3898e903e7SBaptiste Daroussin %token <ival> DREG VREG /* indices into dreg, vreg arrays */
3998e903e7SBaptiste Daroussin %token <dval> CONST /* floating point constant */
4098e903e7SBaptiste Daroussin
4198e903e7SBaptiste Daroussin %type <dval> dexp /* expression */
4298e903e7SBaptiste Daroussin %type <vval> vexp /* interval expression */
4398e903e7SBaptiste Daroussin
4498e903e7SBaptiste Daroussin /* precedence information about the operators */
4598e903e7SBaptiste Daroussin
4698e903e7SBaptiste Daroussin %left '+' '-'
4798e903e7SBaptiste Daroussin %left '*' '/'
4898e903e7SBaptiste Daroussin %left UMINUS /* precedence for unary minus */
4998e903e7SBaptiste Daroussin
5098e903e7SBaptiste Daroussin %% /* beginning of rules section */
5198e903e7SBaptiste Daroussin
5298e903e7SBaptiste Daroussin lines : /* empty */
5398e903e7SBaptiste Daroussin | lines line
5498e903e7SBaptiste Daroussin ;
5598e903e7SBaptiste Daroussin
5698e903e7SBaptiste Daroussin line : dexp '\n'
5798e903e7SBaptiste Daroussin {
5898e903e7SBaptiste Daroussin (void) printf("%15.8f\n", $1);
5998e903e7SBaptiste Daroussin }
6098e903e7SBaptiste Daroussin | vexp '\n'
6198e903e7SBaptiste Daroussin {
6298e903e7SBaptiste Daroussin (void) printf("(%15.8f, %15.8f)\n", $1.lo, $1.hi);
6398e903e7SBaptiste Daroussin }
6498e903e7SBaptiste Daroussin | DREG '=' dexp '\n'
6598e903e7SBaptiste Daroussin {
6698e903e7SBaptiste Daroussin dreg[$1] = $3;
6798e903e7SBaptiste Daroussin }
6898e903e7SBaptiste Daroussin | VREG '=' vexp '\n'
6998e903e7SBaptiste Daroussin {
7098e903e7SBaptiste Daroussin vreg[$1] = $3;
7198e903e7SBaptiste Daroussin }
7298e903e7SBaptiste Daroussin | error '\n'
7398e903e7SBaptiste Daroussin {
7498e903e7SBaptiste Daroussin yyerrok;
7598e903e7SBaptiste Daroussin }
7698e903e7SBaptiste Daroussin ;
7798e903e7SBaptiste Daroussin
7898e903e7SBaptiste Daroussin dexp : CONST
7998e903e7SBaptiste Daroussin | DREG
8098e903e7SBaptiste Daroussin {
8198e903e7SBaptiste Daroussin $$ = dreg[$1];
8298e903e7SBaptiste Daroussin }
8398e903e7SBaptiste Daroussin | dexp '+' dexp
8498e903e7SBaptiste Daroussin {
8598e903e7SBaptiste Daroussin $$ = $1 + $3;
8698e903e7SBaptiste Daroussin }
8798e903e7SBaptiste Daroussin | dexp '-' dexp
8898e903e7SBaptiste Daroussin {
8998e903e7SBaptiste Daroussin $$ = $1 - $3;
9098e903e7SBaptiste Daroussin }
9198e903e7SBaptiste Daroussin | dexp '*' dexp
9298e903e7SBaptiste Daroussin {
9398e903e7SBaptiste Daroussin $$ = $1 * $3;
9498e903e7SBaptiste Daroussin }
9598e903e7SBaptiste Daroussin | dexp '/' dexp
9698e903e7SBaptiste Daroussin {
9798e903e7SBaptiste Daroussin $$ = $1 / $3;
9898e903e7SBaptiste Daroussin }
9998e903e7SBaptiste Daroussin | '-' dexp %prec UMINUS
10098e903e7SBaptiste Daroussin {
10198e903e7SBaptiste Daroussin $$ = -$2;
10298e903e7SBaptiste Daroussin }
10398e903e7SBaptiste Daroussin | '(' dexp ')'
10498e903e7SBaptiste Daroussin {
10598e903e7SBaptiste Daroussin $$ = $2;
10698e903e7SBaptiste Daroussin }
10798e903e7SBaptiste Daroussin ;
10898e903e7SBaptiste Daroussin
10998e903e7SBaptiste Daroussin vexp : dexp
11098e903e7SBaptiste Daroussin {
11198e903e7SBaptiste Daroussin $$.hi = $$.lo = $1;
11298e903e7SBaptiste Daroussin }
11398e903e7SBaptiste Daroussin | '(' dexp ',' dexp ')'
11498e903e7SBaptiste Daroussin {
11598e903e7SBaptiste Daroussin $$.lo = $2;
11698e903e7SBaptiste Daroussin $$.hi = $4;
11798e903e7SBaptiste Daroussin if ( $$.lo > $$.hi )
11898e903e7SBaptiste Daroussin {
11998e903e7SBaptiste Daroussin (void) printf("interval out of order\n");
12098e903e7SBaptiste Daroussin YYERROR;
12198e903e7SBaptiste Daroussin }
12298e903e7SBaptiste Daroussin }
12398e903e7SBaptiste Daroussin | VREG
12498e903e7SBaptiste Daroussin {
12598e903e7SBaptiste Daroussin $$ = vreg[$1];
12698e903e7SBaptiste Daroussin }
12798e903e7SBaptiste Daroussin | vexp '+' vexp
12898e903e7SBaptiste Daroussin {
12998e903e7SBaptiste Daroussin $$.hi = $1.hi + $3.hi;
13098e903e7SBaptiste Daroussin $$.lo = $1.lo + $3.lo;
13198e903e7SBaptiste Daroussin }
13298e903e7SBaptiste Daroussin | dexp '+' vexp
13398e903e7SBaptiste Daroussin {
13498e903e7SBaptiste Daroussin $$.hi = $1 + $3.hi;
13598e903e7SBaptiste Daroussin $$.lo = $1 + $3.lo;
13698e903e7SBaptiste Daroussin }
13798e903e7SBaptiste Daroussin | vexp '-' vexp
13898e903e7SBaptiste Daroussin {
13998e903e7SBaptiste Daroussin $$.hi = $1.hi - $3.lo;
14098e903e7SBaptiste Daroussin $$.lo = $1.lo - $3.hi;
14198e903e7SBaptiste Daroussin }
14298e903e7SBaptiste Daroussin | dexp '-' vexp
14398e903e7SBaptiste Daroussin {
14498e903e7SBaptiste Daroussin $$.hi = $1 - $3.lo;
14598e903e7SBaptiste Daroussin $$.lo = $1 - $3.hi;
14698e903e7SBaptiste Daroussin }
14798e903e7SBaptiste Daroussin | vexp '*' vexp
14898e903e7SBaptiste Daroussin {
14998e903e7SBaptiste Daroussin $$ = vmul( $1.lo, $1.hi, $3 );
15098e903e7SBaptiste Daroussin }
15198e903e7SBaptiste Daroussin | dexp '*' vexp
15298e903e7SBaptiste Daroussin {
15398e903e7SBaptiste Daroussin $$ = vmul ($1, $1, $3 );
15498e903e7SBaptiste Daroussin }
15598e903e7SBaptiste Daroussin | vexp '/' vexp
15698e903e7SBaptiste Daroussin {
15798e903e7SBaptiste Daroussin if (dcheck($3)) YYERROR;
15898e903e7SBaptiste Daroussin $$ = vdiv ( $1.lo, $1.hi, $3 );
15998e903e7SBaptiste Daroussin }
16098e903e7SBaptiste Daroussin | dexp '/' vexp
16198e903e7SBaptiste Daroussin {
16298e903e7SBaptiste Daroussin if (dcheck ( $3 )) YYERROR;
16398e903e7SBaptiste Daroussin $$ = vdiv ($1, $1, $3 );
16498e903e7SBaptiste Daroussin }
16598e903e7SBaptiste Daroussin | '-' vexp %prec UMINUS
16698e903e7SBaptiste Daroussin {
16798e903e7SBaptiste Daroussin $$.hi = -$2.lo;
16898e903e7SBaptiste Daroussin $$.lo = -$2.hi;
16998e903e7SBaptiste Daroussin }
17098e903e7SBaptiste Daroussin | '(' vexp ')'
17198e903e7SBaptiste Daroussin {
17298e903e7SBaptiste Daroussin $$ = $2;
17398e903e7SBaptiste Daroussin }
17498e903e7SBaptiste Daroussin ;
17598e903e7SBaptiste Daroussin
17698e903e7SBaptiste Daroussin %% /* beginning of subroutines section */
17798e903e7SBaptiste Daroussin
17898e903e7SBaptiste Daroussin #define BSZ 50 /* buffer size for floating point numbers */
17998e903e7SBaptiste Daroussin
18098e903e7SBaptiste Daroussin /* lexical analysis */
18198e903e7SBaptiste Daroussin
18298e903e7SBaptiste Daroussin static void
18398e903e7SBaptiste Daroussin yyerror(const char *s)
18498e903e7SBaptiste Daroussin {
18598e903e7SBaptiste Daroussin fprintf(stderr, "%s\n", s);
18698e903e7SBaptiste Daroussin }
18798e903e7SBaptiste Daroussin
18898e903e7SBaptiste Daroussin int
yylex(void)18998e903e7SBaptiste Daroussin yylex(void)
19098e903e7SBaptiste Daroussin {
19198e903e7SBaptiste Daroussin int c;
19298e903e7SBaptiste Daroussin
19398e903e7SBaptiste Daroussin while ((c = getchar()) == ' ')
19498e903e7SBaptiste Daroussin { /* skip over blanks */
19598e903e7SBaptiste Daroussin }
19698e903e7SBaptiste Daroussin
19798e903e7SBaptiste Daroussin if (isupper(c))
19898e903e7SBaptiste Daroussin {
19998e903e7SBaptiste Daroussin yylval.ival = c - 'A';
20098e903e7SBaptiste Daroussin return (VREG);
20198e903e7SBaptiste Daroussin }
20298e903e7SBaptiste Daroussin if (islower(c))
20398e903e7SBaptiste Daroussin {
20498e903e7SBaptiste Daroussin yylval.ival = c - 'a';
20598e903e7SBaptiste Daroussin return (DREG);
20698e903e7SBaptiste Daroussin }
20798e903e7SBaptiste Daroussin
20898e903e7SBaptiste Daroussin if (isdigit(c) || c == '.')
20998e903e7SBaptiste Daroussin {
21098e903e7SBaptiste Daroussin /* gobble up digits, points, exponents */
21198e903e7SBaptiste Daroussin char buf[BSZ + 1], *cp = buf;
21298e903e7SBaptiste Daroussin int dot = 0, expr = 0;
21398e903e7SBaptiste Daroussin
21498e903e7SBaptiste Daroussin for (; (cp - buf) < BSZ; ++cp, c = getchar())
21598e903e7SBaptiste Daroussin {
21698e903e7SBaptiste Daroussin
217*5b91e83fSBaptiste Daroussin *cp = (char) c;
21898e903e7SBaptiste Daroussin if (isdigit(c))
21998e903e7SBaptiste Daroussin continue;
22098e903e7SBaptiste Daroussin if (c == '.')
22198e903e7SBaptiste Daroussin {
22298e903e7SBaptiste Daroussin if (dot++ || expr)
22398e903e7SBaptiste Daroussin return ('.'); /* will cause syntax error */
22498e903e7SBaptiste Daroussin continue;
22598e903e7SBaptiste Daroussin }
22698e903e7SBaptiste Daroussin
22798e903e7SBaptiste Daroussin if (c == 'e')
22898e903e7SBaptiste Daroussin {
22998e903e7SBaptiste Daroussin if (expr++)
23098e903e7SBaptiste Daroussin return ('e'); /* will cause syntax error */
23198e903e7SBaptiste Daroussin continue;
23298e903e7SBaptiste Daroussin }
23398e903e7SBaptiste Daroussin
23498e903e7SBaptiste Daroussin /* end of number */
23598e903e7SBaptiste Daroussin break;
23698e903e7SBaptiste Daroussin }
23798e903e7SBaptiste Daroussin *cp = '\0';
23898e903e7SBaptiste Daroussin
23998e903e7SBaptiste Daroussin if ((cp - buf) >= BSZ)
24098e903e7SBaptiste Daroussin printf("constant too long: truncated\n");
24198e903e7SBaptiste Daroussin else
24298e903e7SBaptiste Daroussin ungetc(c, stdin); /* push back last char read */
24398e903e7SBaptiste Daroussin yylval.dval = atof(buf);
24498e903e7SBaptiste Daroussin return (CONST);
24598e903e7SBaptiste Daroussin }
24698e903e7SBaptiste Daroussin return (c);
24798e903e7SBaptiste Daroussin }
24898e903e7SBaptiste Daroussin
24998e903e7SBaptiste Daroussin static INTERVAL
hilo(double a,double b,double c,double d)25098e903e7SBaptiste Daroussin hilo(double a, double b, double c, double d)
25198e903e7SBaptiste Daroussin {
25298e903e7SBaptiste Daroussin /* returns the smallest interval containing a, b, c, and d */
25398e903e7SBaptiste Daroussin /* used by *, / routines */
25498e903e7SBaptiste Daroussin INTERVAL v;
25598e903e7SBaptiste Daroussin
25698e903e7SBaptiste Daroussin if (a > b)
25798e903e7SBaptiste Daroussin {
25898e903e7SBaptiste Daroussin v.hi = a;
25998e903e7SBaptiste Daroussin v.lo = b;
26098e903e7SBaptiste Daroussin }
26198e903e7SBaptiste Daroussin else
26298e903e7SBaptiste Daroussin {
26398e903e7SBaptiste Daroussin v.hi = b;
26498e903e7SBaptiste Daroussin v.lo = a;
26598e903e7SBaptiste Daroussin }
26698e903e7SBaptiste Daroussin
26798e903e7SBaptiste Daroussin if (c > d)
26898e903e7SBaptiste Daroussin {
26998e903e7SBaptiste Daroussin if (c > v.hi)
27098e903e7SBaptiste Daroussin v.hi = c;
27198e903e7SBaptiste Daroussin if (d < v.lo)
27298e903e7SBaptiste Daroussin v.lo = d;
27398e903e7SBaptiste Daroussin }
27498e903e7SBaptiste Daroussin else
27598e903e7SBaptiste Daroussin {
27698e903e7SBaptiste Daroussin if (d > v.hi)
27798e903e7SBaptiste Daroussin v.hi = d;
27898e903e7SBaptiste Daroussin if (c < v.lo)
27998e903e7SBaptiste Daroussin v.lo = c;
28098e903e7SBaptiste Daroussin }
28198e903e7SBaptiste Daroussin return (v);
28298e903e7SBaptiste Daroussin }
28398e903e7SBaptiste Daroussin
28498e903e7SBaptiste Daroussin INTERVAL
vmul(double a,double b,INTERVAL v)28598e903e7SBaptiste Daroussin vmul(double a, double b, INTERVAL v)
28698e903e7SBaptiste Daroussin {
28798e903e7SBaptiste Daroussin return (hilo(a * v.hi, a * v.lo, b * v.hi, b * v.lo));
28898e903e7SBaptiste Daroussin }
28998e903e7SBaptiste Daroussin
29098e903e7SBaptiste Daroussin int
dcheck(INTERVAL v)29198e903e7SBaptiste Daroussin dcheck(INTERVAL v)
29298e903e7SBaptiste Daroussin {
29398e903e7SBaptiste Daroussin if (v.hi >= 0. && v.lo <= 0.)
29498e903e7SBaptiste Daroussin {
29598e903e7SBaptiste Daroussin printf("divisor interval contains 0.\n");
29698e903e7SBaptiste Daroussin return (1);
29798e903e7SBaptiste Daroussin }
29898e903e7SBaptiste Daroussin return (0);
29998e903e7SBaptiste Daroussin }
30098e903e7SBaptiste Daroussin
30198e903e7SBaptiste Daroussin INTERVAL
vdiv(double a,double b,INTERVAL v)30298e903e7SBaptiste Daroussin vdiv(double a, double b, INTERVAL v)
30398e903e7SBaptiste Daroussin {
30498e903e7SBaptiste Daroussin return (hilo(a / v.hi, a / v.lo, b / v.hi, b / v.lo));
30598e903e7SBaptiste Daroussin }
306