swc_css_parser/parser/
input.rs

1use std::{borrow::Cow, cell::RefCell, fmt::Debug, mem::take, rc::Rc};
2
3use swc_atoms::{Atom, AtomStore};
4use swc_common::{BytePos, Span, Spanned};
5use swc_css_ast::{ComponentValue, FunctionName, ListOfComponentValues, Token, TokenAndSpan};
6
7use super::PResult;
8use crate::error::{Error, ErrorKind};
9
10pub trait ParserInput: Clone + Iterator<Item = TokenAndSpan> {
11    type State: Debug;
12
13    fn start_pos(&mut self) -> BytePos;
14
15    fn state(&mut self) -> Self::State;
16
17    fn reset(&mut self, state: &Self::State);
18
19    fn take_errors(&mut self) -> Vec<Error>;
20
21    /// Returns `last_pos`
22    fn skip_ws(&mut self) -> Option<BytePos>;
23
24    fn atom(&self, s: Cow<'_, str>) -> Atom;
25}
26
27#[derive(Debug, Clone)]
28pub(super) struct Buffer<I>
29where
30    I: ParserInput,
31{
32    cur: Option<TokenAndSpan>,
33    peeked: Option<TokenAndSpan>,
34    input: I,
35    last_pos: BytePos,
36}
37
38impl<I> Buffer<I>
39where
40    I: ParserInput,
41{
42    pub fn new(mut input: I) -> Self {
43        let last_pos = input.start_pos();
44
45        Buffer {
46            cur: None,
47            peeked: None,
48            input,
49            last_pos,
50        }
51    }
52
53    pub fn atom<'a>(&self, s: impl Into<Cow<'a, str>>) -> Atom {
54        self.input.atom(s.into())
55    }
56
57    pub fn last_pos(&mut self) -> BytePos {
58        self.cur();
59        self.last_pos
60    }
61
62    pub fn cur_span(&mut self) -> Span {
63        if self.cur.is_none() {
64            self.bump_inner();
65        }
66
67        self.cur
68            .as_ref()
69            .map(|cur| cur.span)
70            .unwrap_or_else(|| Span::new(self.last_pos, self.last_pos))
71    }
72
73    pub fn cur(&mut self) -> Option<&Token> {
74        if self.cur.is_none() {
75            self.bump_inner();
76        }
77
78        self.cur.as_ref().map(|v| &v.token)
79    }
80
81    pub(super) fn peek(&mut self) -> Option<&Token> {
82        self.cur();
83
84        if self.peeked.is_none() {
85            self.peeked = self.input.next();
86        }
87
88        self.peeked.as_ref().map(|v| &v.token)
89    }
90
91    #[track_caller]
92    pub fn bump(&mut self) -> Option<TokenAndSpan> {
93        debug_assert!(
94            self.cur.is_some(),
95            "bump() is called without checking current token"
96        );
97
98        if let Some(cur) = &self.cur {
99            self.last_pos = cur.span.hi;
100        }
101
102        let token = self.cur.take();
103
104        self.bump_inner();
105
106        token
107    }
108
109    fn bump_inner(&mut self) {
110        if let Some(cur) = &self.cur {
111            self.last_pos = cur.span.hi;
112        }
113
114        self.cur = None;
115
116        if let Some(next) = self.peeked.take() {
117            self.cur = Some(next);
118        }
119
120        if self.cur.is_none() {
121            let token_and_span = self.input.next();
122
123            self.cur = token_and_span;
124        }
125    }
126
127    pub fn take_errors(&mut self) -> Vec<Error> {
128        take(&mut self.input.take_errors())
129    }
130
131    pub(super) fn skip_ws(&mut self) {
132        if self.cur.is_none() {
133            self.bump_inner();
134        }
135
136        if let Some(TokenAndSpan {
137            token: tok!(" "),
138            span,
139        }) = &self.cur
140        {
141            self.last_pos = span.hi;
142            self.cur = None;
143
144            {
145                // Drop peeked
146                if let Some(next) = self.peeked.take() {
147                    self.cur = Some(next);
148                }
149
150                match &self.cur {
151                    Some(TokenAndSpan {
152                        token: tok!(" "),
153                        span,
154                    }) => {
155                        self.last_pos = span.hi;
156                        self.cur = None;
157                    }
158                    Some(..) => return,
159                    None => {}
160                }
161            }
162
163            if let Some(last_pos) = self.input.skip_ws() {
164                self.last_pos = last_pos;
165            }
166
167            self.cur = self.input.next();
168        }
169    }
170
171    pub(super) fn state(&mut self) -> WrappedState<I::State> {
172        WrappedState {
173            cur: self.cur.clone(),
174            inner: self.input.state(),
175        }
176    }
177
178    pub(super) fn reset(&mut self, state: &WrappedState<I::State>) {
179        self.cur.clone_from(&state.cur);
180        self.input.reset(&state.inner);
181    }
182}
183
184#[derive(Debug, Clone)]
185pub(super) struct WrappedState<S> {
186    cur: Option<TokenAndSpan>,
187    inner: S,
188}
189
190#[derive(Debug, Clone)]
191#[allow(clippy::enum_variant_names)]
192enum BalanceToken {
193    /// `]`
194    RBracket,
195
196    /// `)`
197    RParen,
198
199    /// `}`
200    RBrace,
201}
202
203#[derive(Debug)]
204pub struct State {
205    idx: Vec<usize>,
206    balance_stack: Option<Vec<BalanceToken>>,
207}
208
209#[derive(Debug)]
210pub struct Tokens {
211    pub span: Span,
212    pub tokens: Vec<TokenAndSpan>,
213}
214
215#[derive(Clone)]
216pub struct Input<'a> {
217    input: InputType<'a>,
218    idx: Vec<usize>,
219    balance_stack: Option<Vec<BalanceToken>>,
220    atoms: Rc<RefCell<AtomStore>>,
221}
222
223#[derive(Debug, Clone)]
224pub enum InputType<'a> {
225    Tokens(&'a Tokens),
226    ListOfComponentValues(&'a ListOfComponentValues),
227}
228
229type SpanLike = (BytePos, BytePos);
230
231#[derive(Debug)]
232enum TokenOrBlock<'a> {
233    Token(&'a TokenAndSpan),
234    Function(Box<(Span, FunctionName)>),
235    LBracket(SpanLike),
236    LParen(SpanLike),
237    LBrace(SpanLike),
238    RParen(SpanLike),
239    RBracket(SpanLike),
240    RBrace(SpanLike),
241}
242
243impl<'a> Input<'a> {
244    pub fn new(input: InputType<'a>) -> Self {
245        let idx = match input {
246            InputType::Tokens(_) => vec![0],
247            InputType::ListOfComponentValues(_) => {
248                let mut idx = Vec::with_capacity(16);
249
250                idx.push(0);
251
252                idx
253            }
254        };
255        let balance_stack = match input {
256            InputType::Tokens(_) => None,
257            InputType::ListOfComponentValues(_) => Some(Vec::with_capacity(16)),
258        };
259
260        Input {
261            input,
262            idx,
263            balance_stack,
264            atoms: Default::default(),
265        }
266    }
267
268    fn get_component_value(
269        &mut self,
270        list: &'a [ComponentValue],
271        deep: usize,
272    ) -> Option<TokenOrBlock<'a>> {
273        let index = match self.idx.get(deep) {
274            Some(index) => index,
275            _ => return None,
276        };
277
278        match list.get(*index) {
279            Some(ComponentValue::PreservedToken(token_and_span)) => {
280                Some(TokenOrBlock::Token(token_and_span))
281            }
282            Some(ComponentValue::Function(function)) => {
283                if self.idx.len() - 1 == deep {
284                    return Some(TokenOrBlock::Function(Box::new((
285                        Span::new(function.span_lo(), function.name.span_hi() + BytePos(1)),
286                        function.name.clone(),
287                    ))));
288                }
289
290                let res = self.get_component_value(&function.value, deep + 1);
291
292                if res.is_none() {
293                    return Some(TokenOrBlock::RParen((
294                        function.span_hi() - BytePos(1),
295                        function.span_hi(),
296                    )));
297                }
298
299                res
300            }
301            Some(ComponentValue::SimpleBlock(simple_block)) => {
302                if self.idx.len() - 1 == deep {
303                    let close = match simple_block.name.token {
304                        Token::LBracket => TokenOrBlock::LBracket((
305                            simple_block.name.span.lo,
306                            simple_block.name.span.hi,
307                        )),
308                        Token::LParen => TokenOrBlock::LParen((
309                            simple_block.name.span.lo,
310                            simple_block.name.span.hi,
311                        )),
312                        Token::LBrace => TokenOrBlock::LBrace((
313                            simple_block.name.span.lo,
314                            simple_block.name.span.hi,
315                        )),
316                        _ => {
317                            unreachable!();
318                        }
319                    };
320
321                    return Some(close);
322                }
323
324                let res = self.get_component_value(&simple_block.value, deep + 1);
325
326                if res.is_none() {
327                    let span =
328                        Span::new(simple_block.span_hi() - BytePos(1), simple_block.span_hi());
329                    let close = match simple_block.name.token {
330                        Token::LBracket => TokenOrBlock::RBracket((span.lo, span.hi)),
331                        Token::LParen => TokenOrBlock::RParen((span.lo, span.hi)),
332                        Token::LBrace => TokenOrBlock::RBrace((span.lo, span.hi)),
333                        _ => {
334                            unreachable!();
335                        }
336                    };
337
338                    return Some(close);
339                }
340
341                res
342            }
343            None => return None,
344            _ => {
345                unreachable!("Not allowed in the list of component values")
346            }
347        }
348    }
349
350    fn cur(&mut self) -> PResult<Cow<TokenAndSpan>> {
351        match self.input {
352            InputType::Tokens(input) => {
353                let idx = match self.idx.last() {
354                    Some(idx) => idx,
355                    _ => {
356                        let bp = input.span.hi;
357                        let span = Span::new(bp, bp);
358
359                        return Err(Error::new(span, ErrorKind::Eof));
360                    }
361                };
362
363                let token_and_span = match input.tokens.get(*idx) {
364                    Some(token_and_span) => token_and_span,
365                    None => {
366                        let bp = input.span.hi;
367                        let span = Span::new(bp, bp);
368
369                        return Err(Error::new(span, ErrorKind::Eof));
370                    }
371                };
372
373                Ok(Cow::Borrowed(token_and_span))
374            }
375            InputType::ListOfComponentValues(input) => {
376                let token_and_span = match self.get_component_value(&input.children, 0) {
377                    Some(token_or_block) => match token_or_block {
378                        TokenOrBlock::Token(token_and_span) => {
379                            return Ok(Cow::Borrowed(token_and_span))
380                        }
381                        TokenOrBlock::Function(function) => {
382                            let name = match function.1 {
383                                FunctionName::Ident(name) => match name.raw {
384                                    Some(raw) => (name.value, raw),
385                                    _ => (name.value.clone(), name.value),
386                                },
387                                FunctionName::DashedIdent(name) => match name.raw {
388                                    Some(raw) => (
389                                        self.atoms.borrow_mut().atom(format!("--{}", name.value)),
390                                        raw,
391                                    ),
392                                    _ => (name.value.clone(), name.value),
393                                },
394                            };
395
396                            TokenAndSpan {
397                                span: function.0,
398                                token: Token::Function {
399                                    value: name.0,
400                                    raw: name.1,
401                                },
402                            }
403                        }
404                        TokenOrBlock::LBracket(span) => TokenAndSpan {
405                            span: Span::new(span.0, span.1),
406                            token: Token::LBracket,
407                        },
408                        TokenOrBlock::LBrace(span) => TokenAndSpan {
409                            span: Span::new(span.0, span.1),
410                            token: Token::LBrace,
411                        },
412                        TokenOrBlock::LParen(span) => TokenAndSpan {
413                            span: Span::new(span.0, span.1),
414                            token: Token::LParen,
415                        },
416                        TokenOrBlock::RBracket(span) => TokenAndSpan {
417                            span: Span::new(span.0, span.1),
418                            token: Token::RBracket,
419                        },
420                        TokenOrBlock::RBrace(span) => TokenAndSpan {
421                            span: Span::new(span.0, span.1),
422                            token: Token::RBrace,
423                        },
424                        TokenOrBlock::RParen(span) => TokenAndSpan {
425                            span: Span::new(span.0, span.1),
426                            token: Token::RParen,
427                        },
428                    },
429                    None => {
430                        let bp = input.span.hi;
431                        let span = Span::new(bp, bp);
432
433                        return Err(Error::new(span, ErrorKind::Eof));
434                    }
435                };
436
437                Ok(Cow::Owned(token_and_span))
438            }
439        }
440    }
441}
442
443impl ParserInput for Input<'_> {
444    type State = State;
445
446    fn start_pos(&mut self) -> BytePos {
447        match self.input {
448            InputType::Tokens(input) => input.span.lo,
449            InputType::ListOfComponentValues(input) => input.span.lo,
450        }
451    }
452
453    fn state(&mut self) -> Self::State {
454        State {
455            idx: self.idx.clone(),
456            balance_stack: self.balance_stack.clone(),
457        }
458    }
459
460    fn reset(&mut self, state: &Self::State) {
461        self.idx.clone_from(&state.idx);
462        self.balance_stack.clone_from(&state.balance_stack);
463    }
464
465    fn take_errors(&mut self) -> Vec<Error> {
466        Vec::new()
467    }
468
469    fn skip_ws(&mut self) -> Option<BytePos> {
470        let mut last_pos = None;
471
472        while let Ok(TokenAndSpan {
473            token: tok!(" "),
474            span,
475        }) = self.cur().as_deref()
476        {
477            last_pos = Some(span.hi);
478
479            if let Some(idx) = self.idx.last_mut() {
480                *idx += 1;
481            }
482        }
483
484        last_pos
485    }
486
487    fn atom(&self, s: Cow<str>) -> Atom {
488        self.atoms.borrow_mut().atom(s)
489    }
490}
491
492impl Iterator for Input<'_> {
493    type Item = TokenAndSpan;
494
495    fn next(&mut self) -> Option<Self::Item> {
496        let token_and_span = match self.cur() {
497            Ok(token_and_span) => token_and_span.into_owned(),
498            _ => return None,
499        };
500
501        match self.input {
502            InputType::Tokens(_) => {
503                if let Some(idx) = self.idx.last_mut() {
504                    *idx += 1;
505                }
506            }
507            InputType::ListOfComponentValues(_) => match &token_and_span.token {
508                Token::Function { .. } | Token::LParen | Token::LBracket | Token::LBrace => {
509                    self.idx.push(0);
510
511                    let balance = match &token_and_span.token {
512                        Token::Function { .. } | Token::LParen => BalanceToken::RParen,
513                        Token::LBracket => BalanceToken::RBracket,
514                        Token::LBrace => BalanceToken::RBrace,
515                        _ => {
516                            unreachable!();
517                        }
518                    };
519
520                    self.balance_stack.as_mut().unwrap().push(balance);
521                }
522                token => {
523                    match token {
524                        Token::RBrace | Token::RBracket | Token::RParen => {
525                            if let Some(last) = self.balance_stack.as_ref().unwrap().last() {
526                                match (token, last) {
527                                    (Token::RBrace, BalanceToken::RBrace)
528                                    | (Token::RParen, BalanceToken::RParen)
529                                    | (Token::RBracket, BalanceToken::RBracket) => {
530                                        self.balance_stack.as_mut().unwrap().pop();
531                                        self.idx.pop();
532                                    }
533                                    _ => {}
534                                }
535                            }
536                        }
537                        _ => {}
538                    }
539
540                    let index = match self.idx.last_mut() {
541                        Some(index) => index,
542                        _ => return None,
543                    };
544
545                    *index += 1;
546                }
547            },
548        }
549
550        Some(token_and_span)
551    }
552}