Mercurial > hg > dmlib
changeset 740:48c48e94d87f
More work on the evaluator. Still broken, of course.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 22 Apr 2013 09:37:34 +0300 |
parents | 8bf67daf4030 |
children | 9efcdbe5a299 |
files | dmeval.c dmeval.h dmevalw.c |
diffstat | 3 files changed, 168 insertions(+), 103 deletions(-) [+] |
line wrap: on
line diff
--- a/dmeval.c Sun Apr 21 20:40:54 2013 +0300 +++ b/dmeval.c Mon Apr 22 09:37:34 2013 +0300 @@ -242,15 +242,6 @@ } -static DMEvalNode *dm_eval_peek_node(DMEvalNode **list) -{ - if (*list == NULL) - return NULL; - - return (*list)->prev; -} - - static DMEvalNode *dm_eval_insert_node(DMEvalNode **list, DMEvalNode *node) { if (*list != NULL) @@ -316,19 +307,20 @@ enum { - PARSE_NONE = 0x0000, - PARSE_START = 0x1000, - PARSE_END = 0x2000, - PARSE_ERROR = 0x8000, + PARSE_NONE = 0x0000, + PARSE_START = 0x1000, + PARSE_END = 0x2000, + PARSE_ERROR = 0x8000, - PARSE_IDENT = 0x0001, - PARSE_CONST = 0x0002, - PARSE_OPER = 0x0004, // All operators - PARSE_OPER2 = 0x0008, // '-' only - PARSE_SUBEXPR = 0x0010, - PARSE_ARGS = 0x0020, + PARSE_IDENT = 0x0001, // Any identifier (variable, function name) + PARSE_CONST = 0x0002, // Constant value (n, n.nnn, etc) + PARSE_OPER = 0x0004, // All operators + PARSE_OPER_UNARY = 0x0008, // Unary operators ~, - + PARSE_SUBEXPR_START = 0x0010, // ( ... + PARSE_SUBEXPR_END = 0x0020, // ) + PARSE_ARGS = 0x0040, // function args: (xxx[, yyy ...]) - PARSE_NORMAL = PARSE_CONST | PARSE_IDENT | PARSE_SUBEXPR | PARSE_OPER2, + PARSE_NORMAL = PARSE_CONST | PARSE_IDENT | PARSE_SUBEXPR_START | PARSE_OPER_UNARY, }; #define DM_CHECK(x) { if (mode & PARSE_ ## x ) { if (str[0]) strcat(str, " or "); strcat(str, # x ); } } @@ -342,8 +334,9 @@ DM_CHECK(IDENT); DM_CHECK(CONST); DM_CHECK(OPER); - DM_CHECK(OPER2); - DM_CHECK(SUBEXPR); + DM_CHECK(OPER_UNARY); + DM_CHECK(SUBEXPR_START); + DM_CHECK(SUBEXPR_END); DM_CHECK(ARGS); return dm_strdup(str); @@ -402,7 +395,7 @@ if (ev->mode != PARSE_ERROR) { dm_set_mode(ev, PARSE_START); - ev->expect = PARSE_OPER | PARSE_END; + ev->expect = PARSE_OPER | PARSE_SUBEXPR_END; c = tmp; } } @@ -456,7 +449,10 @@ dm_set_mode(ev, func != NULL ? PARSE_ARGS : PARSE_SUBEXPR); else if (*c == '-') - dm_set_mode(ev, (ev->prev == PARSE_START || ev->prev == PARSE_OPER) ? PARSE_OPER2 : PARSE_OPER); + dm_set_mode(ev, (ev->prev == PARSE_START || ev->prev == PARSE_OPER || ev->prev == PARSE_OPER_UNARY) ? PARSE_OPER_UNARY : PARSE_OPER); + + else if (*c == '~') + dm_set_mode(ev, PARSE_OPER_UNARY); else if (strchr("+*/<>%&|!^", *c)) dm_set_mode(ev, PARSE_OPER); @@ -497,11 +493,23 @@ } else { - if (isdigit(*c) || (*c == '.' && !decimal)) + if (isdigit(*c)) + { + tmpStr[tmpStrLen++] = *c++; + } + else + if (*c == '.') { - if (*c == '.') + if (!decimal) + { + tmpStr[tmpStrLen++] = *c++; decimal = TRUE; - tmpStr[tmpStrLen++] = *c++; + } + else + { + dm_eval_err(ev, "Invalid constant expression near '%s'.\n", c); + dm_set_mode(ev, PARSE_ERROR); + } } else { @@ -521,8 +529,30 @@ } break; + case PARSE_OPER_UNARY: + { + int op = OP_NONE; + + switch (*c) + { + case '-': op = OP_SUB_UNARY; c++; break; + case '~': op = OP_COMPLEMENT; c++; break; + } + + if (op != OP_NONE) + { + if ((node = dm_eval_add_node(list, op)) != NULL) + { + ev->expect = PARSE_NORMAL; + dm_set_mode(ev, PARSE_START); + } + else + dm_set_mode(ev, PARSE_ERROR); + } + } + break; + case PARSE_OPER: - case PARSE_OPER2: { int op = OP_NONE; @@ -536,6 +566,7 @@ case '&': op = OP_AND; c++; break; case '^': op = OP_XOR; c++; break; case '|': op = OP_OR; c++; break; + case '>': if (c[1] == '>') { @@ -544,8 +575,8 @@ } else { - dm_eval_err(ev, "Syntax error near '%s'.\n", c); - dm_set_mode(ev, PARSE_ERROR); + op = (c[1] == '=') ? OP_GT_EQ : OP_GT; + c++; } break; @@ -557,29 +588,21 @@ } else { - dm_eval_err(ev, "Syntax error near '%s'.\n", c); - dm_set_mode(ev, PARSE_ERROR); + op = (c[1] == '=') ? OP_LT_EQ : OP_LT; + c++; } break; default: - dm_eval_err(ev, "Unknown operator '%c'.\n", *c); + dm_eval_err(ev, "Unknown operator '%c' at %s\n", *c, c); dm_set_mode(ev, PARSE_ERROR); } if (op != OP_NONE) { - if (ev->mode == PARSE_OPER2 && op == OP_SUB && - (node = dm_eval_add_node(list, op)) != NULL) + if ((node = dm_eval_add_node(list, op)) != NULL) { - ev->expect = PARSE_NORMAL; - dm_set_mode(ev, PARSE_START); - } - else - if (ev->mode == PARSE_OPER && - (node = dm_eval_add_node(list, op)) != NULL) - { - ev->expect = PARSE_NORMAL | PARSE_OPER2; + ev->expect = PARSE_NORMAL | PARSE_OPER_UNARY; dm_set_mode(ev, PARSE_START); } else @@ -602,7 +625,7 @@ else { tmpStr[tmpStrLen] = 0; - dm_eval_err(ev, "Identifier too long! ('%s')\n", tmpStr); + dm_eval_err(ev, "Identifier too long! ('%s') near %s\n", tmpStr, c); } } else @@ -679,35 +702,12 @@ static int dm_eval_reorder_pass0(DMEvalContext *ev, const DMEvalNode *node, DMEvalNode **result) { - DMEvalNode *tmp, *sub; + DMEvalNode *tmp; int i, res; for (; node != NULL; node = node->next) switch (node->op) { - case OP_SUB: - if ((tmp = dm_eval_peek_node(result)) == NULL || tmp->op <= OP_FUNC) - { - // Add subexpression node - if ((sub = dm_eval_add_node(result, OP_SUBEXPR)) == NULL) - return -3; - - // Add this operator into subexpression - dm_eval_add_node(&(sub->subexpr), node->op); - - // Next node - node = node->next; - if (node == NULL) - return -72; - - dm_eval_push_node(&(sub->subexpr), node); - } - else - if (dm_eval_push_node(result, node) == NULL) - return -32; - - break; - case OP_FUNC: if ((tmp = dm_eval_add_node(result, OP_FUNC)) == NULL) return -1; @@ -739,6 +739,48 @@ } +static int dm_eval_reorder_pass1(DMEvalContext *ev, const DMEvalNode *node, DMEvalNode **result, + const int op1, const int op2, const int op3) +{ + DMEvalNode *sub; + + for (; node != NULL; node = node->next) + { + if (!node->ok && node->op == op1 && + (node->prev == NULL || node->prev->op < OP_FUNC)) + { + if (node->next == NULL || node->next->op == op2) + { + if (dm_eval_push_node(result, node) == NULL) + return -32; + } + else + { + // Add subexpression node + if ((sub = dm_eval_add_node(result, OP_SUBEXPR)) == NULL) + return -3; + + // Add this operator into subexpression + dm_eval_add_node(&(sub->subexpr), node->op); + + // Next node + node = node->next; + if (node == NULL) + return -72; + + dm_eval_push_node(&(sub->subexpr), node); + } + } + else + if (dm_eval_push_node(result, node) == NULL) + return -32; + } + + + return 0; +} + + static int dm_eval_reorder_passN(DMEvalContext *ev, const DMEvalNode *node, DMEvalNode **result, const int op1, const int op2, const int op3) { @@ -781,7 +823,7 @@ } -#if 0 +#if 1 #define RO_DEBUG(x, y) do { fprintf(stderr, x); dm_print_optree(stderr, ev, y); } while (0) #else #define RO_DEBUG(x, y) /* stub */ @@ -790,43 +832,46 @@ int dm_eval_reorder(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result) { - DMEvalNode *tmp1 = NULL, *tmp2 = NULL, *tmp3 = NULL; + DMEvalNode *tmp1 = NULL, *tmp2 = NULL, *tmp3 = NULL, *tmp4 = NULL, *tmp5 = NULL; int res; RO_DEBUG("REORD: ", node); - res = dm_eval_reorder_pass0(ev, node, &tmp1); + // Pass 0 + if ((res = dm_eval_reorder_pass0(ev, node, &tmp1)) != 0) + goto out; RO_DEBUG("PASS0: ", tmp1); - - if (res != 0) - { - dm_eval_free(tmp1); - return res; - } + + // Pass 1 + if ((res = dm_eval_reorder_pass1(ev, tmp1, &tmp2, OP_COMPLEMENT, -1, -1)) != 0) + goto out; + RO_DEBUG("PASS1: ", tmp2); + + // Pass 2 + if ((res = dm_eval_reorder_pass1(ev, tmp2, &tmp3, OP_SUB_UNARY, -1, -1)) != 0) + goto out; + RO_DEBUG("PASS2: ", tmp2); - res = dm_eval_reorder_passN(ev, tmp1, &tmp2, OP_MUL, OP_DIV, OP_MOD); - RO_DEBUG("PASS1: ", tmp2); + // Pass 2 + if ((res = dm_eval_reorder_passN(ev, tmp3, &tmp4, OP_MUL, OP_DIV, OP_MOD)) != 0) + goto out; + RO_DEBUG("PASS3: ", tmp2); + + // Pass 3 + if ((res = dm_eval_reorder_passN(ev, tmp4, &tmp5, OP_SUB, OP_ADD, -1)) != 0) + goto out; + RO_DEBUG("PASS4: ", tmp3); + + res = dm_eval_reorder_passN(ev, tmp5, result, OP_LSHIFT, OP_RSHIFT, -1); + RO_DEBUG("PASS5: ", *result); + +out: dm_eval_free(tmp1); - - if (res != 0) - { - dm_eval_free(tmp2); - return res; - } + dm_eval_free(tmp2); + dm_eval_free(tmp3); + dm_eval_free(tmp4); + dm_eval_free(tmp5); - res = dm_eval_reorder_passN(ev, tmp2, &tmp3, OP_SUB, OP_ADD, -1); - RO_DEBUG("PASS2: ", tmp3); - dm_eval_free(tmp2); - if (res != 0) - { - dm_eval_free(tmp3); - return res; - } - - res = dm_eval_reorder_passN(ev, tmp3, result, OP_LSHIFT, OP_RSHIFT, -1); - RO_DEBUG("PASS3: ", *result); - dm_eval_free(tmp3); - return res; } @@ -940,6 +985,8 @@ case OP_ADD: case OP_SUB: + case OP_SUB_UNARY: + case OP_COMPLEMENT: if (dm_eval_get(ev, node->next, &tmp) != 0) return -6; @@ -947,6 +994,8 @@ { case OP_ADD: result += tmp; break; case OP_SUB: result -= tmp; break; + case OP_SUB_UNARY: result -= tmp; break; + case OP_COMPLEMENT: result = DMCONVTYPE ~(DMCONVTYPE tmp); break; } node = node->next;