| 137 | } |
| 138 | |
| 139 | static TString CalcExpression(const char* expr, size_t a, size_t b, const IExpressionAdaptor& data) { |
| 140 | // Cannot compare values less than 1e-5 |
| 141 | static const double EPS = 1e-5; |
| 142 | for (; a < b && expr[a] == ' '; ++a) {} |
| 143 | for (; a < b && expr[b - 1] == ' '; --b) {} |
| 144 | if (a >= b) { |
| 145 | return TString(); |
| 146 | } |
| 147 | size_t oa = 0; |
| 148 | size_t ob = 0; |
| 149 | TExpressionOperation op; |
| 150 | if (FindOperation(expr, a, b, oa, ob, op)) { |
| 151 | TString vl = CalcExpression(expr, a, oa, data); |
| 152 | TString vr = CalcExpression(expr, ob, b, data); |
| 153 | switch (op) { |
| 154 | case EO_OR: |
| 155 | return (!IsEmpty(vl) || !IsEmpty(vr)) ? "1.0" : "0.0"; |
| 156 | case EO_AND: |
| 157 | return (!IsEmpty(vl) && !IsEmpty(vr)) ? "1.0" : "0.0"; |
| 158 | case EO_LE: |
| 159 | return (ToNumeric<double>(vl) <= ToNumeric<double>(vr) + EPS) ? "1.0" : "0.0"; |
| 160 | case EO_L: |
| 161 | return (ToNumeric<double>(vl) < ToNumeric<double>(vr) - EPS) ? "1.0" : "0.0"; |
| 162 | case EO_GE: |
| 163 | return (ToNumeric<double>(vl) >= ToNumeric<double>(vr) - EPS) ? "1.0" : "0.0"; |
| 164 | case EO_G: |
| 165 | return (ToNumeric<double>(vl) > ToNumeric<double>(vr) + EPS) ? "1.0" : "0.0"; |
| 166 | case EO_E: |
| 167 | return IsEqual(vl, vr, EPS) ? "1.0" : "0.0"; |
| 168 | case EO_NE: |
| 169 | return !IsEqual(vl, vr, EPS) ? "1.0" : "0.0"; |
| 170 | case EO_BITS_OR: |
| 171 | return ToString(static_cast<size_t>(ToNumeric<double>(vl)) | static_cast<size_t>(ToNumeric<double>(vr))); |
| 172 | case EO_BITS_AND: |
| 173 | return ToString(static_cast<size_t>(ToNumeric<double>(vl)) & static_cast<size_t>(ToNumeric<double>(vr))); |
| 174 | case EO_ADD: |
| 175 | return ToString(ToNumeric<double>(vl) + ToNumeric<double>(vr)); |
| 176 | case EO_SUBSTRACT: |
| 177 | return ToString(ToNumeric<double>(vl) - ToNumeric<double>(vr)); |
| 178 | case EO_MULTIPLY: |
| 179 | return ToString(ToNumeric<double>(vl) * ToNumeric<double>(vr)); |
| 180 | case EO_DIVIDE: |
| 181 | return ToString(ToNumeric<double>(vl) / ToNumeric<double>(vr)); |
| 182 | |
| 183 | default: |
| 184 | ythrow yexception() << "CalcExpression error: can't parse expression"; |
| 185 | } |
| 186 | } else if (expr[a] == '(') { |
| 187 | if (expr[b - 1] != ')') { |
| 188 | ythrow yexception() << "CalcExpression error: extra symbols"; |
| 189 | } |
| 190 | return CalcExpression(expr, a + 1, b - 1, data); |
| 191 | } else if (expr[a] == '"') { |
| 192 | if (expr[b - 1] != '"') { |
| 193 | ythrow yexception() << "CalcExpression error: extra symbols"; |
| 194 | } |
| 195 | return TString(&expr[a + 1], &expr[b - 1]); |
| 196 | } else if (expr[a] == '-') { |
no test coverage detected