swc_ecma_lexer/
token.rs

1//! Ported from [babel/babylon][]
2//!
3//! [babel/babylon]:https://github.com/babel/babel/blob/2d378d076eb0c5fe63234a8b509886005c01d7ee/packages/babylon/src/tokenizer/types.js
4use std::{
5    borrow::Cow,
6    fmt::{self, Debug, Display, Formatter},
7};
8
9use num_bigint::BigInt as BigIntValue;
10use swc_atoms::{atom, Atom, AtomStore};
11use swc_common::{Span, Spanned};
12pub(crate) use swc_ecma_ast::{AssignOp, BinaryOp};
13
14pub(crate) use self::{Keyword::*, Token::*};
15use crate::{
16    common::{
17        input::Tokens,
18        lexer::{LexResult, Lexer},
19    },
20    error::Error,
21    tok,
22};
23
24macro_rules! define_known_ident {
25    (
26        $(
27            $name:ident => $value:tt,
28        )*
29    ) => {
30        #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
31        #[non_exhaustive]
32        pub enum KnownIdent {
33            $(
34                $name
35            ),*
36        }
37
38        #[macro_export]
39        macro_rules! known_ident_token {
40            $(
41                ($value) => {
42                    $crate::token::TokenKind::Word($crate::token::WordKind::Ident(
43                        $crate::token::IdentKind::Known($crate::token::KnownIdent::$name),
44                    ))
45                };
46            )*
47        }
48
49        #[macro_export]
50        macro_rules! known_ident {
51            $(
52                ($value) => {
53                    $crate::token::KnownIdent::$name
54                };
55            )*
56        }
57        #[macro_export]
58        macro_rules! ident_like {
59            $(
60                ($value) => {
61                    $crate::token::IdentLike::Known(
62                        $crate::token::KnownIdent::$name
63                    )
64                };
65            )*
66        }
67
68        static STR_TO_KNOWN_IDENT: phf::Map<&'static str, KnownIdent> = phf::phf_map! {
69            $(
70                $value => KnownIdent::$name,
71            )*
72        };
73
74        impl From<KnownIdent> for swc_atoms::Atom {
75
76            fn from(s: KnownIdent) -> Self {
77                match s {
78                    $(
79                        KnownIdent::$name => atom!($value),
80                    )*
81                }
82            }
83        }
84        impl From<KnownIdent> for &'static str {
85
86            fn from(s: KnownIdent) -> Self {
87                match s {
88                    $(
89                        KnownIdent::$name => $value,
90                    )*
91                }
92            }
93        }
94    };
95}
96
97define_known_ident!(
98    Abstract => "abstract",
99    As => "as",
100    Async => "async",
101    From => "from",
102    Of => "of",
103    Type => "type",
104    Global => "global",
105    Static => "static",
106    Using => "using",
107    Readonly => "readonly",
108    Unique => "unique",
109    Keyof => "keyof",
110    Declare => "declare",
111    Enum => "enum",
112    Is => "is",
113    Infer => "infer",
114    Symbol => "symbol",
115    Undefined => "undefined",
116    Interface => "interface",
117    Implements => "implements",
118    Asserts => "asserts",
119    Require => "require",
120    Get => "get",
121    Set => "set",
122    Any => "any",
123    Intrinsic => "intrinsic",
124    Unknown => "unknown",
125    String => "string",
126    Object => "object",
127    Number => "number",
128    Bigint => "bigint",
129    Boolean => "boolean",
130    Never => "never",
131    Assert => "assert",
132    Namespace => "namespace",
133    Accessor => "accessor",
134    Meta => "meta",
135    Target => "target",
136    Satisfies => "satisfies",
137    Package => "package",
138    Protected => "protected",
139    Private => "private",
140    Public => "public",
141);
142
143impl std::str::FromStr for KnownIdent {
144    type Err = ();
145
146    fn from_str(s: &str) -> Result<Self, Self::Err> {
147        STR_TO_KNOWN_IDENT.get(s).cloned().ok_or(())
148    }
149}
150
151#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
152pub enum WordKind {
153    Keyword(Keyword),
154
155    Null,
156    True,
157    False,
158
159    Ident(IdentKind),
160}
161
162impl From<Keyword> for WordKind {
163    #[inline(always)]
164    fn from(kwd: Keyword) -> Self {
165        Self::Keyword(kwd)
166    }
167}
168
169#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
170pub enum IdentKind {
171    Known(KnownIdent),
172    Other,
173}
174
175#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
176pub enum TokenKind {
177    Word(WordKind),
178    Arrow,
179    Hash,
180    At,
181    Dot,
182    DotDotDot,
183    Bang,
184    LParen,
185    RParen,
186    LBracket,
187    RBracket,
188    LBrace,
189    RBrace,
190    Semi,
191    Comma,
192    BackQuote,
193    Template,
194    Colon,
195    BinOp(BinOpToken),
196    AssignOp(AssignOp),
197    DollarLBrace,
198    QuestionMark,
199    PlusPlus,
200    MinusMinus,
201    Tilde,
202    Str,
203    /// We abuse `token.raw` for flags
204    Regex,
205    Num,
206    BigInt,
207
208    JSXName,
209    JSXText,
210    JSXTagStart,
211    JSXTagEnd,
212
213    Shebang,
214    Error,
215}
216
217impl crate::common::lexer::state::TokenKind for TokenKind {
218    #[inline(always)]
219    fn is_dot(self) -> bool {
220        self == Self::Dot
221    }
222
223    #[inline(always)]
224    fn is_bin_op(self) -> bool {
225        matches!(self, Self::BinOp(_))
226    }
227
228    #[inline(always)]
229    fn is_semi(self) -> bool {
230        self == Self::Semi
231    }
232
233    #[inline(always)]
234    fn is_template(self) -> bool {
235        self == Self::Template
236    }
237
238    #[inline(always)]
239    fn is_keyword(self) -> bool {
240        matches!(self, Self::Word(WordKind::Keyword(_)))
241    }
242
243    #[inline(always)]
244    fn is_colon(self) -> bool {
245        self == Self::Colon
246    }
247
248    #[inline(always)]
249    fn is_lbrace(self) -> bool {
250        self == Self::LBrace
251    }
252
253    #[inline(always)]
254    fn is_rbrace(self) -> bool {
255        self == Self::RBrace
256    }
257
258    #[inline(always)]
259    fn is_lparen(self) -> bool {
260        self == Self::LParen
261    }
262
263    #[inline(always)]
264    fn is_rparen(self) -> bool {
265        self == Self::RParen
266    }
267
268    #[inline(always)]
269    fn is_keyword_fn(self) -> bool {
270        self == Self::Word(WordKind::Keyword(Keyword::Function))
271    }
272
273    #[inline(always)]
274    fn is_keyword_return(self) -> bool {
275        self == Self::Word(WordKind::Keyword(Keyword::Return))
276    }
277
278    #[inline(always)]
279    fn is_keyword_yield(self) -> bool {
280        self == Self::Word(WordKind::Keyword(Keyword::Yield))
281    }
282
283    #[inline(always)]
284    fn is_keyword_else(self) -> bool {
285        self == Self::Word(WordKind::Keyword(Keyword::Else))
286    }
287
288    #[inline(always)]
289    fn is_keyword_class(self) -> bool {
290        self == Self::Word(WordKind::Keyword(Keyword::Class))
291    }
292
293    #[inline(always)]
294    fn is_keyword_let(self) -> bool {
295        self == Self::Word(WordKind::Keyword(Keyword::Let))
296    }
297
298    #[inline(always)]
299    fn is_keyword_var(self) -> bool {
300        self == Self::Word(WordKind::Keyword(Keyword::Var))
301    }
302
303    #[inline(always)]
304    fn is_keyword_const(self) -> bool {
305        self == Self::Word(WordKind::Keyword(Keyword::Const))
306    }
307
308    #[inline(always)]
309    fn is_keyword_if(self) -> bool {
310        self == Self::Word(WordKind::Keyword(Keyword::If))
311    }
312
313    #[inline(always)]
314    fn is_keyword_while(self) -> bool {
315        self == Self::Word(WordKind::Keyword(Keyword::While))
316    }
317
318    #[inline(always)]
319    fn is_keyword_for(self) -> bool {
320        self == Self::Word(WordKind::Keyword(Keyword::For))
321    }
322
323    #[inline(always)]
324    fn is_keyword_with(self) -> bool {
325        self == Self::Word(WordKind::Keyword(Keyword::With))
326    }
327
328    #[inline(always)]
329    fn is_lt(self) -> bool {
330        self == Self::BinOp(BinOpToken::Lt)
331    }
332
333    #[inline(always)]
334    fn is_gt(self) -> bool {
335        self == Self::BinOp(BinOpToken::Gt)
336    }
337
338    #[inline(always)]
339    fn is_arrow(self) -> bool {
340        self == Self::Arrow
341    }
342
343    #[inline(always)]
344    fn is_ident(self) -> bool {
345        matches!(self, Self::Word(WordKind::Ident(_)))
346    }
347
348    #[inline(always)]
349    fn is_known_ident_of(self) -> bool {
350        self == Self::Word(WordKind::Ident(IdentKind::Known(KnownIdent::Of)))
351    }
352
353    #[inline(always)]
354    fn is_slash(self) -> bool {
355        self == Self::BinOp(BinOpToken::Div)
356    }
357
358    #[inline(always)]
359    fn is_dollar_lbrace(self) -> bool {
360        self == Self::DollarLBrace
361    }
362
363    #[inline(always)]
364    fn is_plus_plus(self) -> bool {
365        self == Self::PlusPlus
366    }
367
368    #[inline(always)]
369    fn is_minus_minus(self) -> bool {
370        self == Self::MinusMinus
371    }
372
373    #[inline(always)]
374    fn is_back_quote(self) -> bool {
375        self == Self::BackQuote
376    }
377
378    #[inline(always)]
379    fn before_expr(self) -> bool {
380        self.before_expr()
381    }
382
383    #[inline(always)]
384    fn is_jsx_tag_start(self) -> bool {
385        self == Self::JSXTagStart
386    }
387
388    #[inline(always)]
389    fn is_jsx_tag_end(self) -> bool {
390        self == Self::JSXTagEnd
391    }
392}
393
394#[derive(Clone, PartialEq)]
395pub enum Token {
396    /// Identifier, "null", "true", "false".
397    ///
398    /// Contains `null` and ``
399    Word(Word),
400
401    /// '=>'
402    Arrow,
403
404    /// '#'
405    Hash,
406
407    /// '@'
408    At,
409    /// '.'
410    Dot,
411
412    /// '...'
413    DotDotDot,
414    /// '!'
415    Bang,
416
417    /// '('
418    LParen,
419    /// ')'
420    RParen,
421    /// `[`
422    LBracket,
423    /// ']'
424    RBracket,
425    /// '{'
426    LBrace,
427    /// '}'
428    RBrace,
429
430    /// ';'
431    Semi,
432    /// ','
433    Comma,
434
435    /// '`'
436    BackQuote,
437    Template {
438        raw: Atom,
439        cooked: LexResult<Atom>,
440    },
441    /// ':'
442    Colon,
443    BinOp(BinOpToken),
444    AssignOp(AssignOp),
445
446    /// '${'
447    DollarLBrace,
448
449    /// '?'
450    QuestionMark,
451
452    /// `++`
453    PlusPlus,
454    /// `--`
455    MinusMinus,
456
457    /// `~`
458    Tilde,
459
460    /// String literal. Span of this token contains quote.
461    Str {
462        value: Atom,
463        raw: Atom,
464    },
465
466    /// Regexp literal.
467    Regex(Atom, Atom),
468
469    /// TODO: Make Num as enum and separate decimal, binary, ..etc
470    Num {
471        value: f64,
472        raw: Atom,
473    },
474
475    BigInt {
476        value: Box<BigIntValue>,
477        raw: Atom,
478    },
479
480    JSXName {
481        name: Atom,
482    },
483    JSXText {
484        value: Atom,
485        raw: Atom,
486    },
487    JSXTagStart,
488    JSXTagEnd,
489
490    Shebang(Atom),
491    Error(Error),
492    Eof,
493}
494
495impl<'a, I: Tokens<TokenAndSpan>> crate::common::lexer::token::TokenFactory<'a, TokenAndSpan, I>
496    for Token
497{
498    type Buffer = crate::input::Buffer<I>;
499    type Lexer = crate::Lexer<'a>;
500
501    const ABSTRACT: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Abstract)));
502    const ACCESSOR: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Accessor)));
503    const ANY: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Any)));
504    const ARROW: Self = Self::Arrow;
505    const AS: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::As)));
506    const ASSERT: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Assert)));
507    const ASSERTS: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Asserts)));
508    const ASYNC: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Async)));
509    const AT: Self = Self::At;
510    const AWAIT: Self = Token::Word(Word::Keyword(Keyword::Await));
511    const BACKQUOTE: Self = Self::BackQuote;
512    const BANG: Self = Self::Bang;
513    const BIGINT: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Bigint)));
514    const BIT_AND: Self = Self::BinOp(BinOpToken::BitAnd);
515    const BIT_AND_EQ: Self = Self::AssignOp(AssignOp::BitAndAssign);
516    const BIT_OR: Self = Self::BinOp(BinOpToken::BitOr);
517    const BIT_OR_EQ: Self = Self::AssignOp(AssignOp::BitOrAssign);
518    const BOOLEAN: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Boolean)));
519    const BREAK: Self = Token::Word(Word::Keyword(Keyword::Break));
520    const CASE: Self = Self::Word(Word::Keyword(Keyword::Case));
521    const CATCH: Self = Self::Word(Word::Keyword(Keyword::Catch));
522    const CLASS: Self = Token::Word(Word::Keyword(Keyword::Class));
523    const COLON: Self = Self::Colon;
524    const COMMA: Self = Self::Comma;
525    const CONST: Self = Token::Word(Word::Keyword(Keyword::Const));
526    const CONTINUE: Self = Self::Word(Word::Keyword(Keyword::Continue));
527    const DEBUGGER: Self = Self::Word(Word::Keyword(Keyword::Debugger));
528    const DECLARE: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Declare)));
529    const DEFAULT: Self = Self::Word(Word::Keyword(Keyword::Default_));
530    const DELETE: Self = Token::Word(Word::Keyword(Keyword::Delete));
531    const DIV: Self = Token::BinOp(BinOpToken::Div);
532    const DIV_EQ: Self = Token::AssignOp(AssignOp::DivAssign);
533    const DO: Self = Token::Word(Word::Keyword(Keyword::Do));
534    const DOLLAR_LBRACE: Self = Self::DollarLBrace;
535    const DOT: Self = Self::Dot;
536    const DOTDOTDOT: Self = Self::DotDotDot;
537    const ELSE: Self = Token::Word(Word::Keyword(Keyword::Else));
538    const ENUM: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Enum)));
539    const EOF: Self = Token::Eof;
540    const EQUAL: Self = Token::AssignOp(AssignOp::Assign);
541    const EXP: Self = Token::BinOp(BinOpToken::Exp);
542    const EXPORT: Self = Token::Word(Word::Keyword(Keyword::Export));
543    const EXP_EQ: Self = Token::AssignOp(AssignOp::ExpAssign);
544    const EXTENDS: Self = Self::Word(Word::Keyword(Keyword::Extends));
545    const FALSE: Self = Token::Word(Word::False);
546    const FINALLY: Self = Self::Word(Word::Keyword(Keyword::Finally));
547    const FOR: Self = Token::Word(Word::Keyword(Keyword::For));
548    const FROM: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::From)));
549    const FUNCTION: Self = Token::Word(Word::Keyword(Keyword::Function));
550    const GET: Self = Self::Word(Word::Ident(IdentLike::Known(KnownIdent::Get)));
551    const GLOBAL: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Global)));
552    const GREATER: Self = Token::BinOp(BinOpToken::Gt);
553    const GREATER_EQ: Self = Token::BinOp(BinOpToken::GtEq);
554    const HASH: Self = Self::Hash;
555    const IF: Self = Token::Word(Word::Keyword(Keyword::If));
556    const IMPLEMENTS: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Implements)));
557    const IMPORT: Self = Token::Word(Word::Keyword(Keyword::Import));
558    const IN: Self = Token::Word(Word::Keyword(Keyword::In));
559    const INFER: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Infer)));
560    const INSTANCEOF: Self = Token::Word(Word::Keyword(Keyword::InstanceOf));
561    const INTERFACE: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Interface)));
562    const INTRINSIC: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Intrinsic)));
563    const IS: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Is)));
564    const JSX_TAG_END: Self = Self::JSXTagEnd;
565    const JSX_TAG_START: Self = Self::JSXTagStart;
566    const KEYOF: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Keyof)));
567    const LBRACE: Self = Self::LBrace;
568    const LBRACKET: Self = Self::LBracket;
569    const LESS: Self = Token::BinOp(BinOpToken::Lt);
570    const LESS_EQ: Self = Token::BinOp(BinOpToken::LtEq);
571    const LET: Self = Token::Word(Word::Keyword(Keyword::Let));
572    const LOGICAL_AND: Self = tok!("&&");
573    const LOGICAL_AND_EQ: Self = Token::AssignOp(AssignOp::AndAssign);
574    const LOGICAL_OR: Self = tok!("||");
575    const LOGICAL_OR_EQ: Self = Token::AssignOp(AssignOp::OrAssign);
576    const LPAREN: Self = Self::LParen;
577    const LSHIFT: Self = Token::BinOp(BinOpToken::LShift);
578    const LSHIFT_EQ: Self = Token::AssignOp(AssignOp::LShiftAssign);
579    const MINUS: Self = Token::BinOp(BinOpToken::Sub);
580    const MINUS_MINUS: Self = Self::MinusMinus;
581    const MOD: Self = Token::BinOp(BinOpToken::Mod);
582    const MOD_EQ: Self = Token::AssignOp(AssignOp::ModAssign);
583    const MUL: Self = Token::BinOp(BinOpToken::Mul);
584    const MUL_EQ: Self = Token::AssignOp(AssignOp::MulAssign);
585    const NAMESPACE: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Namespace)));
586    const NEVER: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Never)));
587    const NEW: Self = Token::Word(Word::Keyword(Keyword::New));
588    const NULL: Self = Token::Word(Word::Null);
589    const NULLISH_ASSIGN: Self = tok!("??=");
590    const NULLISH_COALESCING: Self = tok!("??");
591    const NUMBER: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Number)));
592    const OBJECT: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Object)));
593    const OF: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Of)));
594    const PACKAGE: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Package)));
595    const PLUS: Self = Token::BinOp(BinOpToken::Add);
596    const PLUS_PLUS: Self = Self::PlusPlus;
597    const PRIVATE: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Private)));
598    const PROTECTED: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Protected)));
599    const PUBLIC: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Public)));
600    const QUESTION: Self = Token::QuestionMark;
601    const RBRACE: Self = Self::RBrace;
602    const RBRACKET: Self = Self::RBracket;
603    const READONLY: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Readonly)));
604    const REQUIRE: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Require)));
605    const RETURN: Self = Token::Word(Word::Keyword(Keyword::Return));
606    const RPAREN: Self = Self::RParen;
607    const RSHIFT: Self = Token::BinOp(BinOpToken::RShift);
608    const RSHIFT_EQ: Self = Token::AssignOp(AssignOp::RShiftAssign);
609    const SATISFIES: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Satisfies)));
610    const SEMI: Self = Self::Semi;
611    const SET: Self = Self::Word(Word::Ident(IdentLike::Known(KnownIdent::Set)));
612    const STATIC: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Static)));
613    const STRING: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::String)));
614    const SUPER: Self = Token::Word(Word::Keyword(Keyword::Super));
615    const SWITCH: Self = Self::Word(Word::Keyword(Keyword::Switch));
616    const SYMBOL: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Symbol)));
617    const TARGET: Self = Self::Word(Word::Ident(IdentLike::Known(KnownIdent::Target)));
618    const THIS: Self = Token::Word(Word::Keyword(Keyword::This));
619    const THROW: Self = Token::Word(Word::Keyword(Keyword::Throw));
620    const TILDE: Self = Self::Tilde;
621    const TRUE: Self = Token::Word(Word::True);
622    const TRY: Self = Self::Word(Word::Keyword(Keyword::Try));
623    const TYPE: Self = Self::Word(Word::Ident(IdentLike::Known(KnownIdent::Type)));
624    const TYPEOF: Self = Token::Word(Word::Keyword(Keyword::TypeOf));
625    const UNDEFINED: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Undefined)));
626    const UNIQUE: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Unique)));
627    const UNKNOWN: Self = Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Unknown)));
628    const USING: Self = Self::Word(Word::Ident(IdentLike::Known(KnownIdent::Using)));
629    const VAR: Self = Self::Word(Word::Keyword(Keyword::Var));
630    const VOID: Self = Token::Word(Word::Keyword(Keyword::Void));
631    const WHILE: Self = Token::Word(Word::Keyword(Keyword::While));
632    const WITH: Self = Token::Word(Word::Keyword(Keyword::With));
633    const YIELD: Self = Token::Word(Word::Keyword(Keyword::Yield));
634    const ZERO_FILL_RSHIFT: Self = Token::BinOp(BinOpToken::ZeroFillRShift);
635    const ZERO_FILL_RSHIFT_EQ: Self = Token::AssignOp(AssignOp::ZeroFillRShiftAssign);
636
637    #[inline(always)]
638    fn jsx_name(name: &'a str, lexer: &mut crate::Lexer<'a>) -> Self {
639        let name = lexer.atom(name);
640        Self::JSXName { name }
641    }
642
643    #[inline(always)]
644    fn is_jsx_name(&self) -> bool {
645        matches!(self, Self::JSXName { .. })
646    }
647
648    #[inline(always)]
649    fn take_jsx_name(self, _: &mut Self::Buffer) -> Atom {
650        match self {
651            JSXName { name } => name,
652            _ => unreachable!(),
653        }
654    }
655
656    #[inline(always)]
657    fn str(value: Atom, raw: Atom, _: &mut crate::Lexer<'a>) -> Self {
658        Self::Str { value, raw }
659    }
660
661    #[inline(always)]
662    fn template(cooked: LexResult<Atom>, raw: Atom, _: &mut crate::Lexer<'a>) -> Self {
663        Self::Template { cooked, raw }
664    }
665
666    #[inline(always)]
667    fn regexp(content: Atom, flags: Atom, _: &mut crate::Lexer<'a>) -> Self {
668        Self::Regex(content, flags)
669    }
670
671    #[inline(always)]
672    fn num(value: f64, raw: Atom, _: &mut crate::Lexer<'a>) -> Self {
673        Self::Num { value, raw }
674    }
675
676    #[inline(always)]
677    fn bigint(value: Box<BigIntValue>, raw: Atom, _: &mut crate::Lexer<'a>) -> Self {
678        Self::BigInt { value, raw }
679    }
680
681    #[inline(always)]
682    fn unknown_ident(value: Atom, _: &mut crate::Lexer<'a>) -> Self {
683        Token::Word(Word::Ident(IdentLike::Other(value)))
684    }
685
686    #[inline(always)]
687    fn is_word(&self) -> bool {
688        matches!(self, Self::Word(_))
689    }
690
691    #[inline(always)]
692    fn is_reserved(&self, ctx: crate::common::context::Context) -> bool {
693        if let Token::Word(word) = self {
694            ctx.is_reserved(word)
695        } else {
696            unreachable!()
697        }
698    }
699
700    #[inline(always)]
701    fn into_atom(self, _: &mut crate::Lexer<'a>) -> Option<Atom> {
702        match self {
703            Token::Word(word) => Some(word.into()),
704            _ => None,
705        }
706    }
707
708    #[inline(always)]
709    fn is_error(&self) -> bool {
710        matches!(self, Self::Error(_))
711    }
712
713    #[inline(always)]
714    fn take_error(self, _: &mut Self::Buffer) -> crate::error::Error {
715        match self {
716            Self::Error(e) => e,
717            _ => unreachable!(),
718        }
719    }
720
721    #[inline(always)]
722    fn is_str(&self) -> bool {
723        matches!(self, Self::Str { .. })
724    }
725
726    #[inline(always)]
727    fn is_str_raw_content(&self, content: &str, _: &Self::Buffer) -> bool {
728        if let Self::Str { raw, .. } = self {
729            raw == content
730        } else {
731            false
732        }
733    }
734
735    #[inline(always)]
736    fn take_str(self, _: &mut Self::Buffer) -> (Atom, Atom) {
737        match self {
738            Self::Str { value, raw } => (value, raw),
739            _ => unreachable!(),
740        }
741    }
742
743    #[inline(always)]
744    fn is_num(&self) -> bool {
745        matches!(self, Self::Num { .. })
746    }
747
748    #[inline(always)]
749    fn take_num(self, _: &mut Self::Buffer) -> (f64, Atom) {
750        match self {
751            Self::Num { value, raw } => (value, raw),
752            _ => unreachable!(),
753        }
754    }
755
756    #[inline(always)]
757    fn is_bigint(&self) -> bool {
758        matches!(self, Self::BigInt { .. })
759    }
760
761    #[inline(always)]
762    fn take_bigint(self, _: &mut Self::Buffer) -> (Box<BigIntValue>, Atom) {
763        match self {
764            Self::BigInt { value, raw } => (value, raw),
765            _ => unreachable!(),
766        }
767    }
768
769    #[inline(always)]
770    fn take_word(self, _: &Self::Buffer) -> Option<Atom> {
771        match self {
772            Self::Word(word) => Some(word.into()),
773            _ => unreachable!(),
774        }
775    }
776
777    #[inline(always)]
778    fn is_unknown_ident(&self) -> bool {
779        matches!(self, Self::Word(Word::Ident(IdentLike::Other(_))))
780    }
781
782    #[inline(always)]
783    fn take_unknown_ident(self, _: &mut Self::Buffer) -> Atom {
784        match self {
785            Self::Word(Word::Ident(IdentLike::Other(ident))) => ident,
786            _ => unreachable!(),
787        }
788    }
789
790    #[inline(always)]
791    fn take_unknown_ident_ref<'b>(&'b self, _: &'b Self::Buffer) -> &'b Atom {
792        match self {
793            Self::Word(Word::Ident(IdentLike::Other(ref ident))) => ident,
794            _ => unreachable!(),
795        }
796    }
797
798    #[inline(always)]
799    fn is_keyword(&self) -> bool {
800        matches!(self, Self::Word(Word::Keyword(_)))
801    }
802
803    #[inline(always)]
804    fn is_known_ident(&self) -> bool {
805        matches!(self, Self::Word(Word::Ident(IdentLike::Known(_))))
806    }
807
808    #[inline(always)]
809    fn take_known_ident(&self) -> Atom {
810        match self {
811            Self::Word(Word::Ident(IdentLike::Known(kwd))) => (*kwd).into(),
812            _ => unreachable!(),
813        }
814    }
815
816    #[inline(always)]
817    fn is_regexp(&self) -> bool {
818        matches!(self, Self::Regex(..))
819    }
820
821    #[inline(always)]
822    fn is_template(&self) -> bool {
823        matches!(self, Self::Template { .. })
824    }
825
826    #[inline(always)]
827    fn take_template(self, _: &mut Self::Buffer) -> (LexResult<Atom>, Atom) {
828        match self {
829            Self::Template { cooked, raw } => (cooked, raw),
830            _ => unreachable!(),
831        }
832    }
833
834    #[inline(always)]
835    fn jsx_text(value: Atom, raw: Atom, _: &mut Self::Lexer) -> Self {
836        Self::JSXText { value, raw }
837    }
838
839    #[inline(always)]
840    fn is_jsx_text(&self) -> bool {
841        matches!(self, Self::JSXText { .. })
842    }
843
844    #[inline(always)]
845    fn take_jsx_text(self, _: &mut Self::Buffer) -> (Atom, Atom) {
846        match self {
847            Self::JSXText { value, raw } => (value, raw),
848            _ => unreachable!(),
849        }
850    }
851
852    #[inline(always)]
853    fn starts_expr(&self) -> bool {
854        self.kind().starts_expr()
855    }
856
857    #[inline(always)]
858    fn to_string(&self, _: &Self::Buffer) -> String {
859        format!("{self:?}")
860    }
861
862    #[inline(always)]
863    fn is_bin_op(&self) -> bool {
864        matches!(self, Self::BinOp(_))
865    }
866
867    #[inline(always)]
868    fn as_assign_op(&self) -> Option<AssignOp> {
869        match self {
870            Self::AssignOp(op) => Some(*op),
871            _ => None,
872        }
873    }
874
875    #[inline(always)]
876    fn as_bin_op(&self) -> Option<BinaryOp> {
877        match self {
878            Self::BinOp(op) => Some((*op).into()),
879            _ => None,
880        }
881    }
882
883    #[inline(always)]
884    fn follows_keyword_let(&self) -> bool {
885        self.kind().follows_keyword_let(false)
886    }
887
888    #[inline(always)]
889    fn is_assign_op(&self) -> bool {
890        matches!(self, Self::AssignOp(_))
891    }
892
893    #[inline(always)]
894    fn take_regexp(self, _: &mut Self::Buffer) -> (Atom, Atom) {
895        match self {
896            Self::Regex(content, flags) => (content, flags),
897            _ => unreachable!(),
898        }
899    }
900
901    #[inline(always)]
902    fn shebang(value: Atom, _: &mut Self::Lexer) -> Self {
903        Self::Shebang(value)
904    }
905
906    #[inline(always)]
907    fn is_shebang(&self) -> bool {
908        matches!(self, Self::Shebang(..))
909    }
910
911    #[inline(always)]
912    fn take_shebang(self, _: &mut Self::Buffer) -> Atom {
913        match self {
914            Self::Shebang(value) => value,
915            _ => unreachable!(),
916        }
917    }
918
919    #[inline(always)]
920    fn is_no_substitution_template_literal(&self) -> bool {
921        false
922    }
923
924    #[inline(always)]
925    fn is_template_head(&self) -> bool {
926        false
927    }
928}
929
930impl Token {
931    pub fn kind(&self) -> TokenKind {
932        match self {
933            Self::Arrow => TokenKind::Arrow,
934            Self::Hash => TokenKind::Hash,
935            Self::At => TokenKind::At,
936            Self::Dot => TokenKind::Dot,
937            Self::DotDotDot => TokenKind::DotDotDot,
938            Self::Bang => TokenKind::Bang,
939            Self::LParen => TokenKind::LParen,
940            Self::RParen => TokenKind::RParen,
941            Self::LBracket => TokenKind::LBracket,
942            Self::RBracket => TokenKind::RBracket,
943            Self::LBrace => TokenKind::LBrace,
944            Self::RBrace => TokenKind::RBrace,
945            Self::Semi => TokenKind::Semi,
946            Self::Comma => TokenKind::Comma,
947            Self::BackQuote => TokenKind::BackQuote,
948            Self::Template { .. } => TokenKind::Template,
949            Self::Colon => TokenKind::Colon,
950            Self::BinOp(op) => TokenKind::BinOp(*op),
951            Self::AssignOp(op) => TokenKind::AssignOp(*op),
952            Self::DollarLBrace => TokenKind::DollarLBrace,
953            Self::QuestionMark => TokenKind::QuestionMark,
954            Self::PlusPlus => TokenKind::PlusPlus,
955            Self::MinusMinus => TokenKind::MinusMinus,
956            Self::Tilde => TokenKind::Tilde,
957            Self::Str { .. } => TokenKind::Str,
958            Self::Regex(..) => TokenKind::Regex,
959            Self::Num { .. } => TokenKind::Num,
960            Self::BigInt { .. } => TokenKind::BigInt,
961            Self::JSXName { .. } => TokenKind::JSXName,
962            Self::JSXText { .. } => TokenKind::JSXText,
963            Self::JSXTagStart => TokenKind::JSXTagStart,
964            Self::JSXTagEnd => TokenKind::JSXTagEnd,
965            Self::Shebang(..) => TokenKind::Shebang,
966            Self::Error(..) => TokenKind::Error,
967            Self::Eof => TokenKind::Error,
968            Self::Word(w) => TokenKind::Word(w.kind()),
969        }
970    }
971}
972
973impl TokenKind {
974    pub const fn before_expr(self) -> bool {
975        match self {
976            Self::Word(w) => w.before_expr(),
977            Self::BinOp(w) => w.before_expr(),
978            Self::Arrow
979            | Self::DotDotDot
980            | Self::Bang
981            | Self::LParen
982            | Self::LBrace
983            | Self::LBracket
984            | Self::Semi
985            | Self::Comma
986            | Self::Colon
987            | Self::AssignOp(..)
988            | Self::DollarLBrace
989            | Self::QuestionMark
990            | Self::PlusPlus
991            | Self::MinusMinus
992            | Self::Tilde
993            | Self::JSXText { .. } => true,
994            _ => false,
995        }
996    }
997
998    pub const fn starts_expr(self) -> bool {
999        match self {
1000            Self::Word(w) => w.starts_expr(),
1001            Self::BinOp(w) => w.starts_expr(),
1002            Self::Bang
1003            | Self::LParen
1004            | Self::LBrace
1005            | Self::LBracket
1006            | Self::BackQuote
1007            | Self::DollarLBrace
1008            | Self::PlusPlus
1009            | Self::MinusMinus
1010            | Self::Tilde
1011            | Self::Str
1012            | Self::Regex
1013            | Self::Num
1014            | Self::BigInt
1015            | Self::JSXTagStart => true,
1016            _ => false,
1017        }
1018    }
1019}
1020
1021#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
1022pub enum BinOpToken {
1023    /// `==`
1024    EqEq,
1025    /// `!=`
1026    NotEq,
1027    /// `===`
1028    EqEqEq,
1029    /// `!==`
1030    NotEqEq,
1031    /// `<`
1032    Lt,
1033    /// `<=`
1034    LtEq,
1035    /// `>`
1036    Gt,
1037    /// `>=`
1038    GtEq,
1039    /// `<<`
1040    LShift,
1041    /// `>>`
1042    RShift,
1043    /// `>>>`
1044    ZeroFillRShift,
1045
1046    /// `+`
1047    Add,
1048    /// `-`
1049    Sub,
1050    /// `*`
1051    Mul,
1052    /// `/`
1053    Div,
1054    /// `%`
1055    Mod,
1056
1057    /// `|`
1058    BitOr,
1059    /// `^`
1060    BitXor,
1061    /// `&`
1062    BitAnd,
1063
1064    // /// `in`
1065    // #[kind(precedence = "7")]
1066    // In,
1067    // /// `instanceof`
1068    // #[kind(precedence = "7")]
1069    // InstanceOf,
1070    /// `**`
1071    Exp,
1072
1073    /// `||`
1074    LogicalOr,
1075    /// `&&`
1076    LogicalAnd,
1077
1078    /// `??`
1079    NullishCoalescing,
1080}
1081
1082impl BinOpToken {
1083    pub(crate) const fn starts_expr(self) -> bool {
1084        matches!(self, Self::Add | Self::Sub)
1085    }
1086
1087    pub const fn before_expr(self) -> bool {
1088        true
1089    }
1090}
1091
1092#[derive(Debug, Clone, PartialEq)]
1093pub struct TokenAndSpan {
1094    pub token: Token,
1095    /// Had a line break before this token?
1096    pub had_line_break: bool,
1097    pub span: Span,
1098}
1099
1100impl crate::common::parser::token_and_span::TokenAndSpan for TokenAndSpan {
1101    type Token = Token;
1102
1103    #[inline(always)]
1104    fn new(token: Token, span: Span, had_line_break: bool) -> Self {
1105        Self {
1106            token,
1107            had_line_break,
1108            span,
1109        }
1110    }
1111
1112    #[inline(always)]
1113    fn token(&self) -> &Token {
1114        &self.token
1115    }
1116
1117    #[inline(always)]
1118    fn take_token(self) -> Token {
1119        self.token
1120    }
1121
1122    #[inline(always)]
1123    fn had_line_break(&self) -> bool {
1124        self.had_line_break
1125    }
1126
1127    #[inline(always)]
1128    fn span(&self) -> Span {
1129        self.span
1130    }
1131}
1132
1133impl crate::common::parser::buffer::NextTokenAndSpan for TokenAndSpan {
1134    type Token = Token;
1135
1136    #[inline(always)]
1137    fn token(&self) -> &Self::Token {
1138        &self.token
1139    }
1140
1141    #[inline(always)]
1142    fn span(&self) -> Span {
1143        self.span
1144    }
1145
1146    #[inline(always)]
1147    fn had_line_break(&self) -> bool {
1148        self.had_line_break
1149    }
1150}
1151
1152impl Spanned for TokenAndSpan {
1153    #[inline]
1154    fn span(&self) -> Span {
1155        self.span
1156    }
1157}
1158
1159#[derive(Clone, PartialEq, Eq, Hash)]
1160pub enum Word {
1161    Keyword(Keyword),
1162
1163    Null,
1164    True,
1165    False,
1166
1167    Ident(IdentLike),
1168}
1169
1170#[derive(Clone, PartialEq, Eq, Hash)]
1171pub enum IdentLike {
1172    Known(KnownIdent),
1173    Other(Atom),
1174}
1175
1176impl From<&'_ str> for IdentLike {
1177    fn from(s: &str) -> Self {
1178        s.parse::<KnownIdent>()
1179            .map(Self::Known)
1180            .unwrap_or_else(|_| Self::Other(s.into()))
1181    }
1182}
1183
1184impl IdentLike {
1185    pub(crate) fn from_str(atoms: &mut AtomStore, s: &str) -> IdentLike {
1186        s.parse::<KnownIdent>()
1187            .map(Self::Known)
1188            .unwrap_or_else(|_| Self::Other(atoms.atom(s)))
1189    }
1190}
1191
1192impl Word {
1193    pub fn from_str(atoms: &mut AtomStore, s: &str) -> Self {
1194        match s {
1195            "null" => Word::Null,
1196            "true" => Word::True,
1197            "false" => Word::False,
1198            "await" => Await.into(),
1199            "break" => Break.into(),
1200            "case" => Case.into(),
1201            "catch" => Catch.into(),
1202            "continue" => Continue.into(),
1203            "debugger" => Debugger.into(),
1204            "default" => Default_.into(),
1205            "do" => Do.into(),
1206            "export" => Export.into(),
1207            "else" => Else.into(),
1208            "finally" => Finally.into(),
1209            "for" => For.into(),
1210            "function" => Function.into(),
1211            "if" => If.into(),
1212            "return" => Return.into(),
1213            "switch" => Switch.into(),
1214            "throw" => Throw.into(),
1215            "try" => Try.into(),
1216            "var" => Var.into(),
1217            "let" => Let.into(),
1218            "const" => Const.into(),
1219            "while" => While.into(),
1220            "with" => With.into(),
1221            "new" => New.into(),
1222            "this" => This.into(),
1223            "super" => Super.into(),
1224            "class" => Class.into(),
1225            "extends" => Extends.into(),
1226            "import" => Import.into(),
1227            "yield" => Yield.into(),
1228            "in" => In.into(),
1229            "instanceof" => InstanceOf.into(),
1230            "typeof" => TypeOf.into(),
1231            "void" => Void.into(),
1232            "delete" => Delete.into(),
1233            _ => Word::Ident(IdentLike::from_str(atoms, s)),
1234        }
1235    }
1236
1237    pub(crate) fn kind(&self) -> WordKind {
1238        match self {
1239            Word::Keyword(k) => WordKind::Keyword(*k),
1240            Word::Null => WordKind::Null,
1241            Word::True => WordKind::True,
1242            Word::False => WordKind::False,
1243            Word::Ident(IdentLike::Known(i)) => WordKind::Ident(IdentKind::Known(*i)),
1244            Word::Ident(IdentLike::Other(..)) => WordKind::Ident(IdentKind::Other),
1245        }
1246    }
1247}
1248
1249impl WordKind {
1250    pub(crate) const fn before_expr(self) -> bool {
1251        match self {
1252            Self::Keyword(k) => k.before_expr(),
1253            _ => false,
1254        }
1255    }
1256
1257    pub(crate) const fn starts_expr(self) -> bool {
1258        match self {
1259            Self::Keyword(k) => k.starts_expr(),
1260            _ => true,
1261        }
1262    }
1263}
1264
1265impl AsRef<str> for IdentLike {
1266    fn as_ref(&self) -> &str {
1267        match self {
1268            IdentLike::Known(k) => (*k).into(),
1269            IdentLike::Other(s) => s.as_ref(),
1270        }
1271    }
1272}
1273
1274impl From<Keyword> for Word {
1275    fn from(kwd: Keyword) -> Self {
1276        Word::Keyword(kwd)
1277    }
1278}
1279
1280impl From<Word> for Atom {
1281    fn from(w: Word) -> Self {
1282        match w {
1283            Word::Keyword(k) => match k {
1284                Await => "await",
1285                Break => "break",
1286                Case => "case",
1287                Catch => "catch",
1288                Continue => "continue",
1289                Debugger => "debugger",
1290                Default_ => "default",
1291                Do => "do",
1292                Else => "else",
1293
1294                Finally => "finally",
1295                For => "for",
1296
1297                Function => "function",
1298
1299                If => "if",
1300
1301                Return => "return",
1302
1303                Switch => "switch",
1304
1305                Throw => "throw",
1306
1307                Try => "try",
1308                Var => "var",
1309                Let => "let",
1310                Const => "const",
1311                While => "while",
1312                With => "with",
1313
1314                New => "new",
1315                This => "this",
1316                Super => "super",
1317
1318                Class => "class",
1319
1320                Extends => "extends",
1321
1322                Export => "export",
1323                Import => "import",
1324
1325                Yield => "yield",
1326
1327                In => "in",
1328                InstanceOf => "instanceof",
1329
1330                TypeOf => "typeof",
1331
1332                Void => "void",
1333
1334                Delete => "delete",
1335            }
1336            .into(),
1337
1338            Word::Null => atom!("null"),
1339            Word::True => atom!("true"),
1340            Word::False => atom!("false"),
1341
1342            Word::Ident(w) => w.into(),
1343        }
1344    }
1345}
1346
1347impl From<IdentLike> for Atom {
1348    fn from(i: IdentLike) -> Self {
1349        match i {
1350            IdentLike::Known(i) => i.into(),
1351            IdentLike::Other(i) => i,
1352        }
1353    }
1354}
1355
1356impl Debug for Word {
1357    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1358        match *self {
1359            Word::Ident(ref s) => Display::fmt(s, f),
1360            _ => {
1361                let s: Atom = self.clone().into();
1362                Display::fmt(&s, f)
1363            }
1364        }
1365    }
1366}
1367
1368impl Display for IdentLike {
1369    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1370        match *self {
1371            IdentLike::Known(ref s) => Display::fmt(s, f),
1372            IdentLike::Other(ref s) => Display::fmt(s, f),
1373        }
1374    }
1375}
1376
1377impl Display for KnownIdent {
1378    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1379        let s: &'static str = (*self).into();
1380
1381        Display::fmt(s, f)
1382    }
1383}
1384
1385#[macro_export]
1386macro_rules! declare_keyword {
1387    ($(
1388        $name:ident => $value:tt,
1389    )*) => {
1390        impl Keyword {
1391            pub fn into_atom(self) -> Atom {
1392                match self {
1393                    $(Keyword::$name => atom!($value),)*
1394                }
1395            }
1396        }
1397    };
1398}
1399
1400declare_keyword!(
1401    Await => "await",
1402    Break => "break",
1403    Case => "case",
1404    Catch => "catch",
1405    Continue => "continue",
1406    Debugger => "debugger",
1407    Default_ => "default",
1408    Do => "do",
1409    Else => "else",
1410
1411    Finally => "finally",
1412    For => "for",
1413
1414    Function => "function",
1415
1416    If => "if",
1417
1418    Return => "return",
1419
1420    Switch => "switch",
1421
1422    Throw => "throw",
1423
1424    Try => "try",
1425    Var => "var",
1426    Let => "let",
1427    Const => "const",
1428    While => "while",
1429    With => "with",
1430
1431    New => "new",
1432    This => "this",
1433    Super => "super",
1434
1435    Class => "class",
1436
1437    Extends => "extends",
1438
1439    Export => "export",
1440    Import => "import",
1441
1442    Yield => "yield",
1443
1444    In => "in",
1445    InstanceOf => "instanceof",
1446
1447    TypeOf => "typeof",
1448
1449    Void => "void",
1450
1451    Delete => "delete",
1452);
1453
1454/// Keywords
1455#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1456pub enum Keyword {
1457    /// Spec says this might be identifier.
1458    Await,
1459    Break,
1460    Case,
1461    Catch,
1462    Continue,
1463    Debugger,
1464    Default_,
1465    Do,
1466    Else,
1467
1468    Finally,
1469    For,
1470
1471    Function,
1472
1473    If,
1474
1475    Return,
1476
1477    Switch,
1478
1479    Throw,
1480
1481    Try,
1482    Var,
1483    Let,
1484    Const,
1485    While,
1486    With,
1487
1488    New,
1489    This,
1490    Super,
1491
1492    Class,
1493
1494    Extends,
1495
1496    Export,
1497    Import,
1498
1499    /// Spec says this might be identifier.
1500    Yield,
1501
1502    In,
1503    InstanceOf,
1504    TypeOf,
1505    Void,
1506    Delete,
1507}
1508
1509impl Keyword {
1510    pub const fn before_expr(self) -> bool {
1511        matches!(
1512            self,
1513            Self::Await
1514                | Self::Case
1515                | Self::Default_
1516                | Self::Do
1517                | Self::Else
1518                | Self::Return
1519                | Self::Throw
1520                | Self::New
1521                | Self::Extends
1522                | Self::Yield
1523                | Self::In
1524                | Self::InstanceOf
1525                | Self::TypeOf
1526                | Self::Void
1527                | Self::Delete
1528        )
1529    }
1530
1531    pub(crate) const fn starts_expr(self) -> bool {
1532        matches!(
1533            self,
1534            Self::Await
1535                | Self::Function
1536                | Self::Throw
1537                | Self::New
1538                | Self::This
1539                | Self::Super
1540                | Self::Class
1541                | Self::Import
1542                | Self::Yield
1543                | Self::TypeOf
1544                | Self::Void
1545                | Self::Delete
1546        )
1547    }
1548}
1549
1550impl Debug for Keyword {
1551    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1552        write!(f, "keyword '{}'", self.into_atom())?;
1553
1554        Ok(())
1555    }
1556}
1557
1558impl From<BinOpToken> for BinaryOp {
1559    fn from(t: BinOpToken) -> Self {
1560        use self::BinaryOp::*;
1561        match t {
1562            BinOpToken::EqEq => EqEq,
1563            BinOpToken::NotEq => NotEq,
1564            BinOpToken::EqEqEq => EqEqEq,
1565            BinOpToken::NotEqEq => NotEqEq,
1566            BinOpToken::Lt => Lt,
1567            BinOpToken::LtEq => LtEq,
1568            BinOpToken::Gt => Gt,
1569            BinOpToken::GtEq => GtEq,
1570            BinOpToken::LShift => LShift,
1571            BinOpToken::RShift => RShift,
1572            BinOpToken::ZeroFillRShift => ZeroFillRShift,
1573            BinOpToken::Add => Add,
1574            BinOpToken::Sub => Sub,
1575            BinOpToken::Mul => Mul,
1576            BinOpToken::Div => Div,
1577            BinOpToken::Mod => Mod,
1578            BinOpToken::BitOr => BitOr,
1579            BinOpToken::BitXor => BitXor,
1580            BinOpToken::BitAnd => BitAnd,
1581            BinOpToken::LogicalOr => LogicalOr,
1582            BinOpToken::LogicalAnd => LogicalAnd,
1583            BinOpToken::Exp => Exp,
1584            BinOpToken::NullishCoalescing => NullishCoalescing,
1585        }
1586    }
1587}
1588
1589impl TokenKind {
1590    /// Returns true if `self` can follow keyword let.
1591    ///
1592    /// e.g. `let a = xx;`, `let {a:{}} = 1`
1593    pub fn follows_keyword_let(self, _strict: bool) -> bool {
1594        match self {
1595            Self::Word(WordKind::Keyword(Keyword::Let))
1596            | TokenKind::LBrace
1597            | TokenKind::LBracket
1598            | Self::Word(WordKind::Ident(..))
1599            | TokenKind::Word(WordKind::Keyword(Keyword::Yield))
1600            | TokenKind::Word(WordKind::Keyword(Keyword::Await)) => true,
1601            _ => false,
1602        }
1603    }
1604}
1605
1606impl Word {
1607    pub fn cow(&self) -> Cow<Atom> {
1608        match self {
1609            Word::Keyword(k) => Cow::Owned(k.into_atom()),
1610            Word::Ident(IdentLike::Known(w)) => Cow::Owned((*w).into()),
1611            Word::Ident(IdentLike::Other(w)) => Cow::Borrowed(w),
1612            Word::False => Cow::Owned(atom!("false")),
1613            Word::True => Cow::Owned(atom!("true")),
1614            Word::Null => Cow::Owned(atom!("null")),
1615        }
1616    }
1617}
1618
1619impl Debug for Token {
1620    /// This method is called only in the case of parsing failure.
1621    #[cold]
1622    #[inline(never)]
1623    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1624        match self {
1625            Word(w) => write!(f, "{w:?}")?,
1626            Arrow => write!(f, "=>")?,
1627            Hash => write!(f, "#")?,
1628            At => write!(f, "@")?,
1629            Dot => write!(f, ".")?,
1630            DotDotDot => write!(f, "...")?,
1631            Bang => write!(f, "!")?,
1632            LParen => write!(f, "(")?,
1633            RParen => write!(f, ")")?,
1634            LBracket => write!(f, "[")?,
1635            RBracket => write!(f, "]")?,
1636            LBrace => write!(f, "{{")?,
1637            RBrace => write!(f, "}}")?,
1638            Semi => write!(f, ";")?,
1639            Comma => write!(f, ",")?,
1640            BackQuote => write!(f, "`")?,
1641            Template { raw, .. } => write!(f, "template token ({raw})")?,
1642            Colon => write!(f, ":")?,
1643            BinOp(op) => write!(f, "{}", BinaryOp::from(*op).as_str())?,
1644            AssignOp(op) => write!(f, "{}", op.as_str())?,
1645            DollarLBrace => write!(f, "${{")?,
1646            QuestionMark => write!(f, "?")?,
1647            PlusPlus => write!(f, "++")?,
1648            MinusMinus => write!(f, "--")?,
1649            Tilde => write!(f, "~")?,
1650            Str { value, raw } => write!(f, "string literal ({value}, {raw})")?,
1651            Regex(exp, flags) => write!(f, "regexp literal ({exp}, {flags})")?,
1652            Num { value, raw, .. } => write!(f, "numeric literal ({value}, {raw})")?,
1653            BigInt { value, raw } => write!(f, "bigint literal ({value}, {raw})")?,
1654            JSXName { name } => write!(f, "jsx name ({name})")?,
1655            JSXText { raw, .. } => write!(f, "jsx text ({raw})")?,
1656            JSXTagStart => write!(f, "< (jsx tag start)")?,
1657            JSXTagEnd => write!(f, "> (jsx tag end)")?,
1658            Shebang(_) => write!(f, "#!")?,
1659            Error(e) => write!(f, "<lexing error: {e:?}>")?,
1660            Eof => write!(f, "<eof>")?,
1661        }
1662
1663        Ok(())
1664    }
1665}