grap.y 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. %{
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "grap.h"
  7. #define RAND_MAX 32767 /* if your rand() returns bigger, change this too */
  8. extern int yylex(void);
  9. extern int yyparse(void);
  10. %}
  11. %token <i> FRAME TICKS GRID LABEL COORD
  12. %token <i> LINE ARROW CIRCLE DRAW NEW PLOT NEXT
  13. %token <p> PIC
  14. %token <i> COPY THRU UNTIL
  15. %token <i> FOR FROM TO BY AT WITH
  16. %token <i> IF
  17. %token <p> GRAPH THEN ELSE DOSTR
  18. %token <i> DOT DASH INVIS SOLID
  19. %token <i> TEXT JUST SIZE
  20. %token <i> LOG EXP SIN COS ATAN2 SQRT RAND MAX MIN INT PRINT SPRINTF
  21. %token <i> X Y SIDE IN OUT OFF UP DOWN ACROSS
  22. %token <i> HEIGHT WIDTH RADIUS
  23. %token <f> NUMBER
  24. %token <op> NAME VARNAME DEFNAME
  25. %token <p> STRING
  26. %token <i> ST '(' ')' ','
  27. %right <f> '='
  28. %left <f> OR
  29. %left <f> AND
  30. %nonassoc <f> GT LT LE GE EQ NE
  31. %left <f> '+' '-'
  32. %left <f> '*' '/' '%'
  33. %right <f> UMINUS NOT
  34. %right <f> '^'
  35. %type <f> expr optexpr if_expr number assign
  36. %type <i> optop
  37. %type <p> optstring if
  38. %type <op> optname iterator name
  39. %type <pt> point
  40. %type <i> side optside numlist comma linetype drawtype
  41. %type <ap> linedesc optdesc stringlist string stringattr sattrlist exprlist
  42. %type <i> frameitem framelist coordlog
  43. %type <f> string_expr
  44. %%
  45. top:
  46. graphseq { if (codegen && !synerr) graph((char *) 0); }
  47. | /* empty */ { codegen = 0; }
  48. | error { codegen = 0; ERROR "syntax error" WARNING; }
  49. ;
  50. graphseq:
  51. statlist
  52. | graph statlist
  53. | graphseq graph statlist
  54. ;
  55. graph:
  56. GRAPH { graph($1); endstat(); }
  57. ;
  58. statlist:
  59. ST
  60. | stat ST { endstat(); }
  61. | statlist stat ST { endstat(); }
  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->sval); freeattr($2); }
  82. | /* empty */
  83. ;
  84. numlist:
  85. number { savenum(0, $1); $$ = 1; }
  86. | numlist number { savenum($1, $2); $$ = $1+1; }
  87. | numlist comma number { savenum($1, $3); $$ = $1+1; }
  88. ;
  89. number:
  90. NUMBER
  91. | '-' NUMBER %prec UMINUS { $$ = -$2; }
  92. | '+' NUMBER %prec UMINUS { $$ = $2; }
  93. ;
  94. label:
  95. LABEL optside stringlist lablist { label($2, $3); }
  96. ;
  97. lablist:
  98. labattr
  99. | lablist labattr
  100. | /* empty */
  101. ;
  102. labattr:
  103. UP expr { labelmove($1, $2); }
  104. | DOWN expr { labelmove($1, $2); }
  105. | SIDE expr { labelmove($1, $2); /* LEFT or RIGHT only */ }
  106. | WIDTH expr { labelwid($2); }
  107. ;
  108. framelist:
  109. framelist frameitem
  110. | /* empty */ { $$ = 0; }
  111. ;
  112. frameitem:
  113. HEIGHT expr { frameht($2); }
  114. | WIDTH expr { framewid($2); }
  115. | side linedesc { frameside($1, $2); }
  116. | linedesc { frameside(0, $1); }
  117. ;
  118. side:
  119. SIDE
  120. ;
  121. optside:
  122. side
  123. | /* empty */ { $$ = 0; }
  124. ;
  125. linedesc:
  126. linetype optexpr { $$ = makeattr($1, $2, (char *) 0, 0, 0); }
  127. ;
  128. linetype:
  129. DOT | DASH | SOLID | INVIS
  130. ;
  131. optdesc:
  132. linedesc
  133. | /* empty */ { $$ = makeattr(0, 0.0, (char *) 0, 0, 0); }
  134. ;
  135. ticks:
  136. TICKS tickdesc { ticks(); }
  137. ;
  138. tickdesc:
  139. tickattr
  140. | tickdesc tickattr
  141. ;
  142. tickattr:
  143. side { tickside($1); }
  144. | IN expr { tickdir(IN, $2, 1); }
  145. | OUT expr { tickdir(OUT, $2, 1); }
  146. | IN { tickdir(IN, 0.0, 0); }
  147. | OUT { tickdir(OUT, 0.0, 0); }
  148. | AT optname ticklist { setlist(); ticklist($2, AT); }
  149. | iterator { setlist(); ticklist($1, AT); }
  150. | side OFF { tickoff($1); }
  151. | OFF { tickoff(LEFT|RIGHT|TOP|BOT); }
  152. | labattr
  153. ;
  154. ticklist:
  155. tickpoint
  156. | ticklist comma tickpoint
  157. ;
  158. tickpoint:
  159. expr { savetick($1, (char *) 0); }
  160. | expr string { savetick($1, $2->sval); }
  161. ;
  162. iterator:
  163. FROM optname expr TO optname expr BY optop expr optstring
  164. { iterator($3, $6, $8, $9, $10); $$ = $2; }
  165. | FROM optname expr TO optname expr optstring
  166. { iterator($3, $6, '+', 1.0, $7); $$ = $2; }
  167. ;
  168. optop:
  169. '+' { $$ = '+'; }
  170. | '-' { $$ = '-'; }
  171. | '*' { $$ = '*'; }
  172. | '/' { $$ = '/'; }
  173. | /* empty */ { $$ = ' '; }
  174. ;
  175. optstring:
  176. string { $$ = $1->sval; }
  177. | /* empty */ { $$ = (char *) 0; }
  178. ;
  179. grid:
  180. GRID griddesc { ticks(); }
  181. ;
  182. griddesc:
  183. gridattr
  184. | griddesc gridattr
  185. ;
  186. gridattr:
  187. side { tickside($1); }
  188. | X { tickside(BOT); }
  189. | Y { tickside(LEFT); }
  190. | linedesc { griddesc($1); }
  191. | AT optname ticklist { setlist(); gridlist($2); }
  192. | iterator { setlist(); gridlist($1); }
  193. | TICKS OFF { gridtickoff(); }
  194. | OFF { gridtickoff(); }
  195. | labattr
  196. ;
  197. line:
  198. LINE FROM point TO point optdesc { line($1, $3, $5, $6); }
  199. | LINE optdesc FROM point TO point { line($1, $4, $6, $2); }
  200. ;
  201. circle:
  202. CIRCLE RADIUS expr AT point { circle($3, $5); }
  203. | CIRCLE AT point RADIUS expr { circle($5, $3); }
  204. | CIRCLE AT point { circle(0.0, $3); }
  205. ;
  206. stringlist:
  207. string
  208. | stringlist string { $$ = addattr($1, $2); }
  209. ;
  210. string:
  211. STRING sattrlist { $$ = makesattr($1); }
  212. | SPRINTF '(' STRING ')' sattrlist
  213. { $$ = makesattr(sprntf($3, (Attr*) 0)); }
  214. | SPRINTF '(' STRING ',' exprlist ')' sattrlist
  215. { $$ = makesattr(sprntf($3, $5)); }
  216. ;
  217. exprlist:
  218. expr { $$ = makefattr(NUMBER, $1); }
  219. | exprlist ',' expr { $$ = addattr($1, makefattr(NUMBER, $3)); }
  220. ;
  221. sattrlist:
  222. stringattr
  223. | sattrlist stringattr
  224. | /* empty */ { $$ = (Attr *) 0; }
  225. ;
  226. stringattr:
  227. JUST { setjust($1); }
  228. | SIZE optop expr { setsize($2, $3); }
  229. ;
  230. coord:
  231. COORD optname coordlist { coord($2); }
  232. | COORD optname { resetcoord($2); }
  233. ;
  234. coordlist:
  235. coorditem
  236. | coordlist coorditem
  237. ;
  238. coorditem:
  239. coordlog { coordlog($1); }
  240. | X point { coord_x($2); }
  241. | Y point { coord_y($2); }
  242. | X optname expr TO expr { coord_x(makepoint($2, $3, $5)); }
  243. | Y optname expr TO expr { coord_y(makepoint($2, $3, $5)); }
  244. | X FROM optname expr TO expr { coord_x(makepoint($3, $4, $6)); }
  245. | Y FROM optname expr TO expr { coord_y(makepoint($3, $4, $6)); }
  246. ;
  247. coordlog:
  248. LOG X { $$ = XFLAG; }
  249. | LOG Y { $$ = YFLAG; }
  250. | LOG X LOG Y { $$ = XFLAG|YFLAG; }
  251. | LOG Y LOG X { $$ = XFLAG|YFLAG; }
  252. | LOG LOG { $$ = XFLAG|YFLAG; }
  253. ;
  254. plot:
  255. stringlist AT point { plot($1, $3); }
  256. | PLOT stringlist AT point { plot($2, $4); }
  257. | PLOT expr optstring AT point { plotnum($2, $3, $5); }
  258. ;
  259. draw:
  260. drawtype optname linedesc { drawdesc($1, $2, $3, (char *) 0); }
  261. | drawtype optname optdesc string { drawdesc($1, $2, $3, $4->sval); }
  262. | drawtype optname string optdesc { drawdesc($1, $2, $4, $3->sval); }
  263. ;
  264. drawtype:
  265. DRAW
  266. | NEW
  267. ;
  268. next:
  269. NEXT optname AT point optdesc { next($2, $4, $5); }
  270. copy:
  271. COPY copylist { copy(); }
  272. ;
  273. copylist:
  274. copyattr
  275. | copylist copyattr
  276. ;
  277. copyattr:
  278. string { copyfile($1->sval); }
  279. | THRU DEFNAME { copydef($2); }
  280. | UNTIL string { copyuntil($2->sval); }
  281. ;
  282. for:
  283. FOR name FROM expr TO expr BY optop expr DOSTR
  284. { forloop($2, $4, $6, $8, $9, $10); }
  285. | FOR name FROM expr TO expr DOSTR
  286. { forloop($2, $4, $6, '+', 1.0, $7); }
  287. | FOR name '=' expr TO expr BY optop expr DOSTR
  288. { forloop($2, $4, $6, $8, $9, $10); }
  289. | FOR name '=' expr TO expr DOSTR
  290. { forloop($2, $4, $6, '+', 1.0, $7); }
  291. ;
  292. if:
  293. IF if_expr THEN ELSE { $$ = ifstat($2, $3, $4); }
  294. | IF if_expr THEN { $$ = ifstat($2, $3, (char *) 0); }
  295. ;
  296. if_expr:
  297. expr
  298. | string_expr
  299. | if_expr AND string_expr { $$ = $1 && $3; }
  300. | if_expr OR string_expr { $$ = $1 || $3; }
  301. ;
  302. string_expr:
  303. STRING EQ STRING { $$ = strcmp($1,$3) == 0; free($1); free($3); }
  304. | STRING NE STRING { $$ = strcmp($1,$3) != 0; free($1); free($3); }
  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. optname:
  314. NAME { $$ = $1; }
  315. | /* empty */ { $$ = lookup(curr_coord, 1); }
  316. ;
  317. expr:
  318. NUMBER
  319. | assign
  320. | '(' string_expr ')' { $$ = $2; }
  321. | VARNAME { $$ = getvar($1); }
  322. | expr '+' expr { $$ = $1 + $3; }
  323. | expr '-' expr { $$ = $1 - $3; }
  324. | expr '*' expr { $$ = $1 * $3; }
  325. | expr '/' expr { if ($3 == 0.0) {
  326. ERROR "division by 0" WARNING; $3 = 1; }
  327. $$ = $1 / $3; }
  328. | expr '%' expr { if ((long)$3 == 0) {
  329. ERROR "mod division by 0" WARNING; $3 = 1; }
  330. $$ = (long)$1 % (long)$3; }
  331. | '-' expr %prec UMINUS { $$ = -$2; }
  332. | '+' expr %prec UMINUS { $$ = $2; }
  333. | '(' expr ')' { $$ = $2; }
  334. | LOG '(' expr ')' { $$ = Log10($3); }
  335. | EXP '(' expr ')' { $$ = Exp($3 * log(10.0)); }
  336. | expr '^' expr { $$ = pow($1, $3); }
  337. | SIN '(' expr ')' { $$ = sin($3); }
  338. | COS '(' expr ')' { $$ = cos($3); }
  339. | ATAN2 '(' expr ',' expr ')' { $$ = atan2($3, $5); }
  340. | SQRT '(' expr ')' { $$ = Sqrt($3); }
  341. | RAND '(' ')' { $$ = (double)rand() / (double)RAND_MAX; }
  342. | MAX '(' expr ',' expr ')' { $$ = $3 >= $5 ? $3 : $5; }
  343. | MIN '(' expr ',' expr ')' { $$ = $3 <= $5 ? $3 : $5; }
  344. | INT '(' expr ')' { $$ = (long) $3; }
  345. | expr GT expr { $$ = $1 > $3; }
  346. | expr LT expr { $$ = $1 < $3; }
  347. | expr LE expr { $$ = $1 <= $3; }
  348. | expr GE expr { $$ = $1 >= $3; }
  349. | expr EQ expr { $$ = $1 == $3; }
  350. | expr NE expr { $$ = $1 != $3; }
  351. | expr AND expr { $$ = $1 && $3; }
  352. | expr OR expr { $$ = $1 || $3; }
  353. | NOT expr { $$ = !($2); }
  354. ;
  355. assign:
  356. name '=' expr { $$ = setvar($1, $3); }
  357. ;
  358. name:
  359. NAME
  360. | VARNAME
  361. ;
  362. optexpr:
  363. expr
  364. | /* empty */ { $$ = 0.0; }
  365. ;