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