1use crate::{
2 BadDeclaration, CursorSink, Declaration, DeclarationGroup, DeclarationOrBad, DeclarationValue, Kind, KindSet,
3 NodeMetadata, NodeWithMetadata, Parse, Parser, Peek, Result, RuleVariants, SemanticEq, Span, State, T, ToCursors,
4 ToSpan, token_macros,
5};
6use bumpalo::collections::Vec;
7
8#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize))]
22#[cfg_attr(feature = "serde", serde(bound(serialize = "D: serde::Serialize, R: serde::Serialize")))]
23pub struct Block<'a, D, R, M>
24where
25 D: DeclarationValue<'a, M>,
26 M: NodeMetadata,
27{
28 pub open_curly: token_macros::LeftCurly,
29 pub declarations: Vec<'a, Declaration<'a, D, M>>,
30 pub rules: Vec<'a, R>,
31 pub close_curly: Option<token_macros::RightCurly>,
32 #[cfg_attr(feature = "serde", serde(skip))]
33 pub meta: M,
34}
35
36impl<'a, D, R, M> NodeWithMetadata<M> for Block<'a, D, R, M>
37where
38 D: DeclarationValue<'a, M>,
39 M: NodeMetadata,
40{
41 fn metadata(&self) -> M {
42 self.meta
43 }
44}
45
46impl<'a, D, R, M> Peek<'a> for Block<'a, D, R, M>
47where
48 D: DeclarationValue<'a, M>,
49 M: NodeMetadata,
50{
51 const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::LeftCurly]);
52}
53
54impl<'a, D, R, M> Parse<'a> for Block<'a, D, R, M>
55where
56 D: DeclarationValue<'a, M>,
57 R: Parse<'a> + NodeWithMetadata<M> + RuleVariants<'a, DeclarationValue = D, Metadata = M>,
58 M: NodeMetadata,
59{
60 fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
61 where
62 Iter: Iterator<Item = crate::Cursor> + Clone,
63 {
64 let open_curly = p.parse::<T!['{']>()?;
65 let mut declarations = Vec::new_in(p.bump());
66 let mut rules = Vec::new_in(p.bump());
67 let mut meta = M::default();
68
69 let mut decls: Vec<'a, DeclarationOrBad<'a, D, M>> = Vec::new_in(p.bump());
72
73 macro_rules! flush_decls {
76 () => {
77 if !decls.is_empty() {
78 let group = DeclarationGroup { declarations: std::mem::replace(&mut decls, Vec::new_in(p.bump())) };
79 if let Some(rule) = R::from_declaration_group(group) {
80 meta = meta.merge(rule.metadata());
81 rules.push(rule);
82 }
83 }
84 };
85 }
86
87 loop {
88 if p.parse_if_peek::<T![' ']>()?.is_some() || p.parse_if_peek::<T![;]>()?.is_some() {
92 continue;
93 }
94 if p.at_end() {
95 break;
96 }
97 let c = p.peek_n(1);
98 if <T!['}']>::peek(p, c) {
99 break;
100 }
101 let old_state = p.set_state(State::Nested);
102 let checkpoint = p.checkpoint();
103 if <T![AtKeyword]>::peek(p, c) {
104 flush_decls!();
106 let rule = p.parse::<R>();
107 p.set_state(old_state);
108 let rule = rule?;
109 meta = meta.merge(rule.metadata());
110 rules.push(rule);
111 } else if let Ok(Some(decl)) = p.try_parse_if_peek::<Declaration<'a, D, M>>() {
112 if decl.is_unknown() && !D::valid_declaration_name(p, decl.name.into()) {
129 p.rewind(checkpoint.clone());
130 if let Ok(rule) = p.parse::<R>()
131 && !rule.is_unknown()
132 {
133 flush_decls!();
135 p.set_state(old_state);
136 meta = meta.merge(rule.metadata());
137 rules.push(rule);
138 continue;
139 }
140 p.rewind(checkpoint);
142 p.parse::<Declaration<'a, D, M>>().ok();
143 }
144 p.set_state(old_state);
145 meta = meta.merge(decl.metadata());
146 declarations.push(decl);
147 } else {
148 let result = p.parse::<R>();
150 p.set_state(old_state);
151 match result {
152 Ok(rule) => {
153 flush_decls!();
154 meta = meta.merge(rule.metadata());
155 rules.push(rule);
156 }
157 Err(_) => {
158 p.rewind(checkpoint);
160 p.set_state(State::Nested);
161 if let Ok(bad_decl) = p.parse::<BadDeclaration>() {
162 p.set_state(old_state);
163 decls.push(DeclarationOrBad::Bad(bad_decl));
164 }
165 }
166 }
167 }
168 }
169
170 flush_decls!();
172 let close_curly = p.parse_if_peek::<T!['}']>()?;
173 Ok(Self { open_curly, declarations, rules, close_curly, meta })
174 }
175}
176
177impl<'a, D, R, M> ToCursors for Block<'a, D, R, M>
178where
179 D: DeclarationValue<'a, M> + ToCursors,
180 R: ToCursors,
181 M: NodeMetadata,
182{
183 fn to_cursors(&self, s: &mut impl CursorSink) {
184 ToCursors::to_cursors(&self.open_curly, s);
185 ToCursors::to_cursors(&self.declarations, s);
186 ToCursors::to_cursors(&self.rules, s);
187 ToCursors::to_cursors(&self.close_curly, s);
188 }
189}
190
191impl<'a, D, R, M> ToSpan for Block<'a, D, R, M>
192where
193 D: DeclarationValue<'a, M> + ToSpan,
194 R: ToSpan,
195 M: NodeMetadata,
196{
197 fn to_span(&self) -> Span {
198 self.open_curly.to_span()
199 + if self.close_curly.is_some() {
200 self.close_curly.to_span()
201 } else {
202 self.declarations.to_span() + self.rules.to_span() + self.close_curly.to_span()
203 }
204 }
205}
206
207impl<'a, D, R, M> SemanticEq for Block<'a, D, R, M>
208where
209 D: DeclarationValue<'a, M>,
210 R: SemanticEq,
211 M: NodeMetadata,
212{
213 fn semantic_eq(&self, other: &Self) -> bool {
214 self.open_curly.semantic_eq(&other.open_curly)
215 && self.close_curly.semantic_eq(&other.close_curly)
216 && self.declarations.semantic_eq(&other.declarations)
217 && self.rules.semantic_eq(&other.rules)
218 }
219}
220
221#[cfg(test)]
222mod tests {
223 use super::*;
224 use crate::EmptyAtomSet;
225 use crate::{Cursor, test_helpers::*};
226
227 #[derive(Debug)]
228 struct Decl(T![Ident]);
229
230 impl<M: NodeMetadata> NodeWithMetadata<M> for Decl {
231 fn metadata(&self) -> M {
232 M::default()
233 }
234 }
235
236 impl<'a, M: NodeMetadata> DeclarationValue<'a, M> for Decl {
237 type ComputedValue = T![Eof];
238
239 fn is_initial(&self) -> bool {
240 false
241 }
242
243 fn is_inherit(&self) -> bool {
244 false
245 }
246
247 fn is_unset(&self) -> bool {
248 false
249 }
250
251 fn is_revert(&self) -> bool {
252 false
253 }
254
255 fn is_revert_layer(&self) -> bool {
256 false
257 }
258
259 fn needs_computing(&self) -> bool {
260 false
261 }
262
263 fn parse_specified_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _: Cursor) -> Result<Self>
264 where
265 Iter: Iterator<Item = crate::Cursor> + Clone,
266 {
267 p.parse::<T![Ident]>().map(Self)
268 }
269 }
270
271 impl ToCursors for Decl {
272 fn to_cursors(&self, s: &mut impl CursorSink) {
273 ToCursors::to_cursors(&self.0, s);
274 }
275 }
276
277 impl ToSpan for Decl {
278 fn to_span(&self) -> Span {
279 self.0.to_span()
280 }
281 }
282
283 impl SemanticEq for Decl {
284 fn semantic_eq(&self, other: &Self) -> bool {
285 self.0.semantic_eq(&other.0)
286 }
287 }
288
289 impl NodeWithMetadata<()> for T![Ident] {
290 fn metadata(&self) {}
291 }
292
293 #[derive(Debug)]
294 struct Rule(T![Ident]);
295
296 impl<'a> Parse<'a> for Rule {
297 fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
298 where
299 I: Iterator<Item = Cursor> + Clone,
300 {
301 Ok(Self(p.parse::<T![Ident]>()?))
302 }
303 }
304
305 impl ToCursors for Rule {
306 fn to_cursors(&self, s: &mut impl CursorSink) {
307 ToCursors::to_cursors(&self.0, s);
308 }
309 }
310
311 impl ToSpan for Rule {
312 fn to_span(&self) -> Span {
313 self.0.to_span()
314 }
315 }
316
317 impl NodeWithMetadata<()> for Rule {
318 fn metadata(&self) {}
319 }
320
321 impl<'a> crate::RuleVariants<'a> for Rule {
322 type DeclarationValue = Decl;
323 type Metadata = ();
324 }
325
326 #[test]
327 fn size_test() {
328 assert_eq!(std::mem::size_of::<Block<Decl, Rule, ()>>(), 96);
329 }
330
331 #[test]
332 fn test_writes() {
333 assert_parse!(EmptyAtomSet::ATOMS, Block<Decl, Rule, ()>, "{color:black}");
334 }
335}