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