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 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 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 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 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 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 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}