swc_ecma_fast_parser/parser/
stmt.rs
use swc_common::{Span, Spanned, SyntaxContext};
use swc_ecma_ast::{BlockStmt, ExprStmt, ReturnStmt, Stmt, VarDecl, VarDeclKind, VarDeclarator};
use crate::{error::Result, parser::Parser, token::TokenType};
impl Parser<'_> {
pub fn parse_stmt(&mut self) -> Result<Stmt> {
match self.current_token_type() {
TokenType::LBrace => self.parse_block_stmt(),
TokenType::Return => self.parse_return_stmt(),
TokenType::Var => self.parse_var_decl_stmt(VarDeclKind::Var),
TokenType::Let => self.parse_var_decl_stmt(VarDeclKind::Let),
TokenType::Const => self.parse_var_decl_stmt(VarDeclKind::Const),
_ => self.parse_expr_stmt(),
}
}
fn parse_block_stmt(&mut self) -> Result<Stmt> {
let start_span = self.current_span();
self.lexer.next_token()?; let mut stmts = Vec::new();
while !self.is(TokenType::RBrace) {
let stmt = self.parse_stmt()?;
stmts.push(stmt);
}
let end_span = self.current_span();
self.lexer.next_token()?; let span = Span::new(start_span.lo, end_span.hi);
Ok(Stmt::Block(BlockStmt {
span,
stmts,
ctxt: SyntaxContext::empty(),
}))
}
fn parse_return_stmt(&mut self) -> Result<Stmt> {
let start_span = self.current_span();
self.lexer.next_token()?; let arg = if self.is(TokenType::Semi)
|| self.is(TokenType::RBrace)
|| self.is_line_terminator()
{
None
} else {
Some(self.parse_expr()?)
};
if self.is(TokenType::Semi) {
self.lexer.next_token()?;
}
let end_span = match &arg {
Some(expr) => expr.span(),
None => start_span,
};
let span = Span::new(start_span.lo, end_span.hi);
Ok(Stmt::Return(ReturnStmt { span, arg }))
}
fn parse_expr_stmt(&mut self) -> Result<Stmt> {
let expr = self.parse_expr()?;
let span = expr.span();
if self.is(TokenType::Semi) {
self.lexer.next_token()?;
}
Ok(Stmt::Expr(ExprStmt { span, expr }))
}
fn parse_var_decl_stmt(&mut self, kind: VarDeclKind) -> Result<Stmt> {
let start_span = self.current_span();
self.lexer.next_token()?; let mut decls = Vec::new();
loop {
let decl = self.parse_var_declarator()?;
decls.push(decl);
if self.is(TokenType::Comma) {
self.lexer.next_token()?; } else {
break;
}
}
if self.is(TokenType::Semi) {
self.lexer.next_token()?;
}
let end_span = match decls.last() {
Some(decl) => match &decl.init {
Some(init) => init.span(),
None => decl.name.span(),
},
None => start_span,
};
let span = Span::new(start_span.lo, end_span.hi);
Ok(Stmt::Decl(swc_ecma_ast::Decl::Var(Box::new(VarDecl {
span,
kind,
declare: false,
decls,
ctxt: SyntaxContext::empty(),
}))))
}
fn parse_var_declarator(&mut self) -> Result<VarDeclarator> {
let name = self.parse_pat()?;
let name_span = name.span();
let init = if self.is(TokenType::Eq) {
self.lexer.next_token()?; Some(self.parse_expr()?)
} else {
None
};
let span = match &init {
Some(expr) => {
let expr_span = expr.span();
Span::new(name_span.lo, expr_span.hi)
}
None => name_span,
};
Ok(VarDeclarator {
span,
name,
init,
definite: false,
})
}
fn is_line_terminator(&self) -> bool {
false
}
}