oxc_css_parser/parser/at_rule/
layer.rs1use super::Parser;
2use crate::{
3 Parse,
4 ast::*,
5 bump, eat,
6 error::{Error, PResult},
7 peek,
8 pos::{Span, Spanned},
9 tokenizer::{Token, TokenWithSpan},
10 util,
11};
12
13impl<'cmt, 's: 'cmt> Parse<'cmt, 's> for LayerNames<'s> {
15 fn parse(input: &mut Parser<'cmt, 's>) -> PResult<Self> {
16 let first = input.parse::<LayerName>()?;
17 let mut span = first.span.clone();
18
19 let mut names = vec![first];
20 let mut comma_spans = vec![];
21 while let Some((_, comma_span)) = eat!(input, Comma) {
22 comma_spans.push(comma_span);
23 names.push(input.parse()?);
24 }
25
26 if let Some(last) = names.last() {
27 span.end = last.span.end;
28 }
29 Ok(LayerNames {
30 names,
31 comma_spans,
32 span,
33 })
34 }
35}
36
37impl<'cmt, 's: 'cmt> Parse<'cmt, 's> for LayerName<'s> {
39 fn parse(input: &mut Parser<'cmt, 's>) -> PResult<Self> {
40 let first = input.parse::<InterpolableIdent>()?;
41 let start = first.span().start;
42 let mut end = first.span().end;
43
44 let mut idents = vec![first];
45 while let TokenWithSpan {
46 token: Token::Dot(..),
47 span,
48 } = peek!(input)
49 {
50 if span.start == end {
51 let span = bump!(input).span;
52 let ident = input.parse::<InterpolableIdent>()?;
53 util::assert_no_ws_or_comment(&span, ident.span())?;
54 end = ident.span().end;
55 idents.push(ident);
56 } else {
57 break;
58 }
59 }
60
61 let invalid_ident = idents.iter().find(|ident| match &ident {
62 InterpolableIdent::Literal(ident) => util::is_css_wide_keyword(&ident.name),
63 _ => false,
64 });
65 if let Some(invalid_ident) = invalid_ident {
66 input.recoverable_errors.push(Error {
67 kind: crate::error::ErrorKind::CSSWideKeywordDisallowed,
68 span: invalid_ident.span().clone(),
69 });
70 }
71
72 let span = Span { start, end };
73 Ok(LayerName { idents, span })
74 }
75}