css_parse/syntax/
declaration_rule_list.rs1use crate::{
2 Declaration, DeclarationValue, Kind, KindSet, Parse, Parser, Peek, Result, Span, T, ToCursors, ToSpan, diagnostics,
3 token_macros,
4};
5use bumpalo::collections::Vec;
6
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(tag = "type"))]
30pub struct DeclarationRuleList<'a, D, R>
31where
32 D: DeclarationValue<'a>,
33{
34 pub open_curly: token_macros::LeftCurly,
35 pub declarations: Vec<'a, Declaration<'a, D>>,
36 pub at_rules: Vec<'a, R>,
37 pub close_curly: Option<token_macros::RightCurly>,
38}
39
40impl<'a, D, R> Peek<'a> for DeclarationRuleList<'a, D, R>
41where
42 D: DeclarationValue<'a>,
43{
44 const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::LeftCurly]);
45}
46
47impl<'a, D, R> Parse<'a> for DeclarationRuleList<'a, D, R>
48where
49 D: DeclarationValue<'a>,
50 R: Parse<'a>,
51 Declaration<'a, D>: Parse<'a>,
52{
53 fn parse(p: &mut Parser<'a>) -> Result<Self> {
54 let open_curly = p.parse::<T!['{']>()?;
55 let mut declarations = Vec::new_in(p.bump());
56 let mut at_rules = Vec::new_in(p.bump());
57 loop {
58 if p.at_end() {
59 return Ok(Self { open_curly, declarations, at_rules, close_curly: None });
60 }
61 let close_curly = p.parse_if_peek::<T!['}']>()?;
62 if close_curly.is_some() {
63 return Ok(Self { open_curly, declarations, at_rules, close_curly });
64 }
65 if p.peek::<T![AtKeyword]>() {
66 at_rules.push(p.parse::<R>()?);
67 } else if p.peek::<T![Ident]>() {
68 let rule = p.parse::<Declaration<'a, D>>()?;
69 declarations.push(rule);
70 } else {
71 Err(diagnostics::Unexpected(p.next()))?;
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}