Home | History | Annotate | Line # | Download | only in test
varsyntax_calc1.y revision 1.1.1.2
      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 }
    308