1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use super::Parser;
use crate::{
    tokenizer::{token::Comment, Tokenizer},
    ParserOptions, Syntax,
};

/// Parser builder is for building a parser while allowing us
/// to control advanced behaviors.
///
/// Unlike [`Parser`], syntax isn't required when creating a parser builder,
/// and the default syntax will be CSS. If you need to parse with another syntax,
/// use the [`syntax`](ParserBuilder::syntax) to modify it.
pub struct ParserBuilder<'cmt, 's: 'cmt> {
    source: &'s str,
    syntax: Syntax,
    options: Option<ParserOptions>,
    comments: Option<&'cmt mut Vec<Comment<'s>>>,
}

impl<'cmt, 's: 'cmt> ParserBuilder<'cmt, 's> {
    /// Create a parser builder from given source code.
    pub fn new(source: &'s str) -> Self {
        ParserBuilder {
            source,
            options: None,
            syntax: Syntax::default(),
            comments: None,
        }
    }

    /// Specify the syntax for parsing.
    pub fn syntax(mut self, syntax: Syntax) -> Self {
        self.syntax = syntax;
        self
    }

    /// Customize parser options.
    pub fn options(mut self, options: ParserOptions) -> Self {
        self.options = Some(options);
        self
    }

    /// Collect comments and put them into the given collection.
    pub fn comments(mut self, comments: &'cmt mut Vec<Comment<'s>>) -> Self {
        self.comments = Some(comments);
        self
    }

    /// Disable collecting comments.
    ///
    /// Collecting comments is disabled by default,
    /// so you don't need to use this if you never call the [`comments`](ParserBuilder::comments) method.
    pub fn ignore_comments(mut self) -> Self {
        self.comments = None;
        self
    }

    /// Build a parser.
    pub fn build(self) -> Parser<'cmt, 's> {
        let source = self.source.strip_prefix('\u{feff}').unwrap_or(self.source);
        Parser {
            source,
            syntax: self.syntax,
            options: self.options.unwrap_or_default(),
            tokenizer: Tokenizer::new(self.source, self.syntax, self.comments),
            state: Default::default(),
            recoverable_errors: vec![],
            cached_token: None,
        }
    }
}