From 35b530cd0d92bb6be8025c5c037f045c0f046c7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4=20=28Donny=29?= Date: Sat, 6 Jul 2024 22:49:04 +0900 Subject: [PATCH] Revert "refactor(es/parser): Improve readability (#9141)" This reverts commit 9d9fe6625bd4a7e05e9f29971e8f1a5c5e2470a8. --- .../src/parser/class_and_fn.rs | 6 +- crates/swc_ecma_parser/src/parser/expr.rs | 48 ++++---------- crates/swc_ecma_parser/src/parser/expr/ops.rs | 6 +- crates/swc_ecma_parser/src/parser/macros.rs | 64 +++++++++---------- crates/swc_ecma_parser/src/parser/object.rs | 7 +- crates/swc_ecma_parser/src/parser/stmt.rs | 16 ++--- .../src/parser/stmt/module_item.rs | 4 +- .../swc_ecma_parser/src/parser/typescript.rs | 36 +++++------ 8 files changed, 77 insertions(+), 110 deletions(-) diff --git a/crates/swc_ecma_parser/src/parser/class_and_fn.rs b/crates/swc_ecma_parser/src/parser/class_and_fn.rs index 95d754e0d9c9..83573ecbcfc7 100644 --- a/crates/swc_ecma_parser/src/parser/class_and_fn.rs +++ b/crates/swc_ecma_parser/src/parser/class_and_fn.rs @@ -745,7 +745,7 @@ impl Parser { } trace_cur!(self, parse_class_member_with_is_static__normal_class_member); - let mut key = if readonly.is_some() && is!(self, '!' | ':') { + let mut key = if readonly.is_some() && is_one_of!(self, '!', ':') { Key::Public(PropName::Ident(Ident::new( "readonly".into(), readonly.unwrap(), @@ -1155,8 +1155,8 @@ impl Parser { } fn is_class_property(&mut self, asi: bool) -> bool { - (self.input.syntax().typescript() && is!(self, '!' | ':')) - || is!(self, '=' | '}') + (self.input.syntax().typescript() && is_one_of!(self, '!', ':')) + || is_one_of!(self, '=', '}') || if asi { is!(self, ';') } else { diff --git a/crates/swc_ecma_parser/src/parser/expr.rs b/crates/swc_ecma_parser/src/parser/expr.rs index 05fb21238ca1..c1eb615e8982 100644 --- a/crates/swc_ecma_parser/src/parser/expr.rs +++ b/crates/swc_ecma_parser/src/parser/expr.rs @@ -82,7 +82,7 @@ impl Parser { let start = self.input.cur_span(); if self.input.syntax().typescript() - && (is!(self, '<' | JSXTagStart)) + && (is_one_of!(self, '<', JSXTagStart)) && (peeked_is!(self, IdentName) || peeked_is!(self, JSXName)) { let ctx = Context { @@ -395,7 +395,7 @@ impl Parser { } if is!(self, "let") - || (self.input.syntax().typescript() && is!(self, IdentRef | "await")) + || (self.input.syntax().typescript() && is_one_of!(self, IdentRef, "await")) || is!(self, IdentRef) { let ctx = self.ctx(); @@ -1226,7 +1226,7 @@ impl Parser { ) .map(|expr| (Box::new(Expr::TaggedTpl(expr)), true)) .map(Some) - } else if is!(p, '=' | "as") { + } else if is_one_of!(p, '=', "as") { Ok(Some(( Box::new(Expr::TsInstantiation(TsInstantiation { span: span!(p, start), @@ -1258,7 +1258,7 @@ impl Parser { None }; - if obj.is_import() && !is!(self, '.' | '(') { + if obj.is_import() && !is_one_of!(self, '.', '(') { unexpected!(self, "`.` or `(`") } @@ -1597,7 +1597,7 @@ impl Parser { let callee = self.parse_new_expr()?; return_if_arrow!(self, callee); - let type_args = if self.input.syntax().typescript() && is!(self, '<' | "<<") { + let type_args = if self.input.syntax().typescript() && is_one_of!(self, '<', "<<") { self.try_parse_ts(|p| { let type_args = p.parse_ts_type_args()?; if is!(p, '(') { @@ -2145,44 +2145,18 @@ impl Parser { } fn is_start_of_left_hand_side_expr(&mut self) -> PResult { - Ok(is!( - self, - "this" - | "super" - | "null" - | "true" - | "false" - | Num - | BigInt - | Str - | '`' - | '(' - | '[' - | '{' - | "function" - | "class" - | "new" - | Regex - | IdentRef + Ok(is_one_of!( + self, "this", "super", "null", "true", "false", Num, BigInt, Str, '`', '(', '[', '{', + "function", "class", "new", Regex, IdentRef ) || (is!(self, "import") && (peeked_is!(self, '(') || peeked_is!(self, '<') || peeked_is!(self, '.')))) } pub(super) fn is_start_of_expr(&mut self) -> PResult { Ok(self.is_start_of_left_hand_side_expr()? - || is!( - self, - '+' | '-' - | '~' - | '!' - | "delete" - | "typeof" - | "void" - | "++" - | "--" - | '<' - | "await" - | "yield" + || is_one_of!( + self, '+', '-', '~', '!', "delete", "typeof", "void", "++", "--", '<', "await", + "yield" ) || (is!(self, '#') && peeked_is!(self, IdentName))) } diff --git a/crates/swc_ecma_parser/src/parser/expr/ops.rs b/crates/swc_ecma_parser/src/parser/expr/ops.rs index 0aa232860508..344a4fb31ec3 100644 --- a/crates/swc_ecma_parser/src/parser/expr/ops.rs +++ b/crates/swc_ecma_parser/src/parser/expr/ops.rs @@ -281,7 +281,7 @@ impl Parser { } // Parse unary expression - if is!(self, "delete" | "void" | "typeof" | '+' | '-' | '~' | '!') { + if is_one_of!(self, "delete", "void", "typeof", '+', '-', '~', '!') { let op = match bump!(self) { tok!("delete") => op!("delete"), tok!("void") => op!("void"), @@ -341,7 +341,7 @@ impl Parser { return Ok(expr); } - if is!(self, "++" | "--") { + if is_one_of!(self, "++", "--") { self.check_assign_target(&expr, false); let op = if bump!(self) == tok!("++") { @@ -378,7 +378,7 @@ impl Parser { let span = span!(self, start); - if is!(self, ')' | ']' | ';' | ',') && !ctx.in_async { + if is_one_of!(self, ')', ']', ';', ',') && !ctx.in_async { if ctx.module { self.emit_err(span, SyntaxError::InvalidIdentInAsync); } diff --git a/crates/swc_ecma_parser/src/parser/macros.rs b/crates/swc_ecma_parser/src/parser/macros.rs index ee72def84a5a..78b52a93058d 100644 --- a/crates/swc_ecma_parser/src/parser/macros.rs +++ b/crates/swc_ecma_parser/src/parser/macros.rs @@ -19,7 +19,7 @@ macro_rules! is { ($p:expr, BindingIdent) => {{ let ctx = $p.ctx(); match $p.input.cur() { - Some(&crate::token::Word(ref w)) => !ctx.is_reserved(w), + Some(&Word(ref w)) => !ctx.is_reserved(w), _ => false, } }}; @@ -27,14 +27,14 @@ macro_rules! is { ($p:expr, IdentRef) => {{ let ctx = $p.ctx(); match $p.input.cur() { - Some(&crate::token::Word(ref w)) => !ctx.is_reserved(w), + Some(&Word(ref w)) => !ctx.is_reserved(w), _ => false, } }}; ($p:expr,IdentName) => {{ match $p.input.cur() { - Some(&crate::token::Word(..)) => true, + Some(&Word(..)) => true, _ => false, } }}; @@ -77,10 +77,6 @@ macro_rules! is { ($p:expr, $t:tt) => { is_exact!($p, $t) }; - - ($p:expr, $t:tt | $($rest:tt)*) => {{ - is!($p, $t) || is!($p, $($rest)*) - }}; } #[allow(unused)] @@ -88,7 +84,7 @@ macro_rules! peeked_is { ($p:expr, BindingIdent) => {{ let ctx = $p.ctx(); match peek!($p) { - Some(&crate::token::Word(ref w)) => !ctx.is_reserved(w), + Some(&Word(ref w)) => !ctx.is_reserved(w), _ => false, } }}; @@ -96,14 +92,14 @@ macro_rules! peeked_is { ($p:expr, IdentRef) => {{ let ctx = $p.ctx(); match peek!($p) { - Some(&crate::token::Word(ref w)) => !ctx.is_reserved(w), + Some(&Word(ref w)) => !ctx.is_reserved(w), _ => false, } }}; ($p:expr,IdentName) => {{ match peek!($p) { - Some(&crate::token::Word(..)) => true, + Some(&Word(..)) => true, _ => false, } }}; @@ -125,10 +121,6 @@ macro_rules! peeked_is { _ => false, } }; - - ($p:expr, $t:tt | $($rest:tt)*) => { - peeked_is!($p, $t) || peeked_is!($p, $($rest)*) - }; } /// Returns true on eof. @@ -138,6 +130,15 @@ macro_rules! eof { }; } +macro_rules! is_one_of { + ($p:expr, $($t:tt),+) => {{ + false + $( + || is!($p, $t) + )* + }}; +} + // This will panic if current != token macro_rules! assert_and_bump { ($p:expr, $t:tt) => {{ @@ -160,6 +161,9 @@ macro_rules! assert_and_bump { /// if token has data like string. macro_rules! eat { ($p:expr, ';') => {{ + if cfg!(feature = "debug") { + tracing::trace!("eat(';'): cur={:?}", cur!($p, false)); + } match $p.input.cur() { Some(&Token::Semi) => { $p.input.bump(); @@ -206,11 +210,7 @@ macro_rules! expect { const TOKEN: &Token = &token_including_semi!($t); if !eat!($p, $t) { let cur = $p.input.dump_cur(); - syntax_error!( - $p, - $p.input.cur_span(), - crate::error::SyntaxError::Expected(TOKEN, cur) - ) + syntax_error!($p, $p.input.cur_span(), SyntaxError::Expected(TOKEN, cur)) } }}; } @@ -220,11 +220,7 @@ macro_rules! expect_exact { const TOKEN: &Token = &token_including_semi!($t); if !eat_exact!($p, $t) { let cur = $p.input.dump_cur(); - syntax_error!( - $p, - $p.input.cur_span(), - crate::error::SyntaxError::Expected(TOKEN, cur) - ) + syntax_error!($p, $p.input.cur_span(), SyntaxError::Expected(TOKEN, cur)) } }}; } @@ -295,9 +291,6 @@ macro_rules! bump { $p.input.knows_cur(), "parser should not call bump() without knowing current token" ); - if cfg!(feature = "debug") { - tracing::info!("Bump: {:?}", $p.input.cur()); - } $p.input.bump() }}; } @@ -384,13 +377,16 @@ macro_rules! syntax_error { } } } - tracing::error!( - "Syntax error called from {}:{}:{}\nCurrent token = {:?}", - file!(), - line!(), - column!(), - $p.input.cur() - ); + + if cfg!(feature = "debug") { + tracing::error!( + "Syntax error called from {}:{}:{}\nCurrent token = {:?}", + file!(), + line!(), + column!(), + $p.input.cur() + ); + } return Err(err.into()); }}; } diff --git a/crates/swc_ecma_parser/src/parser/object.rs b/crates/swc_ecma_parser/src/parser/object.rs index f24a5c969708..0eea9a3aa7a4 100644 --- a/crates/swc_ecma_parser/src/parser/object.rs +++ b/crates/swc_ecma_parser/src/parser/object.rs @@ -183,10 +183,7 @@ impl ParseObject> for Parser { let key = self.parse_prop_name()?; if self.input.syntax().typescript() - && !is!( - self, - '(' | '[' | ':' | ',' | '?' | '=' | '*' | IdentName | Str | Num - ) + && !is_one_of!(self, '(', '[', ':', ',', '?', '=', '*', IdentName, Str, Num) && !(self.input.syntax().typescript() && is!(self, '<')) && !(is!(self, '}') && matches!(key, PropName::Ident(..))) { @@ -245,7 +242,7 @@ impl ParseObject> for Parser { // `ident` from parse_prop_name is parsed as 'IdentifierName' // It means we should check for invalid expressions like { for, } - if is!(self, '=' | ',' | '}') { + if is_one_of!(self, '=', ',', '}') { let is_reserved_word = { self.ctx().is_reserved_word(&ident.sym) }; if is_reserved_word { self.emit_err(ident.span, SyntaxError::ReservedWordInObjShorthandOrPat); diff --git a/crates/swc_ecma_parser/src/parser/stmt.rs b/crates/swc_ecma_parser/src/parser/stmt.rs index c5e6a6421a3b..0a8b458ad6e9 100644 --- a/crates/swc_ecma_parser/src/parser/stmt.rs +++ b/crates/swc_ecma_parser/src/parser/stmt.rs @@ -96,7 +96,7 @@ impl<'a, I: Tokens> Parser { let start = cur_pos!(self); let decorators = self.parse_decorators(true)?; - if is!(self, "import" | "export") { + if is_one_of!(self, "import", "export") { return self.handle_import_export(top_level, decorators); } @@ -640,7 +640,7 @@ impl<'a, I: Tokens> Parser { }; self.with_ctx(ctx).parse_with(|p| { - while is!(p, "case" | "default") { + while is_one_of!(p, "case", "default") { let mut cons = vec![]; let is_case = is!(p, "case"); let case_start = cur_pos!(p); @@ -657,7 +657,7 @@ impl<'a, I: Tokens> Parser { }; expect!(p, ':'); - while !eof!(p) && !is!(p, "case" | "default" | '}') { + while !eof!(p) && !is_one_of!(p, "case", "default", '}') { cons.push(p.parse_stmt_list_item(false)?); } @@ -868,7 +868,7 @@ impl<'a, I: Tokens> Parser { let should_include_in = kind != VarDeclKind::Var || !for_loop; if self.syntax().typescript() && for_loop { - let res = if is!(self, "in" | "of") { + let res = if is_one_of!(self, "in", "of") { self.ts_look_ahead(|p| { // if !eat!(p, "of") && !eat!(p, "in") { @@ -999,7 +999,7 @@ impl<'a, I: Tokens> Parser { } //FIXME: This is wrong. Should check in/of only on first loop. - let init = if !for_loop || !is!(self, "in" | "of") { + let init = if !for_loop || !is_one_of!(self, "in", "of") { if eat!(self, '=') { let expr = self.parse_assignment_expr()?; let expr = self.verify_expr(expr)?; @@ -1243,13 +1243,13 @@ impl<'a, I: Tokens> Parser { fn parse_for_head(&mut self) -> PResult { let strict = self.ctx().strict; - if is!(self, "const" | "var") + if is_one_of!(self, "const", "var") || (is!(self, "let") && peek!(self).map_or(false, |v| v.kind().follows_keyword_let(strict))) { let decl = self.parse_var_stmt(true)?; - if is!(self, "of" | "in") { + if is_one_of!(self, "of", "in") { if decl.decls.len() != 1 { for d in decl.decls.iter().skip(1) { self.emit_err(d.name.span(), SyntaxError::TooManyVarInForInHead); @@ -1342,7 +1342,7 @@ impl<'a, I: Tokens> Parser { } // for (a of b) - if is!(self, "of" | "in") { + if is_one_of!(self, "of", "in") { let is_in = is!(self, "in"); let pat = self.reparse_expr_as_pat(PatType::AssignPat, init)?; diff --git a/crates/swc_ecma_parser/src/parser/stmt/module_item.rs b/crates/swc_ecma_parser/src/parser/stmt/module_item.rs index 4743966738e5..c9af578bd205 100644 --- a/crates/swc_ecma_parser/src/parser/stmt/module_item.rs +++ b/crates/swc_ecma_parser/src/parser/stmt/module_item.rs @@ -85,7 +85,7 @@ impl Parser { let mut local = self.parse_imported_default_binding()?; if self.input.syntax().typescript() && local.sym == "type" { - if is!(self, '*' | '{') { + if is_one_of!(self, '*', '{') { type_only = true; break 'import_maybe_ident; } @@ -115,7 +115,7 @@ impl Parser { _ => unreachable!(), }; - if is!(self, '*' | '{') { + if is_one_of!(self, '*', '{') { phase = new_phase; break 'import_maybe_ident; } diff --git a/crates/swc_ecma_parser/src/parser/typescript.rs b/crates/swc_ecma_parser/src/parser/typescript.rs index 18b57c36d229..d7a0ed5e0ad7 100644 --- a/crates/swc_ecma_parser/src/parser/typescript.rs +++ b/crates/swc_ecma_parser/src/parser/typescript.rs @@ -19,10 +19,7 @@ impl Parser { // hasLineBreakUpNext() method... bump!(self); Ok(!self.input.had_line_break_before_cur() - && is!( - self, - '[' | '{' | '*' | "..." | '#' | IdentName | Str | Num | BigInt - )) + && is_one_of!(self, '[', '{', '*', "...", '#', IdentName, Str, Num, BigInt)) } /// Parses a modifier matching one the given modifier names. @@ -581,10 +578,13 @@ impl Parser { self.try_parse_ts(|p| { let type_args = p.parse_ts_type_args()?; - // becomes relational expression - /* these should be type arguments in function call or template, - * not instantiation expression */ - if is!(p, '<' | '>' | '=' | ">>" | ">=" | '+' | '-' | '(' | '`') { + if is_one_of!( + p, '<', // invalid syntax + '>', '=', ">>", ">=", '+', '-', // becomes relational expression + /* these should be type arguments in function call or template, + * not instantiation expression */ + '(', '`' + ) { Ok(None) } else if p.input.had_line_break_before_cur() || matches!(cur!(p, false), Ok(Token::BinOp(..))) @@ -1216,13 +1216,13 @@ impl Parser { debug_assert!(self.input.syntax().typescript()); assert_and_bump!(self, '('); - if is!(self, ')' | "...") { + if is_one_of!(self, ')', "...") { // ( ) // ( ... return Ok(true); } if self.skip_ts_parameter_start()? { - if is!(self, ':' | ',' | '?' | '=') { + if is_one_of!(self, ':', ',', '?', '=') { // ( xxx : // ( xxx , // ( xxx ? @@ -1243,7 +1243,7 @@ impl Parser { let _ = self.eat_any_ts_modifier()?; - if is!(self, IdentName | "this") { + if is_one_of!(self, IdentName, "this") { bump!(self); return Ok(true); } @@ -1320,7 +1320,7 @@ impl Parser { assert_and_bump!(self, '['); // Skip '[' // ',' is for error recovery - Ok(eat!(self, IdentRef) && is!(self, ':' | ',')) + Ok(eat!(self, IdentRef) && is_one_of!(self, ':', ',')) } /// `tsTryParseIndexSignature` @@ -1416,7 +1416,7 @@ impl Parser { let optional = eat!(self, '?'); - if is!(self, '(' | '<') { + if is_one_of!(self, '(', '<') { if readonly { syntax_error!(self, SyntaxError::ReadOnlyMethod) } @@ -1469,7 +1469,7 @@ impl Parser { Either::Right(e) => e.into(), } } - if is!(self, '(' | '<') { + if is_one_of!(self, '(', '<') { return self .parse_ts_signature_member(SignatureParsingMode::TSCallSignatureDeclaration) .map(into_type_elem); @@ -1626,7 +1626,7 @@ impl Parser { let start = cur_pos!(self); expect!(self, '{'); let mut readonly = None; - if is!(self, '+' | '-') { + if is_one_of!(self, '+', '-') { readonly = Some(if is!(self, '+') { TruePlusMinus::Plus } else { @@ -1648,7 +1648,7 @@ impl Parser { expect!(self, ']'); let mut optional = None; - if is!(self, '+' | '-') { + if is_one_of!(self, '+', '-') { optional = Some(if is!(self, '+') { TruePlusMinus::Plus } else { @@ -2443,7 +2443,7 @@ impl Parser { .map(From::from) .map(Some); } - if is!(p, "const" | "var" | "let") { + if is_one_of!(p, "const", "var", "let") { return p .parse_var_stmt(false) .map(|decl| VarDecl { @@ -2606,7 +2606,7 @@ impl Parser { return Ok(Default::default()); } - let res = if is!(self, '<' | JSXTagStart) { + let res = if is_one_of!(self, '<', JSXTagStart) { self.try_parse_ts(|p| { let type_params = p.parse_ts_type_params(false, false)?; // Don't use overloaded parseFunctionParams which would look for "<" again.