1 %{ 2 #include <stdio.h> 3 #include <math.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include "grap.h" 7 8 #define RAND_MAX 32767 /* if your rand() returns bigger, change this too */ 9 10 extern int yylex(void); 11 extern int yyparse(void); 12 13 %} 14 15 %token <i> FRAME TICKS GRID LABEL COORD 16 %token <i> LINE ARROW CIRCLE DRAW NEW PLOT NEXT 17 %token <p> PIC 18 %token <i> COPY THRU UNTIL 19 %token <i> FOR FROM TO BY AT WITH 20 %token <i> IF 21 %token <p> GRAPH THEN ELSE DOSTR 22 %token <i> DOT DASH INVIS SOLID 23 %token <i> TEXT JUST SIZE 24 %token <i> LOG EXP SIN COS ATAN2 SQRT RAND MAX MIN INT PRINT SPRINTF 25 %token <i> X Y SIDE IN OUT OFF UP DOWN ACROSS 26 %token <i> HEIGHT WIDTH RADIUS 27 %token <f> NUMBER 28 %token <op> NAME VARNAME DEFNAME 29 %token <p> STRING 30 %token <i> ST '(' ')' ',' 31 32 %right <f> '=' 33 %left <f> OR 34 %left <f> AND 35 %nonassoc <f> GT LT LE GE EQ NE 36 %left <f> '+' '-' 37 %left <f> '*' '/' '%' 38 %right <f> UMINUS NOT 39 %right <f> '^' 40 41 %type <f> expr optexpr if_expr number assign 42 %type <i> optop 43 %type <p> optstring if 44 %type <op> optname iterator name 45 %type <pt> point 46 %type <i> side optside numlist comma linetype drawtype 47 %type <ap> linedesc optdesc stringlist string stringattr sattrlist exprlist 48 %type <i> frameitem framelist coordlog 49 %type <f> string_expr 50 51 %% 52 53 top: 54 graphseq { if (codegen && !synerr) graph((char *) 0); } 55 | /* empty */ { codegen = 0; } 56 | error { codegen = 0; ERROR "syntax error" WARNING; } 57 ; 58 59 graphseq: 60 statlist 61 | graph statlist 62 | graphseq graph statlist 63 ; 64 graph: 65 GRAPH { graph($1); endstat(); } 66 ; 67 68 statlist: 69 ST 70 | stat ST { endstat(); } 71 | statlist stat ST { endstat(); } 72 ; 73 74 stat: 75 FRAME framelist { codegen = 1; } 76 | ticks { codegen = 1; } 77 | grid { codegen = 1; } 78 | label { codegen = 1; } 79 | coord 80 | plot { codegen = 1; } 81 | line { codegen = 1; } 82 | circle { codegen = 1; } 83 | draw 84 | next { codegen = 1; } 85 | PIC { codegen = 1; pic($1); } 86 | for 87 | if 88 | copy 89 | numlist { codegen = 1; numlist(); } 90 | assign 91 | PRINT expr { fprintf(stderr, "\t%g\n", $2); } 92 | PRINT string { fprintf(stderr, "\t%s\n", $2->sval); freeattr($2); } 93 | /* empty */ 94 ; 95 96 numlist: 97 number { savenum(0, $1); $$ = 1; } 98 | numlist number { savenum($1, $2); $$ = $1+1; } 99 | numlist comma number { savenum($1, $3); $$ = $1+1; } 100 ; 101 number: 102 NUMBER 103 | '-' NUMBER %prec UMINUS { $$ = -$2; } 104 | '+' NUMBER %prec UMINUS { $$ = $2; } 105 ; 106 107 label: 108 LABEL optside stringlist lablist { label($2, $3); } 109 ; 110 lablist: 111 labattr 112 | lablist labattr 113 | /* empty */ 114 ; 115 labattr: 116 UP expr { labelmove($1, $2); } 117 | DOWN expr { labelmove($1, $2); } 118 | SIDE expr { labelmove($1, $2); /* LEFT or RIGHT only */ } 119 | WIDTH expr { labelwid($2); } 120 ; 121 122 framelist: 123 framelist frameitem 124 | /* empty */ { $$ = 0; } 125 ; 126 frameitem: 127 HEIGHT expr { frameht($2); } 128 | WIDTH expr { framewid($2); } 129 | side linedesc { frameside($1, $2); } 130 | linedesc { frameside(0, $1); } 131 ; 132 side: 133 SIDE 134 ; 135 optside: 136 side 137 | /* empty */ { $$ = 0; } 138 ; 139 140 linedesc: 141 linetype optexpr { $$ = makeattr($1, $2, (char *) 0, 0, 0); } 142 ; 143 linetype: 144 DOT | DASH | SOLID | INVIS 145 ; 146 optdesc: 147 linedesc 148 | /* empty */ { $$ = makeattr(0, 0.0, (char *) 0, 0, 0); } 149 ; 150 151 ticks: 152 TICKS tickdesc { ticks(); } 153 ; 154 tickdesc: 155 tickattr 156 | tickdesc tickattr 157 ; 158 tickattr: 159 side { tickside($1); } 160 | IN expr { tickdir(IN, $2, 1); } 161 | OUT expr { tickdir(OUT, $2, 1); } 162 | IN { tickdir(IN, 0.0, 0); } 163 | OUT { tickdir(OUT, 0.0, 0); } 164 | AT optname ticklist { setlist(); ticklist($2, AT); } 165 | iterator { setlist(); ticklist($1, AT); } 166 | side OFF { tickoff($1); } 167 | OFF { tickoff(LEFT|RIGHT|TOP|BOT); } 168 | labattr 169 ; 170 ticklist: 171 tickpoint 172 | ticklist comma tickpoint 173 ; 174 tickpoint: 175 expr { savetick($1, (char *) 0); } 176 | expr string { savetick($1, $2->sval); } 177 ; 178 iterator: 179 FROM optname expr TO optname expr BY optop expr optstring 180 { iterator($3, $6, $8, $9, $10); $$ = $2; } 181 | FROM optname expr TO optname expr optstring 182 { iterator($3, $6, '+', 1.0, $7); $$ = $2; } 183 ; 184 optop: 185 '+' { $$ = '+'; } 186 | '-' { $$ = '-'; } 187 | '*' { $$ = '*'; } 188 | '/' { $$ = '/'; } 189 | /* empty */ { $$ = ' '; } 190 ; 191 optstring: 192 string { $$ = $1->sval; } 193 | /* empty */ { $$ = (char *) 0; } 194 ; 195 196 grid: 197 GRID griddesc { ticks(); } 198 ; 199 griddesc: 200 gridattr 201 | griddesc gridattr 202 ; 203 gridattr: 204 side { tickside($1); } 205 | X { tickside(BOT); } 206 | Y { tickside(LEFT); } 207 | linedesc { griddesc($1); } 208 | AT optname ticklist { setlist(); gridlist($2); } 209 | iterator { setlist(); gridlist($1); } 210 | TICKS OFF { gridtickoff(); } 211 | OFF { gridtickoff(); } 212 | labattr 213 ; 214 215 line: 216 LINE FROM point TO point optdesc { line($1, $3, $5, $6); } 217 | LINE optdesc FROM point TO point { line($1, $4, $6, $2); } 218 ; 219 circle: 220 CIRCLE RADIUS expr AT point { circle($3, $5); } 221 | CIRCLE AT point RADIUS expr { circle($5, $3); } 222 | CIRCLE AT point { circle(0.0, $3); } 223 ; 224 225 stringlist: 226 string 227 | stringlist string { $$ = addattr($1, $2); } 228 ; 229 string: 230 STRING sattrlist { $$ = makesattr($1); } 231 | SPRINTF '(' STRING ')' sattrlist 232 { $$ = makesattr(sprntf($3, (Attr*) 0)); } 233 | SPRINTF '(' STRING ',' exprlist ')' sattrlist 234 { $$ = makesattr(sprntf($3, $5)); } 235 ; 236 exprlist: 237 expr { $$ = makefattr(NUMBER, $1); } 238 | exprlist ',' expr { $$ = addattr($1, makefattr(NUMBER, $3)); } 239 ; 240 sattrlist: 241 stringattr 242 | sattrlist stringattr 243 | /* empty */ { $$ = (Attr *) 0; } 244 ; 245 stringattr: 246 JUST { setjust($1); } 247 | SIZE optop expr { setsize($2, $3); } 248 ; 249 250 coord: 251 COORD optname coordlist { coord($2); } 252 | COORD optname { resetcoord($2); } 253 ; 254 coordlist: 255 coorditem 256 | coordlist coorditem 257 ; 258 coorditem: 259 coordlog { coordlog($1); } 260 | X point { coord_x($2); } 261 | Y point { coord_y($2); } 262 | X optname expr TO expr { coord_x(makepoint($2, $3, $5)); } 263 | Y optname expr TO expr { coord_y(makepoint($2, $3, $5)); } 264 | X FROM optname expr TO expr { coord_x(makepoint($3, $4, $6)); } 265 | Y FROM optname expr TO expr { coord_y(makepoint($3, $4, $6)); } 266 ; 267 coordlog: 268 LOG X { $$ = XFLAG; } 269 | LOG Y { $$ = YFLAG; } 270 | LOG X LOG Y { $$ = XFLAG|YFLAG; } 271 | LOG Y LOG X { $$ = XFLAG|YFLAG; } 272 | LOG LOG { $$ = XFLAG|YFLAG; } 273 ; 274 275 plot: 276 stringlist AT point { plot($1, $3); } 277 | PLOT stringlist AT point { plot($2, $4); } 278 | PLOT expr optstring AT point { plotnum($2, $3, $5); } 279 ; 280 281 draw: 282 drawtype optname linedesc { drawdesc($1, $2, $3, (char *) 0); } 283 | drawtype optname optdesc string { drawdesc($1, $2, $3, $4->sval); } 284 | drawtype optname string optdesc { drawdesc($1, $2, $4, $3->sval); } 285 ; 286 drawtype: 287 DRAW 288 | NEW 289 ; 290 291 next: 292 NEXT optname AT point optdesc { next($2, $4, $5); } 293 294 copy: 295 COPY copylist { copy(); } 296 ; 297 copylist: 298 copyattr 299 | copylist copyattr 300 ; 301 copyattr: 302 string { copyfile($1->sval); } 303 | THRU DEFNAME { copydef($2); } 304 | UNTIL string { copyuntil($2->sval); } 305 ; 306 307 for: 308 FOR name FROM expr TO expr BY optop expr DOSTR 309 { forloop($2, $4, $6, $8, $9, $10); } 310 | FOR name FROM expr TO expr DOSTR 311 { forloop($2, $4, $6, '+', 1.0, $7); } 312 | FOR name '=' expr TO expr BY optop expr DOSTR 313 { forloop($2, $4, $6, $8, $9, $10); } 314 | FOR name '=' expr TO expr DOSTR 315 { forloop($2, $4, $6, '+', 1.0, $7); } 316 ; 317 318 if: 319 IF if_expr THEN ELSE { $$ = ifstat($2, $3, $4); } 320 | IF if_expr THEN { $$ = ifstat($2, $3, (char *) 0); } 321 ; 322 if_expr: 323 expr 324 | string_expr 325 | if_expr AND string_expr { $$ = $1 && $3; } 326 | if_expr OR string_expr { $$ = $1 || $3; } 327 ; 328 string_expr: 329 STRING EQ STRING { $$ = strcmp($1,$3) == 0; free($1); free($3); } 330 | STRING NE STRING { $$ = strcmp($1,$3) != 0; free($1); free($3); } 331 ; 332 333 point: 334 optname expr comma expr { $$ = makepoint($1, $2, $4); } 335 | optname '(' expr comma expr ')' { $$ = makepoint($1, $3, $5); } 336 ; 337 comma: 338 ',' { $$ = ','; } 339 ; 340 341 optname: 342 NAME { $$ = $1; } 343 | /* empty */ { $$ = lookup(curr_coord, 1); } 344 ; 345 346 expr: 347 NUMBER 348 | assign 349 | '(' string_expr ')' { $$ = $2; } 350 | VARNAME { $$ = getvar($1); } 351 | expr '+' expr { $$ = $1 + $3; } 352 | expr '-' expr { $$ = $1 - $3; } 353 | expr '*' expr { $$ = $1 * $3; } 354 | expr '/' expr { if ($3 == 0.0) { 355 ERROR "division by 0" WARNING; $3 = 1; } 356 $$ = $1 / $3; } 357 | expr '%' expr { if ((long)$3 == 0) { 358 ERROR "mod division by 0" WARNING; $3 = 1; } 359 $$ = (long)$1 % (long)$3; } 360 | '-' expr %prec UMINUS { $$ = -$2; } 361 | '+' expr %prec UMINUS { $$ = $2; } 362 | '(' expr ')' { $$ = $2; } 363 | LOG '(' expr ')' { $$ = Log10($3); } 364 | EXP '(' expr ')' { $$ = Exp($3 * log(10.0)); } 365 | expr '^' expr { $$ = pow($1, $3); } 366 | SIN '(' expr ')' { $$ = sin($3); } 367 | COS '(' expr ')' { $$ = cos($3); } 368 | ATAN2 '(' expr ',' expr ')' { $$ = atan2($3, $5); } 369 | SQRT '(' expr ')' { $$ = Sqrt($3); } 370 | RAND '(' ')' { $$ = (double)rand() / (double)RAND_MAX; } 371 | MAX '(' expr ',' expr ')' { $$ = $3 >= $5 ? $3 : $5; } 372 | MIN '(' expr ',' expr ')' { $$ = $3 <= $5 ? $3 : $5; } 373 | INT '(' expr ')' { $$ = (long) $3; } 374 | expr GT expr { $$ = $1 > $3; } 375 | expr LT expr { $$ = $1 < $3; } 376 | expr LE expr { $$ = $1 <= $3; } 377 | expr GE expr { $$ = $1 >= $3; } 378 | expr EQ expr { $$ = $1 == $3; } 379 | expr NE expr { $$ = $1 != $3; } 380 | expr AND expr { $$ = $1 && $3; } 381 | expr OR expr { $$ = $1 || $3; } 382 | NOT expr { $$ = !($2); } 383 ; 384 assign: 385 name '=' expr { $$ = setvar($1, $3); } 386 ; 387 388 name: 389 NAME 390 | VARNAME 391 ; 392 393 optexpr: 394 expr 395 | /* empty */ { $$ = 0.0; } 396 ; 397