1 %{
2 #include <stdio.h>
3 #include "pic.h"
4 #include <math.h>
5 YYSTYPE	y;
6 %}
7 
8 %token	<i>	BOX	1	/* DON'T CHANGE THESE! */
9 %token	<i>	LINE	2
10 %token	<i>	ARROW	3
11 %token	<i>	CIRCLE	4
12 %token	<i>	ELLIPSE	5
13 %token	<i>	ARC	6
14 %token	<i>	SPLINE	7
15 %token	<i>	BLOCK	8
16 %token	<p>	TEXT	9
17 %token	<i>	TROFF	10
18 %token	<i>	MOVE	11
19 %token	<i>	BLOCKEND 12
20 %token	<i>	PLACE
21 %token	<i>	PRINT RESET THRU UNTIL
22 %token	<o>	FOR IF COPY
23 %token	<p>	THENSTR ELSESTR DOSTR DEFNAME PLACENAME VARNAME SPRINTF
24 %token	<i>	ATTR TEXTATTR
25 %token	<i>	LEFT RIGHT UP DOWN FROM TO AT BY WITH HEAD CW CCW THEN
26 %token	<i>	HEIGHT WIDTH RADIUS DIAMETER LENGTH SIZE
27 %token	<i>	CORNER HERE LAST NTH SAME BETWEEN AND
28 %token	<i>	EAST WEST NORTH SOUTH NE NW SE SW START END
29 %token	<i>	DOTX DOTY DOTHT DOTWID DOTRAD
30 %token	<f>	NUMBER
31 %token	<f>	LOG EXP SIN COS ATAN2 SQRT RAND MIN MAX INT
32 %token	<i>	DIR
33 %token	<i>	DOT DASH CHOP
34 %token	<o>	ST	/* statement terminator */
35 
36 %right	<f>	'='
37 %left	<f>	OROR
38 %left	<f>	ANDAND
39 %nonassoc <f>	GT LT LE GE EQ NEQ
40 %left	<f>	'+' '-'
41 %left	<f>	'*' '/' '%'
42 %right	<f>	UMINUS NOT
43 
44 %type	<f>	expr if_expr asgn
45 %type	<p>	name text
46 %type	<i>	optop exprlist
47 %type	<o>	if for copy
48 
49 /* this is a lie:  picture and position are really the whole union */
50 %type	<o>	leftbrace picture piclist position lbracket
51 %type	<o>	prim place blockname
52 %type	<i>	textlist textattr	/* not a sensible value */
53 %type	<i>	last type
54 
55 %%
56 
57 top:
58 	  piclist
59 	| /* empty */
60 	| error		{ yyerror("syntax error"); }
61 	;
62 
63 piclist:
64 	  picture
65 	| piclist picture
66 	;
67 
68 picture:
69 	  prim ST			{ codegen = 1; makeiattr(0, 0); }
70 	| leftbrace piclist '}'		{ rightthing($1, '}'); $$ = $2; }
71 	| PLACENAME ':' picture		{ y.o=$3; makevar($1,PLACENAME,y); $$ = $3; }
72 	| PLACENAME ':' ST picture	{ y.o=$4; makevar($1,PLACENAME,y); $$ = $4; }
73 	| PLACENAME ':' position ST	{ y.o=$3; makevar($1,PLACENAME,y); $$ = $3; }
74 	| asgn ST			{ y.f = $1; $$ = y.o; }
75 	| DIR				{ setdir($1); }
76 	| PRINT expr ST			{ printexpr($2); }
77 	| PRINT position ST		{ printpos($2); }
78 	| PRINT text ST			{ printf("%s\n", $2); free($2); }
79 	| RESET varlist ST		{ resetvar(); makeiattr(0, 0); }
80 	| copy
81 	| for
82 	| if
83 	| ST
84 	;
85 
86 varlist:
87 	  /* empty */
88 	| VARNAME		{ makevattr($1); }
89 	| varlist VARNAME	{ makevattr($2); }
90 	| varlist ',' VARNAME	{ makevattr($3); }
91 	;
92 
93 asgn:
94 	  VARNAME '=' expr	{ $$=y.f=$3; makevar($1,VARNAME,y); checkscale($1); }
95 	;
96 
97 copy:
98 	  COPY copylist		{ copy(); }
99 	;
100 copylist:
101 	  copyattr
102 	| copylist copyattr
103 	;
104 copyattr:
105 	  text			{ copyfile($1); }
106 	| THRU DEFNAME		{ copydef($2); }
107 	| UNTIL text		{ copyuntil($2); }
108 	;
109 
110 for:
111 	  FOR name FROM expr TO expr BY optop expr DOSTR
112 		{ forloop($2, $4, $6, $8, $9, $10); }
113 	| FOR name FROM expr TO expr DOSTR
114 		{ forloop($2, $4, $6, '+', 1.0, $7); }
115 	| FOR name '=' expr TO expr BY optop expr DOSTR
116 		{ forloop($2, $4, $6, $8, $9, $10); }
117 	| FOR name '=' expr TO expr DOSTR
118 		{ forloop($2, $4, $6, '+', 1.0, $7); }
119 	;
120 
121 if:
122 	  IF if_expr THENSTR ELSESTR	{ ifstat($2, $3, $4); }
123 	| IF if_expr THENSTR		{ ifstat($2, $3, (char *) 0); }
124 	;
125 if_expr:
126 	  expr
127 	| text EQ text		{ $$ = strcmp($1,$3) == 0; free($1); free($3); }
128 	| text NEQ text		{ $$ = strcmp($1,$3) != 0; free($1); free($3); }
129 	;
130 
131 name:
132 	  VARNAME	{ y.f = 0; makevar($1, VARNAME, y); }
133 	;
134 optop:
135 	  '+'		{ $$ = '+'; }
136 	| '-'		{ $$ = '-'; }
137 	| '*'		{ $$ = '*'; }
138 	| '/'		{ $$ = '/'; }
139 	| /* empty */	{ $$ = ' '; }
140 	;
141 
142 
143 leftbrace:
144 	  '{'			{ $$ = leftthing('{'); }
145 	;
146 
147 prim:
148 	  BOX attrlist		{ $$ = boxgen($1); }
149 	| CIRCLE attrlist	{ $$ = circgen($1); }
150 	| ELLIPSE attrlist	{ $$ = circgen($1); }
151 	| ARC attrlist		{ $$ = arcgen($1); }
152 	| LINE attrlist		{ $$ = linegen($1); }
153 	| ARROW attrlist	{ $$ = linegen($1); }
154 	| SPLINE attrlist	{ $$ = linegen($1); }
155 	| MOVE attrlist		{ $$ = movegen($1); }
156 	| textlist attrlist	{ $$ = textgen($1); }
157 	| TROFF			{ $$ = troffgen($1); }
158 	| lbracket piclist ']' { $<o>$=rightthing($1,']'); } attrlist
159 				{ $$ = blockgen($1, $2, $<o>4); }
160 	;
161 
162 lbracket:
163 	  '['			{ $$ = leftthing('['); }
164 	;
165 
166 attrlist:
167 	  attrlist attr
168 	| /* empty */
169 	;
170 
171 attr:
172 	  ATTR expr		{ makefattr($1, !DEFAULT, $2); }
173 	| ATTR			{ makefattr($1, DEFAULT, 0.0); }
174 	| expr			{ makefattr(curdir(), !DEFAULT, $1); }
175 	| DIR expr		{ makefattr($1, !DEFAULT, $2); }
176 	| DIR			{ makefattr($1, DEFAULT, 0.0); }
177 	| FROM position		{ makeoattr($1, $2); }
178 	| TO position		{ makeoattr($1, $2); }
179 	| AT position		{ makeoattr($1, $2); }
180 	| BY position		{ makeoattr($1, $2); }
181 	| WITH CORNER		{ makeiattr(WITH, $2); }
182 	| WITH '.' PLACENAME	{ makeoattr(PLACE, getblock(getlast(1,BLOCK), $3)); }
183 	| WITH '.' PLACENAME CORNER
184 		{ makeoattr(PLACE, getpos(getblock(getlast(1,BLOCK), $3), $4)); }
185 	| WITH position		{ makeoattr(PLACE, $2); }
186 	| SAME			{ makeiattr(SAME, $1); }
187 	| TEXTATTR		{ maketattr($1, 0); }
188 	| HEAD			{ makeiattr(HEAD, $1); }
189 	| DOT expr		{ makefattr(DOT, !DEFAULT, $2); }
190 	| DOT			{ makefattr(DOT, DEFAULT, 0.0); }
191 	| DASH expr		{ makefattr(DASH, !DEFAULT, $2); }
192 	| DASH			{ makefattr(DASH, DEFAULT, 0.0); }
193 	| CHOP expr		{ makefattr(CHOP, !DEFAULT, $2); }
194 	| CHOP			{ makefattr(CHOP, DEFAULT, 0.0); }
195 	| textlist
196 	;
197 
198 textlist:
199 	  textattr
200 	| textlist textattr
201 	;
202 textattr:
203 	  text			{ maketattr(CENTER, $1); }
204 	| text TEXTATTR		{ maketattr($2, $1); }
205 	| textattr TEXTATTR	{ addtattr($2); }
206 	;
207 text:
208 	  TEXT
209 	| SPRINTF '(' text ')'			{ $$ = sprintgen($3); }
210 	| SPRINTF '(' text ',' exprlist ')'	{ $$ = sprintgen($3); }
211 	;
212 
213 exprlist:
214 	  expr			{ exprsave($1); $$ = 0; }
215 	| exprlist ',' expr	{ exprsave($3); }
216 	;
217 
218 position:		/* absolute, not relative */
219 	  place
220 	| '(' position ')'			{ $$ = $2; }
221 	| expr ',' expr				{ $$ = makepos($1, $3); }
222 	| position '+' expr ',' expr		{ $$ = fixpos($1, $3, $5); }
223 	| position '-' expr ',' expr		{ $$ = fixpos($1, -$3, -$5); }
224 	| position '+' '(' expr ',' expr ')'	{ $$ = fixpos($1, $4, $6); }
225 	| position '-' '(' expr ',' expr ')'	{ $$ = fixpos($1, -$4, -$6); }
226 	| position '+' place			{ $$ = addpos($1, $3); }
227 	| position '-' place			{ $$ = subpos($1, $3); }
228 	| '(' place ',' place ')'	{ $$ = makepos(getcomp($2,DOTX), getcomp($4,DOTY)); }
229 	| expr LT position ',' position GT	{ $$ = makebetween($1, $3, $5); }
230 	| expr BETWEEN position AND position	{ $$ = makebetween($1, $3, $5); }
231 	;
232 
233 place:
234 	  PLACENAME		{ y = getvar($1); $$ = y.o; }
235 	| PLACENAME CORNER	{ y = getvar($1); $$ = getpos(y.o, $2); }
236 	| CORNER PLACENAME	{ y = getvar($2); $$ = getpos(y.o, $1); }
237 	| HERE			{ $$ = gethere($1); }
238 	| last type		{ $$ = getlast($1, $2); }
239 	| last type CORNER	{ $$ = getpos(getlast($1, $2), $3); }
240 	| CORNER last type	{ $$ = getpos(getlast($2, $3), $1); }
241 	| NTH type		{ $$ = getfirst($1, $2); }
242 	| NTH type CORNER	{ $$ = getpos(getfirst($1, $2), $3); }
243 	| CORNER NTH type	{ $$ = getpos(getfirst($2, $3), $1); }
244 	| blockname
245 	| blockname CORNER	{ $$ = getpos($1, $2); }
246 	| CORNER blockname	{ $$ = getpos($2, $1); }
247 	;
248 
249 blockname:
250 	  last BLOCK '.' PLACENAME	{ $$ = getblock(getlast($1,$2), $4); }
251 	| NTH BLOCK '.' PLACENAME	{ $$ = getblock(getfirst($1,$2), $4); }
252 	| PLACENAME '.' PLACENAME	{ y = getvar($1); $$ = getblock(y.o, $3); }
253 	;
254 
255 last:
256 	  last LAST		{ $$ = $1 + 1; }
257 	| NTH LAST		{ $$ = $1; }
258 	| LAST			{ $$ = 1; }
259 	;
260 
261 type:
262 	  BOX
263 	| CIRCLE
264 	| ELLIPSE
265 	| ARC
266 	| LINE
267 	| ARROW
268 	| SPLINE
269 	| BLOCK
270 	;
271 
272 expr:
273 	  NUMBER
274 	| VARNAME		{ $$ = getfval($1); }
275 	| asgn
276 	| expr '+' expr		{ $$ = $1 + $3; }
277 	| expr '-' expr		{ $$ = $1 - $3; }
278 	| expr '*' expr		{ $$ = $1 * $3; }
279 	| expr '/' expr		{ if ($3 == 0.0) {
280 					yyerror("division by 0"); $3 = 1; }
281 				  $$ = $1 / $3; }
282 	| expr '%' expr		{ if ((long)$3 == 0) {
283 					yyerror("mod division by 0"); $3 = 1; }
284 				  $$ = (long)$1 % (long)$3; }
285 	| '-' expr %prec UMINUS	{ $$ = -$2; }
286 	| '(' expr ')'		{ $$ = $2; }
287 	| place DOTX		{ $$ = getcomp($1, $2); }
288 	| place DOTY		{ $$ = getcomp($1, $2); }
289 	| place DOTHT		{ $$ = getcomp($1, $2); }
290 	| place DOTWID		{ $$ = getcomp($1, $2); }
291 	| place DOTRAD		{ $$ = getcomp($1, $2); }
292 	| PLACENAME '.' VARNAME	{ y = getvar($1); $$ = getblkvar(y.o, $3); }
293 	| last BLOCK '.' VARNAME { $$ = getblkvar(getlast($1,$2), $4); }
294 	| NTH BLOCK '.' VARNAME	{ $$ = getblkvar(getfirst($1,$2), $4); }
295 	| expr GT expr		{ $$ = $1 > $3; }
296 	| expr LT expr		{ $$ = $1 < $3; }
297 	| expr LE expr		{ $$ = $1 <= $3; }
298 	| expr GE expr		{ $$ = $1 >= $3; }
299 	| expr EQ expr		{ $$ = $1 == $3; }
300 	| expr NEQ expr		{ $$ = $1 != $3; }
301 	| expr ANDAND expr	{ $$ = $1 && $3; }
302 	| expr OROR expr	{ $$ = $1 || $3; }
303 	| NOT expr		{ $$ = !($2); }
304 	| LOG '(' expr ')'		{ $$ = Log10($3); }
305 	| EXP '(' expr ')'		{ $$ = Exp($3 * log(10.0)); }
306 	| SIN '(' expr ')'		{ $$ = sin($3); }
307 	| COS '(' expr ')'		{ $$ = cos($3); }
308 	| ATAN2 '(' expr ',' expr ')'	{ $$ = atan2($3, $5); }
309 	| SQRT '(' expr ')'		{ $$ = Sqrt($3); }
310 	| RAND '(' ')'			{ $$ = (float)rand() / 32767.0; /* might be 2^31-1 */ }
311 	| MAX '(' expr ',' expr ')'	{ $$ = $3 >= $5 ? $3 : $5; }
312 	| MIN '(' expr ',' expr ')'	{ $$ = $3 <= $5 ? $3 : $5; }
313 	| INT '(' expr ')'		{ $$ = (long) $3; }
314 	;
315