css_parse/traits/
rule_variants.rs

1use crate::{BadDeclaration, Cursor, Diagnostic, Parser, Peek, Result, State, T, ToCursors, ToSpan};
2
3/// A trait that can be used for AST nodes representing a Declaration's Value. It offers some
4/// convenience functions for handling such values.
5pub trait RuleVariants<'a>: Sized + ToCursors + ToSpan {
6	/// Like [crate::Parse::parse()] but with the additional context of the `name` [Cursor]. This cursor is known to be
7	/// an [AtKeyword][crate::token_macros::AtKeyword], therefore this should return a `Self` reflecting a AtRule. If the
8	/// AtRule is not _known_, or otherwise fails then this should [Err] and [RuleVariants::parse_unknown_at_rule()] can
9	/// be called.
10	///
11	/// The default implementation of this method is to return an Unexpected [Err].
12	fn parse_at_rule<I>(p: &mut Parser<'a, I>, _name: Cursor) -> Result<Self>
13	where
14		I: Iterator<Item = Cursor> + Clone,
15	{
16		let c = p.peek_n(1);
17		Err(Diagnostic::new(c, Diagnostic::unexpected))?
18	}
19
20	/// Like [crate::Parse::parse()] but with the additional context of the `name` [Cursor]. This cursor is known to be
21	/// an AtKeyword and that [RuleVariants::parse_at_rule()] failed. This should therefore return a Self that represents
22	/// an Unknwon AtRule, or otherwise [Err].
23	///
24	/// The default implementation of this method is to return an Unexpected [Err].
25	fn parse_unknown_at_rule<I>(p: &mut Parser<'a, I>, _name: Cursor) -> Result<Self>
26	where
27		I: Iterator<Item = Cursor> + Clone,
28	{
29		let c = p.peek_n(1);
30		Err(Diagnostic::new(c, Diagnostic::unexpected))?
31	}
32
33	/// Like [crate::Parse::parse()] but with the additional context that the next cursor is _not_ an
34	/// [AtKeyword][crate::token_macros::AtKeyword], therefore this can attempt to parse a Qualified Rule. If the rule
35	/// fails to parse, then [RuleVariants::parse_unknown_qualified_rule()] will be called.
36	///
37	/// The default implementation of this method is to return an Unexpected [Err].
38	fn parse_qualified_rule<I>(p: &mut Parser<'a, I>, _name: Cursor) -> Result<Self>
39	where
40		I: Iterator<Item = Cursor> + Clone,
41	{
42		let c = p.peek_n(1);
43		Err(Diagnostic::new(c, Diagnostic::unexpected))?
44	}
45
46	/// Like [crate::Parse::parse()] but with the additional context that the next cursor is _not_ an
47	/// [AtKeyword][crate::token_macros::AtKeyword], and that [RuleVariants::parse_qualified_rule()] has failed.
48	/// Therefore this should attempt to parse an Unknown Qualified Rule, or [Err].
49	///
50	/// The default implementation of this method is to return an Unexpected [Err].
51	fn parse_unknown_qualified_rule<I>(p: &mut Parser<'a, I>, _name: Cursor) -> Result<Self>
52	where
53		I: Iterator<Item = Cursor> + Clone,
54	{
55		let c = p.peek_n(1);
56		Err(Diagnostic::new(c, Diagnostic::unexpected))?
57	}
58
59	/// If all of the parse steps have failed, including parsing the Unknown Qualified Rule, we may want to consume a bad
60	/// declaration (especially if the parser is in a nested context). This is done automatically on failing to parse
61	/// an Unknown Qualified Rule, and this method is given the [BadDeclaration].
62	///
63	/// This should attempt to build a Self that represents the [BadDeclaration], or return [None] so
64	/// [RuleVariants::parse_rule_variants()] can [Err].
65	///
66	/// The default implementation of this method is to return [None].
67	fn bad_declaration(_: BadDeclaration<'a>) -> Option<Self> {
68		None
69	}
70
71	fn parse_rule_variants<I>(p: &mut Parser<'a, I>) -> Result<Self>
72	where
73		I: Iterator<Item = Cursor> + Clone,
74	{
75		let checkpoint = p.checkpoint();
76		let c: Cursor = p.peek_n(1);
77		if <T![AtKeyword]>::peek(p, c) {
78			Self::parse_at_rule(p, c).or_else(|_| {
79				p.rewind(checkpoint);
80				Self::parse_unknown_at_rule(p, c)
81			})
82		} else {
83			Self::parse_qualified_rule(p, c)
84				.or_else(|_| {
85					p.rewind(checkpoint.clone());
86					Self::parse_unknown_qualified_rule(p, c)
87				})
88				.or_else(|_| {
89					p.rewind(checkpoint);
90					let state = p.set_state(State::Nested);
91					let declaration = p.parse::<BadDeclaration>();
92					p.set_state(state);
93					if let Some(s) = Self::bad_declaration(declaration?) {
94						Ok(s)
95					} else {
96						Err(Diagnostic::new(c, Diagnostic::unexpected))?
97					}
98				})
99		}
100	}
101}