Skip to main content

oxc_css_parser/parser/at_rule/
scope.rs

1use super::Parser;
2use crate::{
3    Parse,
4    ast::*,
5    error::{Error, ErrorKind, PResult},
6    pos::Span,
7    tokenizer::{Token, TokenWithSpan},
8};
9
10impl<'a> Parse<'a> for ScopeEnd<'a> {
11    fn parse(input: &mut Parser<'a>) -> PResult<Self> {
12        let to_span = match input.cursor.bump()? {
13            TokenWithSpan { token: Token::Ident(ident), span }
14                if ident.name().eq_ignore_ascii_case("to") =>
15            {
16                span
17            }
18            TokenWithSpan { span, .. } => {
19                return Err(Error { kind: ErrorKind::ExpectScopeTo, span });
20            }
21        };
22
23        let (_, lparen_span) = input.cursor.expect_l_paren()?;
24        let selector = input.parse()?;
25        let (_, Span { end, .. }) = input.cursor.expect_r_paren()?;
26
27        let span = Span { start: to_span.start, end };
28        Ok(ScopeEnd { to_span, lparen_span, selector, span })
29    }
30}
31
32// https://drafts.csswg.org/css-cascade-6/#scope-syntax
33impl<'a> Parse<'a> for ScopePrelude<'a> {
34    fn parse(input: &mut Parser<'a>) -> PResult<Self> {
35        let start = if let Token::LParen(..) = input.cursor.peek()?.token {
36            Some(input.parse::<ScopeStart>()?)
37        } else {
38            None
39        };
40        let end = match &input.cursor.peek()?.token {
41            Token::Ident(ident) if ident.name().eq_ignore_ascii_case("to") => {
42                Some(input.parse::<ScopeEnd>()?)
43            }
44            _ => None,
45        };
46
47        match (start, end) {
48            (Some(start), Some(end)) => {
49                let span = Span { start: start.span.start, end: end.span.end };
50                Ok(ScopePrelude::Both(ScopeStartWithEnd { start, end, span }))
51            }
52            (Some(start), None) => Ok(ScopePrelude::StartOnly(start)),
53            (None, Some(end)) => Ok(ScopePrelude::EndOnly(end)),
54            (None, None) => {
55                let TokenWithSpan { token, span } = input.cursor.bump()?;
56                Err(Error { kind: ErrorKind::Unexpected("(", token.symbol()), span })
57            }
58        }
59    }
60}
61
62impl<'a> Parse<'a> for ScopeStart<'a> {
63    fn parse(input: &mut Parser<'a>) -> PResult<Self> {
64        let (_, Span { start, .. }) = input.cursor.expect_l_paren()?;
65        let selector = input.parse()?;
66        let (_, Span { end, .. }) = input.cursor.expect_r_paren()?;
67
68        Ok(ScopeStart { selector, span: Span { start, end } })
69    }
70}