Serenity Operating System
1/*
2 * Copyright (c) 2020-2021, the SerenityOS developers.
3 * Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#pragma once
9
10#include <AK/FlyString.h>
11#include <AK/Utf8View.h>
12#include <LibWeb/CSS/Number.h>
13
14namespace Web::CSS::Parser {
15
16class Token {
17 friend class Tokenizer;
18
19public:
20 enum class Type {
21 Invalid,
22 EndOfFile,
23 Ident,
24 Function,
25 AtKeyword,
26 Hash,
27 String,
28 BadString,
29 Url,
30 BadUrl,
31 Delim,
32 Number,
33 Percentage,
34 Dimension,
35 Whitespace,
36 CDO,
37 CDC,
38 Colon,
39 Semicolon,
40 Comma,
41 OpenSquare,
42 CloseSquare,
43 OpenParen,
44 CloseParen,
45 OpenCurly,
46 CloseCurly
47 };
48
49 enum class HashType {
50 Id,
51 Unrestricted,
52 };
53
54 struct Position {
55 size_t line { 0 };
56 size_t column { 0 };
57 };
58
59 Type type() const { return m_type; }
60 bool is(Type type) const { return m_type == type; }
61
62 StringView ident() const
63 {
64 VERIFY(m_type == Type::Ident);
65 return m_value.bytes_as_string_view();
66 }
67
68 StringView function() const
69 {
70 VERIFY(m_type == Type::Function);
71 return m_value.bytes_as_string_view();
72 }
73
74 u32 delim() const
75 {
76 VERIFY(m_type == Type::Delim);
77 return *Utf8View(m_value.bytes_as_string_view()).begin();
78 }
79
80 StringView string() const
81 {
82 VERIFY(m_type == Type::String);
83 return m_value.bytes_as_string_view();
84 }
85
86 StringView url() const
87 {
88 VERIFY(m_type == Type::Url);
89 return m_value.bytes_as_string_view();
90 }
91
92 StringView at_keyword() const
93 {
94 VERIFY(m_type == Type::AtKeyword);
95 return m_value.bytes_as_string_view();
96 }
97
98 HashType hash_type() const
99 {
100 VERIFY(m_type == Type::Hash);
101 return m_hash_type;
102 }
103 StringView hash_value() const
104 {
105 VERIFY(m_type == Type::Hash);
106 return m_value.bytes_as_string_view();
107 }
108
109 Number const& number() const
110 {
111 VERIFY(m_type == Type::Number || m_type == Type::Dimension || m_type == Type::Percentage);
112 return m_number_value;
113 }
114 float number_value() const
115 {
116 VERIFY(m_type == Type::Number);
117 return m_number_value.value();
118 }
119 i64 to_integer() const
120 {
121 VERIFY(m_type == Type::Number && m_number_value.is_integer());
122 return m_number_value.integer_value();
123 }
124
125 StringView dimension_unit() const
126 {
127 VERIFY(m_type == Type::Dimension);
128 return m_value.bytes_as_string_view();
129 }
130 float dimension_value() const
131 {
132 VERIFY(m_type == Type::Dimension);
133 return m_number_value.value();
134 }
135 i64 dimension_value_int() const { return m_number_value.integer_value(); }
136
137 float percentage() const
138 {
139 VERIFY(m_type == Type::Percentage);
140 return m_number_value.value();
141 }
142
143 Type mirror_variant() const;
144 StringView bracket_string() const;
145 StringView bracket_mirror_string() const;
146
147 ErrorOr<String> to_string() const;
148 ErrorOr<String> to_debug_string() const;
149
150 Position const& start_position() const { return m_start_position; }
151 Position const& end_position() const { return m_end_position; }
152
153 static Token of_string(FlyString str)
154 {
155 Token token;
156 token.m_type = Type::String;
157 token.m_value = move(str);
158 return token;
159 }
160
161 static Token create_number(float value)
162 {
163 Token token;
164 token.m_type = Type::Number;
165 token.m_number_value = Number(Number::Type::Number, value);
166 return token;
167 }
168
169 static Token create_percentage(float value)
170 {
171 Token token;
172 token.m_type = Type::Percentage;
173 token.m_number_value = Number(Number::Type::Number, value);
174 return token;
175 }
176
177private:
178 Type m_type { Type::Invalid };
179
180 FlyString m_value;
181 Number m_number_value;
182 HashType m_hash_type { HashType::Unrestricted };
183
184 Position m_start_position;
185 Position m_end_position;
186};
187
188}