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