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}