Skip to content

Commit 0fb9940

Browse files
committed
chore(es/parser): rm TokenContext::{Tpl, TplQuasi}
1 parent e5e5764 commit 0fb9940

File tree

3 files changed

+124
-153
lines changed

3 files changed

+124
-153
lines changed

crates/swc_ecma_parser/src/scanner/mod.rs

+115-112
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,121 @@ impl<'a> Lexer<'a> {
654654
Token::AssignOp(AssignOp::Assign)
655655
}))
656656
}
657+
658+
fn read_token_back_quote(&mut self) -> LexResult<Option<Token>> {
659+
let start = self.cur_pos();
660+
self.rescan_token_back_quote(start).map(|t| Some(t))
661+
}
662+
663+
fn rescan_token_back_quote(&mut self, start: BytePos) -> LexResult<Token> {
664+
let mut cooked = Ok(String::new());
665+
let mut cooked_slice_start = start;
666+
let raw_slice_start = start;
667+
668+
macro_rules! consume_cooked {
669+
() => {{
670+
if let Ok(cooked) = &mut cooked {
671+
let last_pos = self.cur_pos();
672+
cooked.push_str(unsafe {
673+
// Safety: Both of start and last_pos are valid position because we got them
674+
// from `self.input`
675+
self.input.slice(cooked_slice_start, last_pos)
676+
});
677+
}
678+
}};
679+
}
680+
681+
while let Some(c) = self.cur() {
682+
if c == '`' || (c == '$' && self.peek() == Some('{')) {
683+
if start == self.cur_pos() && self.state.last_was_tpl_element() {
684+
if c == '$' {
685+
self.bump();
686+
self.bump();
687+
return Ok(tok!("${"));
688+
} else {
689+
self.bump();
690+
return Ok(tok!('`'));
691+
}
692+
}
693+
694+
// If we don't have any escape
695+
let cooked = if cooked_slice_start == raw_slice_start {
696+
let last_pos = self.cur_pos();
697+
let s = unsafe {
698+
// Safety: Both of start and last_pos are valid position because we got them
699+
// from `self.input`
700+
self.input.slice(cooked_slice_start, last_pos)
701+
};
702+
703+
Ok(self.atoms.atom(s))
704+
} else {
705+
consume_cooked!();
706+
707+
cooked.map(|s| self.atoms.atom(s))
708+
};
709+
710+
// TODO: Handle error
711+
let end = self.input.cur_pos();
712+
let raw = unsafe {
713+
// Safety: Both of start and last_pos are valid position because we got them
714+
// from `self.input`
715+
self.input.slice(raw_slice_start, end)
716+
};
717+
return Ok(Token::Template {
718+
cooked,
719+
raw: self.atoms.atom(raw),
720+
});
721+
}
722+
723+
if c == '\\' {
724+
consume_cooked!();
725+
726+
match self.read_escaped_char(true) {
727+
Ok(Some(chars)) => {
728+
if let Ok(ref mut cooked) = cooked {
729+
for c in chars {
730+
cooked.extend(c);
731+
}
732+
}
733+
}
734+
Ok(None) => {}
735+
Err(error) => {
736+
cooked = Err(error);
737+
}
738+
}
739+
740+
cooked_slice_start = self.cur_pos();
741+
} else if c.is_line_terminator() {
742+
self.state.had_line_break = true;
743+
744+
consume_cooked!();
745+
746+
let c = if c == '\r' && self.peek() == Some('\n') {
747+
self.bump(); // '\r'
748+
'\n'
749+
} else {
750+
match c {
751+
'\n' => '\n',
752+
'\r' => '\n',
753+
'\u{2028}' => '\u{2028}',
754+
'\u{2029}' => '\u{2029}',
755+
_ => unreachable!(),
756+
}
757+
};
758+
759+
self.bump();
760+
761+
if let Ok(ref mut cooked) = cooked {
762+
cooked.push(c);
763+
}
764+
cooked_slice_start = self.cur_pos();
765+
} else {
766+
self.bump();
767+
}
768+
}
769+
770+
self.error(start, SyntaxError::UnterminatedTpl)?
771+
}
657772
}
658773

659774
impl Lexer<'_> {
@@ -1240,118 +1355,6 @@ impl Lexer<'_> {
12401355
Ok(Some(self.atoms.atom(s)))
12411356
}
12421357

1243-
fn read_tmpl_token(&mut self, start_of_tpl: BytePos) -> LexResult<Token> {
1244-
let start = self.cur_pos();
1245-
1246-
let mut cooked = Ok(String::new());
1247-
let mut cooked_slice_start = start;
1248-
let raw_slice_start = start;
1249-
1250-
macro_rules! consume_cooked {
1251-
() => {{
1252-
if let Ok(cooked) = &mut cooked {
1253-
let last_pos = self.cur_pos();
1254-
cooked.push_str(unsafe {
1255-
// Safety: Both of start and last_pos are valid position because we got them
1256-
// from `self.input`
1257-
self.input.slice(cooked_slice_start, last_pos)
1258-
});
1259-
}
1260-
}};
1261-
}
1262-
1263-
while let Some(c) = self.cur() {
1264-
if c == '`' || (c == '$' && self.peek() == Some('{')) {
1265-
if start == self.cur_pos() && self.state.last_was_tpl_element() {
1266-
if c == '$' {
1267-
self.bump();
1268-
self.bump();
1269-
return Ok(tok!("${"));
1270-
} else {
1271-
self.bump();
1272-
return Ok(tok!('`'));
1273-
}
1274-
}
1275-
1276-
// If we don't have any escape
1277-
let cooked = if cooked_slice_start == raw_slice_start {
1278-
let last_pos = self.cur_pos();
1279-
let s = unsafe {
1280-
// Safety: Both of start and last_pos are valid position because we got them
1281-
// from `self.input`
1282-
self.input.slice(cooked_slice_start, last_pos)
1283-
};
1284-
1285-
Ok(self.atoms.atom(s))
1286-
} else {
1287-
consume_cooked!();
1288-
1289-
cooked.map(|s| self.atoms.atom(s))
1290-
};
1291-
1292-
// TODO: Handle error
1293-
let end = self.input.cur_pos();
1294-
let raw = unsafe {
1295-
// Safety: Both of start and last_pos are valid position because we got them
1296-
// from `self.input`
1297-
self.input.slice(raw_slice_start, end)
1298-
};
1299-
return Ok(Token::Template {
1300-
cooked,
1301-
raw: self.atoms.atom(raw),
1302-
});
1303-
}
1304-
1305-
if c == '\\' {
1306-
consume_cooked!();
1307-
1308-
match self.read_escaped_char(true) {
1309-
Ok(Some(chars)) => {
1310-
if let Ok(ref mut cooked) = cooked {
1311-
for c in chars {
1312-
cooked.extend(c);
1313-
}
1314-
}
1315-
}
1316-
Ok(None) => {}
1317-
Err(error) => {
1318-
cooked = Err(error);
1319-
}
1320-
}
1321-
1322-
cooked_slice_start = self.cur_pos();
1323-
} else if c.is_line_terminator() {
1324-
self.state.had_line_break = true;
1325-
1326-
consume_cooked!();
1327-
1328-
let c = if c == '\r' && self.peek() == Some('\n') {
1329-
self.bump(); // '\r'
1330-
'\n'
1331-
} else {
1332-
match c {
1333-
'\n' => '\n',
1334-
'\r' => '\n',
1335-
'\u{2028}' => '\u{2028}',
1336-
'\u{2029}' => '\u{2029}',
1337-
_ => unreachable!(),
1338-
}
1339-
};
1340-
1341-
self.bump();
1342-
1343-
if let Ok(ref mut cooked) = cooked {
1344-
cooked.push(c);
1345-
}
1346-
cooked_slice_start = self.cur_pos();
1347-
} else {
1348-
self.bump();
1349-
}
1350-
}
1351-
1352-
self.error(start_of_tpl, SyntaxError::UnterminatedTpl)?
1353-
}
1354-
13551358
#[inline]
13561359
#[allow(clippy::misnamed_getters)]
13571360
pub fn had_line_break_before_last(&self) -> bool {

crates/swc_ecma_parser/src/scanner/state.rs

+6-40
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ pub(super) struct State {
3434
pub cur_line: usize,
3535
pub line_start: BytePos,
3636
pub prev_hi: BytePos,
37-
pub tpl_start: BytePos,
3837

3938
context: TokenContexts,
4039
syntax: Syntax,
@@ -261,11 +260,6 @@ impl Lexer<'_> {
261260
}
262261
}
263262

264-
if let Some(TokenContext::Tpl {}) = self.state.context.current() {
265-
let start = self.state.tpl_start;
266-
return self.read_tmpl_token(start).map(Some);
267-
}
268-
269263
self.read_token()
270264
}
271265
}
@@ -295,7 +289,7 @@ impl Iterator for Lexer<'_> {
295289
}
296290
}
297291

298-
self.state.update(start, token.kind());
292+
self.state.update(token.kind());
299293
self.state.prev_hi = self.last_pos();
300294
self.state.had_line_break_before_last = self.had_line_break_before_last();
301295
}
@@ -325,7 +319,6 @@ impl State {
325319
cur_line: 1,
326320
line_start: BytePos(0),
327321
prev_hi: start_pos,
328-
tpl_start: BytePos::DUMMY,
329322
context,
330323
syntax,
331324
token_type: None,
@@ -365,7 +358,7 @@ impl State {
365358
matches!(self.token_type, Some(TokenType::Template))
366359
}
367360

368-
fn update(&mut self, start: BytePos, next: TokenKind) {
361+
fn update(&mut self, next: TokenKind) {
369362
if cfg!(feature = "debug") {
370363
trace!(
371364
"updating state: next={:?}, had_line_break={} ",
@@ -377,17 +370,12 @@ impl State {
377370
let prev = self.token_type.take();
378371
self.token_type = Some(TokenType::from(next));
379372

380-
self.is_expr_allowed = self.is_expr_allowed_on_next(prev, start, next);
373+
self.is_expr_allowed = self.is_expr_allowed_on_next(prev, next);
381374
}
382375

383376
/// `is_expr_allowed`: previous value.
384377
/// `start`: start of newly produced token.
385-
fn is_expr_allowed_on_next(
386-
&mut self,
387-
prev: Option<TokenType>,
388-
start: BytePos,
389-
next: TokenKind,
390-
) -> bool {
378+
fn is_expr_allowed_on_next(&mut self, prev: Option<TokenType>, next: TokenKind) -> bool {
391379
let State {
392380
ref mut context,
393381
had_line_break,
@@ -423,14 +411,6 @@ impl State {
423411
return false;
424412
}
425413

426-
// ${} in template
427-
if out == TokenContext::TplQuasi {
428-
match context.current() {
429-
Some(TokenContext::Tpl { .. }) => return false,
430-
_ => return true,
431-
}
432-
}
433-
434414
// expression cannot follow expression
435415
!out.is_expr()
436416
}
@@ -502,8 +482,6 @@ impl State {
502482
let cur = context.current();
503483
if syntax.jsx() && cur == Some(TokenContext::JSXOpeningTag) {
504484
context.push(TokenContext::BraceExpr)
505-
} else if syntax.jsx() && cur == Some(TokenContext::JSXExpr) {
506-
context.push(TokenContext::TplQuasi);
507485
} else {
508486
let next_ctxt =
509487
if context.is_brace_block(prev, had_line_break, is_expr_allowed) {
@@ -525,10 +503,7 @@ impl State {
525503
false
526504
}
527505

528-
TokenKind::DollarLBrace => {
529-
context.push(TokenContext::TplQuasi);
530-
true
531-
}
506+
TokenKind::DollarLBrace => true,
532507

533508
TokenKind::LParen => {
534509
// if, for, with, while is statement
@@ -549,16 +524,7 @@ impl State {
549524
// remains unchanged.
550525
TokenKind::PlusPlus | TokenKind::MinusMinus => is_expr_allowed,
551526

552-
TokenKind::BackQuote => {
553-
// If we are in template, ` terminates template.
554-
if let Some(TokenContext::Tpl { .. }) = context.current() {
555-
context.pop();
556-
} else {
557-
self.tpl_start = start;
558-
context.push(TokenContext::Tpl);
559-
}
560-
false
561-
}
527+
TokenKind::BackQuote => false,
562528

563529
// tt.jsxTagStart.updateContext
564530
TokenKind::JSXTagStart => {

crates/swc_ecma_parser/src/scanner/table.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,9 @@ macro_rules! single_char {
346346

347347
single_char!(SEM, b';', Semi);
348348
single_char!(COM, b',', Comma);
349-
single_char!(TPL, b'`', BackQuote);
349+
350+
const TPL: ByteHandler = Some(|lexer| lexer.read_token_back_quote());
351+
350352
single_char!(TLD, b'~', Tilde);
351353
single_char!(AT_, b'@', At);
352354

0 commit comments

Comments
 (0)