shuntingYard string addition, add tohex() function

This commit is contained in:
MichaelDvP
2025-03-12 18:35:57 +01:00
parent 8d9ca33ea3
commit 584d0e0b48
2 changed files with 62 additions and 37 deletions

View File

@@ -81,9 +81,12 @@ std::deque<Token> exprToTokens(const std::string & expr) {
} else if (strncmp(p, "abs", 3) == 0) { } else if (strncmp(p, "abs", 3) == 0) {
p += 2; p += 2;
tokens.emplace_back(Token::Type::Unary, "a", 5); tokens.emplace_back(Token::Type::Unary, "a", 5);
} else if (strncmp(p, "ln", 2) == 0) {
p += 1;
tokens.emplace_back(Token::Type::Unary, "l", 5);
} else if (strncmp(p, "log", 3) == 0) { } else if (strncmp(p, "log", 3) == 0) {
p += 2; p += 2;
tokens.emplace_back(Token::Type::Unary, "l", 5); tokens.emplace_back(Token::Type::Unary, "g", 5);
} else if (strncmp(p, "exp", 3) == 0) { } else if (strncmp(p, "exp", 3) == 0) {
p += 2; p += 2;
tokens.emplace_back(Token::Type::Unary, "e", 5); tokens.emplace_back(Token::Type::Unary, "e", 5);
@@ -93,6 +96,9 @@ std::deque<Token> exprToTokens(const std::string & expr) {
} else if (strncmp(p, "pow", 3) == 0) { } else if (strncmp(p, "pow", 3) == 0) {
p += 2; p += 2;
tokens.emplace_back(Token::Type::Unary, "p", 5); tokens.emplace_back(Token::Type::Unary, "p", 5);
} else if (strncmp(p, "tohex", 5) == 0) {
p += 4;
tokens.emplace_back(Token::Type::Unary, "x", 5);
} else if (strncmp(p, "hex", 3) == 0) { } else if (strncmp(p, "hex", 3) == 0) {
p += 2; p += 2;
tokens.emplace_back(Token::Type::Unary, "h", 5); tokens.emplace_back(Token::Type::Unary, "h", 5);
@@ -102,7 +108,7 @@ std::deque<Token> exprToTokens(const std::string & expr) {
++p; ++p;
} }
const auto s = std::string(b, p); const auto s = std::string(b, p);
tokens.emplace_back(Token::Type::String, s, -2); tokens.emplace_back(Token::Type::String, s, -3);
--p; --p;
} else if (*p == '"') { } else if (*p == '"') {
++p; ++p;
@@ -132,7 +138,7 @@ std::deque<Token> exprToTokens(const std::string & expr) {
++p; ++p;
} }
const auto s = std::string(b, p); const auto s = std::string(b, p);
tokens.emplace_back(Token::Type::Number, s, -4); tokens.emplace_back(Token::Type::Number, s, -2);
--p; --p;
} else { } else {
Token::Type token = Token::Type::Operator; Token::Type token = Token::Type::Operator;
@@ -203,7 +209,7 @@ std::deque<Token> exprToTokens(const std::string & expr) {
precedence = 1; precedence = 1;
token = Token::Type::Compare; token = Token::Type::Compare;
} else { } else {
precedence = 1; precedence = 2;
token = Token::Type::Unary; token = Token::Type::Unary;
} }
break; break;
@@ -359,9 +365,6 @@ std::string commands(std::string & expr, bool quotes = true) {
if (e == std::string::npos) { if (e == std::string::npos) {
e = expr.length(); e = expr.length();
} }
while (e > 0 && expr[e - 1] == ' ') { // remove blanks from end
e--;
}
char cmd[COMMAND_MAX_LENGTH]; char cmd[COMMAND_MAX_LENGTH];
size_t l = e - f; size_t l = e - f;
if (l >= sizeof(cmd) - 1) { if (l >= sizeof(cmd) - 1) {
@@ -420,6 +423,14 @@ std::string to_string(double d) {
return s; return s;
} }
// number to hex string
std::string to_hex(uint32_t i) {
char c[10];
snprintf(c, 10, "%02X", i);
std::string s = c;
return s;
}
// RPN calculator // RPN calculator
std::string calculate(const std::string & expr) { std::string calculate(const std::string & expr) {
std::string expr_new = expr; std::string expr_new = expr;
@@ -459,46 +470,57 @@ std::string calculate(const std::string & expr) {
} }
const auto rhs = stack.back(); const auto rhs = stack.back();
stack.pop_back(); stack.pop_back();
if (token.str[0] == '!') {
if (to_logic(rhs) < 0) {
}
if (to_logic(rhs) >= 0) {
stack.push_back(to_logic(rhs) == 0 ? "1" : "0");
} else if (isnum(rhs)) {
stack.push_back(std::stod(rhs) == 0 ? "1" : "0");
} else {
emsesp::EMSESP::logger().warning("missing operator");
return "";
}
break;
}
auto rhd = std::stod(rhs);
switch (token.str[0]) { switch (token.str[0]) {
default: default:
return ""; return "";
break; break;
case 'm': // Special operator name for unary '-' case 'm': // Special operator name for unary '-'
if (!isnum(rhs)) { stack.push_back(to_string(-1 * rhd));
return "";
}
stack.push_back(to_string(-1 * std::stod(rhs)));
break;
case '!':
if (to_logic(rhs) < 0) {
return "";
}
stack.push_back(to_logic(rhs) == 0 ? "1" : "0");
break; break;
case 'i': case 'i':
stack.push_back(to_string(std::stoi(rhs))); stack.push_back(to_string(static_cast<int>(rhd)));
break; break;
case 'r': case 'r':
stack.push_back(to_string(std::round(std::stod(rhs)))); stack.push_back(to_string(std::round(rhd)));
break; break;
case 'a': case 'a':
stack.push_back(to_string(std::abs(std::stod(rhs)))); stack.push_back(to_string(std::abs(rhd)));
break; break;
case 'e': case 'e':
stack.push_back(to_string(std::exp(std::stod(rhs)))); stack.push_back(to_string(std::exp(rhd)));
break; break;
case 'l': case 'l':
stack.push_back(to_string(std::log(std::stod(rhs)))); stack.push_back(to_string(std::log(rhd)));
break;
case 'g':
stack.push_back(to_string(std::log10(rhd)));
break; break;
case 's': case 's':
stack.push_back(to_string(std::sqrt(std::stod(rhs)))); stack.push_back(to_string(std::sqrt(rhd)));
break; break;
case 'p': case 'p':
stack.push_back(to_string(std::pow(std::stod(rhs), 2))); stack.push_back(to_string(std::pow(rhd, 2)));
break; break;
case 'h': case 'h':
stack.push_back(to_string(std::stoi(rhs, 0, 16))); stack.push_back(to_string(std::stoi(rhs, 0, 16)));
break; break;
case 'x':
stack.push_back(to_hex(static_cast<int>(rhd)));
break;
} }
} break; } break;
case Token::Type::Compare: { case Token::Type::Compare: {
@@ -585,38 +607,40 @@ std::string calculate(const std::string & expr) {
} break; } break;
case Token::Type::Operator: { case Token::Type::Operator: {
// binary operators // binary operators
if (stack.empty() || !isnum(stack.back())) { if (stack.size() < 2) {
return ""; return "";
} }
const auto rhs = std::stod(stack.back()); const auto rhs = stack.back();
stack.pop_back(); stack.pop_back();
if (stack.empty() || !isnum(stack.back())) { const auto lhs = stack.back();
return ""; stack.pop_back();
if (token.str[0] == '+' && (!isnum(rhs) || !isnum(lhs))) {
stack.push_back(lhs + rhs);
break;
} }
const auto lhs = std::stod(stack.back()); auto lhd = std::stod(lhs);
stack.pop_back(); auto rhd = std::stod(rhs);
switch (token.str[0]) { switch (token.str[0]) {
default: default:
return ""; return "";
break; break;
case '^': case '^':
stack.push_back(to_string(pow(lhs, rhs))); stack.push_back(to_string(pow(lhd, rhd)));
break; break;
case '*': case '*':
stack.push_back(to_string(lhs * rhs)); stack.push_back(to_string(lhd * rhd));
break; break;
case '/': case '/':
stack.push_back(to_string(lhs / rhs)); stack.push_back(to_string(lhd / rhd));
break; break;
case '%': case '%':
stack.push_back(std::to_string(static_cast<int>(lhs) % static_cast<int>(rhs))); stack.push_back(std::to_string(static_cast<int>(lhd) % static_cast<int>(rhd)));
break; break;
case '+': case '+':
stack.push_back(to_string(lhs + rhs)); stack.push_back(to_string(lhd + rhd));
break; break;
case '-': case '-':
stack.push_back(to_string(lhs - rhs)); stack.push_back(to_string(lhd - rhd));
break; break;
} }
} break; } break;

View File

@@ -105,6 +105,7 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web
if (entityItem.ram == 0 && entityItem.value_type == DeviceValueType::STRING) { if (entityItem.ram == 0 && entityItem.value_type == DeviceValueType::STRING) {
entityItem.raw = new uint8_t[(size_t)entityItem.factor + 1]; entityItem.raw = new uint8_t[(size_t)entityItem.factor + 1];
entityItem.data = ""; entityItem.data = "";
entityItem.uom = 0;
} else if (entityItem.value_type == DeviceValueType::BOOL) { } else if (entityItem.value_type == DeviceValueType::BOOL) {
entityItem.value = EMS_VALUE_DEFAULT_BOOL; entityItem.value = EMS_VALUE_DEFAULT_BOOL;
entityItem.uom = 0; entityItem.uom = 0;