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