mapcalc.y 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. %{
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdarg.h>
  6. #include <unistd.h>
  7. #include "mapcalc.h"
  8. #define YYDEBUG 1
  9. #define YYERROR_VERBOSE 1
  10. static int syntax_error_occurred;
  11. %}
  12. %union {
  13. int ival;
  14. double fval;
  15. char *sval;
  16. expression *exp;
  17. expr_list *list;
  18. }
  19. %token <sval> VARNAME
  20. %token <sval> NAME
  21. %token <sval> VARSTRING
  22. %token <sval> STRING
  23. %token <ival> INTEGER
  24. %token <fval> FLOAT
  25. %token <fval> DOUBLE
  26. %token GT GE LT LE EQ NE LOGAND LOGOR LOGAND2 LOGOR2 BITAND BITOR LSH RSH RSHU
  27. %type <exp> exp
  28. %type <exp> exp_atom
  29. %type <exp> exp_pre
  30. %type <exp> exp_pow
  31. %type <exp> exp_mul
  32. %type <exp> exp_add
  33. %type <exp> exp_sh
  34. %type <exp> exp_cmp
  35. %type <exp> exp_eq
  36. %type <exp> exp_bitand
  37. %type <exp> exp_bitor
  38. %type <exp> exp_logand
  39. %type <exp> exp_logor
  40. %type <exp> exp_cond
  41. %type <exp> exp_let
  42. %type <exp> atom_var
  43. %type <exp> atom_map
  44. %type <exp> atom_func
  45. %type <exp> def
  46. %type <ival> mapmod
  47. %type <ival> index
  48. %type <sval> name
  49. %type <sval> map
  50. %type <list> expr_list
  51. %type <list> defs
  52. %type <list> program
  53. %{
  54. static expr_list *result;
  55. extern int yylex(void);
  56. int yyparse(void);
  57. void yyerror(char *s);
  58. %}
  59. %%
  60. program : defs { $$ = result = $1; }
  61. ;
  62. defs : def { $$ = list($1,NULL); }
  63. | def ';' { $$ = list($1,NULL); }
  64. | def ';' defs { $$ = list($1,$3); }
  65. | error ';' defs { $$ = $3; }
  66. ;
  67. def : STRING '=' exp { $$ = binding($1,$3); define_variable($$); }
  68. | NAME '=' exp { $$ = binding($1,$3); define_variable($$); }
  69. | atom_func
  70. ;
  71. map : STRING
  72. | NAME
  73. | name '@' name { $$ = composite($1,$3); }
  74. ;
  75. mapmod : '@' { $$ = '@'; }
  76. | 'r' { $$ = 'r'; }
  77. | 'g' { $$ = 'g'; }
  78. | 'b' { $$ = 'b'; }
  79. | '#' { $$ = '#'; }
  80. | 'y' { $$ = 'y'; }
  81. | 'i' { $$ = 'i'; }
  82. ;
  83. index : INTEGER
  84. | '-' INTEGER { $$ = -$2; }
  85. ;
  86. expr_list : exp { $$ = singleton($1); }
  87. | exp ',' expr_list { $$ = list($1, $3); }
  88. ;
  89. atom_var : VARSTRING { $$ = variable($1); }
  90. | VARNAME { $$ = variable($1); }
  91. ;
  92. atom_map : map '[' index ']' { $$ = mapname($1,'M',$3,0,0); }
  93. | map '[' index ',' index ']'
  94. { $$ = mapname($1,'M',$3,$5,0); }
  95. | map '[' index ',' index ',' index ']'
  96. { $$ = mapname($1,'M',$3,$5,$7);}
  97. | map { $$ = mapname($1,'M',0,0,0); }
  98. | mapmod map '[' index ']'
  99. { $$ = mapname($2,$1,$4,0,0); }
  100. | mapmod map '[' index ',' index ']'
  101. { $$ = mapname($2,$1,$4,$6,0); }
  102. | mapmod map '[' index ',' index ',' index ']'
  103. { $$ = mapname($2,$1,$4,$6,$8); }
  104. | mapmod map { $$ = mapname($2,$1,0,0,0); }
  105. ;
  106. atom_func : name '(' ')' { $$ = function($1, NULL); }
  107. | name '(' expr_list ')'
  108. { $$ = function($1, $3); }
  109. ;
  110. exp_atom : '(' exp ')' { $$ = $2; }
  111. | atom_var
  112. | atom_map
  113. | atom_func
  114. | INTEGER { $$ = constant_int($1); }
  115. | FLOAT { $$ = constant_float($1); }
  116. | DOUBLE { $$ = constant_double($1); }
  117. ;
  118. exp_pre : exp_atom
  119. | '-' exp_atom { $$ = operator("neg","-",1,singleton($2)); }
  120. | '~' exp_atom { $$ = operator("bitnot","~",1,singleton($2)); }
  121. | '!' exp_atom { $$ = operator("not","!",1,singleton($2)); }
  122. ;
  123. exp_pow : exp_pre
  124. | exp_pre '^' exp_pow { $$ = operator("pow","^",2,pair($1,$3)); }
  125. ;
  126. exp_mul : exp_pow
  127. | exp_mul '*' exp_pow { $$ = operator("mul","*",3,pair($1,$3)); }
  128. | exp_mul '/' exp_pow { $$ = operator("div","/",3,pair($1,$3)); }
  129. | exp_mul '%' exp_pow { $$ = operator("mod","%",3,pair($1,$3)); }
  130. ;
  131. exp_add : exp_mul
  132. | exp_add '+' exp_mul { $$ = operator("add","+",4,pair($1,$3)); }
  133. | exp_add '-' exp_mul { $$ = operator("sub","-",4,pair($1,$3)); }
  134. ;
  135. exp_sh : exp_add
  136. | exp_sh LSH exp_add { $$ = operator("shiftl","<<",5,pair($1,$3)); }
  137. | exp_sh RSH exp_add { $$ = operator("shiftr",">>",5,pair($1,$3)); }
  138. | exp_sh RSHU exp_add { $$ = operator("shiftru",">>>",5,pair($1,$3)); }
  139. ;
  140. exp_cmp : exp_sh
  141. | exp_cmp GT exp_sh { $$ = operator("gt",">", 6,pair($1,$3)); }
  142. | exp_cmp GE exp_sh { $$ = operator("ge",">=",6,pair($1,$3)); }
  143. | exp_cmp LT exp_sh { $$ = operator("lt","<", 6,pair($1,$3)); }
  144. | exp_cmp LE exp_sh { $$ = operator("le","<=",6,pair($1,$3)); }
  145. exp_eq : exp_cmp
  146. | exp_eq EQ exp_cmp { $$ = operator("eq","==",7,pair($1,$3)); }
  147. | exp_eq NE exp_cmp { $$ = operator("ne","!=",7,pair($1,$3)); }
  148. ;
  149. exp_bitand : exp_eq
  150. | exp_bitand BITAND exp_eq { $$ = operator("bitand","&",8,pair($1,$3)); }
  151. ;
  152. exp_bitor : exp_bitand
  153. | exp_bitor BITOR exp_bitand { $$ = operator("bitor", "|",9,pair($1,$3)); }
  154. ;
  155. exp_logand : exp_bitor
  156. | exp_logand LOGAND exp_bitor { $$ = operator("and","&&",10,pair($1,$3)); }
  157. | exp_logand LOGAND2 exp_bitor { $$ = operator("and2","&&&",10,pair($1,$3)); }
  158. ;
  159. exp_logor : exp_logand
  160. | exp_logor LOGOR exp_logand { $$ = operator("or", "||",11,pair($1,$3)); }
  161. | exp_logor LOGOR2 exp_logand { $$ = operator("or2", "|||",11,pair($1,$3)); }
  162. ;
  163. exp_cond : exp_logor
  164. | exp_logor '?' exp_cond ':' exp_cond
  165. { $$ = operator("if","?:",12,triple($1,$3,$5)); }
  166. ;
  167. exp_let : exp_cond
  168. | name '=' exp_let { $$ = binding($1,$3); define_variable($$); }
  169. ;
  170. exp : exp_let { if (syntax_error_occurred) {syntax_error_occurred = 0; YYERROR; } else $$ = $1; }
  171. ;
  172. name : NAME
  173. | VARNAME
  174. ;
  175. %%
  176. void syntax_error(const char *fmt, ...)
  177. {
  178. va_list va;
  179. va_start(va, fmt);
  180. vfprintf(stderr, fmt, va);
  181. va_end(va);
  182. fprintf(stderr, "\n");
  183. syntax_error_occurred = 1;
  184. }
  185. void yyerror(char *s)
  186. {
  187. fprintf(stderr, "%s\n", s);
  188. syntax_error_occurred = 0;
  189. }
  190. static expr_list *parse(void)
  191. {
  192. #if 0
  193. yydebug = 1;
  194. #endif
  195. syntax_error_occurred = 0;
  196. if (yyparse() != 0)
  197. {
  198. fprintf(stderr, "Parse error\n");
  199. return NULL;
  200. }
  201. if (syntax_error_occurred)
  202. {
  203. fprintf(stderr, "Syntax error\n");
  204. return NULL;
  205. }
  206. return result;
  207. }
  208. expr_list *parse_string(const char *s)
  209. {
  210. initialize_scanner_string(s);
  211. return parse();
  212. }
  213. expr_list *parse_stream(FILE *fp)
  214. {
  215. expr_list *e;
  216. initialize_scanner_stream(fp);
  217. if (isatty(fileno(fp)))
  218. fputs("Enter expressions, \"end\" when done.\n", stderr);
  219. e = parse();
  220. if (isatty(fileno(fp)))
  221. fputs("\n", stderr);
  222. return e;
  223. }