swc_ecma_parser/lexer/
capturing.rs

1use std::mem;
2
3use swc_ecma_lexer::common::syntax::SyntaxFlags;
4
5use crate::{input::Tokens, lexer::token::TokenAndSpan};
6
7#[derive(Debug)]
8pub struct Capturing<I> {
9    inner: I,
10    captured: Vec<TokenAndSpan>,
11}
12
13pub struct CapturingCheckpoint<I: swc_ecma_lexer::common::input::Tokens<TokenAndSpan>> {
14    pos: usize,
15    inner: I::Checkpoint,
16}
17
18impl<I: Clone> Clone for Capturing<I> {
19    fn clone(&self) -> Self {
20        Capturing {
21            inner: self.inner.clone(),
22            captured: self.captured.clone(),
23        }
24    }
25}
26
27impl<I> Capturing<I> {
28    pub fn new(input: I) -> Self {
29        Capturing {
30            inner: input,
31            captured: Default::default(),
32        }
33    }
34
35    pub fn tokens(&self) -> &[TokenAndSpan] {
36        &self.captured
37    }
38
39    /// Take captured tokens
40    pub fn take(&mut self) -> Vec<TokenAndSpan> {
41        mem::take(&mut self.captured)
42    }
43}
44
45impl<I: Iterator<Item = TokenAndSpan>> Iterator for Capturing<I> {
46    type Item = TokenAndSpan;
47
48    fn next(&mut self) -> Option<Self::Item> {
49        let next = self.inner.next();
50
51        match next {
52            Some(ts) => {
53                let v = &mut self.captured;
54
55                // remove tokens that could change due to backtracing
56                while let Some(last) = v.last() {
57                    if last.span.lo >= ts.span.lo {
58                        v.pop();
59                    } else {
60                        break;
61                    }
62                }
63
64                v.push(ts);
65
66                Some(ts)
67            }
68            None => None,
69        }
70    }
71}
72
73impl<I: swc_ecma_lexer::common::input::Tokens<TokenAndSpan>>
74    swc_ecma_lexer::common::input::Tokens<TokenAndSpan> for Capturing<I>
75{
76    type Checkpoint = CapturingCheckpoint<I>;
77
78    fn checkpoint_save(&self) -> Self::Checkpoint {
79        Self::Checkpoint {
80            pos: self.captured.len(),
81            inner: self.inner.checkpoint_save(),
82        }
83    }
84
85    fn checkpoint_load(&mut self, checkpoint: Self::Checkpoint) {
86        self.captured.truncate(checkpoint.pos);
87        self.inner.checkpoint_load(checkpoint.inner);
88    }
89
90    fn set_ctx(&mut self, ctx: swc_ecma_lexer::common::context::Context) {
91        self.inner.set_ctx(ctx);
92    }
93
94    fn ctx(&self) -> swc_ecma_lexer::common::context::Context {
95        self.inner.ctx()
96    }
97
98    fn ctx_mut(&mut self) -> &mut swc_ecma_lexer::common::context::Context {
99        self.inner.ctx_mut()
100    }
101
102    fn syntax(&self) -> SyntaxFlags {
103        self.inner.syntax()
104    }
105
106    fn target(&self) -> swc_ecma_ast::EsVersion {
107        self.inner.target()
108    }
109
110    fn set_expr_allowed(&mut self, allow: bool) {
111        self.inner.set_expr_allowed(allow);
112    }
113
114    fn set_next_regexp(&mut self, start: Option<swc_common::BytePos>) {
115        self.inner.set_next_regexp(start);
116    }
117
118    fn token_context(&self) -> &swc_ecma_lexer::lexer::TokenContexts {
119        self.inner.token_context()
120    }
121
122    fn token_context_mut(&mut self) -> &mut swc_ecma_lexer::lexer::TokenContexts {
123        self.inner.token_context_mut()
124    }
125
126    fn set_token_context(&mut self, c: swc_ecma_lexer::lexer::TokenContexts) {
127        self.inner.set_token_context(c);
128    }
129
130    fn add_error(&mut self, error: swc_ecma_lexer::error::Error) {
131        self.inner.add_error(error);
132    }
133
134    fn add_module_mode_error(&mut self, error: swc_ecma_lexer::error::Error) {
135        self.inner.add_module_mode_error(error);
136    }
137
138    fn end_pos(&self) -> swc_common::BytePos {
139        self.inner.end_pos()
140    }
141
142    fn take_errors(&mut self) -> Vec<swc_ecma_lexer::error::Error> {
143        self.inner.take_errors()
144    }
145
146    fn take_script_module_errors(&mut self) -> Vec<swc_ecma_lexer::error::Error> {
147        self.inner.take_script_module_errors()
148    }
149
150    fn update_token_flags(&mut self, f: impl FnOnce(&mut swc_ecma_lexer::lexer::TokenFlags)) {
151        self.inner.update_token_flags(f);
152    }
153
154    fn token_flags(&self) -> swc_ecma_lexer::lexer::TokenFlags {
155        self.inner.token_flags()
156    }
157}
158
159impl<I: Tokens> Tokens for Capturing<I> {
160    fn clone_token_value(&self) -> Option<super::TokenValue> {
161        self.inner.clone_token_value()
162    }
163
164    fn take_token_value(&mut self) -> Option<super::TokenValue> {
165        self.inner.take_token_value()
166    }
167
168    fn get_token_value(&self) -> Option<&super::TokenValue> {
169        self.inner.get_token_value()
170    }
171
172    fn set_token_value(&mut self, token_value: Option<super::TokenValue>) {
173        self.inner.set_token_value(token_value);
174    }
175
176    fn scan_jsx_token(&mut self, allow_multiline_jsx_text: bool) -> TokenAndSpan {
177        self.inner.scan_jsx_token(allow_multiline_jsx_text)
178    }
179
180    fn scan_jsx_open_el_terminal_token(&mut self) -> TokenAndSpan {
181        self.inner.scan_jsx_open_el_terminal_token()
182    }
183
184    fn rescan_jsx_open_el_terminal_token(&mut self, reset: swc_common::BytePos) -> TokenAndSpan {
185        self.inner.rescan_jsx_open_el_terminal_token(reset)
186    }
187
188    fn rescan_jsx_token(
189        &mut self,
190        allow_multiline_jsx_text: bool,
191        reset: swc_common::BytePos,
192    ) -> TokenAndSpan {
193        self.inner.rescan_jsx_token(allow_multiline_jsx_text, reset)
194    }
195
196    fn scan_jsx_identifier(&mut self, start: swc_common::BytePos) -> TokenAndSpan {
197        self.inner.scan_jsx_identifier(start)
198    }
199
200    fn scan_jsx_attribute_value(&mut self) -> TokenAndSpan {
201        self.inner.scan_jsx_attribute_value()
202    }
203
204    fn rescan_template_token(
205        &mut self,
206        start: swc_common::BytePos,
207        start_with_back_tick: bool,
208    ) -> TokenAndSpan {
209        self.inner
210            .rescan_template_token(start, start_with_back_tick)
211    }
212}