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 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 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 RBracket,
195
196 RParen,
198
199 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}