xref: /freebsd/contrib/byacc/test/calc1.y (revision d1d015864103b253b3fcb2f72a0da5b0cfeb31b6)
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