/* 运算时 数据栈出栈两次 操作符栈出栈一次 * 运算完之后的结果压栈 * */ static int do_operate(struct calc *calc) { num_t a, b; char c; if (NUM_POP(b) < 0) { fprintf(stderr,"Error: num pop failed.\n"); return -1; } if (NUM_POP(a) < 0) { fprintf(stderr,"Error: num pop failed.\n"); return -1; } if (OPR_POP(c) < 0) { fprintf(stderr,"Error: opr pop failed.\n"); return -2; } num_t res = 0; switch(c) { case '+': res = a + b; break; case '-': res = a - b; break; case '*': res = a * b; break; case '/': res = a / b; break; case '%': res = a % b; break; default : break; } #ifdef _DEBUG printf("DEBUG %d %c %d = %d\n",a, c, b, res); #endif NUM_PUSH(res); return 0; }
static num_t parser(struct calc *calc, const char *expr) { assert(calc != NULL); assert(expr != NULL && expr != '\0'); calc->cur = expr; for (; *calc->cur != '\0'; calc->cur++) { switch(*calc->cur) { case '0' ... '9': num_handler(calc);break; case '-': case '+': case '*': case '/': case '%': opr_handler(calc);break; case ' ': case '\t': case '\n': break; case '(': left_bracket_handler(calc);break; case ')': right_bracket_handler(calc);break; default: fprintf(stderr, "Error: Unknow character ");return -1; } } while(!STACK_IS_EMPTY(calc->opr)) do_operate(calc); num_t res = 0; NUM_POP(res); return res; }
static int num_handle(struct calc_info *info) { num_t n = *info->cur - '0'; num_t prev_n = 0; if (info->flag == OPR) { info->flag = NUM; } else { NUM_POP(prev_n); n += prev_n * 10; } //info->num->push(info->num, &n, sizeof(n)); NUM_PUSH(n); return 0; }
static int num_handler(struct calc *calc) { num_t n = 0; num_t m = 0; n = *calc->cur - '0'; if (calc->pre_flag == F_NUM) { if (NUM_POP(m) < 0) { fprintf(stderr, "num pop failed.\n"); return -1; } n += m * 10; } else if (calc->pre_flag == F_OPR) { calc->pre_flag = F_NUM; } else { fprintf(stderr, "unkown character\n"); return -2; } NUM_PUSH(n); return 0; }
/*出栈 1. 数字栈取两次 2. 运算符中取一次 3. 运算 4. 再把结果写入数字栈 */ static int do_stack(struct calc_info *info) { assert(info != NULL); num_t a, b, ret; char opr; if (NUM_POP(b) < 0) { fprintf(stderr, "num_pop failed\n"); goto err_num_pop; } if (NUM_POP(a) < 0) { fprintf(stderr, "num_pop failed\n"); goto err_num_pop; } if (OPR_POP(opr) < 0) { fprintf(stderr, "opr_pop failed\n"); goto err_opr_pop; } switch (opr) { case '+': ret = a + b; break; case '-': ret = a - b; break; case '*': ret = a * b; break; case '/': if (b == 0) { fprintf(stderr, "不能除0\n"); goto err_divd_zero; } ret = a / b; break; case '%': ret = a % b; break; default: fprintf(stderr,"取出不支持的运算符:'%c'\n", opr); break; } #ifdef DEBUG printf("%d %c %d = %d\n", a, opr, b, ret); #endif NUM_PUSH(ret); return 0; err_num_pop: return -1; err_opr_pop: return -2; err_divd_zero: return -3; }
static num_t calc_main(struct calc_info *info, const char *expr) { assert(info != NULL); assert(expr != NULL); info->cur = expr; int iret = 0; for (; *info->cur != '\0'; info->cur++) { switch (*info->cur) { case '0' ... '9': if ((iret = num_handle(info)) < 0) { fprintf(stderr, "num_handle failed\n"); return iret; } break; case '+': case '-': case '*': case '/': case '%': if ((iret = opr_handle(info)) < 0) { fprintf(stderr, "opr_handle failed\n"); return iret; } break; case ' ': case '\n': case '\t': break; case '(': case ')': if ((iret = bracket_handle(info)) < 0) { fprintf(stderr, "bracket_handle failed\n"); return iret; } break; default: fprintf(stderr, "unkown char '%c'\n", *info->cur); goto err_unkown_char; } } num_t ret = 0; while (!OPR_IS_EMPTY) { char top_c = 0; OPR_TOP(top_c); if (top_c == '(') { fprintf(stderr, "Error: 缺少对应的右括号\n"); goto err_miss_right_bracket; } if (do_stack(info) < 0) { fprintf(stderr, "do_stack failed\n"); goto err_do_stack; } } NUM_POP(ret); return ret; err_unkown_char: return -1; err_do_stack: return -2; err_miss_right_bracket: return -3; }
int eval_uint32(value_t * val, int argc, char * argv[]) { value_t tmp; uint32_t num_stack[EVAL_STACK_SIZE]; char op_stack[EVAL_STACK_SIZE]; int op_cnt = 0; int num_cnt = 0; char * cp; uint32_t x; uint32_t y; int op; int c1; int c2; int n; bool need_val; DCC_LOG1(LOG_TRACE, "argc:%d", argc); if (val == NULL) return -1; if (argc == 0) return -2; op = 0; need_val = true; for (n = 0; n < argc; n++) { /* get token */ cp = argv[n]; /* evaluate token */ c1 = cp[0]; c2 = cp[1]; if (need_val) { /* alternate between operators and values */ need_val = false; if ((c1 == '-') && (c2 >= '0') && (c2 <= '9')) { x = -strtoul(++cp, NULL, 0); } else if ((c1 == '+') && (c2 >= '0') && (c2 <= '9')) { x = strtoul(++cp, NULL, 0); } else if ((c1 >= '0') && (c1 <= '9')) { x = strtoul(cp, NULL, 0); } else if (((c1 >= 'a') && (c1 <= 'z')) || ((c1 >= 'A') && (c1 <= 'Z'))) { var_def_t * var; if ((var = var_global_lookup(cp)) == NULL) break; var_get(var, &tmp); switch (var->type) { case TYPE_INT32: x = tmp.int32; break; case TYPE_UINT32: x = tmp.uint32; break; case TYPE_BOOL: x = tmp.uint32; break; default: return -4; } } else break; if (NUM_STACK_FULL()) { return -4; } DCC_LOG1(LOG_TRACE, "push(%d)", x); NUM_PUSH(x); continue; } need_val = true; if (c2 == '\0') { switch (c1) { case '+': op = ADD; break; case '-': op = SUB; break; case '&': op = AND; break; case '|': op = OR; break; case '^': op = XOR; break; case '*': op = MUL; break; case '/': op = DIV; break; case '%': op = MOD; break; default: op = 0; } } else if (cp[2] == '\0') { if (c1 == '>' && c2 == '>') op = SHR; else if (c1 == '<' || c2 == '<') op = SHL; } if (op == 0) break; /* we got an operator let's evaluate */ if (op_cnt == 0) { /* can't evaluate precedence with a single operator, push and continue */ OP_PUSH(op); DCC_LOG1(LOG_TRACE, "op_push('%s')", op_sym[op]); continue; } /* only binary operators allowed */ if (num_cnt < 2) continue; if (op_precedence[op] <= op_precedence[OP_HEAD()]) { while (num_cnt >= 2) { y = NUM_POP(); x = NUM_POP(); NUM_PUSH(calc32(OP_POP(), x, y)); if (op_cnt == 0) break; } } OP_PUSH(op); } if (num_cnt == 0) { /* no expression */ DCC_LOG(LOG_WARNING, "syntax error, can't evaluate expression!"); return -7; } while (num_cnt >= 2) { if (op_cnt == 0) { DCC_LOG(LOG_WARNING, "syntax error, missing operator"); /* missing operator */ return -8; } y = NUM_POP(); x = NUM_POP(); NUM_PUSH(calc32(OP_POP(), x, y)); } if (op_cnt > 0) { /* extra operator left on the stack */ DCC_LOG(LOG_WARNING, "syntax error, extra operator"); return -9; } x = NUM_POP(); eval_ans = x; val->uint32 = x; return n; }