Skip to main content

oxc_css_parser/parser/
builder.rs

1use super::{Parser, ParserCursor};
2use crate::{ParserOptions, Syntax, tokenizer::Tokenizer};
3use oxc_allocator::Allocator;
4
5/// Parser builder is for building a parser while allowing us
6/// to control advanced behaviors.
7///
8/// Unlike [`Parser`], syntax isn't required when creating a parser builder,
9/// and the default syntax will be CSS. If you need to parse with another syntax,
10/// use the [`syntax`](ParserBuilder::syntax) to modify it.
11pub struct ParserBuilder<'a> {
12    allocator: &'a Allocator,
13    source: &'a str,
14    syntax: Syntax,
15    options: Option<ParserOptions>,
16    collect_comments: bool,
17}
18
19impl<'a> ParserBuilder<'a> {
20    /// Create a parser builder from given source code.
21    pub fn new(allocator: &'a Allocator, source: &'a str) -> Self {
22        let source = source.strip_prefix('\u{feff}').unwrap_or(source);
23        ParserBuilder {
24            allocator,
25            source,
26            options: None,
27            syntax: Syntax::default(),
28            collect_comments: false,
29        }
30    }
31
32    /// Specify the syntax for parsing.
33    pub fn syntax(mut self, syntax: Syntax) -> Self {
34        self.syntax = syntax;
35        self
36    }
37
38    /// Customize parser options.
39    pub fn options(mut self, options: ParserOptions) -> Self {
40        self.options = Some(options);
41        self
42    }
43
44    /// Collect comments.
45    pub fn comments(mut self) -> Self {
46        self.collect_comments = true;
47        self
48    }
49
50    /// Disable collecting comments.
51    ///
52    /// Collecting comments is disabled by default,
53    /// so you don't need to use this if you never call the [`comments`](ParserBuilder::comments) method.
54    pub fn ignore_comments(mut self) -> Self {
55        self.collect_comments = false;
56        self
57    }
58
59    /// Build a parser.
60    pub fn build(self) -> Parser<'a> {
61        let options = self.options.unwrap_or_default();
62        // Backtick is not valid CSS/SCSS/Sass; the placeholder lexer path only
63        // makes sense for SCSS (in Less, backtick is the inline-JS delimiter).
64        debug_assert!(
65            options.template_placeholder.is_none() || self.syntax == Syntax::Scss,
66            "template_placeholder requires Syntax::Scss (backtick is Less's inline-JS delimiter)",
67        );
68        Parser {
69            allocator: self.allocator,
70            source: self.source,
71            syntax: self.syntax,
72            options,
73            cursor: ParserCursor::new(Tokenizer::new(
74                self.allocator,
75                self.source,
76                self.syntax,
77                options.template_placeholder,
78                self.collect_comments,
79            )),
80            state: Default::default(),
81            recoverable_errors: vec![],
82            sass_pending_indents: 0,
83        }
84    }
85}