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