void pop() { if(left.empty()) { while(!right.empty()) { left.push(right.top()); right.pop(); } } left.pop(); }
int top() { if(left.empty()) { while(!right.empty()) { left.push(right.top()); right.pop(); } } return left.top(); }
double Utils::evaluate(QString exp) { auto priority = [](QChar o){ switch (o.unicode()) { case '(': return 1; case '+': case '-': return 2; case '*': case '/': return 3; case '+' + 128: case '-' + 128: return 4; case ':': case ':' + 128: return 5; default: return 0; } }; exp.remove(' '); QString pst; SStack<QChar> opt; int i = 0; opt.push('#'); while (i < exp.length()){ if (exp[i].isDigit() || exp[i] == '.'){ pst.append(exp[i]); } else{ auto tra = [&](){ pst.append(' '); while (priority(exp[i]) <= priority(opt.top())){ pst.append(opt.pop()); } opt.push(exp[i]); }; int colon = 0; switch (exp[i].unicode()){ case '(': opt.push(exp[i]); break; case ')': while (opt.top() != '('){ pst.append(opt.pop()); } opt.pop(); break; case '+': case '-': { if ((i == 0 || (!exp[i - 1].isDigit() && exp[i - 1] != ')')) && (i + 1) < exp.length() && (exp[i + 1].isDigit() || exp[i + 1] == '(')){ exp[i].unicode() += 128; } tra(); break; } case ':': switch (colon++){ case 2: exp[i].unicode() += 128; case 1: case 0: break; default: throw std::runtime_error("colon overflow"); } tra(); break; case '*': case '/': tra(); break; default: throw std::runtime_error("token unrecognized"); } } ++i; } while (!opt.isEmpty()){ pst.append(opt.pop()); } SStack<double> num; i = 0; while (pst[i] != '#'){ if (pst[i].isDigit() || pst[i] == '.'){ double n = 0; while (pst[i].isDigit()){ n = n * 10 + pst[i++].toLatin1() - '0'; } if (pst[i] == '.'){ ++i; double d = 1; while (pst[i].isDigit()){ n += (d /= 10)*(pst[i++].toLatin1() - '0'); } } num.push(n); } else{ switch (pst[i].unicode()){ case '+' + 128: num.push(+num.pop()); break; case '-' + 128: num.push(-num.pop()); break; case '+': { double r = num.pop(), l = num.pop(); num.push(l + r); break; } case '-': { double r = num.pop(), l = num.pop(); num.push(l - r); break; } case '*': { double r = num.pop(), l = num.pop(); num.push(l*r); break; } case '/': { double r = num.pop(), l = num.pop(); num.push(l / r); break; } case ':': { double r = num.pop(), l = num.pop(); num.push(l * 60 + r); break; } case ':' + 128: { double r = num.pop(), l = num.pop(); num.push(l * 24 + r); break; } } i++; } } return num.top(); }