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