double Calculator::parseSymbol(std::string_view &ref) { double value = 0; skipSpaces(ref); if (!ref.empty() && ref[0] == '(') { ref.remove_prefix(1); value = parseExprSum(ref); skipSpaces(ref); if (!ref.empty() && ref[0] == ')') { ref.remove_prefix(1); return value; } else { return std::numeric_limits<double>::quiet_NaN(); } } else if (!ref.empty() && !std::isdigit(ref[0]) && ref[0] != '-') { return parseFunction(ref); } else { return parseDouble(ref); } }
double Calculator::parseExprSum(std::string_view &ref) { double value = parseExprMul(ref); while (true) { skipSpaces(ref); if (!ref.empty() && ref[0] == '+') { ref.remove_prefix(1); value += parseExprMul(ref); m_printStrategy->printAddition(); } else if (!ref.empty() && ref[0] == '-') { ref.remove_prefix(1); value -= parseExprMul(ref); m_printStrategy->printSubstraction(); } else { break; } } return value; }
double Calculator::parseExprMul(std::string_view &ref) { double value = parseSymbol(ref); while (true) { skipSpaces(ref); if (!ref.empty() && ref[0] == '*') { ref.remove_prefix(1); value *= parseSymbol(ref); m_printStrategy->printMultiplication(); } else if (!ref.empty() && ref[0] == '/') { ref.remove_prefix(1); value /= parseSymbol(ref); m_printStrategy->printDivision(); } else { break; } } return value; }
bool CSeqConversionDefault::ToValue(std::string_view sv) { m_bReady = false; if (sv == "$$") { m_bHex = true; return true; } if (auto nextTerm = GetNextTerm(sv)) { m_iTargetValue = m_iCurrentValue = *nextTerm; m_iRepeat = m_iValueDiv = 1; if (!sv.empty() && sv.front() == ':') { if (sv.remove_prefix(1), !sv.empty()) { if (auto divTerm = GetNextInteger(sv)) { m_iValueDiv = *divTerm; if (m_iValueDiv <= 0) return false; if (!sv.empty() && sv.front() == ':') { if (sv.remove_prefix(1), sv.empty()) return false; if (auto target = GetNextTerm(sv)) m_iTargetValue = *target; else return false; } } else return false; } else return false; } if (!sv.empty() && sv.front() == '\'') { if (sv.remove_prefix(1), !sv.empty()) { if (auto repTerm = GetNextInteger(sv)) { m_iRepeat = *repTerm; if (m_iRepeat <= 0) return false; } } else return false; } if (sv.empty()) { m_iValueInc = m_iTargetValue - m_iCurrentValue; m_iRepeatCounter = m_iCounter = m_iValueMod = 0; return m_bReady = true; } } return false; }
double Calculator::parseDouble(std::string_view &ref) { double value = 0; bool isNegative = false; bool parsedAny = false; skipSpaces(ref); if (!ref.empty() && ref[0] == '-') { isNegative = true; ref.remove_prefix(1); } skipSpaces(ref); while (!ref.empty() && std::isdigit(ref[0])) { parsedAny = true; const int digit = ref[0] - '0'; value = value * 10.0f + double(digit); ref.remove_prefix(1); } if (!parsedAny) { return std::numeric_limits<double>::quiet_NaN(); } if (isNegative) { value *= -1; } if (ref.empty() || (ref[0] != '.')) { m_printStrategy->printNumber(value); return value; } ref.remove_prefix(1); double factor = 1.f; while (!ref.empty() && std::isdigit(ref[0])) { const int digit = ref[0] - '0'; factor *= 0.1f; value += factor * double(digit); ref.remove_prefix(1); } m_printStrategy->printNumber(value); return value; }
void Calculator::skipSpaces(std::string_view &ref) { size_t i = 0; while (i < ref.size() && std::isspace(ref[i])) { ++i; } ref.remove_prefix(i); }
double Calculator::ParseArguments(std::string_view &ref) { double value = 0; if (!ref.empty() && ref[0] == '(') { ref.remove_prefix(1); value = parseExprSum(ref); skipSpaces(ref); if (!ref.empty() && ref[0] == ')') { ref.remove_prefix(1); return value; } else { return std::numeric_limits<double>::quiet_NaN(); } } else { return std::numeric_limits<double>::quiet_NaN(); } }
double Calculator::parseFunction(std::string_view &ref) { try { std::string_view partStr = ref.substr(0, 3); if (partStr == std::string_view("sin")) { ref.remove_prefix(3); m_printStrategy->printFunctionName("sin"); return sin(ParseArguments(ref) * M_PI / 180); } else if (partStr == std::string_view("cos")) { ref.remove_prefix(3); m_printStrategy->printFunctionName("cos"); return cos(ParseArguments(ref) * M_PI / 180); } else { std::string_view partStr = ref.substr(0, 4); if (partStr == std::string_view("sqrt")) { ref.remove_prefix(4); m_printStrategy->printFunctionName("sqrt"); return sqrt(ParseArguments(ref)); } } } catch(const std::out_of_range&) { return std::numeric_limits<double>::quiet_NaN(); } return std::numeric_limits<double>::quiet_NaN(); }
std::optional<int> CSeqConversionDefault::GetNextInteger(std::string_view &sv, bool Signed) const { re::svmatch m; if (m_bHex) { static const std::regex HEX_RE {R"(^([\+-]?)[0-9A-Fa-f]+)", std::regex_constants::optimize}; if (std::regex_search(sv.begin(), sv.end(), m, HEX_RE)) if (!(Signed && !m[1].length())) if (auto val = conv::to_int(re::sv_from_submatch(m[0]), 16)) { sv.remove_prefix(std::distance(sv.begin(), m.suffix().first)); return val; } } else { static const std::regex NUMBER_RE {R"(^([\+-]?)[0-9]+)", std::regex_constants::optimize}; static const std::regex HEX_PREFIX_RE {R"(^([\+-]?)[\$x]([0-9A-Fa-f]+))", std::regex_constants::optimize}; // do not allow 0x prefix if (std::regex_search(sv.begin(), sv.end(), m, HEX_PREFIX_RE)) { if (!(Signed && !m[1].length())) if (auto val = conv::to_int(re::sv_from_submatch(m[2]), 16)) { if (m[1] == "-") *val = -*val; sv.remove_prefix(std::distance(sv.begin(), m.suffix().first)); return val; } } else if (std::regex_search(sv.begin(), sv.end(), m, NUMBER_RE)) { if (!(Signed && !m[1].length())) if (auto val = conv::to_int(re::sv_from_submatch(m[0]))) { sv.remove_prefix(std::distance(sv.begin(), m.suffix().first)); return val; } } } return std::nullopt; } std::optional<int> CSeqConversionDefault::GetNextTerm(std::string_view &sv) { return GetNextInteger(sv); } std::string CSeqConversion5B::ToString(char Value) const { std::string Str = std::to_string(Value & 0x1F); uint8_t m = (uint8_t)Value & 0xE0; if ((m & value_cast(s5b_mode_t::Square)) == value_cast(s5b_mode_t::Square)) Str.push_back('t'); if ((m & value_cast(s5b_mode_t::Noise)) == value_cast(s5b_mode_t::Noise)) Str.push_back('n'); if ((m & value_cast(s5b_mode_t::Envelope)) == value_cast(s5b_mode_t::Envelope)) Str.push_back('e'); // auto m = enum_cast<s5b_mode_t>((unsigned char)Value); // if ((m & s5b_mode_t::Square) == s5b_mode_t::Square) // Str.push_back('t'); // if ((m & s5b_mode_t::Noise) == s5b_mode_t::Noise) // Str.push_back('n'); // if ((m & s5b_mode_t::Envelope) == s5b_mode_t::Envelope) // Str.push_back('e'); return Str; } bool CSeqConversion5B::ToValue(std::string_view sv) { m_iEnableFlags = -1; return CSeqConversionDefault::ToValue(sv); } char CSeqConversion5B::GetValue() { return CSeqConversionDefault::GetValue() | m_iEnableFlags; } std::optional<int> CSeqConversion5B::GetNextTerm(std::string_view &sv) { if (auto o = GetNextInteger(sv)) { static const std::regex S5B_FLAGS_RE {R"(^[TtNnEe]*)", std::regex_constants::optimize}; if (re::svmatch m; std::regex_search(sv.begin(), sv.end(), m, S5B_FLAGS_RE)) { if (m_iEnableFlags == -1) { m_iEnableFlags = 0; auto flags = re::sv_from_submatch(m[0]); if (flags.find_first_of("Tt") != std::string::npos) m_iEnableFlags |= value_cast(s5b_mode_t::Square); if (flags.find_first_of("Nn") != std::string::npos) m_iEnableFlags |= value_cast(s5b_mode_t::Noise); if (flags.find_first_of("Ee") != std::string::npos) m_iEnableFlags |= value_cast(s5b_mode_t::Envelope); } sv.remove_prefix(std::distance(sv.begin(), m.suffix().first)); }
std::string_view trim(std::string_view str) { str.remove_prefix(str.find_first_not_of(' ')); str.remove_suffix(str.size() - (str.find_last_not_of(' ') + 1)); return str; }