swc_css_parser/parser/at_rules/
mod.rs

1use swc_common::{Span, Spanned};
2use swc_css_ast::*;
3
4use super::{input::ParserInput, PResult, Parser};
5use crate::{
6    error::{Error, ErrorKind},
7    parser::{values_and_units::is_math_function, BlockContentsGrammar, Ctx},
8    Parse,
9};
10
11impl<I> Parser<I>
12where
13    I: ParserInput,
14{
15    pub(super) fn parse_at_rule_prelude(&mut self, name: &str) -> PResult<Option<AtRulePrelude>> {
16        let prelude = match name {
17            "charset" => {
18                self.input.skip_ws();
19
20                let prelude = AtRulePrelude::CharsetPrelude(self.parse()?);
21
22                self.input.skip_ws();
23
24                Some(prelude)
25            }
26            "color-profile" => {
27                self.input.skip_ws();
28
29                let name = match cur!(self) {
30                    Token::Ident { value, .. } => {
31                        if value.starts_with("--") {
32                            ColorProfileName::DashedIdent(self.parse()?)
33                        } else {
34                            let name: Ident = self.parse()?;
35
36                            ColorProfileName::Ident(name)
37                        }
38                    }
39                    _ => {
40                        let span = self.input.cur_span();
41
42                        return Err(Error::new(span, ErrorKind::Expected("ident token")));
43                    }
44                };
45
46                let prelude = AtRulePrelude::ColorProfilePrelude(name);
47
48                self.input.skip_ws();
49
50                Some(prelude)
51            }
52            "container" => {
53                self.input.skip_ws();
54
55                let prelude = AtRulePrelude::ContainerPrelude(self.parse()?);
56
57                self.input.skip_ws();
58
59                Some(prelude)
60            }
61            "counter-style" => {
62                self.input.skip_ws();
63
64                let prelude = AtRulePrelude::CounterStylePrelude(self.parse()?);
65
66                self.input.skip_ws();
67
68                Some(prelude)
69            }
70            "custom-media" => {
71                self.input.skip_ws();
72
73                let prelude = AtRulePrelude::CustomMediaPrelude(self.parse()?);
74
75                self.input.skip_ws();
76
77                Some(prelude)
78            }
79            "document" | "-moz-document" => {
80                self.input.skip_ws();
81
82                let span = self.input.cur_span();
83                let url_match_fn = self.parse()?;
84                let mut matching_functions = vec![url_match_fn];
85
86                loop {
87                    self.input.skip_ws();
88
89                    if !eat!(self, ",") {
90                        break;
91                    }
92
93                    self.input.skip_ws();
94
95                    matching_functions.push(self.parse()?);
96                }
97
98                let prelude = AtRulePrelude::DocumentPrelude(DocumentPrelude {
99                    span: span!(self, span.lo),
100                    matching_functions,
101                });
102
103                self.input.skip_ws();
104
105                Some(prelude)
106            }
107            "font-face" => {
108                self.input.skip_ws();
109
110                if !is!(self, EOF) {
111                    let span = self.input.cur_span();
112
113                    return Err(Error::new(span, ErrorKind::Expected("'{' token")));
114                }
115
116                None
117            }
118            "font-feature-values" => {
119                self.input.skip_ws();
120
121                let prelude = AtRulePrelude::FontFeatureValuesPrelude(self.parse()?);
122
123                self.input.skip_ws();
124
125                Some(prelude)
126            }
127            "font-palette-values" => {
128                self.input.skip_ws();
129
130                let prelude = AtRulePrelude::FontPaletteValuesPrelude(self.parse()?);
131
132                self.input.skip_ws();
133
134                Some(prelude)
135            }
136            "stylistic" | "historical-forms" | "styleset" | "character-variant" | "swash"
137            | "ornaments" | "annotation"
138                if self.ctx.in_font_feature_values_at_rule =>
139            {
140                self.input.skip_ws();
141
142                if !is!(self, EOF) {
143                    let span = self.input.cur_span();
144
145                    return Err(Error::new(span, ErrorKind::Expected("'{' token")));
146                }
147
148                None
149            }
150            "import" => {
151                self.input.skip_ws();
152
153                let span = self.input.cur_span();
154                let href = Box::new(match cur!(self) {
155                    tok!("string") => ImportHref::Str(self.parse()?),
156                    tok!("url") => ImportHref::Url(self.parse()?),
157                    // TODO why we need it?
158                    tok!("function") => ImportHref::Url(self.parse()?),
159                    _ => {
160                        return Err(Error::new(
161                            span,
162                            ErrorKind::Expected("string, url or function token"),
163                        ))
164                    }
165                });
166
167                self.input.skip_ws();
168
169                let layer_name = if !is!(self, EOF) {
170                    match cur!(self) {
171                        Token::Ident { value, .. }
172                            if matches_eq_ignore_ascii_case!(value, "layer") =>
173                        {
174                            let name = ImportLayerName::Ident(self.parse()?);
175
176                            self.input.skip_ws();
177
178                            Some(Box::new(name))
179                        }
180                        Token::Function { value, .. }
181                            if matches_eq_ignore_ascii_case!(value, "layer") =>
182                        {
183                            let ctx = Ctx {
184                                in_import_at_rule: true,
185                                ..self.ctx
186                            };
187                            let func = self.with_ctx(ctx).parse_as::<Function>()?;
188
189                            self.input.skip_ws();
190
191                            Some(Box::new(ImportLayerName::Function(func)))
192                        }
193                        _ => None,
194                    }
195                } else {
196                    None
197                };
198
199                let import_conditions = if !is!(self, EOF) {
200                    Some(self.parse()?)
201                } else {
202                    None
203                };
204
205                let prelude = AtRulePrelude::ImportPrelude(ImportPrelude {
206                    span: span!(self, span.lo),
207                    href,
208                    layer_name,
209                    import_conditions,
210                });
211
212                Some(prelude)
213            }
214            "keyframes" | "-webkit-keyframes" | "-moz-keyframes" | "-o-keyframes"
215            | "-ms-keyframes" => {
216                self.input.skip_ws();
217
218                let prelude = AtRulePrelude::KeyframesPrelude(self.parse()?);
219
220                self.input.skip_ws();
221
222                Some(prelude)
223            }
224            "layer" => {
225                self.input.skip_ws();
226
227                if is!(self, Ident) {
228                    let mut name_list: Vec<LayerName> = Vec::new();
229
230                    name_list.push(self.parse()?);
231
232                    loop {
233                        self.input.skip_ws();
234
235                        if !eat!(self, ",") {
236                            break;
237                        }
238
239                        self.input.skip_ws();
240
241                        name_list.push(self.parse()?);
242                    }
243
244                    let res = if name_list.len() == 1 {
245                        Some(AtRulePrelude::LayerPrelude(LayerPrelude::Name(
246                            name_list.remove(0),
247                        )))
248                    } else {
249                        let first = name_list[0].span;
250                        let last = name_list[name_list.len() - 1].span;
251
252                        Some(AtRulePrelude::LayerPrelude(LayerPrelude::NameList(
253                            LayerNameList {
254                                name_list,
255                                span: Span::new(first.lo, last.hi),
256                            },
257                        )))
258                    };
259
260                    self.input.skip_ws();
261
262                    res
263                } else {
264                    None
265                }
266            }
267            "media" => {
268                self.input.skip_ws();
269
270                let media = if !is!(self, EOF) {
271                    let media_query_list = self.parse()?;
272
273                    Some(AtRulePrelude::MediaPrelude(media_query_list))
274                } else {
275                    None
276                };
277
278                self.input.skip_ws();
279
280                media
281            }
282            "namespace" => {
283                self.input.skip_ws();
284
285                let span = self.input.cur_span();
286                let mut prefix = None;
287
288                if is!(self, Ident) {
289                    prefix = match cur!(self) {
290                        tok!("ident") => Some(self.parse()?),
291                        _ => {
292                            unreachable!()
293                        }
294                    };
295
296                    self.input.skip_ws();
297                }
298
299                let uri = match cur!(self) {
300                    tok!("string") => NamespacePreludeUri::Str(self.parse()?),
301                    tok!("url") => NamespacePreludeUri::Url(self.parse()?),
302                    tok!("function") => NamespacePreludeUri::Url(self.parse()?),
303                    _ => {
304                        let span = self.input.cur_span();
305
306                        return Err(Error::new(
307                            span,
308                            ErrorKind::Expected("string, url or function tokens"),
309                        ));
310                    }
311                };
312
313                let prelude = AtRulePrelude::NamespacePrelude(NamespacePrelude {
314                    span: span!(self, span.lo),
315                    prefix,
316                    uri: Box::new(uri),
317                });
318
319                self.input.skip_ws();
320
321                Some(prelude)
322            }
323            "nest" => {
324                self.input.skip_ws();
325
326                let prelude = AtRulePrelude::NestPrelude(self.parse()?);
327
328                self.input.skip_ws();
329
330                Some(prelude)
331            }
332            "page" => {
333                self.input.skip_ws();
334
335                let prelude = if !is!(self, EOF) {
336                    Some(AtRulePrelude::PagePrelude(self.parse()?))
337                } else {
338                    None
339                };
340
341                self.input.skip_ws();
342
343                prelude
344            }
345            "top-left-corner"
346            | "top-left"
347            | "top-center"
348            | "top-right"
349            | "top-right-corner"
350            | "bottom-left-corner"
351            | "bottom-left"
352            | "bottom-center"
353            | "bottom-right"
354            | "bottom-right-corner"
355            | "left-top"
356            | "left-middle"
357            | "left-bottom"
358            | "right-top"
359            | "right-middle"
360            | "right-bottom"
361                if self.ctx.in_page_at_rule =>
362            {
363                self.input.skip_ws();
364
365                if !is!(self, EOF) {
366                    let span = self.input.cur_span();
367
368                    return Err(Error::new(span, ErrorKind::Expected("'{' token")));
369                }
370
371                None
372            }
373            "property" => {
374                self.input.skip_ws();
375
376                let prelude = AtRulePrelude::PropertyPrelude(self.parse()?);
377
378                self.input.skip_ws();
379
380                Some(prelude)
381            }
382            "supports" => {
383                self.input.skip_ws();
384
385                let prelude = AtRulePrelude::SupportsPrelude(self.parse()?);
386
387                self.input.skip_ws();
388
389                Some(prelude)
390            }
391            "viewport" | "-ms-viewport" | "-o-viewport" => {
392                self.input.skip_ws();
393
394                if !is!(self, EOF) {
395                    let span = self.input.cur_span();
396
397                    return Err(Error::new(span, ErrorKind::Expected("'{' token")));
398                }
399
400                None
401            }
402            "starting-style" => {
403                self.input.skip_ws();
404
405                if !is!(self, EOF) {
406                    let span = self.input.cur_span();
407
408                    return Err(Error::new(span, ErrorKind::Expected("'{' token")));
409                }
410
411                None
412            }
413            "scope" => {
414                self.input.skip_ws();
415
416                let prelude = AtRulePrelude::ScopePrelude(self.parse()?);
417
418                self.input.skip_ws();
419
420                Some(prelude)
421            }
422
423            "value" => {
424                if self.config.css_modules {
425                    let span = self.input.cur_span();
426                    let _: ComponentValue = self.parse()?;
427
428                    self.errors.push(Error::new(span, ErrorKind::ValueAtRule));
429
430                    self.input.skip_ws();
431                }
432
433                return Err(Error::new(Default::default(), ErrorKind::Ignore));
434            }
435            _ => {
436                return Err(Error::new(Default::default(), ErrorKind::Ignore));
437            }
438        };
439
440        if !is!(self, EOF) {
441            let span = self.input.cur_span();
442
443            return Err(Error::new(
444                span,
445                ErrorKind::Unexpected("tokens in at-rule prelude"),
446            ));
447        }
448
449        Ok(prelude)
450    }
451
452    pub(super) fn parse_at_rule_block(&mut self, name: &str) -> PResult<Vec<ComponentValue>> {
453        let block_contents = match name {
454            "charset" => {
455                let span = self.input.cur_span();
456
457                return Err(Error::new(span, ErrorKind::Unexpected("'{' token")));
458            }
459            "color-profile" => {
460                let declaration_list: Vec<DeclarationOrAtRule> = self.parse()?;
461                let declaration_list: Vec<ComponentValue> = declaration_list
462                    .into_iter()
463                    .map(ComponentValue::from)
464                    .collect();
465
466                declaration_list
467            }
468            "container" => match self.ctx.block_contents_grammar {
469                BlockContentsGrammar::StyleBlock => {
470                    let ctx = Ctx {
471                        in_container_at_rule: true,
472                        ..self.ctx
473                    };
474                    let style_blocks = self.with_ctx(ctx).parse_as::<Vec<StyleBlock>>()?;
475                    let style_blocks: Vec<ComponentValue> =
476                        style_blocks.into_iter().map(ComponentValue::from).collect();
477
478                    style_blocks
479                }
480                _ => {
481                    let ctx = Ctx {
482                        in_container_at_rule: true,
483                        ..self.ctx
484                    };
485                    let rule_list = self.with_ctx(ctx).parse_as::<Vec<Rule>>()?;
486                    let rule_list: Vec<ComponentValue> =
487                        rule_list.into_iter().map(ComponentValue::from).collect();
488
489                    rule_list
490                }
491            },
492            "counter-style" => {
493                let declaration_list: Vec<DeclarationOrAtRule> = self.parse()?;
494                let declaration_list: Vec<ComponentValue> = declaration_list
495                    .into_iter()
496                    .map(ComponentValue::from)
497                    .collect();
498
499                declaration_list
500            }
501            "custom-media" => {
502                let span = self.input.cur_span();
503
504                return Err(Error::new(span, ErrorKind::Unexpected("'{' token")));
505            }
506            "document" | "-moz-document" => match self.ctx.block_contents_grammar {
507                BlockContentsGrammar::StyleBlock => {
508                    let style_blocks: Vec<StyleBlock> = self.parse()?;
509                    let style_blocks: Vec<ComponentValue> =
510                        style_blocks.into_iter().map(ComponentValue::from).collect();
511
512                    style_blocks
513                }
514                _ => {
515                    let rule_list = self.parse_as::<Vec<Rule>>()?;
516                    let rule_list: Vec<ComponentValue> =
517                        rule_list.into_iter().map(ComponentValue::from).collect();
518
519                    rule_list
520                }
521            },
522            "font-face" => {
523                let declaration_list: Vec<DeclarationOrAtRule> = self.parse()?;
524                let declaration_list: Vec<ComponentValue> = declaration_list
525                    .into_iter()
526                    .map(ComponentValue::from)
527                    .collect();
528
529                declaration_list
530            }
531            "font-feature-values" => {
532                let ctx = Ctx {
533                    in_font_feature_values_at_rule: true,
534                    ..self.ctx
535                };
536                let declaration_list = self.with_ctx(ctx).parse_as::<Vec<DeclarationOrAtRule>>()?;
537                let declaration_list: Vec<ComponentValue> = declaration_list
538                    .into_iter()
539                    .map(ComponentValue::from)
540                    .collect();
541
542                declaration_list
543            }
544            "stylistic" | "historical-forms" | "styleset" | "character-variant" | "swash"
545            | "ornaments" | "annotation"
546                if self.ctx.in_font_feature_values_at_rule =>
547            {
548                let declaration_list: Vec<DeclarationOrAtRule> = self.parse()?;
549                let declaration_list: Vec<ComponentValue> = declaration_list
550                    .into_iter()
551                    .map(ComponentValue::from)
552                    .collect();
553
554                declaration_list
555            }
556            "font-palette-values" => {
557                let declaration_list: Vec<DeclarationOrAtRule> = self.parse()?;
558                let declaration_list: Vec<ComponentValue> = declaration_list
559                    .into_iter()
560                    .map(ComponentValue::from)
561                    .collect();
562
563                declaration_list
564            }
565            "import" => {
566                let span = self.input.cur_span();
567
568                return Err(Error::new(span, ErrorKind::Unexpected("'{' token")));
569            }
570            "keyframes" | "-webkit-keyframes" | "-moz-keyframes" | "-o-keyframes"
571            | "-ms-keyframes" => {
572                let ctx = Ctx {
573                    block_contents_grammar: BlockContentsGrammar::RuleList,
574                    in_keyframes_at_rule: true,
575                    ..self.ctx
576                };
577                let rule_list = self.with_ctx(ctx).parse_as::<Vec<Rule>>()?;
578                let rule_list: Vec<ComponentValue> = rule_list
579                    .into_iter()
580                    .map(|rule| match rule {
581                        Rule::AtRule(at_rule) => {
582                            self.errors.push(Error::new(
583                                at_rule.span,
584                                ErrorKind::Unexpected("at-rules are not allowed here"),
585                            ));
586
587                            ComponentValue::AtRule(at_rule)
588                        }
589                        Rule::QualifiedRule(qualified_rule) => {
590                            let locv = match qualified_rule.prelude {
591                                QualifiedRulePrelude::ListOfComponentValues(locv) => locv,
592                                _ => {
593                                    unreachable!();
594                                }
595                            };
596
597                            let res = self.parse_according_to_grammar(&locv, |parser| {
598                                parser.input.skip_ws();
599
600                                let child = parser.parse()?;
601                                let mut keyframes_selectors: Vec<KeyframeSelector> = vec![child];
602
603                                loop {
604                                    parser.input.skip_ws();
605
606                                    if !eat!(parser, ",") {
607                                        break;
608                                    }
609
610                                    parser.input.skip_ws();
611
612                                    let child = parser.parse()?;
613
614                                    keyframes_selectors.push(child);
615                                }
616
617                                Ok(keyframes_selectors)
618                            });
619                            match res {
620                                Ok(keyframes_selectors) => {
621                                    ComponentValue::KeyframeBlock(Box::new(KeyframeBlock {
622                                        span: qualified_rule.span,
623                                        prelude: keyframes_selectors,
624                                        block: qualified_rule.block,
625                                    }))
626                                }
627                                Err(err) => {
628                                    self.errors.push(err);
629
630                                    ComponentValue::ListOfComponentValues(Box::new(locv))
631                                }
632                            }
633                        }
634                        Rule::ListOfComponentValues(locv) => {
635                            ComponentValue::ListOfComponentValues(locv)
636                        }
637                    })
638                    .collect();
639
640                rule_list
641            }
642            "layer" => {
643                let rule_list = self.parse_as::<Vec<Rule>>()?;
644                let rule_list: Vec<ComponentValue> =
645                    rule_list.into_iter().map(ComponentValue::from).collect();
646
647                rule_list
648            }
649            "media" => match self.ctx.block_contents_grammar {
650                BlockContentsGrammar::StyleBlock => {
651                    let style_blocks: Vec<StyleBlock> = self.parse()?;
652                    let style_blocks: Vec<ComponentValue> =
653                        style_blocks.into_iter().map(ComponentValue::from).collect();
654
655                    style_blocks
656                }
657                _ => {
658                    let rule_list = self.parse_as::<Vec<Rule>>()?;
659                    let rule_list: Vec<ComponentValue> =
660                        rule_list.into_iter().map(ComponentValue::from).collect();
661
662                    rule_list
663                }
664            },
665            "namespace" => {
666                let span = self.input.cur_span();
667
668                return Err(Error::new(span, ErrorKind::Unexpected("")));
669            }
670            "nest" => {
671                let style_blocks: Vec<StyleBlock> = self.parse()?;
672                let style_blocks: Vec<ComponentValue> =
673                    style_blocks.into_iter().map(ComponentValue::from).collect();
674
675                style_blocks
676            }
677            "page" => {
678                let declaration_list = self
679                    .with_ctx(Ctx {
680                        in_page_at_rule: true,
681                        ..self.ctx
682                    })
683                    .parse_as::<Vec<DeclarationOrAtRule>>()?;
684                let declaration_list: Vec<ComponentValue> = declaration_list
685                    .into_iter()
686                    .map(ComponentValue::from)
687                    .collect();
688
689                declaration_list
690            }
691            "top-left-corner"
692            | "top-left"
693            | "top-center"
694            | "top-right"
695            | "top-right-corner"
696            | "bottom-left-corner"
697            | "bottom-left"
698            | "bottom-center"
699            | "bottom-right"
700            | "bottom-right-corner"
701            | "left-top"
702            | "left-middle"
703            | "left-bottom"
704            | "right-top"
705            | "right-middle"
706            | "right-bottom"
707                if self.ctx.in_page_at_rule =>
708            {
709                let declaration_list: Vec<DeclarationOrAtRule> = self.parse()?;
710                let declaration_list: Vec<ComponentValue> = declaration_list
711                    .into_iter()
712                    .map(ComponentValue::from)
713                    .collect();
714
715                declaration_list
716            }
717            "property" => {
718                let declaration_list: Vec<DeclarationOrAtRule> = self.parse()?;
719                let declaration_list: Vec<ComponentValue> = declaration_list
720                    .into_iter()
721                    .map(ComponentValue::from)
722                    .collect();
723
724                declaration_list
725            }
726            "supports" => match self.ctx.block_contents_grammar {
727                BlockContentsGrammar::StyleBlock => {
728                    let style_blocks: Vec<StyleBlock> = self.parse()?;
729                    let style_blocks: Vec<ComponentValue> =
730                        style_blocks.into_iter().map(ComponentValue::from).collect();
731
732                    style_blocks
733                }
734                _ => {
735                    let rule_list = self.parse_as::<Vec<Rule>>()?;
736                    let rule_list: Vec<ComponentValue> =
737                        rule_list.into_iter().map(ComponentValue::from).collect();
738
739                    rule_list
740                }
741            },
742            "viewport" | "-ms-viewport" | "-o-viewport" => {
743                let declaration_list: Vec<DeclarationOrAtRule> = self.parse()?;
744                let declaration_list: Vec<ComponentValue> = declaration_list
745                    .into_iter()
746                    .map(ComponentValue::from)
747                    .collect();
748
749                declaration_list
750            }
751            "starting-style" => {
752                let rule_list = self.parse_as::<Vec<Rule>>()?;
753                let rule_list: Vec<ComponentValue> =
754                    rule_list.into_iter().map(ComponentValue::from).collect();
755
756                rule_list
757            }
758            "scope" => {
759                let rule_list = self.parse_as::<Vec<Rule>>()?;
760                let rule_list: Vec<ComponentValue> =
761                    rule_list.into_iter().map(ComponentValue::from).collect();
762
763                rule_list
764            }
765            _ => {
766                return Err(Error::new(Default::default(), ErrorKind::Ignore));
767            }
768        };
769
770        Ok(block_contents)
771    }
772}
773
774impl<I> Parse<ImportConditions> for Parser<I>
775where
776    I: ParserInput,
777{
778    fn parse(&mut self) -> PResult<ImportConditions> {
779        let span = self.input.cur_span();
780
781        let supports = if !is!(self, EOF) {
782            match cur!(self) {
783                Token::Function { value, .. }
784                    if matches_eq_ignore_ascii_case!(value, "supports") =>
785                {
786                    let ctx = Ctx {
787                        in_import_at_rule: true,
788                        ..self.ctx
789                    };
790                    let func = self.with_ctx(ctx).parse_as::<Function>()?;
791
792                    self.input.skip_ws();
793
794                    Some(Box::new(func))
795                }
796                _ => None,
797            }
798        } else {
799            None
800        };
801
802        let media = if !is!(self, EOF) {
803            let media_query_list = self.parse()?;
804
805            self.input.skip_ws();
806
807            Some(media_query_list)
808        } else {
809            None
810        };
811
812        Ok(ImportConditions {
813            span: span!(self, span.lo),
814            supports,
815            media,
816        })
817    }
818}
819
820impl<I> Parse<KeyframesName> for Parser<I>
821where
822    I: ParserInput,
823{
824    fn parse(&mut self) -> PResult<KeyframesName> {
825        match cur!(self) {
826            tok!(":") if self.config.css_modules => {
827                let span = self.input.cur_span();
828
829                bump!(self);
830
831                match cur!(self) {
832                    Token::Function { value, .. }
833                        if matches_eq_ignore_ascii_case!(value, "local", "global") =>
834                    {
835                        let span = self.input.cur_span();
836                        let pseudo = match bump!(self) {
837                            Token::Function { value, raw } => Ident {
838                                span: span!(self, span.lo),
839                                value,
840                                raw: Some(raw),
841                            },
842                            _ => {
843                                unreachable!();
844                            }
845                        };
846
847                        self.input.skip_ws();
848
849                        let name = self.parse()?;
850
851                        self.input.skip_ws();
852
853                        expect!(self, ")");
854
855                        Ok(KeyframesName::PseudoFunction(Box::new(
856                            KeyframesPseudoFunction {
857                                span: span!(self, span.lo),
858                                pseudo,
859                                name,
860                            },
861                        )))
862                    }
863                    Token::Ident { value, .. }
864                        if matches_eq_ignore_ascii_case!(value, "local", "global") =>
865                    {
866                        let pseudo = self.parse()?;
867
868                        self.input.skip_ws();
869
870                        let name = self.parse()?;
871
872                        Ok(KeyframesName::PseudoPrefix(Box::new(
873                            KeyframesPseudoPrefix {
874                                span: span!(self, span.lo),
875                                pseudo,
876                                name,
877                            },
878                        )))
879                    }
880                    _ => {
881                        let span = self.input.cur_span();
882
883                        Err(Error::new(
884                            span,
885                            ErrorKind::Expected("ident or function (local or scope) token"),
886                        ))
887                    }
888                }
889            }
890            tok!("ident") => {
891                let custom_ident: CustomIdent = self.parse()?;
892
893                if matches_eq_ignore_ascii_case!(custom_ident.value, "none") {
894                    return Err(Error::new(
895                        custom_ident.span,
896                        ErrorKind::InvalidCustomIdent(custom_ident.value),
897                    ));
898                }
899
900                Ok(KeyframesName::CustomIdent(Box::new(custom_ident)))
901            }
902            tok!("string") => Ok(KeyframesName::Str(Box::new(self.parse()?))),
903            _ => {
904                let span = self.input.cur_span();
905
906                Err(Error::new(span, ErrorKind::Expected("ident or string")))
907            }
908        }
909    }
910}
911
912impl<I> Parse<KeyframeSelector> for Parser<I>
913where
914    I: ParserInput,
915{
916    fn parse(&mut self) -> PResult<KeyframeSelector> {
917        match cur!(self) {
918            tok!("ident") => {
919                let ident: Ident = self.parse()?;
920                let lower = ident.value.to_ascii_lowercase();
921
922                if lower != "from" && lower != "to" {
923                    return Err(Error::new(
924                        ident.span,
925                        ErrorKind::Expected("'from' or 'to' idents"),
926                    ));
927                }
928
929                Ok(KeyframeSelector::Ident(ident))
930            }
931            tok!("percentage") => Ok(KeyframeSelector::Percentage(self.parse()?)),
932            _ => {
933                let span = self.input.cur_span();
934
935                return Err(Error::new(
936                    span,
937                    ErrorKind::Expected("'from', 'to' or percentage"),
938                ));
939            }
940        }
941    }
942}
943
944impl<I> Parse<FontFeatureValuesPrelude> for Parser<I>
945where
946    I: ParserInput,
947{
948    fn parse(&mut self) -> PResult<FontFeatureValuesPrelude> {
949        let span = self.input.cur_span();
950
951        let mut font_family = vec![self.parse()?];
952
953        loop {
954            self.input.skip_ws();
955
956            if !eat!(self, ",") {
957                break;
958            }
959
960            self.input.skip_ws();
961
962            font_family.push(self.parse()?);
963        }
964
965        Ok(FontFeatureValuesPrelude {
966            span: span!(self, span.lo),
967            font_family,
968        })
969    }
970}
971
972impl<I> Parse<SupportsCondition> for Parser<I>
973where
974    I: ParserInput,
975{
976    fn parse(&mut self) -> PResult<SupportsCondition> {
977        let start_pos = self.input.cur_span().lo;
978        let mut last_pos;
979        let mut conditions = Vec::new();
980
981        if is_case_insensitive_ident!(self, "not") {
982            let not = self.parse()?;
983
984            last_pos = self.input.last_pos();
985
986            conditions.push(SupportsConditionType::Not(not));
987        } else {
988            let supports_in_parens = self.parse()?;
989
990            last_pos = self.input.last_pos();
991
992            conditions.push(SupportsConditionType::SupportsInParens(supports_in_parens));
993
994            self.input.skip_ws();
995
996            if is_case_insensitive_ident!(self, "and") {
997                while is_case_insensitive_ident!(self, "and") {
998                    let and = self.parse()?;
999
1000                    last_pos = self.input.last_pos();
1001
1002                    conditions.push(SupportsConditionType::And(and));
1003
1004                    self.input.skip_ws();
1005                }
1006            } else if is_case_insensitive_ident!(self, "or") {
1007                while is_case_insensitive_ident!(self, "or") {
1008                    let or = self.parse()?;
1009
1010                    last_pos = self.input.last_pos();
1011
1012                    conditions.push(SupportsConditionType::Or(or));
1013
1014                    self.input.skip_ws();
1015                }
1016            }
1017        };
1018
1019        Ok(SupportsCondition {
1020            span: Span::new(start_pos, last_pos),
1021            conditions,
1022        })
1023    }
1024}
1025
1026impl<I> Parse<SupportsNot> for Parser<I>
1027where
1028    I: ParserInput,
1029{
1030    fn parse(&mut self) -> PResult<SupportsNot> {
1031        let span = self.input.cur_span();
1032        let keyword = match cur!(self) {
1033            Token::Ident { value, .. } if value.as_ref().eq_ignore_ascii_case("not") => {
1034                let ident: Ident = self.parse()?;
1035
1036                Some(ident)
1037            }
1038            _ => {
1039                return Err(Error::new(
1040                    span,
1041                    ErrorKind::Expected("ident (with 'not' value) token"),
1042                ));
1043            }
1044        };
1045
1046        self.input.skip_ws();
1047
1048        let supports_in_parens = self.parse()?;
1049
1050        Ok(SupportsNot {
1051            span: span!(self, span.lo),
1052            keyword,
1053            condition: supports_in_parens,
1054        })
1055    }
1056}
1057
1058impl<I> Parse<SupportsAnd> for Parser<I>
1059where
1060    I: ParserInput,
1061{
1062    fn parse(&mut self) -> PResult<SupportsAnd> {
1063        let span = self.input.cur_span();
1064        let keyword = match cur!(self) {
1065            Token::Ident { value, .. } if value.as_ref().eq_ignore_ascii_case("and") => {
1066                let ident: Ident = self.parse()?;
1067
1068                Some(ident)
1069            }
1070            _ => {
1071                return Err(Error::new(
1072                    span,
1073                    ErrorKind::Expected("ident (with 'and' value) token"),
1074                ));
1075            }
1076        };
1077
1078        self.input.skip_ws();
1079
1080        let supports_in_parens = self.parse()?;
1081
1082        Ok(SupportsAnd {
1083            span: span!(self, span.lo),
1084            keyword,
1085            condition: supports_in_parens,
1086        })
1087    }
1088}
1089
1090impl<I> Parse<SupportsOr> for Parser<I>
1091where
1092    I: ParserInput,
1093{
1094    fn parse(&mut self) -> PResult<SupportsOr> {
1095        let span = self.input.cur_span();
1096        let keyword = match cur!(self) {
1097            Token::Ident { value, .. } if value.as_ref().eq_ignore_ascii_case("or") => {
1098                let ident: Ident = self.parse()?;
1099
1100                Some(ident)
1101            }
1102            _ => {
1103                return Err(Error::new(
1104                    span,
1105                    ErrorKind::Expected("ident (with 'or' value) token"),
1106                ));
1107            }
1108        };
1109
1110        self.input.skip_ws();
1111
1112        let supports_in_parens = self.parse()?;
1113
1114        Ok(SupportsOr {
1115            span: span!(self, span.lo),
1116            keyword,
1117            condition: supports_in_parens,
1118        })
1119    }
1120}
1121
1122impl<I> Parse<SupportsInParens> for Parser<I>
1123where
1124    I: ParserInput,
1125{
1126    fn parse(&mut self) -> PResult<SupportsInParens> {
1127        let state = self.input.state();
1128
1129        match self.parse() {
1130            Ok(feature) => Ok(SupportsInParens::Feature(feature)),
1131            Err(_) => {
1132                self.input.reset(&state);
1133
1134                let mut parse_condition = || {
1135                    expect!(self, "(");
1136
1137                    self.input.skip_ws();
1138
1139                    let condition = self.parse()?;
1140
1141                    self.input.skip_ws();
1142
1143                    expect!(self, ")");
1144
1145                    Ok(SupportsInParens::SupportsCondition(condition))
1146                };
1147
1148                match parse_condition() {
1149                    Ok(condition) => Ok(condition),
1150                    Err(_) => {
1151                        self.input.reset(&state);
1152
1153                        match self.parse() {
1154                            Ok(general_enclosed) => {
1155                                Ok(SupportsInParens::GeneralEnclosed(general_enclosed))
1156                            }
1157                            Err(err) => Err(err),
1158                        }
1159                    }
1160                }
1161            }
1162        }
1163    }
1164}
1165
1166impl<I> Parse<SupportsFeature> for Parser<I>
1167where
1168    I: ParserInput,
1169{
1170    fn parse(&mut self) -> PResult<SupportsFeature> {
1171        match cur!(self) {
1172            tok!("(") => {
1173                bump!(self);
1174
1175                self.input.skip_ws();
1176
1177                let declaration = match self.try_to_parse_declaration_in_parens() {
1178                    Some(declaration) => declaration,
1179                    None => {
1180                        let span = self.input.cur_span();
1181
1182                        return Err(Error::new(
1183                            span,
1184                            ErrorKind::Expected("declaration in parens"),
1185                        ));
1186                    }
1187                };
1188
1189                expect!(self, ")");
1190
1191                Ok(SupportsFeature::Declaration(Box::new(declaration)))
1192            }
1193            Token::Function { value, .. }
1194                if matches_eq_ignore_ascii_case!(&**value, "selector") =>
1195            {
1196                // TODO improve me
1197                let ctx = Ctx {
1198                    in_supports_at_rule: true,
1199                    ..self.ctx
1200                };
1201                let function = self.with_ctx(ctx).parse_as::<Function>()?;
1202
1203                Ok(SupportsFeature::Function(function))
1204            }
1205            _ => {
1206                let span = self.input.cur_span();
1207
1208                Err(Error::new(
1209                    span,
1210                    ErrorKind::Expected("'(' or 'function' token"),
1211                ))
1212            }
1213        }
1214    }
1215}
1216
1217impl<I> Parse<GeneralEnclosed> for Parser<I>
1218where
1219    I: ParserInput,
1220{
1221    fn parse(&mut self) -> PResult<GeneralEnclosed> {
1222        match cur!(self) {
1223            tok!("function") => {
1224                let ctx = Ctx {
1225                    need_canonicalize: false,
1226                    ..self.ctx
1227                };
1228                let function = self.with_ctx(ctx).parse_as::<Function>()?;
1229
1230                Ok(GeneralEnclosed::Function(function))
1231            }
1232            tok!("(") => {
1233                let block = self.parse_as::<SimpleBlock>()?;
1234
1235                let mut found_ident = false;
1236
1237                for component_value in &block.value {
1238                    match component_value {
1239                        ComponentValue::PreservedToken(token_and_span) => {
1240                            match token_and_span.token {
1241                                Token::WhiteSpace { .. } => {
1242                                    continue;
1243                                }
1244                                Token::Ident { .. } => {
1245                                    found_ident = true;
1246
1247                                    break;
1248                                }
1249                                _ => {
1250                                    return Err(Error::new(
1251                                        block.span,
1252                                        ErrorKind::Expected(
1253                                            "ident at first position in <general-enclosed>",
1254                                        ),
1255                                    ));
1256                                }
1257                            }
1258                        }
1259                        _ => {
1260                            return Err(Error::new(
1261                                block.span,
1262                                ErrorKind::Expected(
1263                                    "ident at first position in <general-enclosed>",
1264                                ),
1265                            ));
1266                        }
1267                    }
1268                }
1269
1270                if !found_ident {
1271                    return Err(Error::new(
1272                        block.span,
1273                        ErrorKind::Expected("ident at first position in <general-enclosed>"),
1274                    ));
1275                }
1276
1277                Ok(GeneralEnclosed::SimpleBlock(block))
1278            }
1279            _ => {
1280                let span = self.input.cur_span();
1281
1282                Err(Error::new(span, ErrorKind::Expected("function or '('")))
1283            }
1284        }
1285    }
1286}
1287
1288impl<I> Parse<DocumentPreludeMatchingFunction> for Parser<I>
1289where
1290    I: ParserInput,
1291{
1292    fn parse(&mut self) -> PResult<DocumentPreludeMatchingFunction> {
1293        match cur!(self) {
1294            tok!("url") => Ok(DocumentPreludeMatchingFunction::Url(self.parse()?)),
1295            Token::Function {
1296                value: function_name,
1297                ..
1298            } => {
1299                if matches_eq_ignore_ascii_case!(function_name, "url", "src") {
1300                    Ok(DocumentPreludeMatchingFunction::Url(self.parse()?))
1301                } else {
1302                    // TODO improve me
1303                    let function = self.parse()?;
1304
1305                    Ok(DocumentPreludeMatchingFunction::Function(function))
1306                }
1307            }
1308            _ => {
1309                let span = self.input.cur_span();
1310
1311                Err(Error::new(span, ErrorKind::Expected("url or function")))
1312            }
1313        }
1314    }
1315}
1316
1317impl<I> Parse<MediaQueryList> for Parser<I>
1318where
1319    I: ParserInput,
1320{
1321    fn parse(&mut self) -> PResult<MediaQueryList> {
1322        let query: MediaQuery = self.parse()?;
1323        let mut queries = vec![query];
1324
1325        // TODO error recovery
1326        // To parse a <media-query-list> production, parse a comma-separated list of
1327        // component values, then parse each entry in the returned list as a
1328        // <media-query>. Its value is the list of <media-query>s so produced.
1329        loop {
1330            self.input.skip_ws();
1331
1332            if !eat!(self, ",") {
1333                break;
1334            }
1335
1336            self.input.skip_ws();
1337
1338            let query = self.parse()?;
1339
1340            queries.push(query);
1341        }
1342
1343        let start_pos = match queries.first() {
1344            Some(first) => first.span_lo(),
1345            _ => {
1346                unreachable!();
1347            }
1348        };
1349        let last_pos = match queries.last() {
1350            Some(last) => last.span_hi(),
1351            _ => {
1352                unreachable!();
1353            }
1354        };
1355
1356        Ok(MediaQueryList {
1357            span: Span::new(start_pos, last_pos),
1358            queries,
1359        })
1360    }
1361}
1362
1363impl<I> Parse<MediaQuery> for Parser<I>
1364where
1365    I: ParserInput,
1366{
1367    fn parse(&mut self) -> PResult<MediaQuery> {
1368        let start_pos = self.input.cur_span().lo;
1369        let state = self.input.state();
1370
1371        let is_not = is_one_of_case_insensitive_ident!(self, "not");
1372        let modifier = if is_one_of_case_insensitive_ident!(self, "not", "only") {
1373            let modifier = Some(self.parse()?);
1374
1375            self.input.skip_ws();
1376
1377            modifier
1378        } else {
1379            None
1380        };
1381
1382        if is!(self, "ident") {
1383            let media_type = Some(self.parse()?);
1384
1385            self.input.skip_ws();
1386
1387            let mut keyword = None;
1388            let mut condition_without_or = None;
1389
1390            if is_one_of_case_insensitive_ident!(self, "and") {
1391                keyword = Some(self.parse()?);
1392
1393                self.input.skip_ws();
1394
1395                condition_without_or = Some(Box::new(MediaConditionType::WithoutOr(self.parse()?)));
1396            }
1397
1398            let end_pos = if let Some(MediaConditionType::WithoutOr(condition_without_or)) =
1399                condition_without_or.as_deref()
1400            {
1401                condition_without_or.span.hi
1402            } else if let Some(MediaType::Ident(ident)) = &media_type {
1403                ident.span.hi
1404            } else {
1405                unreachable!();
1406            };
1407
1408            return Ok(MediaQuery {
1409                span: Span::new(start_pos, end_pos),
1410                modifier,
1411                media_type,
1412                keyword,
1413                condition: condition_without_or,
1414            });
1415        }
1416
1417        if is_not {
1418            self.input.reset(&state);
1419        }
1420
1421        let condition: MediaCondition = self.parse()?;
1422
1423        Ok(MediaQuery {
1424            span: Span::new(start_pos, condition.span.hi),
1425            modifier: None,
1426            media_type: None,
1427            keyword: None,
1428            condition: Some(Box::new(MediaConditionType::All(condition))),
1429        })
1430    }
1431}
1432
1433impl<I> Parse<MediaType> for Parser<I>
1434where
1435    I: ParserInput,
1436{
1437    fn parse(&mut self) -> PResult<MediaType> {
1438        match cur!(self) {
1439            _ if !is_one_of_case_insensitive_ident!(self, "not", "and", "or", "only", "layer") => {
1440                let name: Ident = self.parse()?;
1441
1442                Ok(MediaType::Ident(name))
1443            }
1444            _ => {
1445                let span = self.input.cur_span();
1446
1447                Err(Error::new(
1448                    span,
1449                    ErrorKind::Expected(
1450                        "ident (exclude the keywords 'only', 'not', 'and', 'or' and 'layer')",
1451                    ),
1452                ))
1453            }
1454        }
1455    }
1456}
1457
1458impl<I> Parse<MediaCondition> for Parser<I>
1459where
1460    I: ParserInput,
1461{
1462    fn parse(&mut self) -> PResult<MediaCondition> {
1463        let start_pos = self.input.cur_span().lo;
1464        let mut last_pos;
1465        let mut conditions = Vec::new();
1466
1467        if is_case_insensitive_ident!(self, "not") {
1468            let not = self.parse()?;
1469
1470            last_pos = self.input.last_pos();
1471
1472            conditions.push(MediaConditionAllType::Not(not));
1473        } else {
1474            let media_in_parens = self.parse()?;
1475
1476            last_pos = self.input.last_pos();
1477
1478            conditions.push(MediaConditionAllType::MediaInParens(media_in_parens));
1479
1480            self.input.skip_ws();
1481
1482            if is_case_insensitive_ident!(self, "and") {
1483                while is_case_insensitive_ident!(self, "and") {
1484                    let and = self.parse()?;
1485
1486                    last_pos = self.input.last_pos();
1487
1488                    conditions.push(MediaConditionAllType::And(and));
1489
1490                    self.input.skip_ws();
1491                }
1492            } else if is_case_insensitive_ident!(self, "or") {
1493                while is_case_insensitive_ident!(self, "or") {
1494                    let or = self.parse()?;
1495
1496                    last_pos = self.input.last_pos();
1497
1498                    conditions.push(MediaConditionAllType::Or(or));
1499
1500                    self.input.skip_ws();
1501                }
1502            }
1503        };
1504
1505        Ok(MediaCondition {
1506            span: Span::new(start_pos, last_pos),
1507            conditions,
1508        })
1509    }
1510}
1511
1512impl<I> Parse<MediaConditionWithoutOr> for Parser<I>
1513where
1514    I: ParserInput,
1515{
1516    fn parse(&mut self) -> PResult<MediaConditionWithoutOr> {
1517        let start_pos = self.input.cur_span().lo;
1518        let mut last_pos;
1519        let mut conditions = Vec::new();
1520
1521        if is_case_insensitive_ident!(self, "not") {
1522            let not = self.parse()?;
1523
1524            last_pos = self.input.last_pos();
1525
1526            conditions.push(MediaConditionWithoutOrType::Not(not));
1527        } else {
1528            let media_in_parens = self.parse()?;
1529
1530            last_pos = self.input.last_pos();
1531
1532            conditions.push(MediaConditionWithoutOrType::MediaInParens(media_in_parens));
1533
1534            self.input.skip_ws();
1535
1536            if is_case_insensitive_ident!(self, "and") {
1537                while is_case_insensitive_ident!(self, "and") {
1538                    let and = self.parse()?;
1539
1540                    last_pos = self.input.last_pos();
1541
1542                    conditions.push(MediaConditionWithoutOrType::And(and));
1543
1544                    self.input.skip_ws();
1545                }
1546            }
1547        };
1548
1549        Ok(MediaConditionWithoutOr {
1550            span: Span::new(start_pos, last_pos),
1551            conditions,
1552        })
1553    }
1554}
1555
1556impl<I> Parse<MediaNot> for Parser<I>
1557where
1558    I: ParserInput,
1559{
1560    fn parse(&mut self) -> PResult<MediaNot> {
1561        let span = self.input.cur_span();
1562        let keyword = match cur!(self) {
1563            Token::Ident { value, .. } if value.as_ref().eq_ignore_ascii_case("not") => {
1564                let ident: Ident = self.parse()?;
1565
1566                Some(ident)
1567            }
1568            _ => {
1569                return Err(Error::new(
1570                    span,
1571                    ErrorKind::Expected("ident (with 'not' value) token"),
1572                ));
1573            }
1574        };
1575
1576        self.input.skip_ws();
1577
1578        let media_in_parens = self.parse()?;
1579
1580        Ok(MediaNot {
1581            span: span!(self, span.lo),
1582            keyword,
1583            condition: media_in_parens,
1584        })
1585    }
1586}
1587
1588impl<I> Parse<MediaAnd> for Parser<I>
1589where
1590    I: ParserInput,
1591{
1592    fn parse(&mut self) -> PResult<MediaAnd> {
1593        let span = self.input.cur_span();
1594        let keyword = match cur!(self) {
1595            Token::Ident { value, .. } if value.as_ref().eq_ignore_ascii_case("and") => {
1596                let ident: Ident = self.parse()?;
1597
1598                Some(ident)
1599            }
1600            _ => {
1601                return Err(Error::new(
1602                    span,
1603                    ErrorKind::Expected("ident (with 'and' value) token"),
1604                ));
1605            }
1606        };
1607
1608        self.input.skip_ws();
1609
1610        let media_in_parens = self.parse()?;
1611
1612        Ok(MediaAnd {
1613            span: span!(self, span.lo),
1614            keyword,
1615            condition: media_in_parens,
1616        })
1617    }
1618}
1619
1620impl<I> Parse<MediaOr> for Parser<I>
1621where
1622    I: ParserInput,
1623{
1624    fn parse(&mut self) -> PResult<MediaOr> {
1625        let span = self.input.cur_span();
1626        let keyword = match cur!(self) {
1627            Token::Ident { value, .. } if value.as_ref().eq_ignore_ascii_case("or") => {
1628                let ident: Ident = self.parse()?;
1629
1630                Some(ident)
1631            }
1632            _ => {
1633                return Err(Error::new(
1634                    span,
1635                    ErrorKind::Expected("ident (with 'or' value) token"),
1636                ));
1637            }
1638        };
1639
1640        self.input.skip_ws();
1641
1642        let media_in_parens = self.parse()?;
1643
1644        Ok(MediaOr {
1645            span: span!(self, span.lo),
1646            keyword,
1647            condition: media_in_parens,
1648        })
1649    }
1650}
1651
1652impl<I> Parse<MediaInParens> for Parser<I>
1653where
1654    I: ParserInput,
1655{
1656    fn parse(&mut self) -> PResult<MediaInParens> {
1657        let state = self.input.state();
1658
1659        match self.parse() {
1660            Ok(media_feature) => Ok(MediaInParens::Feature(media_feature)),
1661            Err(_) => {
1662                self.input.reset(&state);
1663
1664                let mut parse_media_condition = || {
1665                    expect!(self, "(");
1666
1667                    self.input.skip_ws();
1668
1669                    let media_condition = self.parse()?;
1670
1671                    self.input.skip_ws();
1672
1673                    expect!(self, ")");
1674
1675                    Ok(MediaInParens::MediaCondition(media_condition))
1676                };
1677
1678                match parse_media_condition() {
1679                    Ok(media_in_parens) => Ok(media_in_parens),
1680                    Err(_) => {
1681                        self.input.reset(&state);
1682
1683                        let general_enclosed = self.parse()?;
1684
1685                        Ok(MediaInParens::GeneralEnclosed(general_enclosed))
1686                    }
1687                }
1688            }
1689        }
1690    }
1691}
1692
1693impl<I> Parse<MediaFeature> for Parser<I>
1694where
1695    I: ParserInput,
1696{
1697    fn parse(&mut self) -> PResult<MediaFeature> {
1698        let span = self.input.cur_span();
1699
1700        expect!(self, "(");
1701
1702        self.input.skip_ws();
1703
1704        match cur!(self) {
1705            // The <extension-name> can then be used in a media feature. It must be used in a
1706            // boolean context; using them in a normal or range context is a syntax error.
1707            Token::Ident { value, .. } if value.starts_with("--") => {
1708                let name = MediaFeatureName::ExtensionName(self.parse()?);
1709
1710                self.input.skip_ws();
1711
1712                expect!(self, ")");
1713
1714                return Ok(MediaFeature::Boolean(MediaFeatureBoolean {
1715                    span: span!(self, span.lo),
1716                    name,
1717                }));
1718            }
1719            _ => {}
1720        };
1721
1722        let left = self.parse()?;
1723
1724        self.input.skip_ws();
1725
1726        match cur!(self) {
1727            tok!(")") => {
1728                bump!(self);
1729
1730                let name = match left {
1731                    MediaFeatureValue::Ident(ident) => MediaFeatureName::Ident(ident),
1732                    _ => {
1733                        return Err(Error::new(span, ErrorKind::Expected("identifier value")));
1734                    }
1735                };
1736
1737                Ok(MediaFeature::Boolean(MediaFeatureBoolean {
1738                    span: span!(self, span.lo),
1739                    name,
1740                }))
1741            }
1742            tok!(":") => {
1743                bump!(self);
1744
1745                self.input.skip_ws();
1746
1747                let name = match left {
1748                    MediaFeatureValue::Ident(ident) => MediaFeatureName::Ident(ident),
1749                    _ => {
1750                        return Err(Error::new(span, ErrorKind::Expected("identifier value")));
1751                    }
1752                };
1753                let value = self.parse()?;
1754
1755                self.input.skip_ws();
1756
1757                expect!(self, ")");
1758
1759                Ok(MediaFeature::Plain(MediaFeaturePlain {
1760                    span: span!(self, span.lo),
1761                    name,
1762                    value,
1763                }))
1764            }
1765            tok!("<") | tok!(">") | tok!("=") => {
1766                let left_comparison = match bump!(self) {
1767                    tok!("<") => {
1768                        if eat!(self, "=") {
1769                            MediaFeatureRangeComparison::Le
1770                        } else {
1771                            MediaFeatureRangeComparison::Lt
1772                        }
1773                    }
1774                    tok!(">") => {
1775                        if eat!(self, "=") {
1776                            MediaFeatureRangeComparison::Ge
1777                        } else {
1778                            MediaFeatureRangeComparison::Gt
1779                        }
1780                    }
1781                    tok!("=") => MediaFeatureRangeComparison::Eq,
1782                    _ => {
1783                        unreachable!();
1784                    }
1785                };
1786
1787                self.input.skip_ws();
1788
1789                let center = self.parse()?;
1790
1791                self.input.skip_ws();
1792
1793                if eat!(self, ")") {
1794                    return Ok(MediaFeature::Range(MediaFeatureRange {
1795                        span: span!(self, span.lo),
1796                        left: Box::new(left),
1797                        comparison: left_comparison,
1798                        right: Box::new(center),
1799                    }));
1800                }
1801
1802                let right_comparison = match bump!(self) {
1803                    tok!("<") => {
1804                        if eat!(self, "=") {
1805                            MediaFeatureRangeComparison::Le
1806                        } else {
1807                            MediaFeatureRangeComparison::Lt
1808                        }
1809                    }
1810                    tok!(">") => {
1811                        if eat!(self, "=") {
1812                            MediaFeatureRangeComparison::Ge
1813                        } else {
1814                            MediaFeatureRangeComparison::Gt
1815                        }
1816                    }
1817                    _ => {
1818                        return Err(Error::new(
1819                            span,
1820                            ErrorKind::Expected("'>' or '<' operators"),
1821                        ));
1822                    }
1823                };
1824
1825                self.input.skip_ws();
1826
1827                let right = self.parse()?;
1828
1829                self.input.skip_ws();
1830
1831                expect!(self, ")");
1832
1833                let name = match center {
1834                    MediaFeatureValue::Ident(ident) => MediaFeatureName::Ident(ident),
1835                    _ => {
1836                        return Err(Error::new(span, ErrorKind::Expected("identifier value")));
1837                    }
1838                };
1839
1840                let is_valid_operator = match left_comparison {
1841                    MediaFeatureRangeComparison::Lt | MediaFeatureRangeComparison::Le
1842                        if right_comparison == MediaFeatureRangeComparison::Lt
1843                            || right_comparison == MediaFeatureRangeComparison::Le =>
1844                    {
1845                        true
1846                    }
1847                    MediaFeatureRangeComparison::Gt | MediaFeatureRangeComparison::Ge
1848                        if right_comparison == MediaFeatureRangeComparison::Gt
1849                            || right_comparison == MediaFeatureRangeComparison::Ge =>
1850                    {
1851                        true
1852                    }
1853                    _ => false,
1854                };
1855
1856                if !is_valid_operator {
1857                    return Err(Error::new(
1858                        span,
1859                        ErrorKind::Expected(
1860                            "left comparison operator should be equal right comparison operator",
1861                        ),
1862                    ));
1863                }
1864
1865                Ok(MediaFeature::RangeInterval(MediaFeatureRangeInterval {
1866                    span: span!(self, span.lo),
1867                    left: Box::new(left),
1868                    left_comparison,
1869                    name,
1870                    right_comparison,
1871                    right,
1872                }))
1873            }
1874            _ => Err(Error::new(span, ErrorKind::Expected("identifier value"))),
1875        }
1876    }
1877}
1878
1879impl<I> Parse<MediaFeatureValue> for Parser<I>
1880where
1881    I: ParserInput,
1882{
1883    fn parse(&mut self) -> PResult<MediaFeatureValue> {
1884        let span = self.input.cur_span();
1885
1886        match cur!(self) {
1887            tok!("number") => {
1888                let left = self.parse()?;
1889
1890                self.input.skip_ws();
1891
1892                if eat!(self, "/") {
1893                    self.input.skip_ws();
1894
1895                    let right = Some(self.parse()?);
1896
1897                    return Ok(MediaFeatureValue::Ratio(Ratio {
1898                        span: span!(self, span.lo),
1899                        left,
1900                        right,
1901                    }));
1902                }
1903
1904                Ok(MediaFeatureValue::Number(left))
1905            }
1906            tok!("ident") => {
1907                let name: Ident = self.parse()?;
1908
1909                Ok(MediaFeatureValue::Ident(name))
1910            }
1911            tok!("dimension") => Ok(MediaFeatureValue::Dimension(self.parse()?)),
1912            Token::Function { value, .. } if is_math_function(value) => {
1913                let function = self.parse()?;
1914
1915                Ok(MediaFeatureValue::Function(function))
1916            }
1917            _ => Err(Error::new(
1918                span,
1919                ErrorKind::Expected("number, ident, dimension or function token"),
1920            )),
1921        }
1922    }
1923}
1924
1925impl<I> Parse<PageSelectorList> for Parser<I>
1926where
1927    I: ParserInput,
1928{
1929    fn parse(&mut self) -> PResult<PageSelectorList> {
1930        let selector: PageSelector = self.parse()?;
1931        let mut selectors = vec![selector];
1932
1933        loop {
1934            self.input.skip_ws();
1935
1936            if !eat!(self, ",") {
1937                break;
1938            }
1939
1940            self.input.skip_ws();
1941
1942            let selector = self.parse()?;
1943
1944            selectors.push(selector);
1945        }
1946
1947        let start_pos = match selectors.first() {
1948            Some(first) => first.span_lo(),
1949            _ => {
1950                unreachable!();
1951            }
1952        };
1953        let last_pos = match selectors.last() {
1954            Some(last) => last.span_hi(),
1955            _ => {
1956                unreachable!();
1957            }
1958        };
1959
1960        Ok(PageSelectorList {
1961            span: Span::new(start_pos, last_pos),
1962            selectors,
1963        })
1964    }
1965}
1966
1967impl<I> Parse<PageSelector> for Parser<I>
1968where
1969    I: ParserInput,
1970{
1971    fn parse(&mut self) -> PResult<PageSelector> {
1972        let span = self.input.cur_span();
1973
1974        let page_type = if is!(self, Ident) {
1975            Some(self.parse()?)
1976        } else {
1977            None
1978        };
1979
1980        let pseudos = if is!(self, ":") {
1981            let mut pseudos = Vec::new();
1982
1983            loop {
1984                if !is!(self, ":") {
1985                    break;
1986                }
1987
1988                let pseudo = self.parse()?;
1989
1990                pseudos.push(pseudo);
1991            }
1992
1993            Some(pseudos)
1994        } else {
1995            None
1996        };
1997
1998        Ok(PageSelector {
1999            span: span!(self, span.lo),
2000            page_type,
2001            pseudos,
2002        })
2003    }
2004}
2005
2006impl<I> Parse<PageSelectorType> for Parser<I>
2007where
2008    I: ParserInput,
2009{
2010    fn parse(&mut self) -> PResult<PageSelectorType> {
2011        let span = self.input.cur_span();
2012        let value = self.parse()?;
2013
2014        Ok(PageSelectorType {
2015            span: span!(self, span.lo),
2016            value,
2017        })
2018    }
2019}
2020
2021impl<I> Parse<PageSelectorPseudo> for Parser<I>
2022where
2023    I: ParserInput,
2024{
2025    fn parse(&mut self) -> PResult<PageSelectorPseudo> {
2026        let span = self.input.cur_span();
2027
2028        expect!(self, ":");
2029
2030        let value = match cur!(self) {
2031            Token::Ident { value, .. }
2032                if matches_eq_ignore_ascii_case!(value, "left", "right", "first", "blank") =>
2033            {
2034                let name: Ident = self.parse()?;
2035
2036                name
2037            }
2038            _ => {
2039                let span = self.input.cur_span();
2040
2041                return Err(Error::new(
2042                    span,
2043                    ErrorKind::Expected("'left', 'right', 'first' or 'blank' ident"),
2044                ));
2045            }
2046        };
2047
2048        Ok(PageSelectorPseudo {
2049            span: span!(self, span.lo),
2050            value,
2051        })
2052    }
2053}
2054
2055impl<I> Parse<LayerName> for Parser<I>
2056where
2057    I: ParserInput,
2058{
2059    fn parse(&mut self) -> PResult<LayerName> {
2060        let start = self.input.cur_span().lo;
2061        let mut name = Vec::new();
2062
2063        while is!(self, Ident) {
2064            name.push(self.parse()?);
2065
2066            if is!(self, ".") {
2067                eat!(self, ".");
2068            }
2069        }
2070
2071        Ok(LayerName {
2072            name,
2073            span: span!(self, start),
2074        })
2075    }
2076}
2077
2078impl<I> Parse<ContainerCondition> for Parser<I>
2079where
2080    I: ParserInput,
2081{
2082    fn parse(&mut self) -> PResult<ContainerCondition> {
2083        let start_pos = self.input.cur_span().lo;
2084
2085        let mut name: Option<ContainerName> = None;
2086
2087        if is!(self, "ident") && !is_case_insensitive_ident!(self, "not") {
2088            name = Some(self.parse()?);
2089
2090            self.input.skip_ws();
2091        }
2092
2093        let query: ContainerQuery = self.parse()?;
2094
2095        Ok(ContainerCondition {
2096            span: Span::new(start_pos, query.span.hi),
2097            name,
2098            query,
2099        })
2100    }
2101}
2102
2103impl<I> Parse<ContainerName> for Parser<I>
2104where
2105    I: ParserInput,
2106{
2107    fn parse(&mut self) -> PResult<ContainerName> {
2108        match cur!(self) {
2109            tok!("ident") => {
2110                let custom_ident: CustomIdent = self.parse()?;
2111
2112                Ok(ContainerName::CustomIdent(custom_ident))
2113            }
2114            _ => {
2115                let span = self.input.cur_span();
2116
2117                Err(Error::new(span, ErrorKind::Expected("ident")))
2118            }
2119        }
2120    }
2121}
2122
2123impl<I> Parse<ContainerQuery> for Parser<I>
2124where
2125    I: ParserInput,
2126{
2127    fn parse(&mut self) -> PResult<ContainerQuery> {
2128        let start_pos = self.input.cur_span().lo;
2129        let mut last_pos;
2130
2131        let mut queries = Vec::new();
2132
2133        if is_case_insensitive_ident!(self, "not") {
2134            let not = self.parse()?;
2135
2136            queries.push(ContainerQueryType::Not(not));
2137
2138            last_pos = self.input.last_pos();
2139        } else {
2140            self.input.skip_ws();
2141
2142            let query_in_parens = self.parse()?;
2143
2144            queries.push(ContainerQueryType::QueryInParens(query_in_parens));
2145
2146            last_pos = self.input.last_pos();
2147
2148            self.input.skip_ws();
2149
2150            if is_case_insensitive_ident!(self, "and") {
2151                while is_case_insensitive_ident!(self, "and") {
2152                    let and = self.parse()?;
2153
2154                    last_pos = self.input.last_pos();
2155
2156                    queries.push(ContainerQueryType::And(and));
2157
2158                    self.input.skip_ws();
2159                }
2160            } else if is_case_insensitive_ident!(self, "or") {
2161                while is_case_insensitive_ident!(self, "or") {
2162                    let or = self.parse()?;
2163
2164                    last_pos = self.input.last_pos();
2165
2166                    queries.push(ContainerQueryType::Or(or));
2167
2168                    self.input.skip_ws();
2169                }
2170            };
2171        }
2172
2173        Ok(ContainerQuery {
2174            span: Span::new(start_pos, last_pos),
2175            queries,
2176        })
2177    }
2178}
2179
2180impl<I> Parse<ContainerQueryNot> for Parser<I>
2181where
2182    I: ParserInput,
2183{
2184    fn parse(&mut self) -> PResult<ContainerQueryNot> {
2185        let span = self.input.cur_span();
2186        let keyword = match cur!(self) {
2187            Token::Ident { value, .. } if value.as_ref().eq_ignore_ascii_case("not") => {
2188                let ident: Ident = self.parse()?;
2189
2190                Some(ident)
2191            }
2192            _ => {
2193                return Err(Error::new(
2194                    span,
2195                    ErrorKind::Expected("ident (with 'not' value) token"),
2196                ));
2197            }
2198        };
2199
2200        self.input.skip_ws();
2201
2202        let query_in_parens = self.parse()?;
2203
2204        Ok(ContainerQueryNot {
2205            span: span!(self, span.lo),
2206            keyword,
2207            query: query_in_parens,
2208        })
2209    }
2210}
2211
2212impl<I> Parse<ContainerQueryAnd> for Parser<I>
2213where
2214    I: ParserInput,
2215{
2216    fn parse(&mut self) -> PResult<ContainerQueryAnd> {
2217        let span = self.input.cur_span();
2218        let keyword = match cur!(self) {
2219            Token::Ident { value, .. } if value.as_ref().eq_ignore_ascii_case("and") => {
2220                let ident: Ident = self.parse()?;
2221
2222                Some(ident)
2223            }
2224            _ => {
2225                return Err(Error::new(
2226                    span,
2227                    ErrorKind::Expected("ident (with 'and' value) token"),
2228                ));
2229            }
2230        };
2231
2232        self.input.skip_ws();
2233
2234        let query_in_parens = self.parse()?;
2235
2236        Ok(ContainerQueryAnd {
2237            span: span!(self, span.lo),
2238            keyword,
2239            query: query_in_parens,
2240        })
2241    }
2242}
2243
2244impl<I> Parse<ContainerQueryOr> for Parser<I>
2245where
2246    I: ParserInput,
2247{
2248    fn parse(&mut self) -> PResult<ContainerQueryOr> {
2249        let span = self.input.cur_span();
2250        let keyword = match cur!(self) {
2251            Token::Ident { value, .. } if value.as_ref().eq_ignore_ascii_case("or") => {
2252                let ident: Ident = self.parse()?;
2253
2254                Some(ident)
2255            }
2256            _ => {
2257                return Err(Error::new(
2258                    span,
2259                    ErrorKind::Expected("ident (with 'or' value) token"),
2260                ));
2261            }
2262        };
2263
2264        self.input.skip_ws();
2265
2266        let query_in_parens = self.parse()?;
2267
2268        Ok(ContainerQueryOr {
2269            span: span!(self, span.lo),
2270            keyword,
2271            query: query_in_parens,
2272        })
2273    }
2274}
2275
2276impl<I> Parse<QueryInParens> for Parser<I>
2277where
2278    I: ParserInput,
2279{
2280    fn parse(&mut self) -> PResult<QueryInParens> {
2281        let state = self.input.state();
2282
2283        match self.parse() {
2284            Ok(size_feature) => Ok(QueryInParens::SizeFeature(size_feature)),
2285            Err(_) => {
2286                self.input.reset(&state);
2287
2288                let mut parse_container_query = || {
2289                    expect!(self, "(");
2290
2291                    let container_query = self.parse()?;
2292
2293                    expect!(self, ")");
2294
2295                    Ok(QueryInParens::ContainerQuery(Box::new(container_query)))
2296                };
2297
2298                match parse_container_query() {
2299                    Ok(query_in_parens) => Ok(query_in_parens),
2300                    Err(_) => {
2301                        self.input.reset(&state);
2302
2303                        let general_enclosed = self.parse()?;
2304
2305                        Ok(QueryInParens::GeneralEnclosed(general_enclosed))
2306                    }
2307                }
2308            }
2309        }
2310    }
2311}
2312
2313impl<I> Parse<SizeFeature> for Parser<I>
2314where
2315    I: ParserInput,
2316{
2317    fn parse(&mut self) -> PResult<SizeFeature> {
2318        let span = self.input.cur_span();
2319
2320        expect!(self, "(");
2321
2322        self.input.skip_ws();
2323
2324        let left = self.parse()?;
2325
2326        self.input.skip_ws();
2327
2328        match cur!(self) {
2329            tok!(")") => {
2330                bump!(self);
2331
2332                let name = match left {
2333                    SizeFeatureValue::Ident(ident) => SizeFeatureName::Ident(ident),
2334                    _ => {
2335                        return Err(Error::new(span, ErrorKind::Expected("identifier value")));
2336                    }
2337                };
2338
2339                Ok(SizeFeature::Boolean(SizeFeatureBoolean {
2340                    span: span!(self, span.lo),
2341                    name,
2342                }))
2343            }
2344            tok!(":") => {
2345                bump!(self);
2346
2347                self.input.skip_ws();
2348
2349                let name = match left {
2350                    SizeFeatureValue::Ident(ident) => SizeFeatureName::Ident(ident),
2351                    _ => {
2352                        return Err(Error::new(span, ErrorKind::Expected("identifier value")));
2353                    }
2354                };
2355                let value = self.parse()?;
2356
2357                self.input.skip_ws();
2358
2359                expect!(self, ")");
2360
2361                Ok(SizeFeature::Plain(SizeFeaturePlain {
2362                    span: span!(self, span.lo),
2363                    name,
2364                    value,
2365                }))
2366            }
2367            tok!("<") | tok!(">") | tok!("=") => {
2368                let left_comparison = match bump!(self) {
2369                    tok!("<") => {
2370                        if eat!(self, "=") {
2371                            SizeFeatureRangeComparison::Le
2372                        } else {
2373                            SizeFeatureRangeComparison::Lt
2374                        }
2375                    }
2376                    tok!(">") => {
2377                        if eat!(self, "=") {
2378                            SizeFeatureRangeComparison::Ge
2379                        } else {
2380                            SizeFeatureRangeComparison::Gt
2381                        }
2382                    }
2383                    tok!("=") => SizeFeatureRangeComparison::Eq,
2384                    _ => {
2385                        unreachable!();
2386                    }
2387                };
2388
2389                self.input.skip_ws();
2390
2391                let center = self.parse()?;
2392
2393                self.input.skip_ws();
2394
2395                if eat!(self, ")") {
2396                    return Ok(SizeFeature::Range(SizeFeatureRange {
2397                        span: span!(self, span.lo),
2398                        left: Box::new(left),
2399                        comparison: left_comparison,
2400                        right: Box::new(center),
2401                    }));
2402                }
2403
2404                let right_comparison = match bump!(self) {
2405                    tok!("<") => {
2406                        if eat!(self, "=") {
2407                            SizeFeatureRangeComparison::Le
2408                        } else {
2409                            SizeFeatureRangeComparison::Lt
2410                        }
2411                    }
2412                    tok!(">") => {
2413                        if eat!(self, "=") {
2414                            SizeFeatureRangeComparison::Ge
2415                        } else {
2416                            SizeFeatureRangeComparison::Gt
2417                        }
2418                    }
2419                    _ => {
2420                        return Err(Error::new(
2421                            span,
2422                            ErrorKind::Expected("'>' or '<' operators"),
2423                        ));
2424                    }
2425                };
2426
2427                self.input.skip_ws();
2428
2429                let right = self.parse()?;
2430
2431                self.input.skip_ws();
2432
2433                expect!(self, ")");
2434
2435                let name = match center {
2436                    SizeFeatureValue::Ident(ident) => SizeFeatureName::Ident(ident),
2437                    _ => {
2438                        return Err(Error::new(span, ErrorKind::Expected("identifier value")));
2439                    }
2440                };
2441
2442                let is_valid_operator = match left_comparison {
2443                    SizeFeatureRangeComparison::Lt | SizeFeatureRangeComparison::Le
2444                        if right_comparison == SizeFeatureRangeComparison::Lt
2445                            || right_comparison == SizeFeatureRangeComparison::Le =>
2446                    {
2447                        true
2448                    }
2449                    SizeFeatureRangeComparison::Gt | SizeFeatureRangeComparison::Ge
2450                        if right_comparison == SizeFeatureRangeComparison::Gt
2451                            || right_comparison == SizeFeatureRangeComparison::Ge =>
2452                    {
2453                        true
2454                    }
2455                    _ => false,
2456                };
2457
2458                if !is_valid_operator {
2459                    return Err(Error::new(
2460                        span,
2461                        ErrorKind::Expected(
2462                            "left comparison operator should be equal right comparison operator",
2463                        ),
2464                    ));
2465                }
2466
2467                Ok(SizeFeature::RangeInterval(SizeFeatureRangeInterval {
2468                    span: span!(self, span.lo),
2469                    left: Box::new(left),
2470                    left_comparison,
2471                    name,
2472                    right_comparison,
2473                    right,
2474                }))
2475            }
2476            _ => Err(Error::new(span, ErrorKind::Expected("identifier value"))),
2477        }
2478    }
2479}
2480
2481impl<I> Parse<SizeFeatureValue> for Parser<I>
2482where
2483    I: ParserInput,
2484{
2485    fn parse(&mut self) -> PResult<SizeFeatureValue> {
2486        let span = self.input.cur_span();
2487
2488        match cur!(self) {
2489            tok!("number") => {
2490                let left = self.parse()?;
2491
2492                self.input.skip_ws();
2493
2494                if eat!(self, "/") {
2495                    self.input.skip_ws();
2496
2497                    let right = Some(self.parse()?);
2498
2499                    return Ok(SizeFeatureValue::Ratio(Ratio {
2500                        span: span!(self, span.lo),
2501                        left,
2502                        right,
2503                    }));
2504                }
2505
2506                Ok(SizeFeatureValue::Number(left))
2507            }
2508            tok!("ident") => {
2509                let name: Ident = self.parse()?;
2510
2511                Ok(SizeFeatureValue::Ident(name))
2512            }
2513            tok!("dimension") => Ok(SizeFeatureValue::Dimension(self.parse()?)),
2514            Token::Function { value, .. } if is_math_function(value) => {
2515                let function = self.parse()?;
2516
2517                Ok(SizeFeatureValue::Function(function))
2518            }
2519            _ => Err(Error::new(
2520                span,
2521                ErrorKind::Expected("number, ident, dimension or function token"),
2522            )),
2523        }
2524    }
2525}
2526
2527impl<I> Parse<ExtensionName> for Parser<I>
2528where
2529    I: ParserInput,
2530{
2531    fn parse(&mut self) -> PResult<ExtensionName> {
2532        let span = self.input.cur_span();
2533
2534        if !is!(self, Ident) {
2535            return Err(Error::new(span, ErrorKind::Expected("indent token")));
2536        }
2537
2538        // All extensions defined in this specification use a common syntax for defining
2539        // their ”names”: the <extension-name> production. An <extension-name> is any
2540        // identifier that starts with two dashes (U+002D HYPHEN-MINUS), like --foo, or
2541        // even exotic names like -- or ------. The CSS language will never use
2542        // identifiers of this form for any language-defined purpose, so it’s safe to
2543        // use them for author-defined purposes without ever having to worry about
2544        // colliding with CSS-defined names.
2545        match bump!(self) {
2546            Token::Ident { value, raw, .. } => {
2547                if !value.starts_with("--") {
2548                    return Err(Error::new(
2549                        span,
2550                        ErrorKind::Expected("Extension name should start with '--'"),
2551                    ));
2552                }
2553
2554                Ok(ExtensionName {
2555                    span,
2556                    value,
2557                    raw: Some(raw),
2558                })
2559            }
2560            _ => {
2561                unreachable!()
2562            }
2563        }
2564    }
2565}
2566
2567impl<I> Parse<CustomMediaQuery> for Parser<I>
2568where
2569    I: ParserInput,
2570{
2571    fn parse(&mut self) -> PResult<CustomMediaQuery> {
2572        let span = self.input.cur_span();
2573        let name = self.parse()?;
2574
2575        self.input.skip_ws();
2576
2577        let media = match cur!(self) {
2578            _ if is_case_insensitive_ident!(self, "true")
2579                || is_case_insensitive_ident!(self, "false") =>
2580            {
2581                CustomMediaQueryMediaType::Ident(self.parse()?)
2582            }
2583            _ => CustomMediaQueryMediaType::MediaQueryList(self.parse()?),
2584        };
2585
2586        Ok(CustomMediaQuery {
2587            span: span!(self, span.lo),
2588            name,
2589            media,
2590        })
2591    }
2592}
2593
2594impl<I> Parse<ScopeRange> for Parser<I>
2595where
2596    I: ParserInput,
2597{
2598    fn parse(&mut self) -> PResult<ScopeRange> {
2599        let span = self.input.cur_span();
2600
2601        if is!(self, EOF) {
2602            return Ok(ScopeRange {
2603                span: span!(self, span.lo),
2604                scope_start: None,
2605                scope_end: None,
2606            });
2607        }
2608
2609        match cur!(self) {
2610            tok!("(") => {
2611                bump!(self);
2612                let start = self.parse()?;
2613                expect!(self, ")");
2614                self.input.skip_ws();
2615
2616                let end = if is!(self, EOF) {
2617                    None
2618                } else if is_case_insensitive_ident!(self, "to") {
2619                    bump!(self);
2620                    self.input.skip_ws();
2621                    expect!(self, "(");
2622                    let result = self.parse()?;
2623                    expect!(self, ")");
2624                    Some(result)
2625                } else {
2626                    None
2627                };
2628
2629                Ok(ScopeRange {
2630                    span: span!(self, span.lo),
2631                    scope_start: Some(start),
2632                    scope_end: end,
2633                })
2634            }
2635            _ => {
2636                if is_case_insensitive_ident!(self, "to") {
2637                    bump!(self);
2638
2639                    self.input.skip_ws();
2640
2641                    expect!(self, "(");
2642                    let end = self.parse()?;
2643                    expect!(self, ")");
2644
2645                    return Ok(ScopeRange {
2646                        span: span!(self, span.lo),
2647                        scope_start: None,
2648                        scope_end: Some(end),
2649                    });
2650                }
2651
2652                return Err(Error::new(span, ErrorKind::InvalidScopeAtRule));
2653            }
2654        }
2655    }
2656}