swc_css_parser/parser/syntax/mod.rs
1use swc_common::{BytePos, Span, Spanned};
2use swc_css_ast::*;
3
4use super::{input::ParserInput, PResult, Parser};
5use crate::{
6 error::{Error, ErrorKind},
7 parser::{BlockContentsGrammar, Ctx},
8 Parse,
9};
10
11impl<I> Parse<Stylesheet> for Parser<I>
12where
13 I: ParserInput,
14{
15 fn parse(&mut self) -> PResult<Stylesheet> {
16 // Create a new stylesheet, with its location set to location (or null, if
17 // location was not passed).
18 let start = self.input.cur_span();
19
20 // Consume a list of rules from input, with the top-level flag set, and set the
21 // stylesheet’s value to the result.
22 let rules = self
23 .with_ctx(Ctx {
24 is_top_level: true,
25 ..self.ctx
26 })
27 .parse_as::<Vec<Rule>>()?;
28 let last = self.input.last_pos();
29
30 // Return the stylesheet.
31 Ok(Stylesheet {
32 span: Span::new(start.lo, last),
33 rules,
34 })
35 }
36}
37
38impl<I> Parse<Vec<Rule>> for Parser<I>
39where
40 I: ParserInput,
41{
42 fn parse(&mut self) -> PResult<Vec<Rule>> {
43 // To consume a list of rules, given a top-level flag:
44
45 // Create an initially empty list of rules.
46 let mut rules = Vec::new();
47
48 // Repeatedly consume the next input token:
49
50 // Reset the `is_top_level` value
51 let ctx = Ctx {
52 is_top_level: false,
53 ..self.ctx
54 };
55 loop {
56 // <EOF-token>
57 // Return the list of rules.
58 if is!(self, EOF) {
59 return Ok(rules);
60 }
61
62 match cur!(self) {
63 // <whitespace-token>
64 // Do nothing.
65 tok!(" ") => {
66 self.input.skip_ws();
67 }
68 // <CDO-token>
69 // <CDC-token>
70 tok!("<!--") | tok!("-->") => {
71 // If the top-level flag is set, do nothing.
72 if self.ctx.is_top_level {
73 bump!(self);
74 }
75 // Otherwise, reconsume the current input token. Consume a qualified rule. If
76 // anything is returned, append it to the list of rules.
77 else {
78 let qualified_rule = self.with_ctx(ctx).parse_as::<Box<QualifiedRule>>()?;
79
80 rules.push(Rule::QualifiedRule(qualified_rule));
81 }
82 }
83 // <at-keyword-token>
84 // Reconsume the current input token. Consume an at-rule, and append the returned
85 // value to the list of rules.
86 tok!("@") => {
87 let at_rule = self.with_ctx(ctx).parse_as::<Box<AtRule>>()?;
88
89 rules.push(Rule::AtRule(at_rule));
90 }
91 // anything else
92 // Reconsume the current input token. Consume a qualified rule. If anything is
93 // returned, append it to the list of rules.
94 //
95 // For better recovery we parse broken code into the list of component values and
96 // append it to the list of rules.
97 _ => {
98 let state = self.input.state();
99 let qualified_rule = self.with_ctx(ctx).parse_as::<Box<QualifiedRule>>();
100
101 match qualified_rule {
102 Ok(i) => rules.push(Rule::QualifiedRule(i)),
103 Err(err) => {
104 self.errors.push(err);
105 self.input.reset(&state);
106
107 let span = self.input.cur_span();
108 let mut list_of_component_values = ListOfComponentValues {
109 span: Default::default(),
110 children: Vec::new(),
111 };
112
113 while !is_one_of!(self, EOF) {
114 let component_value =
115 self.with_ctx(ctx).parse_as::<ComponentValue>()?;
116
117 list_of_component_values.children.push(component_value);
118 }
119
120 list_of_component_values.span = span!(self, span.lo);
121
122 rules.push(Rule::ListOfComponentValues(Box::new(
123 list_of_component_values,
124 )));
125 }
126 };
127 }
128 }
129 }
130 }
131}
132
133impl<I> Parse<AtRule> for Parser<I>
134where
135 I: ParserInput,
136{
137 fn parse(&mut self) -> PResult<AtRule> {
138 // To consume an at-rule:
139
140 // Consume the next input token. Create a new at-rule with its name set to the
141 // value of the current input token, its prelude initially set to an empty list,
142 // and its value initially set to nothing.
143 let span = self.input.cur_span();
144 let at_keyword_name = match bump!(self) {
145 Token::AtKeyword { value, raw } => (value, raw),
146 _ => {
147 unreachable!()
148 }
149 };
150 let is_dashed_ident = at_keyword_name.0.starts_with("--");
151 let name = if is_dashed_ident {
152 AtRuleName::DashedIdent(DashedIdent {
153 span: Span::new(span.lo + BytePos(1), span.hi),
154 value: self.input.atom(&at_keyword_name.0[2..]),
155 raw: Some(at_keyword_name.1),
156 })
157 } else {
158 AtRuleName::Ident(Ident {
159 span: Span::new(span.lo + BytePos(1), span.hi),
160 value: at_keyword_name.0,
161 raw: Some(at_keyword_name.1),
162 })
163 };
164 let mut prelude = Vec::new();
165 let mut at_rule = AtRule {
166 span: Default::default(),
167 name,
168 prelude: None,
169 block: None,
170 };
171
172 loop {
173 // <EOF-token>
174 // This is a parse error. Return the at-rule.
175 if is!(self, EOF) {
176 if prelude.is_empty() {
177 self.errors.push(Error::new(
178 span!(self, span.lo),
179 ErrorKind::EofButExpected("';' or '{'"),
180 ));
181
182 at_rule.span = span!(self, span.lo);
183
184 return Ok(at_rule);
185 }
186
187 at_rule.prelude = Some(Box::new(AtRulePrelude::ListOfComponentValues(
188 self.create_locv(prelude),
189 )));
190 at_rule.span = span!(self, span.lo);
191
192 // Canonicalization against a grammar
193 if !is_dashed_ident && self.ctx.need_canonicalize {
194 at_rule = self.canonicalize_at_rule_prelude(at_rule)?;
195 }
196
197 return Ok(at_rule);
198 }
199
200 match cur!(self) {
201 // <semicolon-token>
202 // Return the at-rule.
203 tok!(";") => {
204 self.input.bump();
205
206 at_rule.prelude = Some(Box::new(AtRulePrelude::ListOfComponentValues(
207 self.create_locv(prelude),
208 )));
209 at_rule.span = span!(self, span.lo);
210
211 // Canonicalization against a grammar
212 if !is_dashed_ident && self.ctx.need_canonicalize {
213 at_rule = self.canonicalize_at_rule_prelude(at_rule)?;
214 }
215
216 return Ok(at_rule);
217 }
218 // <{-token>
219 // Consume a simple block and assign it to the at-rule’s block. Return the at-rule.
220 tok!("{") => {
221 let block = self.parse_as::<SimpleBlock>()?;
222
223 at_rule.prelude = Some(Box::new(AtRulePrelude::ListOfComponentValues(
224 self.create_locv(prelude),
225 )));
226 at_rule.block = Some(block);
227 at_rule.span = span!(self, span.lo);
228
229 // Canonicalization against a grammar
230 if !is_dashed_ident && self.ctx.need_canonicalize {
231 at_rule = self.canonicalize_at_rule_prelude(at_rule)?;
232 at_rule = self.canonicalize_at_rule_block(at_rule)?;
233 }
234
235 return Ok(at_rule);
236 }
237 // anything else
238 // Reconsume the current input token. Consume a component value. Append the returned
239 // value to the at-rule’s prelude.
240 _ => {
241 let component_value = self.parse_as::<ComponentValue>()?;
242 prelude.push(component_value);
243 }
244 }
245 }
246 }
247}
248
249impl<I> Parse<QualifiedRule> for Parser<I>
250where
251 I: ParserInput,
252{
253 fn parse(&mut self) -> PResult<QualifiedRule> {
254 // To consume a qualified rule:
255
256 // Create a new qualified rule with its prelude initially set to an empty list,
257 // and its value initially set to nothing.
258 let span = self.input.cur_span();
259 let mut prelude = Vec::new();
260
261 // Repeatedly consume the next input token:
262 loop {
263 // <EOF-token>
264 // This is a parse error. Return nothing.
265 if is!(self, EOF) {
266 return Err(Error::new(
267 span!(self, span.lo),
268 ErrorKind::EofButExpected("'{'"),
269 ));
270 }
271
272 match cur!(self) {
273 // <semicolon-token>
274 // If mixed with declarations is true, this is a parse error; return nothing.
275 // Otherwise, append a <semicolon-token> to the qualified rule’s prelude.
276 tok!(";") => {
277 if self.ctx.mixed_with_declarations {
278 let span = self.input.cur_span();
279
280 return Err(Error::new(span, ErrorKind::Expected("'{'")));
281 } else {
282 let component_value = self.parse_as::<ComponentValue>()?;
283
284 prelude.push(component_value);
285 }
286 }
287 // <{-token>
288 // Consume a simple block and assign it to the qualified rule’s block. Return the
289 // qualified rule.
290 tok!("{") => {
291 let block = self.parse_as::<SimpleBlock>()?;
292 let mut qualified_rule = QualifiedRule {
293 span: span!(self, span.lo),
294 prelude: QualifiedRulePrelude::ListOfComponentValues(
295 self.create_locv(prelude),
296 ),
297 block,
298 };
299
300 // Canonicalization against a grammar
301 if self.ctx.need_canonicalize {
302 qualified_rule =
303 self.canonicalize_qualified_rule_prelude(qualified_rule)?;
304 qualified_rule = self.canonicalize_qualified_rule_block(qualified_rule)?;
305 }
306
307 return Ok(qualified_rule);
308 }
309 // Reconsume the current input token. Consume a component value. Append the returned
310 // value to the qualified rule’s prelude.
311 _ => {
312 let component_value = self.parse_as::<ComponentValue>()?;
313
314 prelude.push(component_value);
315 }
316 }
317 }
318 }
319}
320
321impl<I> Parse<Vec<StyleBlock>> for Parser<I>
322where
323 I: ParserInput,
324{
325 fn parse(&mut self) -> PResult<Vec<StyleBlock>> {
326 let mut declarations = Vec::new();
327 let mut rules = Vec::new();
328
329 loop {
330 // <EOF-token>
331 // Extend decls with rules, then return decls.
332 if is!(self, EOF) {
333 declarations.extend(rules);
334
335 return Ok(declarations);
336 }
337
338 match cur!(self) {
339 // <whitespace-token>
340 // Do nothing.
341 tok!(" ") => {
342 self.input.skip_ws();
343 }
344 // <semicolon-token>
345 // Do nothing.
346 tok!(";") => {
347 let token_and_span = self.input.bump().unwrap();
348
349 // For recovery mode
350 if let Some(StyleBlock::ListOfComponentValues(list_of_component_values)) =
351 declarations.last_mut()
352 {
353 list_of_component_values.span =
354 Span::new(list_of_component_values.span_lo(), token_and_span.span_hi());
355 list_of_component_values
356 .children
357 .push(ComponentValue::PreservedToken(Box::new(token_and_span)));
358 }
359 }
360 // <at-keyword-token>
361 // Reconsume the current input token. Consume an at-rule, and append the result to
362 // rules.
363 tok!("@") => {
364 let at_rule = self.parse()?;
365
366 rules.push(StyleBlock::AtRule(Box::new(at_rule)));
367 }
368 // <ident-token>
369 // <function-token>
370 // <function>
371 //
372 // Reconsume the current input token. Initialize a temporary list, initially empty.
373 // As long as the next input token is anything other than a <semicolon-token> or
374 // <EOF-token>, consume a component value and append it to the temporary list.
375 // Consume a declaration from the temporary list. If anything was returned, append
376 // it to decls.
377 tok!("ident") | tok!("function") => {
378 // Legacy nested parsing conflict with custom properties, but selectors can't
379 // start with `--`, so it is safe to ignore them.
380 //
381 // Constructions like `a { prop: {value}; }` still affected this problem, but
382 // `{`/`}` doesn't used in declarations
383 if self.config.legacy_nesting
384 && matches!(self.input.cur(), Some(Token::Ident { value, .. }) if !value.starts_with("--"))
385 {
386 if let Some(legacy_nested) = self.try_to_parse_legacy_nesting() {
387 rules.push(StyleBlock::QualifiedRule(Box::new(legacy_nested)));
388
389 continue;
390 }
391 }
392
393 let span = self.input.cur_span();
394 let mut temporary_list = ListOfComponentValues {
395 span: Default::default(),
396 children: Vec::new(),
397 };
398
399 while !is_one_of!(self, ";", EOF) {
400 let component_value = self.parse_as::<ComponentValue>()?;
401
402 temporary_list.children.push(component_value);
403 }
404
405 let decl_or_list_of_component_values =
406 match self.parse_declaration_from_temporary_list(&temporary_list) {
407 Ok(decl) => StyleBlock::Declaration(Box::new(decl)),
408 Err(err) => {
409 self.errors.push(err);
410
411 temporary_list.span = span!(self, span.lo);
412
413 StyleBlock::ListOfComponentValues(Box::new(temporary_list))
414 }
415 };
416
417 declarations.push(decl_or_list_of_component_values);
418 }
419 // anything else
420 // Reconsume the current input token. Consume a qualified rule, with mixed with
421 // declarations set to true. If anything was returned, append it to rules.
422 _ => {
423 let state = self.input.state();
424 let qualified_rule = self
425 .with_ctx(Ctx {
426 block_contents_grammar: BlockContentsGrammar::StyleBlock,
427 mixed_with_declarations: true,
428 ..self.ctx
429 })
430 .parse_as::<Box<QualifiedRule>>();
431
432 match qualified_rule {
433 Ok(i) => rules.push(StyleBlock::QualifiedRule(i)),
434 Err(err) => {
435 self.errors.push(err);
436 self.input.reset(&state);
437
438 let span = self.input.cur_span();
439
440 self.errors
441 .push(Error::new(span, ErrorKind::Unexpected("token")));
442
443 // For recovery mode
444 let mut list_of_component_values = ListOfComponentValues {
445 span: Default::default(),
446 children: Vec::new(),
447 };
448
449 while !is_one_of!(self, ";", EOF) {
450 let component_value = self.parse_as::<ComponentValue>()?;
451
452 list_of_component_values.children.push(component_value);
453 }
454
455 list_of_component_values.span = span!(self, span.lo);
456
457 declarations.push(StyleBlock::ListOfComponentValues(Box::new(
458 list_of_component_values,
459 )));
460 }
461 };
462 }
463 }
464 }
465 }
466}
467
468impl<I> Parse<Vec<DeclarationOrAtRule>> for Parser<I>
469where
470 I: ParserInput,
471{
472 fn parse(&mut self) -> PResult<Vec<DeclarationOrAtRule>> {
473 // Create an initially empty list of declarations.
474 let mut declarations = Vec::new();
475
476 // Repeatedly consume the next input token:
477 loop {
478 // <EOF-token>
479 // Return the list of declarations.
480 if is!(self, EOF) {
481 return Ok(declarations);
482 }
483
484 match cur!(self) {
485 // <whitespace-token>
486 // Do nothing.
487 tok!(" ") => {
488 self.input.skip_ws();
489 }
490 // <semicolon-token>
491 // Do nothing.
492 tok!(";") => {
493 let token_and_span = self.input.bump().unwrap();
494
495 // For recovery mode
496 if let Some(DeclarationOrAtRule::ListOfComponentValues(
497 list_of_component_values,
498 )) = declarations.last_mut()
499 {
500 list_of_component_values.span =
501 Span::new(list_of_component_values.span_lo(), token_and_span.span_hi());
502 list_of_component_values
503 .children
504 .push(ComponentValue::PreservedToken(Box::new(token_and_span)));
505 }
506 }
507 // <at-keyword-token>
508 // Reconsume the current input token. Consume an at-rule. Append the returned rule
509 // to the list of declarations.
510 tok!("@") => {
511 let at_rule = self
512 .with_ctx(Ctx {
513 block_contents_grammar: BlockContentsGrammar::DeclarationList,
514 ..self.ctx
515 })
516 .parse_as::<AtRule>()?;
517
518 declarations.push(DeclarationOrAtRule::AtRule(Box::new(at_rule)));
519 }
520 // <ident-token>
521 // Initialize a temporary list initially filled with the current input token. As
522 // long as the next input token is anything other than a <semicolon-token> or
523 // <EOF-token>, consume a component value and append it to the temporary list.
524 // Consume a declaration from the temporary list. If anything was returned, append
525 // it to the list of declarations.
526 tok!("ident") => {
527 let span = self.input.cur_span();
528 let mut temporary_list = ListOfComponentValues {
529 span: Default::default(),
530 children: Vec::new(),
531 };
532
533 while !is_one_of!(self, ";", EOF) {
534 let component_value = self.parse_as::<ComponentValue>()?;
535
536 temporary_list.children.push(component_value);
537 }
538
539 let decl_or_list_of_component_values =
540 match self.parse_declaration_from_temporary_list(&temporary_list) {
541 Ok(decl) => DeclarationOrAtRule::Declaration(Box::new(decl)),
542 Err(err) => {
543 self.errors.push(err);
544
545 temporary_list.span = span!(self, span.lo);
546
547 DeclarationOrAtRule::ListOfComponentValues(Box::new(temporary_list))
548 }
549 };
550
551 declarations.push(decl_or_list_of_component_values);
552 }
553 // anything else
554 // This is a parse error. Reconsume the current input token. As long as the next
555 // input token is anything other than a <semicolon-token> or <EOF-token>, consume a
556 // component value and throw away the returned value.
557 //
558 // We don't throw away the return value because of the recovery mode and return list
559 // of components values in this case
560 _ => {
561 let span = self.input.cur_span();
562
563 self.errors.push(Error::new(
564 span,
565 ErrorKind::Expected("whitespace, ';', '@', ident or EOF"),
566 ));
567
568 // For recovery mode
569 let mut list_of_component_values = ListOfComponentValues {
570 span: Default::default(),
571 children: Vec::new(),
572 };
573
574 while !is_one_of!(self, ";", EOF) {
575 let component_value = self.parse_as::<ComponentValue>()?;
576
577 list_of_component_values.children.push(component_value);
578 }
579
580 list_of_component_values.span = span!(self, span.lo);
581
582 declarations.push(DeclarationOrAtRule::ListOfComponentValues(Box::new(
583 list_of_component_values,
584 )));
585 }
586 }
587 }
588 }
589}
590
591impl<I> Parse<Declaration> for Parser<I>
592where
593 I: ParserInput,
594{
595 fn parse(&mut self) -> PResult<Declaration> {
596 // To consume a declaration:
597
598 // Let decl be a new declaration, with an initially empty name and a value set
599 // to an empty list.
600
601 // TODO improve me
602 // Consume a component value.
603 // <ident-token>
604 // Set decl’s name to the value of the <ident-token>.
605 //
606 // anything else
607 // This is a parse error.
608 //
609 // While the next input token is anything but a <semicolon-token> or
610 // <eof-token>, consume a component value and throw it away.
611 //
612 // Return nothing.
613 let span = self.input.cur_span();
614 let declaration_name = match cur!(self) {
615 Token::Ident { value, .. } => value,
616 _ => {
617 return Err(Error::new(span, ErrorKind::Expected("ident")));
618 }
619 };
620 let is_dashed_ident = declaration_name.starts_with("--");
621 let name = if is_dashed_ident {
622 let ident = self.parse()?;
623
624 DeclarationName::DashedIdent(ident)
625 } else {
626 let ident: Ident = self.parse()?;
627
628 DeclarationName::Ident(ident)
629 };
630 let mut declaration = Declaration {
631 span: Default::default(),
632 name,
633 value: Vec::new(),
634 important: None,
635 };
636
637 // 2. While the next input token is a <whitespace-token>, consume the next input
638 // token.
639 self.input.skip_ws();
640
641 // 3. If the next input token is anything other than a <colon-token>, this is a
642 // parse error. Return nothing. Otherwise, consume the next input token.
643 expect!(self, ":");
644
645 // 4. While the next input token is a <whitespace-token>, consume the next input
646 // token.
647 self.input.skip_ws();
648
649 // 5. As long as the next input token is anything other than an <EOF-token>,
650 // consume a component value and append it to the declaration’s value.
651 let mut is_valid_to_canonicalize = true;
652 let mut last_whitespaces = (0, 0, 0);
653 let mut exclamation_point_span = None;
654 let mut important_ident = None;
655
656 loop {
657 if is!(self, EOF) {
658 break;
659 }
660
661 let component_value = self.parse_as::<ComponentValue>()?;
662
663 match &component_value {
664 // Optimization for step 6
665 ComponentValue::PreservedToken(token_and_span)
666 if matches!(token_and_span.token, Token::Delim { value: '!', .. })
667 && (is!(self, " ") || is_case_insensitive_ident!(self, "important")) =>
668 {
669 if let Some(span) = &exclamation_point_span {
670 is_valid_to_canonicalize = false;
671
672 self.errors.push(Error::new(
673 *span,
674 ErrorKind::Unexpected("'!' in declaration value"),
675 ));
676
677 important_ident = None;
678 last_whitespaces = (last_whitespaces.2, 0, 0);
679 }
680
681 exclamation_point_span = Some(token_and_span.span);
682 }
683 ComponentValue::PreservedToken(token_and_span)
684 if matches!(token_and_span.token, Token::WhiteSpace { .. }) =>
685 {
686 match (&exclamation_point_span, &important_ident) {
687 (Some(_), Some(_)) => {
688 last_whitespaces.2 += 1;
689 }
690 (Some(_), None) => {
691 last_whitespaces.1 += 1;
692 }
693 (None, None) => {
694 last_whitespaces.0 += 1;
695 }
696 _ => {
697 unreachable!();
698 }
699 }
700 }
701 ComponentValue::PreservedToken(token_and_span)
702 if exclamation_point_span.is_some()
703 && matches!(
704 &token_and_span.token,
705 Token::Ident { value, .. } if matches_eq_ignore_ascii_case!(value, "important")
706 ) =>
707 {
708 important_ident = Some(token_and_span.clone());
709 }
710 _ => {
711 if let Err(err) = self.validate_declaration_value(&component_value) {
712 is_valid_to_canonicalize = false;
713
714 self.errors.push(err);
715 }
716
717 last_whitespaces = (0, 0, 0);
718
719 if let Some(span) = &exclamation_point_span {
720 is_valid_to_canonicalize = false;
721
722 self.errors.push(Error::new(
723 *span,
724 ErrorKind::Unexpected("'!' in declaration value"),
725 ));
726
727 important_ident = None;
728 exclamation_point_span = None;
729 }
730 }
731 }
732
733 declaration.value.push(component_value);
734 }
735
736 // 6. If the last two non-<whitespace-token>s in the declaration’s value are a
737 // <delim-token> with the value "!" followed by an <ident-token> with a value
738 // that is an ASCII case-insensitive match for "important", remove them from the
739 // declaration’s value and set the declaration’s important flag to true.
740 if let (Some(exclamation_point_span), Some(important_ident)) =
741 (exclamation_point_span, important_ident)
742 {
743 let span = Span::new(exclamation_point_span.lo, important_ident.span_hi());
744 let value = match important_ident.token {
745 Token::Ident { value, raw, .. } => (value, raw),
746 _ => {
747 unreachable!();
748 }
749 };
750 let value = Ident {
751 span: important_ident.span,
752 value: value.0.to_ascii_lowercase(),
753 raw: Some(value.1),
754 };
755
756 declaration.important = Some(ImportantFlag { span, value });
757 }
758
759 // 7. While the last token in the declaration’s value is a <whitespace-token>,
760 // remove that token.
761 let len = if declaration.important.is_some() {
762 declaration.value.len()
763 - (last_whitespaces.0 + last_whitespaces.1 + last_whitespaces.2 + 2)
764 } else {
765 declaration.value.len() - (last_whitespaces.0 + last_whitespaces.1 + last_whitespaces.2)
766 };
767
768 declaration.value.truncate(len);
769
770 // Update span
771 declaration.span = span!(self, span.lo);
772
773 if is_dashed_ident {
774 // Don't parse custom properties
775 //
776 // 8. Return the declaration.
777 return Ok(declaration);
778 }
779
780 // Canonicalization against a grammar
781 if is_valid_to_canonicalize && self.ctx.need_canonicalize {
782 declaration = self.canonicalize_declaration_value(declaration)?;
783 }
784
785 // 8. Return the declaration.
786 Ok(declaration)
787 }
788}
789
790impl<I> Parse<ComponentValue> for Parser<I>
791where
792 I: ParserInput,
793{
794 fn parse(&mut self) -> PResult<ComponentValue> {
795 match cur!(self) {
796 // If the current input token is a <{-token>, <[-token>, or <(-token>, consume a
797 // simple block and return it.
798 tok!("[") | tok!("(") | tok!("{") => {
799 let block = self.parse()?;
800
801 Ok(ComponentValue::SimpleBlock(block))
802 }
803 // Otherwise, if the current input token is a <function-token>, consume a
804 // function and return it.
805 tok!("function") => {
806 let function = self
807 .with_ctx({
808 Ctx {
809 // We canonize it later
810 need_canonicalize: false,
811 ..self.ctx
812 }
813 })
814 .parse_as::<Box<Function>>()?;
815
816 Ok(ComponentValue::Function(function))
817 }
818 // Otherwise, return the current input token.
819 _ => {
820 let token_and_span = self.input.bump();
821
822 match token_and_span {
823 Some(t) => Ok(ComponentValue::PreservedToken(Box::new(t))),
824 _ => {
825 unreachable!();
826 }
827 }
828 }
829 }
830 }
831}
832
833impl<I> Parse<SimpleBlock> for Parser<I>
834where
835 I: ParserInput,
836{
837 fn parse(&mut self) -> PResult<SimpleBlock> {
838 // To consume a simple block:
839
840 // Create a simple block with its associated token set to the current input
841 // token and with its value initially set to an empty list.
842 let span = self.input.cur_span();
843 let name = match cur!(self) {
844 tok!("{") | tok!("(") | tok!("[") => self.input.bump().unwrap(),
845 _ => {
846 return Err(Error::new(
847 span,
848 ErrorKind::Expected("'{', '(' or '[' token"),
849 ));
850 }
851 };
852 let mut simple_block = SimpleBlock {
853 span: Default::default(),
854 name,
855 value: Vec::new(),
856 };
857
858 // Repeatedly consume the next input token and process it as follows:
859 loop {
860 // <EOF-token>
861 // This is a parse error. Return the block.
862 if is!(self, EOF) {
863 let mirror = match &simple_block.name.token {
864 Token::LBracket => "']'",
865 Token::LParen => "')'",
866 Token::LBrace => "'}'",
867 _ => {
868 unreachable!();
869 }
870 };
871
872 self.errors.push(Error::new(
873 span!(self, span.lo),
874 ErrorKind::EofButExpected(mirror),
875 ));
876
877 break;
878 }
879
880 match cur!(self) {
881 // ending token
882 // Return the block.
883 tok!("]") if simple_block.name.token == Token::LBracket => {
884 bump!(self);
885
886 break;
887 }
888 tok!(")") if simple_block.name.token == Token::LParen => {
889 bump!(self);
890
891 break;
892 }
893 tok!("}") if simple_block.name.token == Token::LBrace => {
894 bump!(self);
895
896 break;
897 }
898 // anything else
899 // Reconsume the current input token. Consume a component value and append it to the
900 // value of the block.
901 _ => {
902 let component_value = self.parse()?;
903
904 simple_block.value.push(component_value);
905 }
906 }
907 }
908
909 simple_block.span = span!(self, span.lo);
910
911 Ok(simple_block)
912 }
913}
914
915impl<I> Parse<Function> for Parser<I>
916where
917 I: ParserInput,
918{
919 fn parse(&mut self) -> PResult<Function> {
920 // Note: This algorithm assumes that the current input token has already been
921 // checked to be a <function-token>.
922 //
923 // To consume a function:
924
925 // Create a function with its name equal to the value of the current input token
926 // and with its value initially set to an empty list.
927 let span = self.input.cur_span();
928 let function_name = match bump!(self) {
929 Token::Function { value, raw } => (value, raw),
930 _ => {
931 unreachable!()
932 }
933 };
934 let is_dashed_ident = function_name.0.starts_with("--");
935 let name = if is_dashed_ident {
936 FunctionName::DashedIdent(DashedIdent {
937 span: Span::new(span.lo, span.hi - BytePos(1)),
938 value: self.input.atom(&function_name.0[2..]),
939 raw: Some(function_name.1),
940 })
941 } else {
942 FunctionName::Ident(Ident {
943 span: Span::new(span.lo, span.hi - BytePos(1)),
944 value: function_name.0,
945 raw: Some(function_name.1),
946 })
947 };
948 let mut function = Function {
949 span: Default::default(),
950 name,
951 value: Vec::new(),
952 };
953
954 // Repeatedly consume the next input token and process it as follows:
955 loop {
956 // <EOF-token>
957 // This is a parse error. Return the function.
958 if is!(self, EOF) {
959 self.errors.push(Error::new(
960 span!(self, span.lo),
961 ErrorKind::EofButExpected("')'"),
962 ));
963
964 break;
965 }
966
967 match cur!(self) {
968 // <)-token>
969 // Return the function.
970 tok!(")") => {
971 bump!(self);
972
973 break;
974 }
975 // anything else
976 // Reconsume the current input token. Consume a component value and append the
977 // returned value to the function’s value.
978 _ => {
979 let component_value = self.parse_as::<ComponentValue>()?;
980
981 function.value.push(component_value);
982 }
983 }
984 }
985
986 function.span = span!(self, span.lo);
987
988 // Canonicalization against a grammar
989 if !is_dashed_ident && self.ctx.need_canonicalize {
990 function = self.canonicalize_function_value(function)?;
991 }
992
993 return Ok(function);
994 }
995}
996
997impl<I> Parse<ListOfComponentValues> for Parser<I>
998where
999 I: ParserInput,
1000{
1001 fn parse(&mut self) -> PResult<ListOfComponentValues> {
1002 let span = self.input.cur_span();
1003 let mut children = Vec::new();
1004
1005 // Repeatedly consume a component value from input until an <EOF-token> is
1006 // returned, appending the returned values (except the final <EOF-token>) into a
1007 // list. Return the list.
1008 loop {
1009 if is!(self, EOF) {
1010 break;
1011 }
1012
1013 let components_value = self.parse_as::<ComponentValue>()?;
1014
1015 children.push(components_value);
1016 }
1017
1018 Ok(ListOfComponentValues {
1019 span: span!(self, span.lo),
1020 children,
1021 })
1022 }
1023}