1use crate::{
2 Arena, Cursor, Diagnostic, Feature, Kind, KindSet, ParserCheckpoint, ParserReturn, Result, SourceOffset, ToCursors,
3 Vec,
4 traits::{Parse, Peek},
5};
6use atom_set::{AtomSet, DynAtomSet};
7use bitmask_enum::bitmask;
8use css_lexer::SourceCursor;
9use std::mem;
10
11const BUFFER_LEN: usize = 12;
16const BUFFER_REFILL_INDEX: usize = BUFFER_LEN - 5;
20
21#[derive(Debug)]
22pub struct Parser<'a, I: Iterator<Item = Cursor> + Clone> {
23 pub(crate) source_text: &'a str,
24
25 pub(crate) cursor_iter: I,
26
27 #[allow(dead_code)]
28 pub(crate) features: Feature,
29
30 pub(crate) errors: Vec<'a, Diagnostic>,
31
32 pub(crate) trivia: Vec<'a, (Vec<'a, Cursor>, Cursor)>,
33
34 pub(crate) state: State,
35
36 pub(crate) alloc: &'a Arena,
37
38 skip: KindSet,
39
40 stop: KindSet,
41
42 buffer: [Cursor; BUFFER_LEN],
43 buffer_index: usize,
44
45 substitution_depth: u8,
48
49 #[cfg(debug_assertions)]
50 pub(crate) last_cursor: Option<Cursor>,
51}
52
53#[bitmask(u8)]
54#[bitmask_config(vec_debug)]
55#[derive(Default)]
56pub enum State {
57 Nested = 0b0000_0001,
58 DisallowRelativeSelector = 0b0000_0010,
60}
61
62#[inline]
63fn eof_cursor(len: usize) -> Cursor {
64 let eof_offset = css_lexer::SourceOffset(len as u32);
65 Cursor::new(eof_offset, css_lexer::Token::EOF)
66}
67
68impl<'a, I> Parser<'a, I>
69where
70 I: Iterator<Item = Cursor> + Clone,
71{
72 pub fn new(alloc: &'a Arena, source_text: &'a str, mut cursor_iter: I) -> Self {
74 let eof_cursor = eof_cursor(source_text.len());
75 let mut buffer = [eof_cursor; BUFFER_LEN];
76 buffer.fill_with(|| cursor_iter.next().unwrap_or(eof_cursor));
77
78 Self {
79 source_text,
80 cursor_iter,
81 features: Feature::none(),
82 errors: Vec::new_in(alloc),
83 trivia: Vec::new_in(alloc),
84 state: State::none(),
85 skip: KindSet::TRIVIA,
86 stop: KindSet::NONE,
87 buffer,
88 buffer_index: 0,
89 substitution_depth: 0,
90 alloc,
91 #[cfg(debug_assertions)]
92 last_cursor: None,
93 }
94 }
95
96 pub fn with_features(mut self, features: Feature) -> Self {
97 self.features = features;
98 self
99 }
100
101 fn fill_buffer(&mut self, from: usize) {
102 self.buffer.copy_within(from..BUFFER_LEN, 0);
104 let eof = eof_cursor(self.source_text.len());
106 for i in BUFFER_LEN - from..BUFFER_LEN {
107 self.buffer[i] = self.cursor_iter.next().unwrap_or(eof);
108 }
109 self.buffer_index = 0;
110 }
111
112 #[inline]
113 pub fn alloc(&self) -> &'a Arena {
114 self.alloc
115 }
116
117 pub const MAX_SUBSTITUTION_DEPTH: u8 = 32;
119
120 #[inline]
126 #[must_use]
127 pub fn enter_substitution(&mut self) -> bool {
128 if self.substitution_depth >= Self::MAX_SUBSTITUTION_DEPTH {
129 return false;
130 }
131 self.substitution_depth += 1;
132 true
133 }
134
135 #[inline]
137 pub fn exit_substitution(&mut self) {
138 debug_assert!(self.substitution_depth > 0);
139 self.substitution_depth = self.substitution_depth.saturating_sub(1);
140 }
141
142 #[inline]
143 pub fn enabled(&self, other: Feature) -> bool {
144 self.features.contains(other)
145 }
146
147 #[inline]
149 pub fn source_text(&self) -> &'a str {
150 self.source_text
151 }
152
153 #[inline]
154 pub fn is(&self, state: State) -> bool {
155 self.state.contains(state)
156 }
157
158 #[inline]
159 pub fn set_state(&mut self, state: State) -> State {
160 let old = self.state;
161 self.state = state;
162 old
163 }
164
165 #[inline]
166 pub fn set_skip(&mut self, skip: KindSet) -> KindSet {
167 let old = self.skip;
168 self.skip = skip;
169 old
170 }
171
172 #[inline]
173 pub fn set_stop(&mut self, stop: KindSet) -> KindSet {
174 let old = self.stop;
175 self.stop = stop;
176 old
177 }
178
179 pub fn parse_entirely<T: Parse<'a> + ToCursors>(&mut self) -> ParserReturn<'a, T> {
180 let output = match T::parse(self) {
181 Ok(output) => Some(output),
182 Err(error) => {
183 self.errors.push(error);
184 None
185 }
186 };
187 let remaining_non_trivia = !self.at_end() && self.peek_n(1) != Kind::Eof;
188 let at_end = self.peek_n_with_skip(1, KindSet::NONE) == Kind::Eof;
189
190 if !at_end {
191 let start = self.peek_n_with_skip(1, KindSet::NONE);
192 let mut end;
193 loop {
194 end = self.next();
195 if end == Kind::Eof {
196 break;
197 }
198 }
199 if remaining_non_trivia {
200 self.errors.push(Diagnostic::new(start, Diagnostic::expected_end).with_end_cursor(end));
201 }
202 }
203 let errors = mem::replace(&mut self.errors, Vec::new_in(self.alloc));
204 let trivia = mem::replace(&mut self.trivia, Vec::new_in(self.alloc));
205 ParserReturn::new(output, self.source_text, errors, trivia)
206 }
207
208 pub fn parse<T: Parse<'a>>(&mut self) -> Result<T> {
209 T::parse(self)
210 }
211
212 pub fn peek<T: Peek<'a>>(&self) -> bool {
213 T::peek(self, self.peek_n(1))
214 }
215
216 pub fn parse_if_peek<T: Peek<'a> + Parse<'a>>(&mut self) -> Result<Option<T>> {
217 if T::peek(self, self.peek_n(1)) { T::parse(self).map(Some) } else { Ok(None) }
218 }
219
220 pub fn try_parse<T: Parse<'a>>(&mut self) -> Result<T> {
221 T::try_parse(self)
222 }
223
224 pub fn try_parse_if_peek<T: Peek<'a> + Parse<'a>>(&mut self) -> Result<Option<T>> {
225 if T::peek(self, self.peek_n(1)) { T::try_parse(self).map(Some) } else { Ok(None) }
226 }
227
228 pub fn equals_atom(&self, c: Cursor, atom: &'static dyn DynAtomSet) -> bool {
229 let mut cursor_bits = c.token().atom_bits();
230 if cursor_bits == 0 {
231 if c != KindSet::ATOM_LIKE {
232 return false;
233 }
234 let source_cursor = self.to_source_cursor(c);
235 cursor_bits = atom.str_to_bits(&source_cursor.parse(self.alloc));
236 }
237 cursor_bits == atom.bits()
238 }
239
240 pub fn to_atom<A: AtomSet + PartialEq>(&self, c: Cursor) -> A {
241 let bits = c.token().atom_bits();
242 if bits == 0 {
243 if c != KindSet::ATOM_LIKE {
244 return A::from_bits(0);
245 }
246 let source_cursor = self.to_source_cursor(c);
247 return A::from_str(&source_cursor.parse(self.alloc));
248 }
249 #[cfg(debug_assertions)]
250 if c == KindSet::ATOM_LIKE && c != Kind::Dimension {
251 let is_dashed = c.token().is_dashed_ident();
252 let source_cursor = self.to_source_cursor(c);
253 let text = source_cursor.parse(self.alloc);
254 let comparable = if is_dashed { &text[2..] } else { &text[..] };
255 debug_assert!(
256 A::from_bits(bits) == A::from_str(comparable),
257 "{:?} -> {:?} != {:?} ({:?})",
258 c,
259 A::from_bits(bits),
260 A::from_str(comparable),
261 comparable
262 );
263 }
264 A::from_bits(bits)
265 }
266
267 #[inline(always)]
268 pub fn offset(&self) -> SourceOffset {
269 self.buffer[self.buffer_index].offset()
270 }
271
272 #[inline(always)]
273 pub fn at_end(&self) -> bool {
274 self.buffer[self.buffer_index] == Kind::Eof
275 }
276
277 pub fn rewind(&mut self, checkpoint: ParserCheckpoint<I>) {
278 let ParserCheckpoint { iter, errors_pos, trivia_pos, buffer, buffer_index, skip, stop, state, .. } = checkpoint;
279
280 self.cursor_iter = iter;
281
282 self.errors.truncate(errors_pos as usize);
283 self.trivia.truncate(trivia_pos as usize);
284
285 self.buffer = buffer;
286 self.buffer_index = buffer_index;
287
288 self.skip = skip;
289 self.stop = stop;
290 self.state = state;
291
292 #[cfg(debug_assertions)]
293 {
294 self.last_cursor = None;
295 }
296 }
297
298 #[inline]
299 pub fn checkpoint(&self) -> ParserCheckpoint<I> {
300 ParserCheckpoint {
301 cursor: self.buffer[self.buffer_index],
302 errors_pos: self.errors.len() as u8,
303 trivia_pos: self.trivia.len() as u16,
304 iter: self.cursor_iter.clone(),
305 buffer: self.buffer,
306 buffer_index: self.buffer_index,
307 skip: self.skip,
308 stop: self.stop,
309 state: self.state,
310 }
311 }
312
313 #[inline]
314 pub fn next_is_stop(&self) -> bool {
315 for c in &self.buffer[self.buffer_index..BUFFER_LEN] {
316 if c != self.skip {
317 return c == self.stop;
318 }
319 }
320
321 let mut iter = self.cursor_iter.clone();
322 loop {
323 let Some(cursor) = iter.next() else {
324 return false;
325 };
326 if cursor != self.skip {
327 return cursor == self.stop;
328 }
329 }
330 }
331
332 #[inline]
333 pub(crate) fn peek_n_with_skip(&self, n: u8, skip: KindSet) -> Cursor {
334 let mut remaining = n;
335
336 for c in &self.buffer[self.buffer_index..BUFFER_LEN] {
337 if c == Kind::Eof {
338 return *c;
339 }
340 if c != skip {
341 remaining -= 1;
342 if remaining == 0 {
343 return *c;
344 }
345 }
346 }
347
348 let mut iter = self.cursor_iter.clone();
349 loop {
350 let Some(cursor) = iter.next() else {
351 return eof_cursor(self.source_text.len());
352 };
353 if cursor == Kind::Eof {
354 return cursor;
355 }
356 if cursor != skip {
357 remaining -= 1;
358 if remaining == 0 {
359 return cursor;
360 }
361 }
362 }
363 }
364
365 #[inline]
366 pub fn peek_n(&self, n: u8) -> Cursor {
367 self.peek_n_with_skip(n, self.skip)
368 }
369
370 #[inline]
371 pub fn peek_n_including_whitespace(&self, n: u8) -> Cursor {
372 self.peek_n_with_skip(n, self.skip.remove(Kind::Whitespace))
373 }
374
375 pub fn to_source_cursor(&self, cursor: Cursor) -> SourceCursor<'a> {
376 SourceCursor::from(cursor, cursor.str_slice(self.source_text))
377 }
378
379 pub fn consume_trivia(&mut self) -> Vec<'a, Cursor> {
380 let mut trivia = Vec::new_in(self.alloc);
381 for i in self.buffer_index..BUFFER_LEN {
382 let c = self.buffer[i];
383 if c == Kind::Eof {
384 self.buffer_index = i;
385 return trivia;
386 } else if c == self.skip {
387 trivia.push(c)
388 } else {
389 self.buffer_index = i;
390 self.fill_buffer(i);
391 return trivia;
392 }
393 }
394
395 let eof = eof_cursor(self.source_text.len());
396 loop {
397 let Some(c) = self.cursor_iter.next() else {
398 self.buffer = [eof; BUFFER_LEN];
399 self.buffer_index = 0;
400 return trivia;
401 };
402 if c == Kind::Eof {
403 self.buffer = [eof; BUFFER_LEN];
404 self.buffer_index = 0;
405 return trivia;
406 } else if c == self.skip {
407 trivia.push(c)
408 } else {
409 self.buffer[0] = c;
410 for i in 1..BUFFER_LEN {
411 self.buffer[i] = self.cursor_iter.next().unwrap_or(eof);
412 }
413 self.buffer_index = 0;
414 return trivia;
415 }
416 }
417 }
418
419 pub fn consume_trivia_as_leading(&mut self) {
423 let trivia = self.consume_trivia();
424 if !trivia.is_empty() {
425 let next = self.peek_n(1);
427 self.trivia.push((trivia, next));
428 }
429 }
430
431 #[allow(clippy::should_implement_trait)]
432 pub fn next(&mut self) -> Cursor {
433 let mut pending_trivia = Vec::new_in(self.alloc);
435
436 loop {
437 if self.buffer_index >= BUFFER_REFILL_INDEX {
438 self.fill_buffer(self.buffer_index);
439 }
440
441 for i in self.buffer_index..BUFFER_LEN {
442 let c = self.buffer[i];
443 if c == Kind::Eof {
444 self.buffer_index = i;
445 if !pending_trivia.is_empty() {
447 self.trivia.push((pending_trivia.clone(), c));
448 }
449 #[cfg(debug_assertions)]
450 {
451 self.last_cursor = None;
452 }
453 return c;
454 } else if c == self.skip {
455 pending_trivia.push(c);
456 } else {
457 self.buffer_index = i + 1;
458 if self.buffer_index >= BUFFER_REFILL_INDEX {
459 self.fill_buffer(self.buffer_index);
460 }
461 if !pending_trivia.is_empty() {
463 self.trivia.push((pending_trivia.clone(), c));
464 }
465 #[cfg(debug_assertions)]
466 {
467 if let Some(last_cursor) = self.last_cursor {
468 debug_assert!(last_cursor != c, "Detected a next loop, {c:?} was fetched twice");
469 }
470 self.last_cursor = Some(c);
471 }
472 return c;
473 }
474 }
475
476 self.fill_buffer(BUFFER_LEN);
478 }
479 }
480}
481
482#[test]
483fn test_filling_buffer_with_skip_tokens() {
484 let str = "/*x*//*x*//*x*//*x*//*x*//*x*//*x*//*x*//*x*//*x*//*x*/a";
485 let alloc = crate::Arena::default();
486 let lexer = css_lexer::Lexer::new(&css_lexer::EmptyAtomSet::ATOMS, str);
487 let mut p = Parser::new(&alloc, str, lexer);
488 let c = p.next();
489 assert_eq!(c.token(), Kind::Ident);
490 let _ = p.at_end();
492 let _ = p.offset();
493}
494
495#[test]
496fn peek_and_next() {
497 let str = "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21";
498 let alloc = crate::Arena::default();
499 let lexer = css_lexer::Lexer::new(&css_lexer::EmptyAtomSet::ATOMS, str);
500 let mut p = Parser::new(&alloc, str, lexer);
501 assert!(!p.at_end());
502 assert_eq!(p.offset(), 0);
503 for n in 0..=1 {
504 let c = p.checkpoint();
505 for i in 0..=19 {
506 let c = p.peek_n(1);
507 assert_eq!(c.token(), Kind::Number);
508 assert_eq!(c.token().value(), i as f32);
509 let c = p.peek_n(2);
510 assert_eq!(c.token(), Kind::Number);
511 assert_eq!(c.token().value(), (i + 1) as f32);
512 let c = p.peek_n(3);
513 assert_eq!(c.token(), Kind::Number);
514 assert_eq!(c.token().value(), (i + 2) as f32);
515 let c = p.next();
516 assert_eq!(c.token().value(), i as f32);
517 let c = p.peek_n(1);
518 assert_eq!(c.token(), Kind::Number);
519 assert_eq!(c.token().value(), (i + 1) as f32);
520 }
521 if n == 0 {
522 p.rewind(c)
523 }
524 }
525 let c = p.next();
526 assert_eq!(c.token(), Kind::Number);
527 assert_eq!(c.token().value(), 20.0);
528 let c = p.next();
529 assert_eq!(c.token(), Kind::Number);
530 assert_eq!(c.token().value(), 21.0);
531 let c = p.next();
532 assert_eq!(c.token(), Kind::Eof);
533}
534
535#[test]
536fn peek_and_next_with_whitsespace() {
537 let str = "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21";
538 let alloc = crate::Arena::default();
539 let lexer = css_lexer::Lexer::new(&css_lexer::EmptyAtomSet::ATOMS, str);
540 let mut p = Parser::new(&alloc, str, lexer);
541 p.set_skip(KindSet::COMMENTS);
542 assert!(!p.at_end());
543 assert_eq!(p.offset(), 0);
544 for n in 0..=1 {
545 let c = p.checkpoint();
546 for i in 0..=19 {
547 let c = p.peek_n(1);
548 assert_eq!(c.token(), Kind::Number);
549 assert_eq!(c.token().value(), i as f32);
550 let c = p.peek_n(2);
551 assert_eq!(c.token(), Kind::Whitespace);
552 let c = p.peek_n(3);
553 assert_eq!(c.token(), Kind::Number);
554 assert_eq!(c.token().value(), (i + 1) as f32);
555 let c = p.peek_n(4);
556 assert_eq!(c.token(), Kind::Whitespace);
557 let c = p.peek_n(5);
558 assert_eq!(c.token(), Kind::Number);
559 assert_eq!(c.token().value(), (i + 2) as f32);
560 let c = p.next();
561 assert_eq!(c.token().value(), i as f32);
562 let c = p.peek_n(1);
563 assert_eq!(c.token(), Kind::Whitespace);
564 let c = p.peek_n(2);
565 assert_eq!(c.token(), Kind::Number);
566 assert_eq!(c.token().value(), (i + 1) as f32);
567 p.next();
568 }
569 if n == 0 {
570 p.rewind(c);
571 }
572 }
573 let c = p.next();
574 assert_eq!(c.token(), Kind::Number);
575 assert_eq!(c.token().value(), 20.0);
576 let c = p.next();
577 assert_eq!(c.token(), Kind::Whitespace);
578 let c = p.next();
579 assert_eq!(c.token(), Kind::Number);
580 assert_eq!(c.token().value(), 21.0);
581 let c = p.next();
582 assert_eq!(c.token(), Kind::Eof);
583}