/* * Copyright (c) 2021 - 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ES2PANDA_LEXER_TOKEN_NUMBER_H #define ES2PANDA_LEXER_TOKEN_NUMBER_H #include "macros.h" #include "util/ustring.h" #include "util/enumbitops.h" #include #include #include namespace panda::es2panda::lexer { enum class NumberFlags : uint32_t { NONE, BIGINT = 1U << 0U, DECIMAL_POINT = 1U << 1U, EXPONENT = 1U << 2U, ERROR = 1U << 3U, }; DEFINE_BITOPS(NumberFlags) // NOLINTBEGIN(readability-identifier-naming) // NOLINTBEGIN(fuchsia-multiple-inheritance) template struct overloaded : Ts... { using Ts::operator()...; }; template overloaded(Ts...) -> overloaded; // NOLINTEND(fuchsia-multiple-inheritance) template inline constexpr bool dependent_false_v = false; // NOLINTEND(readability-identifier-naming) // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) class Number { public: // NOLINTBEGIN(cppcoreguidelines-pro-type-member-init) explicit Number() noexcept : num_(static_cast(0)) {}; explicit Number(util::StringView str) noexcept : str_(str) {} // NOLINTNEXTLINE(bugprone-exception-escape) explicit Number(util::StringView str, const std::string &utf8, NumberFlags flags) noexcept; explicit Number(util::StringView str, double num) noexcept : str_(str), num_(num) {} explicit Number(uint32_t num) noexcept : Number(static_cast(num)) {} explicit Number(int32_t num) noexcept : num_(num) {} explicit Number(uint64_t num) noexcept : Number(static_cast(num)) {} explicit Number(int64_t num) noexcept : num_(num) {} explicit Number(float num) noexcept : num_(num) {} explicit Number(double num) noexcept : num_(num) {} DEFAULT_COPY_SEMANTIC(Number); DEFAULT_MOVE_SEMANTIC(Number); ~Number() = default; // NOLINTEND(cppcoreguidelines-pro-type-member-init) bool IsInt() const noexcept { return std::holds_alternative(num_); } bool IsLong() const noexcept { return std::holds_alternative(num_); } bool IsInteger() const noexcept { return IsInt() || IsLong(); } bool IsFloat() const noexcept { return std::holds_alternative(num_); } bool IsDouble() const noexcept { return std::holds_alternative(num_); } bool IsReal() const noexcept { return IsFloat() || IsDouble(); } bool ConversionError() const { return (flags_ & NumberFlags::ERROR) != 0; } int32_t GetInt() const { ASSERT(IsInt()); return std::get(num_); } int64_t GetLong() const { return std::visit(overloaded {[](int64_t value) { return value; }, [](int32_t value) { return static_cast(value); }, []([[maybe_unused]] auto value) { ASSERT(false); return static_cast(0); }}, num_); } float GetFloat() const { ASSERT(IsFloat()); return std::get(num_); } double GetDouble() const { return std::visit( overloaded {[](double value) { return value; }, [](auto value) { return static_cast(value); }}, num_); } const util::StringView &Str() const { return str_; } void Negate() { std::visit(overloaded {[](auto &value) { value = -value; }}, num_); } template bool CanGetValue() const noexcept { using T = typename std::remove_cv_t>; if constexpr (std::is_same_v) { return IsInteger(); } else if constexpr (std::is_same_v) { return IsInt(); } else if constexpr (std::is_same_v) { return true; } else if constexpr (std::is_same_v) { return IsFloat(); } else { return false; } } template auto GetValue() const { using T = typename std::remove_cv_t>; if constexpr (std::is_same_v) { return GetLong(); } else if constexpr (std::is_same_v) { return GetInt(); } else if constexpr (std::is_same_v) { return GetDouble(); } else if constexpr (std::is_same_v) { return GetFloat(); } else { static_assert(dependent_false_v, "Invalid value type was requested for Number."); } } template void SetValue(RT &&value) { using T = typename std::remove_cv_t>; if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v) { num_ = std::forward(value); } else { static_assert(dependent_false_v, "Invalid value type was requested for Number."); } } private: util::StringView str_ {}; std::variant num_; NumberFlags flags_ {NumberFlags::NONE}; }; } // namespace panda::es2panda::lexer #endif