Skip to main content

css_parse/syntax/
bad_declaration.rs

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