css_parse/syntax/
bad_declaration.rs

1use crate::{
2	CursorSink, Parse, Parser, Peek, Result as ParserResult, SemanticEq, Span, State, T, ToCursors, ToSpan,
3	syntax::ComponentValue,
4};
5use bumpalo::collections::Vec;
6
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
9pub struct BadDeclaration<'a>(Vec<'a, ComponentValue<'a>>);
10
11// https://drafts.csswg.org/css-syntax-3/#consume-the-remnants-of-a-bad-declaration
12impl<'a> Parse<'a> for BadDeclaration<'a> {
13	fn parse<Iter>(p: &mut Parser<'a, Iter>) -> ParserResult<Self>
14	where
15		Iter: Iterator<Item = crate::Cursor> + Clone,
16	{
17		let mut values = Vec::new_in(p.bump());
18		// To consume the remnants of a bad declaration from a token stream input, given a bool nested:
19		//
20		// Process input:
21		loop {
22			// <eof-token>
23			// <semicolon-token>
24			//
25			//     Discard a token from input, and return nothing.
26			if p.at_end() {
27				return Ok(Self(values));
28			}
29			let c = p.peek_n(1);
30			if <T![;]>::peek(p, c) {
31				values.push(p.parse::<ComponentValue>()?);
32				return Ok(Self(values));
33			}
34
35			// <}-token>
36			//
37			//     If nested is true, return nothing. Otherwise, discard a token.
38			if <T!['}']>::peek(p, c) {
39				if p.is(State::Nested) {
40					return Ok(Self(values));
41				} else {
42					p.parse::<T!['}']>()?;
43				}
44			}
45
46			// anything else
47			//
48			//     Consume a component value from input, and do nothing.
49			//
50			values.push(p.parse::<ComponentValue>()?);
51		}
52	}
53}
54
55impl<'a> ToSpan for BadDeclaration<'a> {
56	fn to_span(&self) -> Span {
57		self.0.to_span()
58	}
59}
60
61impl<'a> ToCursors for BadDeclaration<'a> {
62	fn to_cursors(&self, s: &mut impl CursorSink) {
63		for value in &self.0 {
64			ToCursors::to_cursors(value, s);
65		}
66	}
67}
68
69impl<'a> SemanticEq for BadDeclaration<'a> {
70	fn semantic_eq(&self, other: &Self) -> bool {
71		self.0.semantic_eq(&other.0)
72	}
73}
74
75impl<'a, M: crate::NodeMetadata> crate::NodeWithMetadata<M> for BadDeclaration<'a> {
76	fn metadata(&self) -> M {
77		M::default()
78	}
79}