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