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