cpp_exp.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // TODO: ternary
  2. // name , arity, precedence, associativity (L = 0, R = 1)
  3. #define OPERATOR_LIST \
  4. X(PLUS, 2, 40, 0) \
  5. X(MINUS, 2, 40, 0) \
  6. X(MUL, 2, 30, 0) \
  7. X(DIV, 2, 30, 0) \
  8. X(MOD, 2, 30, 0) \
  9. X(BIT_AND, 2, 80, 0) \
  10. X(BIT_OR, 2, 82, 0) \
  11. X(BIT_NOT, 1, 20, 1) \
  12. X(BIT_XOR, 2, 81, 0) \
  13. X(SHR, 2, 50, 0) \
  14. X(SHL, 2, 50, 0) \
  15. X(LOGIC_AND, 2, 90, 0) \
  16. X(LOGIC_OR, 2, 91, 0) \
  17. X(LOGIC_NOT, 1, 20, 1) \
  18. X(GT, 2, 60, 0) \
  19. X(LT, 2, 60, 0) \
  20. X(GTE, 2, 60, 0) \
  21. X(LTE, 2, 60, 0) \
  22. X(NEQ, 2, 70, 0) \
  23. X(EQ, 2, 70, 0) \
  24. X(TERN, 3, 92, 0) \
  25. X(COLON, 1, 92, 0) \
  26. X(UNARY_NEG, 1, 20, 1) \
  27. X(DEFINED, 1, 10, 1) \
  28. X(LPAREN, -1, 127, 0) \
  29. X(RPAREN, -1, -1, 0) \
  30. #define X(a, ...) OP_##a,
  31. enum {
  32. OP_NONE = 0,
  33. OPERATOR_LIST
  34. };
  35. #undef X
  36. #define X(a, ...) [OP_##a] = #a,
  37. char* operator_names[] = {
  38. [OP_NONE] = "none",
  39. OPERATOR_LIST
  40. };
  41. #undef X
  42. #define X(a, b, c, d) [OP_##a] = {OP_##a, b, c, d},
  43. cpp_stack_token_t operator_data[] = {
  44. [OP_NONE] = {-1, 0, 127, 0},
  45. OPERATOR_LIST
  46. };
  47. #undef X
  48. int is_defined(cpp_tu_t* tu, lexer_token_t* name) {
  49. return NULL != get_macro_def(tu, name);
  50. }
  51. int is_integer(lexer_token_t* t, long* val) {
  52. char* end;
  53. long l = strtol(t->text, &end, 0);
  54. if(end != t->text + strlen(t->text)) {
  55. if(val) *val = 0;
  56. return 0; // not a valid integer
  57. }
  58. if(val) *val = l;
  59. return 1;
  60. }
  61. int probe_operator_type(lexer_token_t* t) {
  62. char* s = t->text;
  63. int type = OP_NONE;
  64. switch(s[0]) {
  65. case '=':
  66. switch(s[1]) {
  67. case '=': type = OP_EQ; break;
  68. }
  69. break;
  70. case '<':
  71. switch(s[1]) {
  72. case '<': type = OP_SHL; break;
  73. case '=': type = OP_LTE; break;
  74. default: type = OP_LT; break;
  75. }
  76. break;
  77. case '>':
  78. switch(s[1]) {
  79. case '>': type = OP_SHR; break;
  80. case '=': type = OP_GTE; break;
  81. default: type = OP_GT; break;
  82. }
  83. break;
  84. case '!':
  85. switch(s[1]) {
  86. case '=': type = OP_NEQ; break;
  87. default: type = OP_LOGIC_NOT; break;
  88. }
  89. break;
  90. case '~': type = OP_BIT_NOT; break;
  91. case '^': type = OP_BIT_XOR; break;
  92. case '|':
  93. switch(s[1]) {
  94. case '|': type = OP_LOGIC_OR; break;
  95. default: type = OP_BIT_OR; break;
  96. }
  97. break;
  98. case '&':
  99. switch(s[1]) {
  100. case '&': type = OP_LOGIC_AND; break;
  101. default: type = OP_BIT_AND; break;
  102. }
  103. break;
  104. case '/': type = OP_DIV; break;
  105. case '*': type = OP_MUL; break;
  106. case '%': type = OP_MOD; break;
  107. case '-': type = OP_MINUS; break;
  108. case '+': type = OP_PLUS; break;
  109. case '?': type = OP_TERN; break;
  110. case ':': type = OP_COLON; break;
  111. case ')': type = OP_RPAREN; break;
  112. case '(': type = OP_LPAREN; break;
  113. }
  114. return type;
  115. }
  116. void reduce(cpp_tu_t* tu, cpp_context_t* ctx) {
  117. int op;
  118. /*
  119. printf("!reducing:\n");
  120. VEC_EACH(&ctx->value_stack, vi, v) {
  121. printf(" #%ld - %s\n", vi, v->text);
  122. }
  123. */
  124. VEC_POP(&ctx->oper_stack, op);
  125. long lval, rval, tval, res = 0;
  126. lexer_token_t* ltok, *rtok, *ttok;
  127. if(operator_data[op].arity > 0) {
  128. VEC_POP(&ctx->value_stack, rtok);
  129. is_integer(rtok, &rval);
  130. }
  131. if(operator_data[op].arity > 1) {
  132. VEC_POP(&ctx->value_stack, ltok);
  133. is_integer(ltok, &lval);
  134. }
  135. if(operator_data[op].arity > 2) {
  136. VEC_POP(&ctx->value_stack, ttok);
  137. is_integer(ttok, &tval);
  138. }
  139. switch(op) {
  140. case OP_EQ: res = lval == rval; break;
  141. case OP_NEQ: res = lval != rval; break;
  142. case OP_GTE: res = lval >= rval; break;
  143. case OP_LTE: res = lval <= rval; break;
  144. case OP_GT: res = lval > rval; break;
  145. case OP_LT: res = lval < rval; break;
  146. case OP_PLUS: res = lval + rval; break;
  147. case OP_MINUS: res = lval - rval; break;
  148. case OP_MUL: res = lval * rval; break;
  149. case OP_BIT_NOT: res = ~rval; break;
  150. case OP_LOGIC_NOT: res = !rval; break;
  151. case OP_LOGIC_AND: res = lval && rval; break;
  152. case OP_LOGIC_OR: res = lval || rval; break;
  153. case OP_BIT_AND: res = lval & rval; break;
  154. case OP_BIT_OR: res = lval | rval; break;
  155. case OP_BIT_XOR: res = lval ^ rval; break;
  156. case OP_SHR: res = lval >> rval; break;
  157. case OP_SHL: res = lval << rval; break;
  158. case OP_UNARY_NEG: res = -rval; break;
  159. case OP_COLON:
  160. // VEC_PUSH(&ctx->value_stack, ttok);
  161. // VEC_PUSH(&ctx->value_stack, ltok);
  162. res = rval; //VEC_PUSH(&ctx->value_stack, rtok);
  163. break;
  164. case OP_TERN:
  165. res = tval ? lval : rval;
  166. break;
  167. // these are just hacked because this parser doesn't handle logical operator shortcutting
  168. case OP_DIV: rval != 0 ? res = lval / rval : 0; break;
  169. case OP_MOD: rval != 0 ? res = lval % rval : 0; break;
  170. case OP_DEFINED:
  171. res = is_defined(tu, rtok);
  172. break;
  173. case OP_LPAREN:
  174. // printf(" evaluating lparen!!!!\n");
  175. return;
  176. case OP_RPAREN:
  177. // printf(" evaluating rparen!!!!\n");
  178. return;
  179. }
  180. // printf(" %s - res %ld, tval: %ld, lval: %ld, rval: %ld\n", operator_names[op], res, tval, lval, rval);
  181. // BUG: this leaks...
  182. lexer_token_t* res_tok = malloc(sizeof(*res_tok));
  183. res_tok->type = LEXER_TOK_NUMBER;
  184. res_tok->text = sprintfdup("%ld", res);
  185. VEC_PUSH(&ctx->value_stack, res_tok);
  186. }
  187. long eval_exp(cpp_tu_t* tu, cpp_context_t* ctx, cpp_token_list_t* exp) {
  188. char* _defined = strint_(tu->str_table, "defined");
  189. int was_oper = 1;
  190. VEC_TRUNC(&ctx->oper_stack);
  191. VEC_TRUNC(&ctx->value_stack);
  192. VEC_EACH(&exp->tokens, ni, n) {
  193. if(n->type == LEXER_TOK_NUMBER || n->type == LEXER_TOK_IDENT) {
  194. VEC_PUSH(&ctx->value_stack, n);
  195. // printf(" pushing %s to value stack\n", n->text);
  196. was_oper = 0;
  197. }
  198. if(n->type == LEXER_TOK_PUNCT) {
  199. // check for operators, rest are 0
  200. int op = probe_operator_type(n);
  201. if(op == OP_LPAREN) {
  202. VEC_PUSH(&ctx->oper_stack, op);
  203. // printf(" pushing lparen to the stack\n");
  204. was_oper = 1;
  205. }
  206. else if(op == OP_RPAREN) {
  207. // printf(" executing rparen\n");
  208. do {
  209. int top = VEC_TAIL(&ctx->oper_stack);
  210. // printf(" - %s\n", operator_names[top]);
  211. if(top == OP_LPAREN) {
  212. // printf(" - found lparen, exiting loop (top value: --)\n" /*VEC_TAIL(&ctx->value_stack)*/);
  213. VEC_POP1(&ctx->oper_stack);
  214. break;
  215. }
  216. reduce(tu, ctx);
  217. } while(VEC_LEN(&ctx->oper_stack));
  218. was_oper = 0;
  219. }
  220. else if(op == OP_MINUS && was_oper) {
  221. VEC_PUSH(&ctx->oper_stack, OP_UNARY_NEG);
  222. // printf(" pushing operator UNARY_NEG to the stack\n");
  223. }
  224. else if(op > 0) {
  225. int top = 0;
  226. if(VEC_LEN(&ctx->oper_stack))
  227. top = VEC_TAIL(&ctx->oper_stack);
  228. // printf("top: %d, op: %d\n", top, op);
  229. if(operator_data[top].prec < operator_data[op].prec) {
  230. // if(top.prec == r->prec && r->assoc == STI_OP_ASSOC_LEFT) break;
  231. reduce(tu, ctx);
  232. }
  233. VEC_PUSH(&ctx->oper_stack, op);
  234. // printf(" pushing operator %s to the stack\n", operator_names[op]);
  235. was_oper = 1;
  236. }
  237. else {
  238. VEC_PUSH(&ctx->value_stack, n);
  239. // printf(" pushing 0 to the stack due to '%s'\n", n->text);
  240. was_oper = 0;
  241. }
  242. }
  243. }
  244. // finish off the operator stack
  245. while(VEC_LEN(&ctx->oper_stack)) {
  246. reduce(tu, ctx);
  247. }
  248. lexer_token_t* final_tok;
  249. long final = 0;
  250. VEC_POP(&ctx->value_stack, final_tok);
  251. final = strtol(final_tok->text, NULL, 0);
  252. return final;
  253. }