picy.y 9.2 KB

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