oxc_css_parser/parser/at_rule/
custom_selector.rs1use super::Parser;
2use crate::{Parse, ast::*, error::PResult, expect, peek, pos::Span, tokenizer::Token, util};
3
4impl<'cmt, 's: 'cmt> Parse<'cmt, 's> for CustomSelector<'s> {
5 fn parse(input: &mut Parser<'cmt, 's>) -> PResult<Self> {
6 let prefix_arg = if matches!(peek!(input).token, Token::DollarVar(..)) {
7 Some(input.parse::<CustomSelectorArg>()?)
8 } else {
9 None
10 };
11
12 let (_, colon_span) = expect!(input, Colon);
13 if let Some(prefix_arg) = &prefix_arg {
14 util::assert_no_ws_or_comment(&prefix_arg.span, &colon_span)?;
15 }
16 let name = input.parse::<Ident>()?;
17 util::assert_no_ws_or_comment(&colon_span, &name.span)?;
18
19 let args = if matches!(peek!(input).token, Token::LParen(..)) {
20 Some(input.parse::<CustomSelectorArgs>()?)
21 } else {
22 None
23 };
24
25 let span = Span {
26 start: prefix_arg
27 .as_ref()
28 .map(|prefix_arg| prefix_arg.span.start)
29 .unwrap_or(name.span.start),
30 end: args
31 .as_ref()
32 .map(|args| args.span.end)
33 .unwrap_or(name.span.end),
34 };
35 Ok(CustomSelector {
36 prefix_arg,
37 name,
38 args,
39 span,
40 })
41 }
42}
43
44impl<'cmt, 's: 'cmt> Parse<'cmt, 's> for CustomSelectorArg<'s> {
45 fn parse(input: &mut Parser<'cmt, 's>) -> PResult<Self> {
46 let (dollar_var, dollar_var_span) = expect!(input, DollarVar);
47 Ok(CustomSelectorArg {
48 name: (
49 dollar_var.ident,
50 Span {
51 start: dollar_var_span.start + 1,
52 end: dollar_var_span.end,
53 },
54 )
55 .into(),
56 span: dollar_var_span,
57 })
58 }
59}
60
61impl<'cmt, 's: 'cmt> Parse<'cmt, 's> for CustomSelectorArgs<'s> {
62 fn parse(input: &mut Parser<'cmt, 's>) -> PResult<Self> {
63 let (_, Span { start, .. }) = expect!(input, LParen);
64
65 let mut args = vec![];
66 let mut comma_spans = vec![];
67 while !matches!(peek!(input).token, Token::RParen(..)) {
68 args.push(input.parse()?);
69 if !matches!(peek!(input).token, Token::RParen(..)) {
70 comma_spans.push(expect!(input, Comma).1);
71 }
72 }
73
74 let (_, Span { end, .. }) = expect!(input, RParen);
75 Ok(CustomSelectorArgs {
76 args,
77 comma_spans,
78 span: Span { start, end },
79 })
80 }
81}
82
83impl<'cmt, 's: 'cmt> Parse<'cmt, 's> for CustomSelectorPrelude<'s> {
85 fn parse(input: &mut Parser<'cmt, 's>) -> PResult<Self> {
86 let custom_selector = input.parse::<CustomSelector>()?;
87 let selector = input.parse::<SelectorList>()?;
88 let span = Span {
89 start: custom_selector.span.start,
90 end: selector.span.end,
91 };
92 Ok(CustomSelectorPrelude {
93 custom_selector,
94 selector,
95 span,
96 })
97 }
98}