css_parse/syntax/
declaration_rule_list.rs1use crate::{
2 Declaration, DeclarationValue, Diagnostic, Kind, KindSet, Parse, Parser, Peek, Result, Span, T, ToCursors, ToSpan,
3 token_macros,
4};
5use bumpalo::collections::Vec;
6
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
28#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
29pub struct DeclarationRuleList<'a, D, R>
30where
31 D: DeclarationValue<'a>,
32{
33 pub open_curly: token_macros::LeftCurly,
34 pub declarations: Vec<'a, Declaration<'a, D>>,
35 pub at_rules: Vec<'a, R>,
36 pub close_curly: Option<token_macros::RightCurly>,
37}
38
39impl<'a, D, R> Peek<'a> for DeclarationRuleList<'a, D, R>
40where
41 D: DeclarationValue<'a>,
42{
43 const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::LeftCurly]);
44}
45
46impl<'a, D, R> Parse<'a> for DeclarationRuleList<'a, D, R>
47where
48 D: DeclarationValue<'a>,
49 R: Parse<'a>,
50 Declaration<'a, D>: Parse<'a>,
51{
52 fn parse(p: &mut Parser<'a>) -> Result<Self> {
53 let open_curly = p.parse::<T!['{']>()?;
54 let mut declarations = Vec::new_in(p.bump());
55 let mut at_rules = Vec::new_in(p.bump());
56 loop {
57 if p.at_end() {
58 return Ok(Self { open_curly, declarations, at_rules, close_curly: None });
59 }
60 let close_curly = p.parse_if_peek::<T!['}']>()?;
61 if close_curly.is_some() {
62 return Ok(Self { open_curly, declarations, at_rules, close_curly });
63 }
64 let c = p.peek_n(1);
65 if <T![AtKeyword]>::peek(p, c) {
66 at_rules.push(p.parse::<R>()?);
67 } else if <T![Ident]>::peek(p, c) {
68 let rule = p.parse::<Declaration<'a, D>>()?;
69 declarations.push(rule);
70 } else {
71 Err(Diagnostic::new(p.next(), Diagnostic::unexpected))?;
72 }
73 }
74 }
75}
76
77impl<'a, D, R> ToCursors for DeclarationRuleList<'a, D, R>
78where
79 D: DeclarationValue<'a> + ToCursors,
80 R: ToCursors,
81{
82 fn to_cursors(&self, s: &mut impl crate::CursorSink) {
83 ToCursors::to_cursors(&self.open_curly, s);
84 ToCursors::to_cursors(&self.declarations, s);
85 ToCursors::to_cursors(&self.at_rules, s);
86 ToCursors::to_cursors(&self.close_curly, s);
87 }
88}
89
90impl<'a, D, R> ToSpan for DeclarationRuleList<'a, D, R>
91where
92 D: DeclarationValue<'a> + ToSpan,
93 R: ToSpan,
94{
95 fn to_span(&self) -> Span {
96 self.open_curly.to_span()
97 + if let Some(close) = self.close_curly {
98 close.to_span()
99 } else {
100 self.declarations.to_span() + self.at_rules.to_span()
101 }
102 }
103}