Token.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * Copyright (c) 2020-2021, the SerenityOS developers.
  3. * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/FlyString.h>
  9. #include <AK/String.h>
  10. #include <math.h>
  11. namespace Web::CSS {
  12. class Token {
  13. friend class Tokenizer;
  14. public:
  15. enum class Type {
  16. Invalid,
  17. EndOfFile,
  18. Ident,
  19. Function,
  20. AtKeyword,
  21. Hash,
  22. String,
  23. BadString,
  24. Url,
  25. BadUrl,
  26. Delim,
  27. Number,
  28. Percentage,
  29. Dimension,
  30. Whitespace,
  31. CDO,
  32. CDC,
  33. Colon,
  34. Semicolon,
  35. Comma,
  36. OpenSquare,
  37. CloseSquare,
  38. OpenParen,
  39. CloseParen,
  40. OpenCurly,
  41. CloseCurly
  42. };
  43. enum class HashType {
  44. Id,
  45. Unrestricted,
  46. };
  47. enum class NumberType {
  48. Integer,
  49. Number,
  50. };
  51. struct Position {
  52. size_t line { 0 };
  53. size_t column { 0 };
  54. };
  55. Type type() const { return m_type; }
  56. bool is(Type type) const { return m_type == type; }
  57. StringView ident() const
  58. {
  59. VERIFY(m_type == Type::Ident);
  60. return m_value.view();
  61. }
  62. StringView function() const
  63. {
  64. VERIFY(m_type == Type::Function);
  65. return m_value.view();
  66. }
  67. StringView delim() const
  68. {
  69. VERIFY(m_type == Type::Delim);
  70. return m_value.view();
  71. }
  72. StringView string() const
  73. {
  74. VERIFY(m_type == Type::String);
  75. return m_value.view();
  76. }
  77. StringView url() const
  78. {
  79. VERIFY(m_type == Type::Url);
  80. return m_value.view();
  81. }
  82. StringView at_keyword() const
  83. {
  84. VERIFY(m_type == Type::AtKeyword);
  85. return m_value.view();
  86. }
  87. HashType hash_type() const
  88. {
  89. VERIFY(m_type == Type::Hash);
  90. return m_hash_type;
  91. }
  92. StringView hash_value() const
  93. {
  94. VERIFY(m_type == Type::Hash);
  95. return m_value.view();
  96. }
  97. bool is(NumberType number_type) const { return is(Token::Type::Number) && m_number_type == number_type; }
  98. StringView number_string_value() const
  99. {
  100. VERIFY(m_type == Type::Number);
  101. return m_value.view();
  102. }
  103. double number_value() const
  104. {
  105. VERIFY(m_type == Type::Number);
  106. return m_number_value;
  107. }
  108. i64 to_integer() const
  109. {
  110. VERIFY(m_type == Type::Number && m_number_type == NumberType::Integer);
  111. return to_closest_integer(m_number_value);
  112. }
  113. bool is_integer_value_signed() const { return number_string_value().starts_with('-') || number_string_value().starts_with('+'); }
  114. StringView dimension_unit() const
  115. {
  116. VERIFY(m_type == Type::Dimension);
  117. return m_unit.view();
  118. }
  119. double dimension_value() const
  120. {
  121. VERIFY(m_type == Type::Dimension);
  122. return m_number_value;
  123. }
  124. i64 dimension_value_int() const { return to_closest_integer(dimension_value()); }
  125. double percentage() const
  126. {
  127. VERIFY(m_type == Type::Percentage);
  128. return m_number_value;
  129. }
  130. NumberType number_type() const
  131. {
  132. VERIFY((m_type == Type::Number) || (m_type == Type::Dimension) || (m_type == Type::Percentage));
  133. return m_number_type;
  134. }
  135. Type mirror_variant() const;
  136. String bracket_string() const;
  137. String bracket_mirror_string() const;
  138. String to_string() const;
  139. String to_debug_string() const;
  140. Position const& start_position() const { return m_start_position; }
  141. Position const& end_position() const { return m_end_position; }
  142. private:
  143. static i64 to_closest_integer(double value)
  144. {
  145. // https://www.w3.org/TR/css-values-4/#numeric-types
  146. // When a value cannot be explicitly supported due to range/precision limitations, it must be converted
  147. // to the closest value supported by the implementation, but how the implementation defines "closest"
  148. // is explicitly undefined as well.
  149. return static_cast<i64>(clamp(round(value), NumericLimits<i64>::min(), NumericLimits<i64>::max()));
  150. }
  151. Type m_type { Type::Invalid };
  152. FlyString m_value;
  153. FlyString m_unit;
  154. HashType m_hash_type { HashType::Unrestricted };
  155. NumberType m_number_type { NumberType::Integer };
  156. double m_number_value { 0 };
  157. Position m_start_position;
  158. Position m_end_position;
  159. };
  160. }