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