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}