swc_html_parser/parser/
input.rs1use std::{fmt::Debug, mem::take};
2
3use swc_atoms::Atom;
4use swc_common::{BytePos, Span};
5use swc_html_ast::{Token, TokenAndSpan};
6
7use super::PResult;
8use crate::{error::Error, lexer::State};
9
10pub trait ParserInput: Iterator<Item = TokenAndSpan> {
11 fn start_pos(&mut self) -> BytePos;
12
13 fn last_pos(&mut self) -> BytePos;
14
15 fn take_errors(&mut self) -> Vec<Error>;
16
17 fn set_last_start_tag_name(&mut self, tag_name: &Atom);
18
19 fn set_input_state(&mut self, state: State);
20
21 fn set_adjusted_current_node_to_html_namespace(&mut self, value: bool);
22}
23
24#[derive(Debug)]
25pub(super) struct Buffer<I>
26where
27 I: ParserInput,
28{
29 cur: Option<TokenAndSpan>,
30 input: I,
31}
32
33impl<I> Buffer<I>
34where
35 I: ParserInput,
36{
37 pub fn new(input: I) -> Self {
38 Buffer { cur: None, input }
39 }
40
41 pub fn start_pos(&mut self) -> PResult<BytePos> {
43 Ok(self.input.start_pos())
44 }
45
46 pub fn last_pos(&mut self) -> PResult<BytePos> {
48 Ok(self.input.last_pos())
49 }
50
51 pub fn cur_span(&mut self) -> PResult<Span> {
52 if self.cur.is_none() {
53 self.bump_inner()?;
54 }
55
56 Ok(self.cur.as_ref().map(|cur| cur.span).unwrap_or_default())
57 }
58
59 pub fn cur(&mut self) -> PResult<Option<&Token>> {
60 if self.cur.is_none() {
61 self.bump_inner()?;
62 }
63
64 Ok(self.cur.as_ref().map(|v| &v.token))
65 }
66
67 #[track_caller]
68 pub fn bump(&mut self) -> PResult<Option<TokenAndSpan>> {
69 debug_assert!(
70 self.cur.is_some(),
71 "bump() is called without checking current token"
72 );
73
74 let token = self.cur.take();
75
76 Ok(token)
77 }
78
79 fn bump_inner(&mut self) -> PResult<()> {
80 self.cur = None;
81
82 if self.cur.is_none() {
83 let result = self.input.next();
84
85 if let Some(result) = result {
86 self.cur = Some(result);
87 } else {
88 return Ok(());
89 }
90 }
91
92 Ok(())
93 }
94
95 pub fn take_errors(&mut self) -> Vec<Error> {
96 take(&mut self.input.take_errors())
97 }
98
99 pub(super) fn set_input_state(&mut self, state: State) {
100 self.input.set_input_state(state);
101 }
102
103 pub(super) fn set_adjusted_current_node_to_html_namespace(&mut self, value: bool) {
104 self.input
105 .set_adjusted_current_node_to_html_namespace(value);
106 }
107}