swc_ecma_parser/parser/
util.rsuse swc_atoms::js_word;
use super::*;
use crate::token::Keyword;
impl Context {
pub(crate) fn is_reserved(self, word: &Word) -> bool {
match *word {
Word::Keyword(Keyword::Let) => self.strict,
Word::Keyword(Keyword::Await) => self.in_async || self.strict,
Word::Keyword(Keyword::Yield) => self.in_generator || self.strict,
Word::Null
| Word::True
| Word::False
| Word::Keyword(Keyword::Break)
| Word::Keyword(Keyword::Case)
| Word::Keyword(Keyword::Catch)
| Word::Keyword(Keyword::Continue)
| Word::Keyword(Keyword::Debugger)
| Word::Keyword(Keyword::Default_)
| Word::Keyword(Keyword::Do)
| Word::Keyword(Keyword::Export)
| Word::Keyword(Keyword::Else)
| Word::Keyword(Keyword::Finally)
| Word::Keyword(Keyword::For)
| Word::Keyword(Keyword::Function)
| Word::Keyword(Keyword::If)
| Word::Keyword(Keyword::Return)
| Word::Keyword(Keyword::Switch)
| Word::Keyword(Keyword::Throw)
| Word::Keyword(Keyword::Try)
| Word::Keyword(Keyword::Var)
| Word::Keyword(Keyword::Const)
| Word::Keyword(Keyword::While)
| Word::Keyword(Keyword::With)
| Word::Keyword(Keyword::New)
| Word::Keyword(Keyword::This)
| Word::Keyword(Keyword::Super)
| Word::Keyword(Keyword::Class)
| Word::Keyword(Keyword::Extends)
| Word::Keyword(Keyword::Import)
| Word::Keyword(Keyword::In)
| Word::Keyword(Keyword::InstanceOf)
| Word::Keyword(Keyword::TypeOf)
| Word::Keyword(Keyword::Void)
| Word::Keyword(Keyword::Delete) => true,
Word::Ident(js_word!("enum")) => true,
Word::Ident(js_word!("implements"))
| Word::Ident(js_word!("package"))
| Word::Ident(js_word!("protected"))
| Word::Ident(js_word!("interface"))
| Word::Ident(js_word!("private"))
| Word::Ident(js_word!("public"))
if self.strict =>
{
true
}
_ => false,
}
}
pub fn is_reserved_word(self, word: &JsWord) -> bool {
match *word {
js_word!("let") => self.strict,
js_word!("await") => self.in_async || self.module,
js_word!("yield") => self.in_generator || self.strict,
js_word!("null")
| js_word!("true")
| js_word!("false")
| js_word!("break")
| js_word!("case")
| js_word!("catch")
| js_word!("continue")
| js_word!("debugger")
| js_word!("default")
| js_word!("do")
| js_word!("export")
| js_word!("else")
| js_word!("finally")
| js_word!("for")
| js_word!("function")
| js_word!("if")
| js_word!("return")
| js_word!("switch")
| js_word!("throw")
| js_word!("try")
| js_word!("var")
| js_word!("const")
| js_word!("while")
| js_word!("with")
| js_word!("new")
| js_word!("this")
| js_word!("super")
| js_word!("class")
| js_word!("extends")
| js_word!("import")
| js_word!("in")
| js_word!("instanceof")
| js_word!("typeof")
| js_word!("void")
| js_word!("delete") => true,
js_word!("enum") => true,
js_word!("implements")
| js_word!("package")
| js_word!("protected")
| js_word!("interface")
| js_word!("private")
| js_word!("public")
if self.strict =>
{
true
}
_ => false,
}
}
}
impl<I: Tokens> Parser<I> {
pub(super) fn with_ctx(&mut self, ctx: Context) -> WithCtx<I> {
let orig_ctx = self.ctx();
self.set_ctx(ctx);
WithCtx {
orig_ctx,
inner: self,
}
}
pub(super) fn with_state(&mut self, state: State) -> WithState<I> {
let orig_state = std::mem::replace(&mut self.state, state);
WithState {
orig_state,
inner: self,
}
}
pub(super) fn set_ctx(&mut self, ctx: Context) {
self.input.set_ctx(ctx);
}
pub(super) fn strict_mode(&mut self) -> WithCtx<I> {
let ctx = Context {
strict: true,
..self.ctx()
};
self.with_ctx(ctx)
}
pub(super) fn in_type(&mut self) -> WithCtx<I> {
let ctx = Context {
in_type: true,
..self.ctx()
};
self.with_ctx(ctx)
}
pub(super) fn include_in_expr(&mut self, include_in_expr: bool) -> WithCtx<I> {
let ctx = Context {
include_in_expr,
..self.ctx()
};
self.with_ctx(ctx)
}
#[inline(always)]
pub(super) fn parse_with<F, Ret>(&mut self, f: F) -> PResult<Ret>
where
F: FnOnce(&mut Self) -> PResult<Ret>,
{
f(self)
}
pub(super) fn syntax(&self) -> Syntax {
self.input.syntax()
}
}
pub trait ParseObject<Obj> {
type Prop;
fn make_object(
&mut self,
span: Span,
props: Vec<Self::Prop>,
trailing_comma: Option<Span>,
) -> PResult<Obj>;
fn parse_object_prop(&mut self) -> PResult<Self::Prop>;
}
pub struct WithState<'w, I: 'w + Tokens> {
inner: &'w mut Parser<I>,
orig_state: State,
}
impl<'w, I: Tokens> Deref for WithState<'w, I> {
type Target = Parser<I>;
fn deref(&self) -> &Parser<I> {
self.inner
}
}
impl<'w, I: Tokens> DerefMut for WithState<'w, I> {
fn deref_mut(&mut self) -> &mut Parser<I> {
self.inner
}
}
impl<'w, I: Tokens> Drop for WithState<'w, I> {
fn drop(&mut self) {
std::mem::swap(&mut self.inner.state, &mut self.orig_state);
}
}
pub struct WithCtx<'w, I: 'w + Tokens> {
inner: &'w mut Parser<I>,
orig_ctx: Context,
}
impl<'w, I: Tokens> Deref for WithCtx<'w, I> {
type Target = Parser<I>;
fn deref(&self) -> &Parser<I> {
self.inner
}
}
impl<'w, I: Tokens> DerefMut for WithCtx<'w, I> {
fn deref_mut(&mut self) -> &mut Parser<I> {
self.inner
}
}
impl<'w, I: Tokens> Drop for WithCtx<'w, I> {
fn drop(&mut self) {
self.inner.set_ctx(self.orig_ctx);
}
}
pub(super) trait ExprExt {
fn as_expr(&self) -> &Expr;
fn is_valid_simple_assignment_target(&self, strict: bool) -> bool {
match self.as_expr() {
Expr::Ident(ident) => {
if strict && ident.is_reserved_in_strict_bind() {
return false;
}
true
}
Expr::This(..)
| Expr::Lit(..)
| Expr::Array(..)
| Expr::Object(..)
| Expr::Fn(..)
| Expr::Class(..)
| Expr::Tpl(..)
| Expr::TaggedTpl(..) => false,
Expr::Paren(ParenExpr { expr, .. }) => expr.is_valid_simple_assignment_target(strict),
Expr::Member(MemberExpr { obj, .. }) => match obj.as_ref() {
Expr::Member(..) => obj.is_valid_simple_assignment_target(strict),
Expr::OptChain(..) => false,
_ => true,
},
Expr::SuperProp(..) => true,
Expr::New(..) | Expr::Call(..) => false,
Expr::MetaProp(..) => false,
Expr::Update(..) => false,
Expr::Unary(..) | Expr::Await(..) => false,
Expr::Bin(..) => false,
Expr::Cond(..) => false,
Expr::Yield(..) | Expr::Arrow(..) | Expr::Assign(..) => false,
Expr::Seq(..) => false,
Expr::OptChain(..) => false,
Expr::PrivateName(..) => false,
Expr::JSXMember(..)
| Expr::JSXNamespacedName(..)
| Expr::JSXEmpty(..)
| Expr::JSXElement(..)
| Expr::JSXFragment(..) => false,
Expr::TsNonNull(TsNonNullExpr { ref expr, .. })
| Expr::TsTypeAssertion(TsTypeAssertion { ref expr, .. })
| Expr::TsAs(TsAsExpr { ref expr, .. })
| Expr::TsInstantiation(TsInstantiation { ref expr, .. })
| Expr::TsSatisfies(TsSatisfiesExpr { ref expr, .. }) => {
expr.is_valid_simple_assignment_target(strict)
}
Expr::TsConstAssertion(..) => false,
Expr::Invalid(..) => false,
}
}
}
impl ExprExt for Box<Expr> {
fn as_expr(&self) -> &Expr {
self
}
}
impl ExprExt for Expr {
fn as_expr(&self) -> &Expr {
self
}
}