📄 ccalc.cpp
字号:
pos += 2; return LSR; } else if (buf[pos+1] == '=') { pos += 2; return SETASR; } else { pos += 1; return ASR; } } else if (buf[pos] == '=') { pos += 1; return GE; } return GT; case '=': if (buf[pos] == '=') { pos += 1; return EQ; } return SET; case '&': if (buf[pos] == '&') { pos += 1; return AND; } else if (buf[pos] == '=') { pos += 1; return SETAND; } return AND; case '|': if (buf[pos] == '|') { pos += 1; return OR; } else if (buf[pos] == '=') { pos += 1; return SETOR; } return OR; case '^': if (buf[pos] == '=') { pos += 1; return SETXOR; } return XOR; case ',': return COMMA; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int_t ival; double fval; int ierr, ferr; char *ipos, *fpos;#ifdef _WIN32 int n = 0; ierr = sscanf(buf+pos-1, "%" INT_FORMAT "i%n", &ival, &n) != 1; ipos = buf+pos-1+n;#else errno = 0; #if SIZEOF_LONG == 8 ival = strtoul(buf+pos-1, &ipos, 0); #else ival = strtoull(buf+pos-1, &ipos, 0); #endif ierr = errno;#endif errno = 0; fval = strtod(buf+pos-1, &fpos); ferr = errno; if (ierr && ferr) { error("bad numeric constant"); return ERROR; } if (v_sp == max_stack_size) { error("stack overflow"); return ERROR; } if (!ierr && ipos >= fpos) { v_stack[v_sp].tag = INT; v_stack[v_sp].ival = ival; pos = ipos - buf; } else { v_stack[v_sp].tag = FLOAT; v_stack[v_sp].fval = fval; pos = fpos - buf; } v_stack[v_sp].pos = pos; v_stack[v_sp++].var = NULL; return OPERAND; } default: pos -= 1; np = name; while (isalnum(buf[pos]) || buf[pos] == '$' || buf[pos] == '_') { *np++ = buf[pos++]; } if (np == buf) { error("Bad character"); return ERROR; } *np = '\0'; symbol* sym = symbol::add(VARIABLE, name); if (v_sp == max_stack_size) { error("stack overflow"); return ERROR; } v_stack[v_sp] = sym->val; v_stack[v_sp].pos = pos; v_stack[v_sp++].var = sym; return (sym->tag == VARIABLE) ? OPERAND : FUNC; }}static int lpr[TERMINALS] = { 2, 0, 0, 0, // BEGIN, OPERAND, ERROR, END, 4, 4, // LPAR, RPAR 5, 98, 98, // FUNC, POSTINC, POSTDEC, 98, 98, 98, 98, 98, 98, // PREINC, PREDEC, PLUS, MINUS, NOT, COM, 90, // POW, 80, 80, 80, // MUL, DIV, MOD, 70, 70, // ADD, SUB, 60, 60, 60, // ASL, ASR, LSR, 50, 50, 50, 50, // GT, GE, LT, LE, 40, 40, // EQ, NE, 38, // AND, 36, // XOR, 34, // OR, 20, 20, 20, 20, 20, 20, 20, //SET, SETADD, SETSUB, SETMUL, SETDIV, SETMOD, 20, 20, 20, 20, 20, 20, // SETASL, SETASR, SETLSR, SETAND, SETXOR, SETOR, 10 // COMMA};static int rpr[TERMINALS] = { 0, 0, 0, 1, // BEGIN, OPERAND, ERROR, END, 110, 3, // LPAR, RPAR 120, 99, 99, // FUNC, POSTINC, POSTDEC 99, 99, 99, 99, 99, 99, // PREINC, PREDEC, PLUS, MINUS, NOT, COM, 95, // POW, 80, 80, 80, // MUL, DIV, MOD, 70, 70, // ADD, SUB, 60, 60, 60, // ASL, ASR, LSR, 50, 50, 50, 50, // GT, GE, LT, LE, 40, 40, // EQ, NE, 38, // AND, 36, // XOR, 34, // OR, 25, 25, 25, 25, 25, 25, 25, //SET, SETADD, SETSUB, SETMUL, SETDIV, SETMOD, 25, 25, 25, 25, 25, 25, // SETASL, SETASR, SETLSR, SETAND, SETXOR, SETOR, 15 // COMMA};bool calculator::assign() { value& v = v_stack[v_sp-1]; if (v.var == NULL) { error(v.pos, "variable expected"); return false; } else { v.var->val = v; return true; }}void calculator::evaluate(char* expression) { char var_name[16]; buf = expression; v_sp = 0; o_sp = 0; pos = 0; o_stack[o_sp++] = BEGIN; bool operand = true; int n_args = 0; while (true) { next_token: int op_pos = pos; int oper = scan(operand); if (oper == ERROR) { return; } if (!operand) { if (!BINARY(oper) && oper != END && oper != POSTINC && oper != POSTDEC && oper != RPAR) { error(op_pos, "operator expected"); return; } if (oper != POSTINC && oper != POSTDEC && oper != RPAR) { operand = true; } } else { if (oper == OPERAND) { operand = false; n_args += 1; continue; } if (BINARY(oper) || oper == RPAR) { error(op_pos, "operand expected"); return; } } int n_args = 1; while (lpr[o_stack[o_sp-1]] >= rpr[oper]) { int cop = o_stack[--o_sp]; switch (cop) { case BEGIN: if (oper == RPAR) { error("Unmatched ')'"); return; } if (oper != END) { error("Unexpected end of input"); } if (v_sp == 1) { sprintf(var_name, "$%d", ++tmp_var_count); printf("%s = ", var_name); symbol::add(VARIABLE, var_name)->val = v_stack[0]; if (v_stack[0].tag == INT) { printf("%" INT_FORMAT "d [%#" INT_FORMAT "x %#" INT_FORMAT "o]\n", v_stack[0].ival, v_stack[0].ival, v_stack[0].ival); } else { printf("%.10g\n", v_stack[0].fval); } } else if (v_sp != 0) { error("Unexpected end of expression"); } return; case COMMA: n_args += 1; continue; case ADD: case SETADD: if (v_stack[v_sp-1].tag == INT && v_stack[v_sp-2].tag == INT) { v_stack[v_sp-2].ival += v_stack[v_sp-1].ival; } else { v_stack[v_sp-2].fval = v_stack[v_sp-2].get() + v_stack[v_sp-1].get(); v_stack[v_sp-2].tag = FLOAT; } v_sp -= 1; if (cop == SETADD) { if (!assign()) return; } v_stack[v_sp-1].var = NULL; break; case SUB: case SETSUB: if (v_stack[v_sp-1].tag == INT && v_stack[v_sp-2].tag == INT) { v_stack[v_sp-2].ival -= v_stack[v_sp-1].ival; } else { v_stack[v_sp-2].fval = v_stack[v_sp-2].get() - v_stack[v_sp-1].get(); v_stack[v_sp-2].tag = FLOAT; } v_sp -= 1; if (cop == SETSUB) { if (!assign()) return; } v_stack[v_sp-1].var = NULL; break; case MUL: case SETMUL: if (v_stack[v_sp-1].tag == INT && v_stack[v_sp-2].tag == INT) { v_stack[v_sp-2].ival *= v_stack[v_sp-1].ival; } else { v_stack[v_sp-2].fval = v_stack[v_sp-2].get() * v_stack[v_sp-1].get(); v_stack[v_sp-2].tag = FLOAT; } v_sp -= 1; if (cop == SETMUL) { if (!assign()) return; } v_stack[v_sp-1].var = NULL; break; case DIV: case SETDIV: if (v_stack[v_sp-1].get() == 0.0) { error(v_stack[v_sp-2].pos, "Division by zero"); return; } if (v_stack[v_sp-1].tag == INT && v_stack[v_sp-2].tag == INT) { v_stack[v_sp-2].ival /= v_stack[v_sp-1].ival; } else { v_stack[v_sp-2].fval = v_stack[v_sp-2].get() / v_stack[v_sp-1].get(); v_stack[v_sp-2].tag = FLOAT; } v_sp -= 1; if (cop == SETDIV) { if (!assign()) return; } v_stack[v_sp-1].var = NULL; break; case MOD: case SETMOD: if (v_stack[v_sp-1].get() == 0.0) { error(v_stack[v_sp-2].pos, "Division by zero"); return; } if (v_stack[v_sp-1].tag == INT && v_stack[v_sp-2].tag == INT) { v_stack[v_sp-2].ival %= v_stack[v_sp-1].ival; } else { v_stack[v_sp-2].fval = fmod(v_stack[v_sp-2].get(), v_stack[v_sp-1].get()); v_stack[v_sp-2].tag = FLOAT; } v_sp -= 1; if (cop == SETMOD) { if (!assign()) return; } v_stack[v_sp-1].var = NULL; break; case POW: case SETPOW: if (v_stack[v_sp-1].tag == INT && v_stack[v_sp-2].tag == INT) { v_stack[v_sp-2].ival = (int_t)pow((double)v_stack[v_sp-2].ival, (double)v_stack[v_sp-1].ival); } else { v_stack[v_sp-2].fval = pow(v_stack[v_sp-2].get(), v_stack[v_sp-1].get()); v_stack[v_sp-2].tag = FLOAT; } v_sp -= 1; if (cop == SETPOW) { if (!assign()) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -