Skip to content

Commit bc52104

Browse files
committed
continue working on parser
1 parent 3456367 commit bc52104

File tree

4 files changed

+432
-30
lines changed

4 files changed

+432
-30
lines changed

.editorconfig

+2
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ root = true
33
[*]
44
end_of_line = lf
55
insert_final_newline = true
6+
indent_size = 2
7+
indent_style = space

include/ada/url_pattern-inl.h

+238
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,244 @@ inline bool url_pattern_part::is_regexp() const noexcept {
8080
return type == url_pattern_part_type::REGEXP;
8181
}
8282

83+
namespace url_pattern_helpers {
84+
inline void constructor_string_parser::rewind() {
85+
// Set parser’s token index to parser’s component start.
86+
token_index = component_start;
87+
// Set parser’s token increment to 0.
88+
token_increment = 0;
89+
}
90+
91+
inline bool constructor_string_parser::is_hash_prefix() {
92+
// Return the result of running is a non-special pattern char given parser,
93+
// parser’s token index and "#".
94+
return is_non_special_pattern_char(token_index, "#");
95+
}
96+
97+
inline bool constructor_string_parser::is_search_prefix() {
98+
// If result of running is a non-special pattern char given parser, parser’s
99+
// token index and "?" is true, then return true.
100+
if (is_non_special_pattern_char(token_index, "?")) {
101+
return true;
102+
}
103+
104+
// If parser’s token list[parser’s token index]'s value is not "?", then
105+
// return false.
106+
if (token_list[token_index].value != "?") {
107+
return false;
108+
}
109+
110+
// If previous index is less than 0, then return true.
111+
if (token_index == 0) return true;
112+
// Let previous index be parser’s token index − 1.
113+
auto previous_index = token_index - 1;
114+
// Let previous token be the result of running get a safe token given parser
115+
// and previous index.
116+
auto previous_token = get_safe_token(previous_index);
117+
// If any of the following are true, then return false:
118+
// - previous token’s type is "name".
119+
// - previous token’s type is "regexp".
120+
// - previous token’s type is "close".
121+
// - previous token’s type is "asterisk".
122+
return !(previous_token.type == token_type::NAME ||
123+
previous_token.type == token_type::REGEXP ||
124+
previous_token.type == token_type::CLOSE ||
125+
previous_token.type == token_type::ASTERISK);
126+
}
127+
128+
inline bool constructor_string_parser::is_non_special_pattern_char(
129+
size_t index, std::string_view value) {
130+
// Let token be the result of running get a safe token given parser and index.
131+
auto token = get_safe_token(index);
132+
133+
// If token’s value is not value, then return false.
134+
if (token.value != value) {
135+
return false;
136+
}
137+
138+
// If any of the following are true:
139+
// - token’s type is "char";
140+
// - token’s type is "escaped-char"; or
141+
// - token’s type is "invalid-char",
142+
// - then return true.
143+
return token.type == token_type::CHAR ||
144+
token.type == token_type::ESCAPED_CHAR ||
145+
token.type == token_type::INVALID_CHAR ||
146+
token.type == token_type::INVALID_CHAR;
147+
}
148+
149+
inline const Token& constructor_string_parser::get_safe_token(size_t index) {
150+
// If index is less than parser’s token list's size, then return parser’s
151+
// token list[index].
152+
if (index < token_list.size()) [[likely]] {
153+
return token_list[index];
154+
}
155+
156+
// Assert: parser’s token list's size is greater than or equal to 1.
157+
ADA_ASSERT_TRUE(token_list.size() >= 1);
158+
159+
// Let token be parser’s token list[last index].
160+
// Assert: token’s type is "end".
161+
ADA_ASSERT_TRUE(token_list.end()->type == token_type::END);
162+
163+
// Return token.
164+
return *token_list.end();
165+
}
166+
167+
inline bool constructor_string_parser::is_group_open() const {
168+
// If parser’s token list[parser’s token index]'s type is "open", then return
169+
// true.
170+
return token_list[token_index].type == token_type::OPEN;
171+
}
172+
173+
inline bool constructor_string_parser::is_group_close() const {
174+
// If parser’s token list[parser’s token index]'s type is "close", then return
175+
// true.
176+
return token_list[token_index].type == token_type::CLOSE;
177+
}
178+
179+
inline bool constructor_string_parser::next_is_authority_slashes() {
180+
// If the result of running is a non-special pattern char given parser,
181+
// parser’s token index + 1, and "/" is false, then return false.
182+
if (!is_non_special_pattern_char(token_index + 1, "/")) {
183+
return false;
184+
}
185+
// If the result of running is a non-special pattern char given parser,
186+
// parser’s token index + 2, and "/" is false, then return false.
187+
if (!is_non_special_pattern_char(token_index + 2, "/")) {
188+
return false;
189+
}
190+
return true;
191+
}
192+
193+
inline bool constructor_string_parser::is_protocol_suffix() {
194+
// Return the result of running is a non-special pattern char given parser,
195+
// parser’s token index, and ":".
196+
return is_non_special_pattern_char(token_index, ":");
197+
}
198+
199+
inline void
200+
constructor_string_parser::compute_protocol_matches_special_scheme_flag() {
201+
// Let protocol string be the result of running make a component string given
202+
// parser.
203+
auto protocol_string = make_component_string();
204+
// Let protocol component be the result of compiling a component given
205+
// protocol string, canonicalize a protocol, and default options.
206+
auto protocol_component = url_pattern_component::compile(
207+
protocol_string, canonicalize_protocol,
208+
url_pattern_compile_component_options::DEFAULT);
209+
// If the result of running protocol component matches a special scheme given
210+
// protocol component is true, then set parser’s protocol matches a special
211+
// scheme flag to true.
212+
if (protocol_component_matches_special_scheme(
213+
protocol_component.get_pattern())) {
214+
protocol_matches_a_special_scheme_flag = true;
215+
}
216+
}
217+
218+
inline void constructor_string_parser::change_state(State new_state,
219+
size_t skip) {
220+
// If parser’s state is not "init", not "authority", and not "done", then set
221+
// parser’s result[parser’s state] to the result of running make a component
222+
// string given parser.
223+
if (state != State::INIT && state != State::AUTHORITY &&
224+
state != State::DONE) {
225+
auto value = make_component_string();
226+
// TODO: Simplify this.
227+
switch (state) {
228+
case State::PROTOCOL: {
229+
result.protocol = value;
230+
break;
231+
}
232+
case State::USERNAME: {
233+
result.username = value;
234+
break;
235+
}
236+
case State::PASSWORD: {
237+
result.password = value;
238+
break;
239+
}
240+
case State::HOSTNAME: {
241+
result.hostname = value;
242+
break;
243+
}
244+
case State::PORT: {
245+
result.port = value;
246+
break;
247+
}
248+
case State::PATHNAME: {
249+
result.pathname = value;
250+
break;
251+
}
252+
case State::SEARCH: {
253+
result.search = value;
254+
break;
255+
}
256+
case State::HASH: {
257+
result.hash = value;
258+
break;
259+
}
260+
default:
261+
unreachable();
262+
}
263+
} else if ((state == State::PROTOCOL || state == State::AUTHORITY ||
264+
state == State::USERNAME || state == State::PASSWORD ||
265+
state == State::HOSTNAME || state == State::PORT) &&
266+
(new_state == State::SEARCH || new_state == State::HASH) &&
267+
!result.pathname.has_value()) {
268+
// If parser’s state is "protocol", "authority", "username", "password",
269+
// "hostname", or "port"; new state is "search" or "hash"; and parser’s
270+
// result["pathname"] does not exist, then:
271+
// If parser’s protocol matches a special scheme flag is true, then set
272+
// parser’s result["pathname"] to "/".
273+
if (protocol_matches_a_special_scheme_flag) {
274+
result.pathname = "/";
275+
} else {
276+
// Otherwise, set parser’s result["pathname"] to the empty string.
277+
result.pathname = "";
278+
}
279+
} else if ((state == State::PROTOCOL || state == State::AUTHORITY ||
280+
state == State::USERNAME || state == State::PASSWORD ||
281+
state == State::HOSTNAME || state == State::PORT ||
282+
state == State::PATHNAME) &&
283+
new_state == State::HASH && !result.search.has_value()) {
284+
// If parser’s state is "protocol", "authority", "username", "password",
285+
// "hostname", "port", or "pathname"; new state is "hash"; and parser’s
286+
// result["search"] does not exist, then set parser’s result["search"] to
287+
// the empty string.
288+
result.search = "";
289+
}
290+
291+
// If parser’s state is not "init" and new state is not "done", then:
292+
293+
// Set parser’s state to new state.
294+
state = new_state;
295+
// Increment parser’s token index by skip.
296+
token_index += skip;
297+
// Set parser’s token increment to 0.
298+
token_increment = 0;
299+
}
300+
301+
inline std::string_view constructor_string_parser::make_component_string() {
302+
// Assert: parser’s token index is less than parser’s token list's size.
303+
ADA_ASSERT_TRUE(token_index < token_list.size());
304+
305+
// Let token be parser’s token list[parser’s token index].
306+
const auto token = token_list[token_index];
307+
// Let component start token be the result of running get a safe token given
308+
// parser and parser’s component start.
309+
const auto component_start_token = get_safe_token(component_start);
310+
// Let component start input index be component start token’s index.
311+
const auto component_start_input_index = component_start_token.index;
312+
// Let end index be token’s index.
313+
const auto end_index = token.index;
314+
// Return the code point substring from component start input index to end
315+
// index within parser’s input.
316+
return input.substr(component_start_input_index, end_index);
317+
}
318+
319+
} // namespace url_pattern_helpers
320+
83321
} // namespace ada
84322

85323
#endif

0 commit comments

Comments
 (0)