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