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, Vec, token_macros,
5};
6use csskit_proc_macro::node;
7
8#[node]
21#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize))]
23#[cfg_attr(feature = "serde", serde(bound(serialize = "D: serde::Serialize, R: serde::Serialize")))]
24pub struct Block<'a, D, R, M>
25where
26 D: DeclarationValue<'a, M>,
27 M: NodeMetadata,
28{
29 pub open_curly: token_macros::LeftCurly,
30 pub declarations: Vec<'a, Declaration<'a, D, M>>,
31 pub rules: Vec<'a, R>,
32 pub close_curly: Option<token_macros::RightCurly>,
33 #[cfg_attr(feature = "serde", serde(skip))]
34 pub meta: M,
35}
36
37impl<'a, D, R, M> NodeWithMetadata<M> for Block<'a, D, R, M>
38where
39 D: DeclarationValue<'a, M>,
40 M: NodeMetadata,
41{
42 fn metadata(&self) -> M {
43 self.meta
44 }
45}
46
47impl<'a, D, R, M> Peek<'a> for Block<'a, D, R, M>
48where
49 D: DeclarationValue<'a, M>,
50 M: NodeMetadata,
51{
52 const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::LeftCurly]);
53}
54
55impl<'a, D, R, M> Parse<'a> for Block<'a, D, R, M>
56where
57 D: DeclarationValue<'a, M>,
58 R: Parse<'a> + NodeWithMetadata<M> + RuleVariants<'a, DeclarationValue = D, Metadata = M>,
59 M: NodeMetadata,
60{
61 fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
62 where
63 Iter: Iterator<Item = crate::Cursor> + Clone,
64 {
65 let open_curly = p.parse::<T!['{']>()?;
66 let mut declarations = Vec::new_in(p.alloc());
67 let mut rules = Vec::new_in(p.alloc());
68 let mut meta = M::default();
69
70 let mut decls: Vec<'a, DeclarationOrBad<'a, D, M>> = Vec::new_in(p.alloc());
73
74 macro_rules! flush_decls {
77 () => {
78 if !decls.is_empty() {
79 let group =
80 DeclarationGroup { declarations: std::mem::replace(&mut decls, Vec::new_in(p.alloc())) };
81 if let Some(rule) = R::from_declaration_group(group) {
82 meta = meta.merge(rule.metadata());
83 rules.push(rule);
84 }
85 }
86 };
87 }
88
89 loop {
90 p.consume_trivia_as_leading();
98 const ERROR_KINDS: KindSet = KindSet::new(&[
99 Kind::CdcOrCdo,
100 Kind::Semicolon,
101 Kind::RightParen,
102 Kind::RightSquare,
103 Kind::BadString,
104 Kind::BadUrl,
105 ]);
106 let c = p.peek_n(1);
107 if c == ERROR_KINDS {
108 let old_skip = p.set_skip(ERROR_KINDS);
109 p.consume_trivia_as_leading();
110 p.set_skip(old_skip);
111 continue;
112 }
113 if p.at_end() {
114 break;
115 }
116 let c = p.peek_n(1);
117 if <T!['}']>::peek(p, c) {
118 break;
119 }
120 let old_state = p.set_state(State::Nested);
121 let checkpoint = p.checkpoint();
122 if <T![AtKeyword]>::peek(p, c) {
123 flush_decls!();
125 let rule = p.parse::<R>();
126 p.set_state(old_state);
127 let rule = rule?;
128 meta = meta.merge(rule.metadata());
129 rules.push(rule);
130 } else if let Ok(Some(decl)) = p.try_parse_if_peek::<Declaration<'a, D, M>>() {
131 if decl.is_unknown() && !D::valid_declaration_name(p, decl.name.into()) {
148 p.rewind(checkpoint.clone());
149 if let Ok(rule) = p.parse::<R>()
150 && !rule.is_unknown()
151 {
152 flush_decls!();
154 p.set_state(old_state);
155 meta = meta.merge(rule.metadata());
156 rules.push(rule);
157 continue;
158 }
159 p.rewind(checkpoint);
161 p.parse::<Declaration<'a, D, M>>().ok();
162 }
163 p.set_state(old_state);
164 meta = meta.merge(decl.metadata());
165 declarations.push(decl);
166 } else {
167 let result = p.parse::<R>();
169 p.set_state(old_state);
170 match result {
171 Ok(rule) => {
172 flush_decls!();
173 meta = meta.merge(rule.metadata());
174 rules.push(rule);
175 }
176 Err(_) => {
177 p.rewind(checkpoint);
179 p.set_state(State::Nested);
180 if let Ok(bad_decl) = p.parse::<BadDeclaration>() {
181 p.set_state(old_state);
182 decls.push(DeclarationOrBad::Bad(bad_decl));
183 }
184 }
185 }
186 }
187 }
188
189 flush_decls!();
191 let close_curly = p.parse_if_peek::<T!['}']>()?;
192 Ok(Self { open_curly, declarations, rules, close_curly, meta })
193 }
194}
195
196impl<'a, D, R, M> ToCursors for Block<'a, D, R, M>
197where
198 D: DeclarationValue<'a, M> + ToCursors,
199 R: ToCursors,
200 M: NodeMetadata,
201{
202 fn to_cursors(&self, s: &mut impl CursorSink) {
203 ToCursors::to_cursors(&self.open_curly, s);
204 ToCursors::to_cursors(&self.declarations, s);
205 ToCursors::to_cursors(&self.rules, s);
206 ToCursors::to_cursors(&self.close_curly, s);
207 }
208}
209
210impl<'a, D, R, M> ToSpan for Block<'a, D, R, M>
211where
212 D: DeclarationValue<'a, M> + ToSpan,
213 R: ToSpan,
214 M: NodeMetadata,
215{
216 fn to_span(&self) -> Span {
217 self.open_curly.to_span()
218 + if self.close_curly.is_some() {
219 self.close_curly.to_span()
220 } else {
221 self.declarations.to_span() + self.rules.to_span() + self.close_curly.to_span()
222 }
223 }
224}
225
226impl<'a, D, R, M> SemanticEq for Block<'a, D, R, M>
227where
228 D: DeclarationValue<'a, M>,
229 R: SemanticEq,
230 M: NodeMetadata,
231{
232 fn semantic_eq(&self, other: &Self) -> bool {
233 self.open_curly.semantic_eq(&other.open_curly)
234 && self.close_curly.semantic_eq(&other.close_curly)
235 && self.declarations.semantic_eq(&other.declarations)
236 && self.rules.semantic_eq(&other.rules)
237 }
238}
239
240#[cfg(test)]
241mod tests {
242 use super::*;
243 use crate::EmptyAtomSet;
244 use crate::{Cursor, test_helpers::*};
245
246 #[derive(Debug)]
247 struct Decl(T![Ident]);
248
249 impl<M: NodeMetadata> NodeWithMetadata<M> for Decl {
250 fn metadata(&self) -> M {
251 M::default()
252 }
253 }
254
255 impl<'a, M: NodeMetadata> DeclarationValue<'a, M> for Decl {
256 fn is_initial(&self) -> bool {
257 false
258 }
259
260 fn is_inherit(&self) -> bool {
261 false
262 }
263
264 fn is_unset(&self) -> bool {
265 false
266 }
267
268 fn is_revert(&self) -> bool {
269 false
270 }
271
272 fn is_revert_layer(&self) -> bool {
273 false
274 }
275
276 fn needs_computing(&self) -> bool {
277 false
278 }
279
280 fn parse_specified_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _: Cursor) -> Result<Self>
281 where
282 Iter: Iterator<Item = crate::Cursor> + Clone,
283 {
284 p.parse::<T![Ident]>().map(Self)
285 }
286 }
287
288 impl ToCursors for Decl {
289 fn to_cursors(&self, s: &mut impl CursorSink) {
290 ToCursors::to_cursors(&self.0, s);
291 }
292 }
293
294 impl ToSpan for Decl {
295 fn to_span(&self) -> Span {
296 self.0.to_span()
297 }
298 }
299
300 impl SemanticEq for Decl {
301 fn semantic_eq(&self, other: &Self) -> bool {
302 self.0.semantic_eq(&other.0)
303 }
304 }
305
306 impl NodeWithMetadata<()> for T![Ident] {
307 fn metadata(&self) {}
308 }
309
310 #[derive(Debug)]
311 struct Rule(T![Ident]);
312
313 impl<'a> Parse<'a> for Rule {
314 fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
315 where
316 I: Iterator<Item = Cursor> + Clone,
317 {
318 Ok(Self(p.parse::<T![Ident]>()?))
319 }
320 }
321
322 impl ToCursors for Rule {
323 fn to_cursors(&self, s: &mut impl CursorSink) {
324 ToCursors::to_cursors(&self.0, s);
325 }
326 }
327
328 impl ToSpan for Rule {
329 fn to_span(&self) -> Span {
330 self.0.to_span()
331 }
332 }
333
334 impl NodeWithMetadata<()> for Rule {
335 fn metadata(&self) {}
336 }
337
338 impl<'a> crate::RuleVariants<'a> for Rule {
339 type DeclarationValue = Decl;
340 type Metadata = ();
341 }
342
343 #[test]
344 fn test_writes() {
345 assert_parse!(EmptyAtomSet::ATOMS, Block<Decl, Rule, ()>, "{color:black}");
346 }
347
348 #[test]
349 fn test_bad_string_in_block_does_not_hang() {
350 let alloc = crate::Arena::new();
351 for src in
352 [":{\".\n", "am:{\"\n", "alm:{\"\n", "alm:{\";.\n", "alm:{\"; }.\n", "alm:s {\n \x16\x00\x00:\";\n }\n"]
353 {
354 let lexer = css_lexer::Lexer::new(&EmptyAtomSet::ATOMS, src);
355 let mut parser = crate::Parser::new(&alloc, src, lexer);
356 let _ = parser.parse::<Block<Decl, Rule, ()>>();
357 }
358 }
359
360 #[test]
361 fn test_trailing_error_kinds_do_not_oom() {
362 let alloc = crate::Arena::new();
363 for src in ["{)))))))))))))", "{))))))))))))))", "{\r)))))))))))))"] {
364 let lexer = css_lexer::Lexer::new(&EmptyAtomSet::ATOMS, src);
365 let mut parser = crate::Parser::new(&alloc, src, lexer);
366 let _ = parser.parse::<Block<Decl, Rule, ()>>();
367 }
368 }
369}