1 /* 2 * Copyright (c) 2021 - 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ES2PANDA_LEXER_TOKEN_NUMBER_H 17 #define ES2PANDA_LEXER_TOKEN_NUMBER_H 18 19 #include "macros.h" 20 #include "util/ustring.h" 21 #include "util/enumbitops.h" 22 23 #include <cstdint> 24 #include <type_traits> 25 #include <utility> 26 27 namespace panda::es2panda::lexer { 28 enum class NumberFlags : uint32_t { 29 NONE, 30 BIGINT = 1U << 0U, 31 DECIMAL_POINT = 1U << 1U, 32 EXPONENT = 1U << 2U, 33 ERROR = 1U << 3U, 34 }; 35 36 DEFINE_BITOPS(NumberFlags) 37 38 // NOLINTBEGIN(readability-identifier-naming) 39 // NOLINTBEGIN(fuchsia-multiple-inheritance) 40 template <class... Ts> 41 struct overloaded : Ts... { 42 using Ts::operator()...; 43 }; 44 45 template <class... Ts> 46 overloaded(Ts...) -> overloaded<Ts...>; 47 // NOLINTEND(fuchsia-multiple-inheritance) 48 49 template <typename> 50 inline constexpr bool dependent_false_v = false; 51 // NOLINTEND(readability-identifier-naming) 52 53 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 54 class Number { 55 public: 56 // NOLINTBEGIN(cppcoreguidelines-pro-type-member-init) Number()57 explicit Number() noexcept : num_(static_cast<int32_t>(0)) {}; Number(util::StringView str)58 explicit Number(util::StringView str) noexcept : str_(str) {} 59 // NOLINTNEXTLINE(bugprone-exception-escape) 60 explicit Number(util::StringView str, const std::string &utf8, NumberFlags flags) noexcept; Number(util::StringView str,double num)61 explicit Number(util::StringView str, double num) noexcept : str_(str), num_(num) {} Number(uint32_t num)62 explicit Number(uint32_t num) noexcept : Number(static_cast<int32_t>(num)) {} Number(int32_t num)63 explicit Number(int32_t num) noexcept : num_(num) {} Number(uint64_t num)64 explicit Number(uint64_t num) noexcept : Number(static_cast<int64_t>(num)) {} Number(int64_t num)65 explicit Number(int64_t num) noexcept : num_(num) {} Number(float num)66 explicit Number(float num) noexcept : num_(num) {} Number(double num)67 explicit Number(double num) noexcept : num_(num) {} 68 DEFAULT_COPY_SEMANTIC(Number); 69 DEFAULT_MOVE_SEMANTIC(Number); 70 ~Number() = default; 71 // NOLINTEND(cppcoreguidelines-pro-type-member-init) 72 IsInt()73 bool IsInt() const noexcept 74 { 75 return std::holds_alternative<int32_t>(num_); 76 } 77 IsLong()78 bool IsLong() const noexcept 79 { 80 return std::holds_alternative<int64_t>(num_); 81 } 82 IsInteger()83 bool IsInteger() const noexcept 84 { 85 return IsInt() || IsLong(); 86 } 87 IsFloat()88 bool IsFloat() const noexcept 89 { 90 return std::holds_alternative<float>(num_); 91 } 92 IsDouble()93 bool IsDouble() const noexcept 94 { 95 return std::holds_alternative<double>(num_); 96 } 97 IsReal()98 bool IsReal() const noexcept 99 { 100 return IsFloat() || IsDouble(); 101 } 102 ConversionError()103 bool ConversionError() const 104 { 105 return (flags_ & NumberFlags::ERROR) != 0; 106 } 107 GetInt()108 int32_t GetInt() const 109 { 110 ASSERT(IsInt()); 111 return std::get<int32_t>(num_); 112 } 113 GetLong()114 int64_t GetLong() const 115 { 116 return std::visit(overloaded {[](int64_t value) { return value; }, 117 [](int32_t value) { return static_cast<int64_t>(value); }, 118 []([[maybe_unused]] auto value) { 119 ASSERT(false); 120 return static_cast<int64_t>(0); 121 }}, 122 num_); 123 } 124 GetFloat()125 float GetFloat() const 126 { 127 ASSERT(IsFloat()); 128 return std::get<float>(num_); 129 } 130 GetDouble()131 double GetDouble() const 132 { 133 return std::visit( 134 overloaded {[](double value) { return value; }, [](auto value) { return static_cast<double>(value); }}, 135 num_); 136 } 137 Str()138 const util::StringView &Str() const 139 { 140 return str_; 141 } 142 Negate()143 void Negate() 144 { 145 std::visit(overloaded {[](auto &value) { value = -value; }}, num_); 146 } 147 148 template <typename RT> CanGetValue()149 bool CanGetValue() const noexcept 150 { 151 using T = typename std::remove_cv_t<typename std::remove_reference_t<RT>>; 152 153 if constexpr (std::is_same_v<T, int64_t>) { 154 return IsInteger(); 155 } else if constexpr (std::is_same_v<T, int32_t>) { 156 return IsInt(); 157 } else if constexpr (std::is_same_v<T, double>) { 158 return true; 159 } else if constexpr (std::is_same_v<T, float>) { 160 return IsFloat(); 161 } else { 162 return false; 163 } 164 } 165 166 template <typename RT> GetValue()167 auto GetValue() const 168 { 169 using T = typename std::remove_cv_t<typename std::remove_reference_t<RT>>; 170 171 if constexpr (std::is_same_v<T, int64_t>) { 172 return GetLong(); 173 } else if constexpr (std::is_same_v<T, int32_t>) { 174 return GetInt(); 175 } else if constexpr (std::is_same_v<T, double>) { 176 return GetDouble(); 177 } else if constexpr (std::is_same_v<T, float>) { 178 return GetFloat(); 179 } else { 180 static_assert(dependent_false_v<T>, "Invalid value type was requested for Number."); 181 } 182 } 183 184 template <typename RT> SetValue(RT && value)185 void SetValue(RT &&value) 186 { 187 using T = typename std::remove_cv_t<typename std::remove_reference_t<RT>>; 188 189 if constexpr (std::is_same_v<T, int64_t> || std::is_same_v<T, int32_t> || std::is_same_v<T, double> || 190 std::is_same_v<T, float>) { 191 num_ = std::forward<RT>(value); 192 } else { 193 static_assert(dependent_false_v<T>, "Invalid value type was requested for Number."); 194 } 195 } 196 197 private: 198 util::StringView str_ {}; 199 std::variant<int32_t, int64_t, float, double> num_; 200 NumberFlags flags_ {NumberFlags::NONE}; 201 }; 202 } // namespace panda::es2panda::lexer 203 204 #endif 205