css_parse/syntax/
no_block_allowed.rs

1use crate::{Cursor, CursorSink, Diagnostic, Parse, Parser, Peek, Result, Span, T, ToCursors, ToSpan};
2
3/// A struct to provide to rules to disallow blocks.
4///
5/// Sometimes a rule will not allow a block - for example `@charset`, `@import`. In those case, assigning this struct
6/// to the `Block` can be useful to ensure that the [QualifiedRule][crate::syntax::QualifiedRule] appropriately errors
7/// if it enters the Block parsing context. This captures the `;` token that may optionally end a "statement-style"
8/// at-rule.
9#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
11pub struct NoBlockAllowed(Option<T![;]>);
12
13impl<'a> Parse<'a> for NoBlockAllowed {
14	fn parse(p: &mut Parser<'a>) -> Result<Self> {
15		if p.at_end() {
16			Ok(Self(None))
17		} else if let Some(semicolon) = p.parse_if_peek::<T![;]>()? {
18			Ok(Self(Some(semicolon)))
19		} else {
20			Err(Diagnostic::new(p.next(), Diagnostic::unexpected))?
21		}
22	}
23}
24
25impl<'a> Peek<'a> for NoBlockAllowed {
26	fn peek(_: &Parser<'a>, _: Cursor) -> bool {
27		false
28	}
29}
30
31impl ToCursors for NoBlockAllowed {
32	fn to_cursors(&self, s: &mut impl CursorSink) {
33		if let Some(semicolon) = self.0 {
34			s.append(semicolon.into());
35		}
36	}
37}
38
39impl ToSpan for NoBlockAllowed {
40	fn to_span(&self) -> Span {
41		self.0.to_span()
42	}
43}