css_parse/traits/declaration_value.rs
1use crate::{Cursor, KindSet, Parser, Peek, Result, T, diagnostics};
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 DeclarationValue<'a>: Sized {
6 type ComputedValue: Peek<'a>;
7
8 /// Determines if the given [Cursor] represents a valid [Ident][crate::token_macros::Ident] matching a known property
9 /// name.
10 ///
11 /// If implementing a set of declarations where ony limited property-ids are valid (such as the declarations allowed
12 /// by an at-rule) then it might be worthwhile changing this to sometimes return `false`, which consumers of this
13 /// trait can use to error early without having to do too much backtracking.
14 fn valid_declaration_name(_p: &Parser<'a>, _c: Cursor) -> bool {
15 true
16 }
17
18 /// Determines if the parsed Self was parsed as an unknown value.
19 ///
20 /// If implementing a set of declarations where any name is accepted, or where the value might result in re-parsing
21 /// as unknown, this method can be used to signal that to upstream consumers of this trait. By default this returns
22 /// `false` because `valid_declaration_name` returns `true`, the assumption being that any successful construction of
23 /// Self is indeed a valid and known declaration.
24 fn is_unknown(&self) -> bool {
25 false
26 }
27
28 /// Determines if the parsed Self was parsed as a Custom value.
29 ///
30 /// If implementing a set of declarations where custom names are accepted, or where the value might result in
31 /// re-parsing as unknown, this method can be used to signal that to upstream consumers of this trait. By default
32 /// this returns `false` because `valid_declaration_name` returns `true`, the assumption being that any successful
33 /// construction of Self is indeed a valid and known declaration.
34 fn is_custom(&self) -> bool {
35 false
36 }
37
38 /// Determines if the parsed Self was parsed as the "initial" keyword.
39 ///
40 /// If implementing a set of declarations where the "initial" keyword is accepted this method can be used to signal
41 /// that to upstream consumers of this trait.
42 fn is_initial(&self) -> bool;
43
44 /// Determines if the parsed Self was parsed as the "inherit" keyword.
45 ///
46 /// If implementing a set of declarations where the "inherit" keyword is accepted this method can be used to signal
47 /// that to upstream consumers of this trait.
48 fn is_inherit(&self) -> bool;
49
50 /// Determines if the parsed Self was parsed as the "unset" keyword.
51 ///
52 /// If implementing a set of declarations where the "unset" keyword is accepted this method can be used to signal
53 /// that to upstream consumers of this trait.
54 fn is_unset(&self) -> bool;
55
56 /// Determines if the parsed Self was parsed as the "revert" keyword.
57 ///
58 /// If implementing a set of declarations where the "revert" keyword is accepted this method can be used to signal
59 /// that to upstream consumers of this trait.
60 fn is_revert(&self) -> bool;
61
62 /// Determines if the parsed Self was parsed as the "revert" keyword.
63 ///
64 /// If implementing a set of declarations where the "revert" keyword is accepted this method can be used to signal
65 /// that to upstream consumers of this trait.
66 fn is_revert_layer(&self) -> bool;
67
68 /// Determines if the parsed Self is not a valid literal production of the grammar, and instead some of its
69 /// constituent parts will need additional computation to reify into a known value.
70 ///
71 /// CSS properties are allowed to include substitutions, such as `calc()` or `var()`. These are not defined in the
72 /// declaration's grammar but are instead stored so that when a style object is reified the declarations that had
73 /// those tokens can be recomputed against the context of their node.
74 fn needs_computing(&self) -> bool;
75
76 /// Like `parse()` but with the additional context of the `name` [Cursor]. This cursor is known to be dashed ident,
77 /// therefore this should return a `Self` reflecting a Custom property. Alternatively, if this DeclarationValue
78 /// disallows custom declarations then this is the right place to return a parse Error.
79 ///
80 /// The default implementation of this method is to return an Unexpected Err.
81 fn parse_custom_declaration_value(p: &mut Parser<'a>, _name: Cursor) -> Result<Self> {
82 let c = p.peek_n(1);
83 Err(diagnostics::Unexpected(c))?
84 }
85
86 /// Like `parse()` but with the additional context of the `name` [Cursor]. This is only called before verifying that
87 /// the next token was peeked to be a ComputedValue, therefore this should return a `Self` reflecting a Computed
88 /// property. Alternatively, if this DeclarationValue disallows computed declarations then this is the right place to
89 /// return a parse Error.
90 ///
91 /// The default implementation of this method is to return an Unexpected Err.
92 fn parse_computed_declaration_value(p: &mut Parser<'a>, _name: Cursor) -> Result<Self> {
93 let c = p.peek_n(1);
94 Err(diagnostics::Unexpected(c))?
95 }
96
97 /// Like `parse()` but with the additional context of the `name` [Cursor]. This is only called on values that are
98 /// assumed to be _specified_, that is, they're not custom and not computed. Therefore this should return a `Self`
99 /// reflecting a specified value. If this results in a Parse error then ComputedValue will be checked to see if the
100 /// parser stopped because it saw a computed value function. If this results in a success, the next token is still
101 /// checked as it may be a ComputedValue, which - if so - the parsed value will be discarded, and the parser rewound
102 /// to re-parse this as a ComputedValue.
103 ///
104 /// The default implementation of this method is to return an Unexpected Err.
105 fn parse_specified_declaration_value(p: &mut Parser<'a>, _name: Cursor) -> Result<Self> {
106 let c = p.peek_n(1);
107 Err(diagnostics::Unexpected(c))?
108 }
109
110 /// Like `parse()` but with the additional context of the `name` [Cursor]. This is only called on values that are
111 /// didn't parse as either a Custom, Computed or Specified value therefore this should return a `Self` reflecting an
112 /// unknown property, or alternatively the right place to return a parse error.
113 ///
114 /// The default implementation of this method is to return an Unexpected Err.
115 fn parse_unknown_declaration_value(p: &mut Parser<'a>, _name: Cursor) -> Result<Self> {
116 let c = p.peek_n(1);
117 Err(diagnostics::Unexpected(c))?
118 }
119
120 // Like `parse()` but with the additional context of the `name` [Cursor] - the same [Cursor]
121 // passed to [DeclarationValue::valid_declaration_name()].
122 fn parse_declaration_value(p: &mut Parser<'a>, name: Cursor) -> Result<Self> {
123 if name.token().is_dashed_ident() {
124 return Self::parse_custom_declaration_value(p, name);
125 }
126 if !Self::valid_declaration_name(p, name) {
127 return Self::parse_unknown_declaration_value(p, name);
128 }
129 if p.peek::<Self::ComputedValue>() {
130 return Self::parse_computed_declaration_value(p, name);
131 }
132 let checkpoint = p.checkpoint();
133 if let Ok(val) = Self::parse_specified_declaration_value(p, name) {
134 if p.at_end() || p.peek_n(1) == KindSet::RIGHT_CURLY_OR_SEMICOLON || p.peek::<T![!]>() {
135 return Ok(val);
136 }
137 }
138 if p.peek::<Self::ComputedValue>() {
139 p.rewind(checkpoint);
140 if let Ok(val) = Self::parse_computed_declaration_value(p, name) {
141 return Ok(val);
142 }
143 }
144 p.rewind(checkpoint);
145 Self::parse_unknown_declaration_value(p, name)
146 }
147}