mirror of
https://github.com/swc-project/swc.git
synced 2024-11-23 00:32:15 +03:00
refactor(es/parser): Improve readability (#9141)
This commit is contained in:
parent
0d830ee3be
commit
9d9fe6625b
@ -745,7 +745,7 @@ impl<I: Tokens> Parser<I> {
|
||||
}
|
||||
|
||||
trace_cur!(self, parse_class_member_with_is_static__normal_class_member);
|
||||
let mut key = if readonly.is_some() && is_one_of!(self, '!', ':') {
|
||||
let mut key = if readonly.is_some() && is!(self, '!' | ':') {
|
||||
Key::Public(PropName::Ident(Ident::new(
|
||||
"readonly".into(),
|
||||
readonly.unwrap(),
|
||||
@ -1155,8 +1155,8 @@ impl<I: Tokens> Parser<I> {
|
||||
}
|
||||
|
||||
fn is_class_property(&mut self, asi: bool) -> bool {
|
||||
(self.input.syntax().typescript() && is_one_of!(self, '!', ':'))
|
||||
|| is_one_of!(self, '=', '}')
|
||||
(self.input.syntax().typescript() && is!(self, '!' | ':'))
|
||||
|| is!(self, '=' | '}')
|
||||
|| if asi {
|
||||
is!(self, ';')
|
||||
} else {
|
||||
|
@ -82,7 +82,7 @@ impl<I: Tokens> Parser<I> {
|
||||
let start = self.input.cur_span();
|
||||
|
||||
if self.input.syntax().typescript()
|
||||
&& (is_one_of!(self, '<', JSXTagStart))
|
||||
&& (is!(self, '<' | JSXTagStart))
|
||||
&& (peeked_is!(self, IdentName) || peeked_is!(self, JSXName))
|
||||
{
|
||||
let ctx = Context {
|
||||
@ -395,7 +395,7 @@ impl<I: Tokens> Parser<I> {
|
||||
}
|
||||
|
||||
if is!(self, "let")
|
||||
|| (self.input.syntax().typescript() && is_one_of!(self, IdentRef, "await"))
|
||||
|| (self.input.syntax().typescript() && is!(self, IdentRef | "await"))
|
||||
|| is!(self, IdentRef)
|
||||
{
|
||||
let ctx = self.ctx();
|
||||
@ -1226,7 +1226,7 @@ impl<I: Tokens> Parser<I> {
|
||||
)
|
||||
.map(|expr| (Box::new(Expr::TaggedTpl(expr)), true))
|
||||
.map(Some)
|
||||
} else if is_one_of!(p, '=', "as") {
|
||||
} else if is!(p, '=' | "as") {
|
||||
Ok(Some((
|
||||
Box::new(Expr::TsInstantiation(TsInstantiation {
|
||||
span: span!(p, start),
|
||||
@ -1258,7 +1258,7 @@ impl<I: Tokens> Parser<I> {
|
||||
None
|
||||
};
|
||||
|
||||
if obj.is_import() && !is_one_of!(self, '.', '(') {
|
||||
if obj.is_import() && !is!(self, '.' | '(') {
|
||||
unexpected!(self, "`.` or `(`")
|
||||
}
|
||||
|
||||
@ -1597,7 +1597,7 @@ impl<I: Tokens> Parser<I> {
|
||||
let callee = self.parse_new_expr()?;
|
||||
return_if_arrow!(self, callee);
|
||||
|
||||
let type_args = if self.input.syntax().typescript() && is_one_of!(self, '<', "<<") {
|
||||
let type_args = if self.input.syntax().typescript() && is!(self, '<' | "<<") {
|
||||
self.try_parse_ts(|p| {
|
||||
let type_args = p.parse_ts_type_args()?;
|
||||
if is!(p, '(') {
|
||||
@ -2145,18 +2145,44 @@ impl<I: Tokens> Parser<I> {
|
||||
}
|
||||
|
||||
fn is_start_of_left_hand_side_expr(&mut self) -> PResult<bool> {
|
||||
Ok(is_one_of!(
|
||||
self, "this", "super", "null", "true", "false", Num, BigInt, Str, '`', '(', '[', '{',
|
||||
"function", "class", "new", Regex, IdentRef
|
||||
Ok(is!(
|
||||
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<bool> {
|
||||
Ok(self.is_start_of_left_hand_side_expr()?
|
||||
|| is_one_of!(
|
||||
self, '+', '-', '~', '!', "delete", "typeof", "void", "++", "--", '<', "await",
|
||||
"yield"
|
||||
|| is!(
|
||||
self,
|
||||
'+' | '-'
|
||||
| '~'
|
||||
| '!'
|
||||
| "delete"
|
||||
| "typeof"
|
||||
| "void"
|
||||
| "++"
|
||||
| "--"
|
||||
| '<'
|
||||
| "await"
|
||||
| "yield"
|
||||
)
|
||||
|| (is!(self, '#') && peeked_is!(self, IdentName)))
|
||||
}
|
||||
|
@ -281,7 +281,7 @@ impl<I: Tokens> Parser<I> {
|
||||
}
|
||||
|
||||
// Parse unary expression
|
||||
if is_one_of!(self, "delete", "void", "typeof", '+', '-', '~', '!') {
|
||||
if is!(self, "delete" | "void" | "typeof" | '+' | '-' | '~' | '!') {
|
||||
let op = match bump!(self) {
|
||||
tok!("delete") => op!("delete"),
|
||||
tok!("void") => op!("void"),
|
||||
@ -341,7 +341,7 @@ impl<I: Tokens> Parser<I> {
|
||||
return Ok(expr);
|
||||
}
|
||||
|
||||
if is_one_of!(self, "++", "--") {
|
||||
if is!(self, "++" | "--") {
|
||||
self.check_assign_target(&expr, false);
|
||||
|
||||
let op = if bump!(self) == tok!("++") {
|
||||
@ -378,7 +378,7 @@ impl<I: Tokens> Parser<I> {
|
||||
|
||||
let span = span!(self, start);
|
||||
|
||||
if is_one_of!(self, ')', ']', ';', ',') && !ctx.in_async {
|
||||
if is!(self, ')' | ']' | ';' | ',') && !ctx.in_async {
|
||||
if ctx.module {
|
||||
self.emit_err(span, SyntaxError::InvalidIdentInAsync);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ macro_rules! is {
|
||||
($p:expr, BindingIdent) => {{
|
||||
let ctx = $p.ctx();
|
||||
match $p.input.cur() {
|
||||
Some(&Word(ref w)) => !ctx.is_reserved(w),
|
||||
Some(&crate::token::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(&Word(ref w)) => !ctx.is_reserved(w),
|
||||
Some(&crate::token::Word(ref w)) => !ctx.is_reserved(w),
|
||||
_ => false,
|
||||
}
|
||||
}};
|
||||
|
||||
($p:expr,IdentName) => {{
|
||||
match $p.input.cur() {
|
||||
Some(&Word(..)) => true,
|
||||
Some(&crate::token::Word(..)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}};
|
||||
@ -77,6 +77,10 @@ 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)]
|
||||
@ -84,7 +88,7 @@ macro_rules! peeked_is {
|
||||
($p:expr, BindingIdent) => {{
|
||||
let ctx = $p.ctx();
|
||||
match peek!($p) {
|
||||
Some(&Word(ref w)) => !ctx.is_reserved(w),
|
||||
Some(&crate::token::Word(ref w)) => !ctx.is_reserved(w),
|
||||
_ => false,
|
||||
}
|
||||
}};
|
||||
@ -92,14 +96,14 @@ macro_rules! peeked_is {
|
||||
($p:expr, IdentRef) => {{
|
||||
let ctx = $p.ctx();
|
||||
match peek!($p) {
|
||||
Some(&Word(ref w)) => !ctx.is_reserved(w),
|
||||
Some(&crate::token::Word(ref w)) => !ctx.is_reserved(w),
|
||||
_ => false,
|
||||
}
|
||||
}};
|
||||
|
||||
($p:expr,IdentName) => {{
|
||||
match peek!($p) {
|
||||
Some(&Word(..)) => true,
|
||||
Some(&crate::token::Word(..)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}};
|
||||
@ -121,6 +125,10 @@ macro_rules! peeked_is {
|
||||
_ => false,
|
||||
}
|
||||
};
|
||||
|
||||
($p:expr, $t:tt | $($rest:tt)*) => {
|
||||
peeked_is!($p, $t) || peeked_is!($p, $($rest)*)
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns true on eof.
|
||||
@ -130,15 +138,6 @@ 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) => {{
|
||||
@ -161,9 +160,6 @@ 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();
|
||||
@ -210,7 +206,11 @@ 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(), SyntaxError::Expected(TOKEN, cur))
|
||||
syntax_error!(
|
||||
$p,
|
||||
$p.input.cur_span(),
|
||||
crate::error::SyntaxError::Expected(TOKEN, cur)
|
||||
)
|
||||
}
|
||||
}};
|
||||
}
|
||||
@ -220,7 +220,11 @@ 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(), SyntaxError::Expected(TOKEN, cur))
|
||||
syntax_error!(
|
||||
$p,
|
||||
$p.input.cur_span(),
|
||||
crate::error::SyntaxError::Expected(TOKEN, cur)
|
||||
)
|
||||
}
|
||||
}};
|
||||
}
|
||||
@ -291,6 +295,9 @@ 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()
|
||||
}};
|
||||
}
|
||||
@ -377,16 +384,13 @@ macro_rules! syntax_error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if cfg!(feature = "debug") {
|
||||
tracing::error!(
|
||||
"Syntax error called from {}:{}:{}\nCurrent token = {:?}",
|
||||
file!(),
|
||||
line!(),
|
||||
column!(),
|
||||
$p.input.cur()
|
||||
);
|
||||
}
|
||||
tracing::error!(
|
||||
"Syntax error called from {}:{}:{}\nCurrent token = {:?}",
|
||||
file!(),
|
||||
line!(),
|
||||
column!(),
|
||||
$p.input.cur()
|
||||
);
|
||||
return Err(err.into());
|
||||
}};
|
||||
}
|
||||
|
@ -183,7 +183,10 @@ impl<I: Tokens> ParseObject<Box<Expr>> for Parser<I> {
|
||||
let key = self.parse_prop_name()?;
|
||||
|
||||
if self.input.syntax().typescript()
|
||||
&& !is_one_of!(self, '(', '[', ':', ',', '?', '=', '*', IdentName, Str, Num)
|
||||
&& !is!(
|
||||
self,
|
||||
'(' | '[' | ':' | ',' | '?' | '=' | '*' | IdentName | Str | Num
|
||||
)
|
||||
&& !(self.input.syntax().typescript() && is!(self, '<'))
|
||||
&& !(is!(self, '}') && matches!(key, PropName::Ident(..)))
|
||||
{
|
||||
@ -242,7 +245,7 @@ impl<I: Tokens> ParseObject<Box<Expr>> for Parser<I> {
|
||||
|
||||
// `ident` from parse_prop_name is parsed as 'IdentifierName'
|
||||
// It means we should check for invalid expressions like { for, }
|
||||
if is_one_of!(self, '=', ',', '}') {
|
||||
if is!(self, '=' | ',' | '}') {
|
||||
let is_reserved_word = { self.ctx().is_reserved_word(&ident.sym) };
|
||||
if is_reserved_word {
|
||||
self.emit_err(ident.span, SyntaxError::ReservedWordInObjShorthandOrPat);
|
||||
|
@ -96,7 +96,7 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
let start = cur_pos!(self);
|
||||
let decorators = self.parse_decorators(true)?;
|
||||
|
||||
if is_one_of!(self, "import", "export") {
|
||||
if is!(self, "import" | "export") {
|
||||
return self.handle_import_export(top_level, decorators);
|
||||
}
|
||||
|
||||
@ -642,7 +642,7 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
};
|
||||
|
||||
self.with_ctx(ctx).parse_with(|p| {
|
||||
while is_one_of!(p, "case", "default") {
|
||||
while is!(p, "case" | "default") {
|
||||
let mut cons = vec![];
|
||||
let is_case = is!(p, "case");
|
||||
let case_start = cur_pos!(p);
|
||||
@ -659,7 +659,7 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
};
|
||||
expect!(p, ':');
|
||||
|
||||
while !eof!(p) && !is_one_of!(p, "case", "default", '}') {
|
||||
while !eof!(p) && !is!(p, "case" | "default" | '}') {
|
||||
cons.push(p.parse_stmt_list_item(false)?);
|
||||
}
|
||||
|
||||
@ -870,7 +870,7 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
let should_include_in = kind != VarDeclKind::Var || !for_loop;
|
||||
|
||||
if self.syntax().typescript() && for_loop {
|
||||
let res = if is_one_of!(self, "in", "of") {
|
||||
let res = if is!(self, "in" | "of") {
|
||||
self.ts_look_ahead(|p| {
|
||||
//
|
||||
if !eat!(p, "of") && !eat!(p, "in") {
|
||||
@ -1001,7 +1001,7 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
}
|
||||
|
||||
//FIXME: This is wrong. Should check in/of only on first loop.
|
||||
let init = if !for_loop || !is_one_of!(self, "in", "of") {
|
||||
let init = if !for_loop || !is!(self, "in" | "of") {
|
||||
if eat!(self, '=') {
|
||||
let expr = self.parse_assignment_expr()?;
|
||||
let expr = self.verify_expr(expr)?;
|
||||
@ -1245,13 +1245,13 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
fn parse_for_head(&mut self) -> PResult<TempForHead> {
|
||||
let strict = self.ctx().strict;
|
||||
|
||||
if is_one_of!(self, "const", "var")
|
||||
if is!(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_one_of!(self, "of", "in") {
|
||||
if is!(self, "of" | "in") {
|
||||
if decl.decls.len() != 1 {
|
||||
for d in decl.decls.iter().skip(1) {
|
||||
self.emit_err(d.name.span(), SyntaxError::TooManyVarInForInHead);
|
||||
@ -1344,7 +1344,7 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
}
|
||||
|
||||
// for (a of b)
|
||||
if is_one_of!(self, "of", "in") {
|
||||
if is!(self, "of" | "in") {
|
||||
let is_in = is!(self, "in");
|
||||
|
||||
let pat = self.reparse_expr_as_pat(PatType::AssignPat, init)?;
|
||||
|
@ -85,7 +85,7 @@ impl<I: Tokens> Parser<I> {
|
||||
let mut local = self.parse_imported_default_binding()?;
|
||||
|
||||
if self.input.syntax().typescript() && local.sym == "type" {
|
||||
if is_one_of!(self, '*', '{') {
|
||||
if is!(self, '*' | '{') {
|
||||
type_only = true;
|
||||
break 'import_maybe_ident;
|
||||
}
|
||||
@ -115,7 +115,7 @@ impl<I: Tokens> Parser<I> {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if is_one_of!(self, '*', '{') {
|
||||
if is!(self, '*' | '{') {
|
||||
phase = new_phase;
|
||||
break 'import_maybe_ident;
|
||||
}
|
||||
|
@ -19,7 +19,10 @@ impl<I: Tokens> Parser<I> {
|
||||
// hasLineBreakUpNext() method...
|
||||
bump!(self);
|
||||
Ok(!self.input.had_line_break_before_cur()
|
||||
&& is_one_of!(self, '[', '{', '*', "...", '#', IdentName, Str, Num, BigInt))
|
||||
&& is!(
|
||||
self,
|
||||
'[' | '{' | '*' | "..." | '#' | IdentName | Str | Num | BigInt
|
||||
))
|
||||
}
|
||||
|
||||
/// Parses a modifier matching one the given modifier names.
|
||||
@ -578,13 +581,10 @@ impl<I: Tokens> Parser<I> {
|
||||
self.try_parse_ts(|p| {
|
||||
let type_args = p.parse_ts_type_args()?;
|
||||
|
||||
if is_one_of!(
|
||||
p, '<', // invalid syntax
|
||||
'>', '=', ">>", ">=", '+', '-', // becomes relational expression
|
||||
/* these should be type arguments in function call or template,
|
||||
* not instantiation expression */
|
||||
'(', '`'
|
||||
) {
|
||||
// becomes relational expression
|
||||
/* these should be type arguments in function call or template,
|
||||
* not instantiation expression */
|
||||
if is!(p, '<' | '>' | '=' | ">>" | ">=" | '+' | '-' | '(' | '`') {
|
||||
Ok(None)
|
||||
} else if p.input.had_line_break_before_cur()
|
||||
|| matches!(cur!(p, false), Ok(Token::BinOp(..)))
|
||||
@ -1216,13 +1216,13 @@ impl<I: Tokens> Parser<I> {
|
||||
debug_assert!(self.input.syntax().typescript());
|
||||
|
||||
assert_and_bump!(self, '(');
|
||||
if is_one_of!(self, ')', "...") {
|
||||
if is!(self, ')' | "...") {
|
||||
// ( )
|
||||
// ( ...
|
||||
return Ok(true);
|
||||
}
|
||||
if self.skip_ts_parameter_start()? {
|
||||
if is_one_of!(self, ':', ',', '?', '=') {
|
||||
if is!(self, ':' | ',' | '?' | '=') {
|
||||
// ( xxx :
|
||||
// ( xxx ,
|
||||
// ( xxx ?
|
||||
@ -1243,7 +1243,7 @@ impl<I: Tokens> Parser<I> {
|
||||
|
||||
let _ = self.eat_any_ts_modifier()?;
|
||||
|
||||
if is_one_of!(self, IdentName, "this") {
|
||||
if is!(self, IdentName | "this") {
|
||||
bump!(self);
|
||||
return Ok(true);
|
||||
}
|
||||
@ -1320,7 +1320,7 @@ impl<I: Tokens> Parser<I> {
|
||||
assert_and_bump!(self, '['); // Skip '['
|
||||
|
||||
// ',' is for error recovery
|
||||
Ok(eat!(self, IdentRef) && is_one_of!(self, ':', ','))
|
||||
Ok(eat!(self, IdentRef) && is!(self, ':' | ','))
|
||||
}
|
||||
|
||||
/// `tsTryParseIndexSignature`
|
||||
@ -1416,7 +1416,7 @@ impl<I: Tokens> Parser<I> {
|
||||
|
||||
let optional = eat!(self, '?');
|
||||
|
||||
if is_one_of!(self, '(', '<') {
|
||||
if is!(self, '(' | '<') {
|
||||
if readonly {
|
||||
syntax_error!(self, SyntaxError::ReadOnlyMethod)
|
||||
}
|
||||
@ -1469,7 +1469,7 @@ impl<I: Tokens> Parser<I> {
|
||||
Either::Right(e) => e.into(),
|
||||
}
|
||||
}
|
||||
if is_one_of!(self, '(', '<') {
|
||||
if is!(self, '(' | '<') {
|
||||
return self
|
||||
.parse_ts_signature_member(SignatureParsingMode::TSCallSignatureDeclaration)
|
||||
.map(into_type_elem);
|
||||
@ -1626,7 +1626,7 @@ impl<I: Tokens> Parser<I> {
|
||||
let start = cur_pos!(self);
|
||||
expect!(self, '{');
|
||||
let mut readonly = None;
|
||||
if is_one_of!(self, '+', '-') {
|
||||
if is!(self, '+' | '-') {
|
||||
readonly = Some(if is!(self, '+') {
|
||||
TruePlusMinus::Plus
|
||||
} else {
|
||||
@ -1648,7 +1648,7 @@ impl<I: Tokens> Parser<I> {
|
||||
expect!(self, ']');
|
||||
|
||||
let mut optional = None;
|
||||
if is_one_of!(self, '+', '-') {
|
||||
if is!(self, '+' | '-') {
|
||||
optional = Some(if is!(self, '+') {
|
||||
TruePlusMinus::Plus
|
||||
} else {
|
||||
@ -2443,7 +2443,7 @@ impl<I: Tokens> Parser<I> {
|
||||
.map(From::from)
|
||||
.map(Some);
|
||||
}
|
||||
if is_one_of!(p, "const", "var", "let") {
|
||||
if is!(p, "const" | "var" | "let") {
|
||||
return p
|
||||
.parse_var_stmt(false)
|
||||
.map(|decl| VarDecl {
|
||||
@ -2606,7 +2606,7 @@ impl<I: Tokens> Parser<I> {
|
||||
return Ok(Default::default());
|
||||
}
|
||||
|
||||
let res = if is_one_of!(self, '<', JSXTagStart) {
|
||||
let res = if is!(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.
|
||||
|
Loading…
Reference in New Issue
Block a user