1 /* 2 * Copyright (c) 2021-2024 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 "util/ustring.h" 20 #include "util/enumbitops.h" 21 22 namespace ark::es2panda::lexer { 23 24 using ENUMBITOPS_OPERATORS; 25 26 enum class NumberFlags : uint32_t { 27 NONE, 28 BIGINT = 1U << 0U, 29 DECIMAL_POINT = 1U << 1U, 30 EXPONENT = 1U << 2U, 31 ERROR = 1U << 3U, 32 }; 33 34 } // namespace ark::es2panda::lexer 35 36 template <> 37 struct enumbitops::IsAllowedType<ark::es2panda::lexer::NumberFlags> : std::true_type { 38 }; 39 40 namespace ark::es2panda::lexer { 41 42 // NOLINTBEGIN(readability-identifier-naming) 43 // NOLINTBEGIN(fuchsia-multiple-inheritance) 44 template <class... Ts> 45 struct overloaded : Ts... { 46 using Ts::operator()...; 47 }; 48 49 template <class... Ts> 50 overloaded(Ts...) -> overloaded<Ts...>; 51 // NOLINTEND(fuchsia-multiple-inheritance) 52 53 template <typename> 54 inline constexpr bool dependent_false_v = false; 55 // NOLINTEND(readability-identifier-naming) 56 57 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 58 class Number { 59 public: 60 // NOLINTBEGIN(cppcoreguidelines-pro-type-member-init) 61 explicit Number() noexcept : num_(static_cast<int32_t>(0)) {}; 62 explicit Number(util::StringView str) noexcept : str_(str) {} 63 // NOLINTNEXTLINE(bugprone-exception-escape) 64 explicit Number(util::StringView str, NumberFlags flags) noexcept; 65 explicit Number(util::StringView str, double num) noexcept : str_(str), num_(num) {} 66 explicit Number(uint32_t num) noexcept : Number(static_cast<int32_t>(num)) {} 67 explicit Number(int32_t num) noexcept : num_(num) {} 68 explicit Number(uint64_t num) noexcept : Number(static_cast<int64_t>(num)) {} 69 explicit Number(int64_t num) noexcept : num_(num) {} 70 explicit Number(float num) noexcept : num_(num) {} 71 explicit Number(double num) noexcept : num_(num) {} 72 DEFAULT_COPY_SEMANTIC(Number); 73 DEFAULT_MOVE_SEMANTIC(Number); 74 ~Number() = default; 75 // NOLINTEND(cppcoreguidelines-pro-type-member-init) 76 77 bool IsInt() const noexcept 78 { 79 return std::holds_alternative<int32_t>(num_); 80 } 81 82 bool IsLong() const noexcept 83 { 84 return std::holds_alternative<int64_t>(num_); 85 } 86 87 bool IsInteger() const noexcept 88 { 89 return IsInt() || IsLong(); 90 } 91 92 bool IsFloat() const noexcept 93 { 94 return std::holds_alternative<float>(num_); 95 } 96 97 bool IsDouble() const noexcept 98 { 99 return std::holds_alternative<double>(num_); 100 } 101 102 bool IsReal() const noexcept 103 { 104 return IsFloat() || IsDouble(); 105 } 106 107 bool ConversionError() const 108 { 109 return (flags_ & NumberFlags::ERROR) != 0; 110 } 111 112 int32_t GetInt() const 113 { 114 ASSERT(IsInt()); 115 return std::get<int32_t>(num_); 116 } 117 118 int64_t GetLong() const 119 { 120 return std::visit(overloaded {[](int64_t value) { return value; }, 121 [](int32_t value) { return static_cast<int64_t>(value); }, 122 []([[maybe_unused]] auto value) { 123 ASSERT(false); 124 return static_cast<int64_t>(0); 125 }}, 126 num_); 127 } 128 129 float GetFloat() const 130 { 131 ASSERT(IsFloat()); 132 return std::get<float>(num_); 133 } 134 135 double GetDouble() const 136 { 137 return std::visit( 138 overloaded {[](double value) { return value; }, [](auto value) { return static_cast<double>(value); }}, 139 num_); 140 } 141 142 const util::StringView &Str() const 143 { 144 return str_; 145 } 146 147 void Negate() 148 { 149 std::visit(overloaded {[](auto &value) { value = -value; }}, num_); 150 if (std::holds_alternative<int64_t>(num_)) { 151 int64_t num = std::get<int64_t>(num_); 152 if (num == INT32_MIN) { 153 SetValue<int32_t>(num); 154 } 155 } 156 } 157 158 template <typename RT> 159 bool CanGetValue() const noexcept 160 { 161 using T = typename std::remove_cv_t<typename std::remove_reference_t<RT>>; 162 163 if constexpr (std::is_same_v<T, int64_t>) { 164 return IsInteger(); 165 } else if constexpr (std::is_same_v<T, int32_t>) { 166 return IsInt(); 167 } else if constexpr (std::is_same_v<T, double>) { 168 return true; 169 } else if constexpr (std::is_same_v<T, float>) { 170 return IsFloat(); 171 } else { 172 return false; 173 } 174 } 175 176 template <typename RT> 177 auto GetValue() const 178 { 179 using T = typename std::remove_cv_t<typename std::remove_reference_t<RT>>; 180 181 if constexpr (std::is_same_v<T, int64_t>) { 182 return GetLong(); 183 } else if constexpr (std::is_same_v<T, int32_t>) { 184 return GetInt(); 185 } else if constexpr (std::is_same_v<T, double>) { 186 return GetDouble(); 187 } else if constexpr (std::is_same_v<T, float>) { 188 return GetFloat(); 189 } else { 190 static_assert(dependent_false_v<T>, "Invalid value type was requested for Number."); 191 } 192 } 193 194 template <typename RT> 195 void SetValue(RT &&value) 196 { 197 using T = typename std::remove_cv_t<typename std::remove_reference_t<RT>>; 198 199 if constexpr (std::is_same_v<T, int64_t> || std::is_same_v<T, int32_t> || std::is_same_v<T, double> || 200 std::is_same_v<T, float>) { 201 num_ = std::forward<RT>(value); 202 } else { 203 static_assert(dependent_false_v<T>, "Invalid value type was requested for Number."); 204 } 205 } 206 207 private: 208 util::StringView str_ {}; 209 std::variant<int32_t, int64_t, float, double> num_; 210 NumberFlags flags_ {NumberFlags::NONE}; 211 }; 212 } // namespace ark::es2panda::lexer 213 214 #endif 215