xref: /plan9/sys/src/cmd/grap/grap.y (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
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