• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1namespace ts {
2    export type ErrorCallback = (message: DiagnosticMessage, length: number) => void;
3
4    /* @internal */
5    export function tokenIsIdentifierOrKeyword(token: SyntaxKind): boolean {
6        return token >= SyntaxKind.Identifier;
7    }
8
9    /* @internal */
10    export function tokenIsIdentifierOrKeywordOrGreaterThan(token: SyntaxKind): boolean {
11        return token === SyntaxKind.GreaterThanToken || tokenIsIdentifierOrKeyword(token);
12    }
13
14    export interface Scanner {
15        getStartPos(): number;
16        getToken(): SyntaxKind;
17        getTextPos(): number;
18        getTokenPos(): number;
19        getTokenText(): string;
20        getTokenValue(): string;
21        hasUnicodeEscape(): boolean;
22        hasExtendedUnicodeEscape(): boolean;
23        hasPrecedingLineBreak(): boolean;
24        /* @internal */
25        hasPrecedingJSDocComment(): boolean;
26        isIdentifier(): boolean;
27        isReservedWord(): boolean;
28        isUnterminated(): boolean;
29        /* @internal */
30        getNumericLiteralFlags(): TokenFlags;
31        /* @internal */
32        getCommentDirectives(): CommentDirective[] | undefined;
33        /* @internal */
34        getTokenFlags(): TokenFlags;
35        reScanGreaterToken(): SyntaxKind;
36        reScanSlashToken(): SyntaxKind;
37        reScanAsteriskEqualsToken(): SyntaxKind;
38        reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind;
39        reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind;
40        scanJsxIdentifier(): SyntaxKind;
41        scanJsxAttributeValue(): SyntaxKind;
42        reScanJsxAttributeValue(): SyntaxKind;
43        reScanJsxToken(): JsxTokenSyntaxKind;
44        reScanLessThanToken(): SyntaxKind;
45        reScanQuestionToken(): SyntaxKind;
46        reScanInvalidIdentifier(): SyntaxKind;
47        scanJsxToken(): JsxTokenSyntaxKind;
48        scanJsDocToken(): JSDocSyntaxKind;
49        scan(): SyntaxKind;
50
51        getText(): string;
52        /* @internal */
53        clearCommentDirectives(): void;
54        // Sets the text for the scanner to scan.  An optional subrange starting point and length
55        // can be provided to have the scanner only scan a portion of the text.
56        setText(text: string | undefined, start?: number, length?: number): void;
57        setOnError(onError: ErrorCallback | undefined): void;
58        setScriptTarget(scriptTarget: ScriptTarget): void;
59        setLanguageVariant(variant: LanguageVariant): void;
60        setTextPos(textPos: number): void;
61        /* @internal */
62        setInJSDocType(inType: boolean): void;
63        // Invokes the provided callback then unconditionally restores the scanner to the state it
64        // was in immediately prior to invoking the callback.  The result of invoking the callback
65        // is returned from this function.
66        lookAhead<T>(callback: () => T): T;
67
68        // Invokes the callback with the scanner set to scan the specified range. When the callback
69        // returns, the scanner is restored to the state it was in before scanRange was called.
70        scanRange<T>(start: number, length: number, callback: () => T): T;
71
72        // Invokes the provided callback.  If the callback returns something falsy, then it restores
73        // the scanner to the state it was in immediately prior to invoking the callback.  If the
74        // callback returns something truthy, then the scanner state is not rolled back.  The result
75        // of invoking the callback is returned from this function.
76        tryScan<T>(callback: () => T): T;
77    }
78
79    const textToKeywordObj: MapLike<KeywordSyntaxKind> = {
80        abstract: SyntaxKind.AbstractKeyword,
81        any: SyntaxKind.AnyKeyword,
82        as: SyntaxKind.AsKeyword,
83        asserts: SyntaxKind.AssertsKeyword,
84        bigint: SyntaxKind.BigIntKeyword,
85        boolean: SyntaxKind.BooleanKeyword,
86        break: SyntaxKind.BreakKeyword,
87        case: SyntaxKind.CaseKeyword,
88        catch: SyntaxKind.CatchKeyword,
89        class: SyntaxKind.ClassKeyword,
90        struct: SyntaxKind.StructKeyword,
91        continue: SyntaxKind.ContinueKeyword,
92        const: SyntaxKind.ConstKeyword,
93        ["" + "constructor"]: SyntaxKind.ConstructorKeyword,
94        debugger: SyntaxKind.DebuggerKeyword,
95        declare: SyntaxKind.DeclareKeyword,
96        default: SyntaxKind.DefaultKeyword,
97        delete: SyntaxKind.DeleteKeyword,
98        do: SyntaxKind.DoKeyword,
99        else: SyntaxKind.ElseKeyword,
100        enum: SyntaxKind.EnumKeyword,
101        export: SyntaxKind.ExportKeyword,
102        extends: SyntaxKind.ExtendsKeyword,
103        false: SyntaxKind.FalseKeyword,
104        finally: SyntaxKind.FinallyKeyword,
105        for: SyntaxKind.ForKeyword,
106        from: SyntaxKind.FromKeyword,
107        function: SyntaxKind.FunctionKeyword,
108        get: SyntaxKind.GetKeyword,
109        if: SyntaxKind.IfKeyword,
110        implements: SyntaxKind.ImplementsKeyword,
111        import: SyntaxKind.ImportKeyword,
112        in: SyntaxKind.InKeyword,
113        infer: SyntaxKind.InferKeyword,
114        instanceof: SyntaxKind.InstanceOfKeyword,
115        interface: SyntaxKind.InterfaceKeyword,
116        intrinsic: SyntaxKind.IntrinsicKeyword,
117        is: SyntaxKind.IsKeyword,
118        keyof: SyntaxKind.KeyOfKeyword,
119        let: SyntaxKind.LetKeyword,
120        module: SyntaxKind.ModuleKeyword,
121        namespace: SyntaxKind.NamespaceKeyword,
122        never: SyntaxKind.NeverKeyword,
123        new: SyntaxKind.NewKeyword,
124        null: SyntaxKind.NullKeyword,
125        number: SyntaxKind.NumberKeyword,
126        object: SyntaxKind.ObjectKeyword,
127        package: SyntaxKind.PackageKeyword,
128        private: SyntaxKind.PrivateKeyword,
129        protected: SyntaxKind.ProtectedKeyword,
130        public: SyntaxKind.PublicKeyword,
131        readonly: SyntaxKind.ReadonlyKeyword,
132        require: SyntaxKind.RequireKeyword,
133        global: SyntaxKind.GlobalKeyword,
134        return: SyntaxKind.ReturnKeyword,
135        set: SyntaxKind.SetKeyword,
136        static: SyntaxKind.StaticKeyword,
137        string: SyntaxKind.StringKeyword,
138        super: SyntaxKind.SuperKeyword,
139        switch: SyntaxKind.SwitchKeyword,
140        symbol: SyntaxKind.SymbolKeyword,
141        this: SyntaxKind.ThisKeyword,
142        throw: SyntaxKind.ThrowKeyword,
143        true: SyntaxKind.TrueKeyword,
144        try: SyntaxKind.TryKeyword,
145        type: SyntaxKind.TypeKeyword,
146        typeof: SyntaxKind.TypeOfKeyword,
147        undefined: SyntaxKind.UndefinedKeyword,
148        unique: SyntaxKind.UniqueKeyword,
149        unknown: SyntaxKind.UnknownKeyword,
150        var: SyntaxKind.VarKeyword,
151        void: SyntaxKind.VoidKeyword,
152        while: SyntaxKind.WhileKeyword,
153        with: SyntaxKind.WithKeyword,
154        yield: SyntaxKind.YieldKeyword,
155        async: SyntaxKind.AsyncKeyword,
156        await: SyntaxKind.AwaitKeyword,
157        of: SyntaxKind.OfKeyword,
158    };
159
160    const textToKeyword = new Map(getEntries(textToKeywordObj));
161
162    const textToToken = new Map(getEntries({
163        ...textToKeywordObj,
164        "{": SyntaxKind.OpenBraceToken,
165        "}": SyntaxKind.CloseBraceToken,
166        "(": SyntaxKind.OpenParenToken,
167        ")": SyntaxKind.CloseParenToken,
168        "[": SyntaxKind.OpenBracketToken,
169        "]": SyntaxKind.CloseBracketToken,
170        ".": SyntaxKind.DotToken,
171        "...": SyntaxKind.DotDotDotToken,
172        ";": SyntaxKind.SemicolonToken,
173        ",": SyntaxKind.CommaToken,
174        "<": SyntaxKind.LessThanToken,
175        ">": SyntaxKind.GreaterThanToken,
176        "<=": SyntaxKind.LessThanEqualsToken,
177        ">=": SyntaxKind.GreaterThanEqualsToken,
178        "==": SyntaxKind.EqualsEqualsToken,
179        "!=": SyntaxKind.ExclamationEqualsToken,
180        "===": SyntaxKind.EqualsEqualsEqualsToken,
181        "!==": SyntaxKind.ExclamationEqualsEqualsToken,
182        "=>": SyntaxKind.EqualsGreaterThanToken,
183        "+": SyntaxKind.PlusToken,
184        "-": SyntaxKind.MinusToken,
185        "**": SyntaxKind.AsteriskAsteriskToken,
186        "*": SyntaxKind.AsteriskToken,
187        "/": SyntaxKind.SlashToken,
188        "%": SyntaxKind.PercentToken,
189        "++": SyntaxKind.PlusPlusToken,
190        "--": SyntaxKind.MinusMinusToken,
191        "<<": SyntaxKind.LessThanLessThanToken,
192        "</": SyntaxKind.LessThanSlashToken,
193        ">>": SyntaxKind.GreaterThanGreaterThanToken,
194        ">>>": SyntaxKind.GreaterThanGreaterThanGreaterThanToken,
195        "&": SyntaxKind.AmpersandToken,
196        "|": SyntaxKind.BarToken,
197        "^": SyntaxKind.CaretToken,
198        "!": SyntaxKind.ExclamationToken,
199        "~": SyntaxKind.TildeToken,
200        "&&": SyntaxKind.AmpersandAmpersandToken,
201        "||": SyntaxKind.BarBarToken,
202        "?": SyntaxKind.QuestionToken,
203        "??": SyntaxKind.QuestionQuestionToken,
204        "?.": SyntaxKind.QuestionDotToken,
205        ":": SyntaxKind.ColonToken,
206        "=": SyntaxKind.EqualsToken,
207        "+=": SyntaxKind.PlusEqualsToken,
208        "-=": SyntaxKind.MinusEqualsToken,
209        "*=": SyntaxKind.AsteriskEqualsToken,
210        "**=": SyntaxKind.AsteriskAsteriskEqualsToken,
211        "/=": SyntaxKind.SlashEqualsToken,
212        "%=": SyntaxKind.PercentEqualsToken,
213        "<<=": SyntaxKind.LessThanLessThanEqualsToken,
214        ">>=": SyntaxKind.GreaterThanGreaterThanEqualsToken,
215        ">>>=": SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken,
216        "&=": SyntaxKind.AmpersandEqualsToken,
217        "|=": SyntaxKind.BarEqualsToken,
218        "^=": SyntaxKind.CaretEqualsToken,
219        "||=": SyntaxKind.BarBarEqualsToken,
220        "&&=": SyntaxKind.AmpersandAmpersandEqualsToken,
221        "??=": SyntaxKind.QuestionQuestionEqualsToken,
222        "@": SyntaxKind.AtToken,
223        "`": SyntaxKind.BacktickToken
224    }));
225
226    /*
227        As per ECMAScript Language Specification 3th Edition, Section 7.6: Identifiers
228        IdentifierStart ::
229            Can contain Unicode 3.0.0 categories:
230            Uppercase letter (Lu),
231            Lowercase letter (Ll),
232            Titlecase letter (Lt),
233            Modifier letter (Lm),
234            Other letter (Lo), or
235            Letter number (Nl).
236        IdentifierPart :: =
237            Can contain IdentifierStart + Unicode 3.0.0 categories:
238            Non-spacing mark (Mn),
239            Combining spacing mark (Mc),
240            Decimal number (Nd), or
241            Connector punctuation (Pc).
242
243        Codepoint ranges for ES3 Identifiers are extracted from the Unicode 3.0.0 specification at:
244        http://www.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.txt
245    */
246    const unicodeES3IdentifierStart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1610, 1649, 1747, 1749, 1749, 1765, 1766, 1786, 1788, 1808, 1808, 1810, 1836, 1920, 1957, 2309, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2784, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3294, 3294, 3296, 3297, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3424, 3425, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805, 3840, 3840, 3904, 3911, 3913, 3946, 3976, 3979, 4096, 4129, 4131, 4135, 4137, 4138, 4176, 4181, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6067, 6176, 6263, 6272, 6312, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8319, 8319, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12346, 12353, 12436, 12445, 12446, 12449, 12538, 12540, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65138, 65140, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, ];
247    const unicodeES3IdentifierPart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 768, 846, 864, 866, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1155, 1158, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1441, 1443, 1465, 1467, 1469, 1471, 1471, 1473, 1474, 1476, 1476, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1621, 1632, 1641, 1648, 1747, 1749, 1756, 1759, 1768, 1770, 1773, 1776, 1788, 1808, 1836, 1840, 1866, 1920, 1968, 2305, 2307, 2309, 2361, 2364, 2381, 2384, 2388, 2392, 2403, 2406, 2415, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2492, 2494, 2500, 2503, 2504, 2507, 2509, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2562, 2562, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2649, 2652, 2654, 2654, 2662, 2676, 2689, 2691, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2784, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2876, 2883, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2913, 2918, 2927, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3031, 3031, 3047, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3134, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3168, 3169, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3262, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3297, 3302, 3311, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3390, 3395, 3398, 3400, 3402, 3405, 3415, 3415, 3424, 3425, 3430, 3439, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3805, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3946, 3953, 3972, 3974, 3979, 3984, 3991, 3993, 4028, 4038, 4038, 4096, 4129, 4131, 4135, 4137, 4138, 4140, 4146, 4150, 4153, 4160, 4169, 4176, 4185, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 4969, 4977, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6099, 6112, 6121, 6160, 6169, 6176, 6263, 6272, 6313, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8255, 8256, 8319, 8319, 8400, 8412, 8417, 8417, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12346, 12353, 12436, 12441, 12442, 12445, 12446, 12449, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65056, 65059, 65075, 65076, 65101, 65103, 65136, 65138, 65140, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65381, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, ];
248
249    /*
250        As per ECMAScript Language Specification 5th Edition, Section 7.6: ISyntaxToken Names and Identifiers
251        IdentifierStart ::
252            Can contain Unicode 6.2 categories:
253            Uppercase letter (Lu),
254            Lowercase letter (Ll),
255            Titlecase letter (Lt),
256            Modifier letter (Lm),
257            Other letter (Lo), or
258            Letter number (Nl).
259        IdentifierPart ::
260            Can contain IdentifierStart + Unicode 6.2 categories:
261            Non-spacing mark (Mn),
262            Combining spacing mark (Mc),
263            Decimal number (Nd),
264            Connector punctuation (Pc),
265            <ZWNJ>, or
266            <ZWJ>.
267
268        Codepoint ranges for ES5 Identifiers are extracted from the Unicode 6.2 specification at:
269        http://www.unicode.org/Public/6.2.0/ucd/UnicodeData.txt
270    */
271    const unicodeES5IdentifierStart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610, 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2208, 2208, 2210, 2220, 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312, 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516, 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823, 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409, 7413, 7414, 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11502, 11506, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539, 42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43009, 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259, 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442, 43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595, 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44002, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, ];
272    const unicodeES5IdentifierPart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 768, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1155, 1159, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1469, 1471, 1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1520, 1522, 1552, 1562, 1568, 1641, 1646, 1747, 1749, 1756, 1759, 1768, 1770, 1788, 1791, 1791, 1808, 1866, 1869, 1969, 1984, 2037, 2042, 2042, 2048, 2093, 2112, 2139, 2208, 2208, 2210, 2220, 2276, 2302, 2304, 2403, 2406, 2415, 2417, 2423, 2425, 2431, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2500, 2503, 2504, 2507, 2510, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2561, 2563, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652, 2654, 2654, 2662, 2677, 2689, 2691, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2787, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876, 2884, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2915, 2918, 2927, 2929, 2929, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3024, 3024, 3031, 3031, 3046, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3160, 3161, 3168, 3171, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3260, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3299, 3302, 3311, 3313, 3314, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3396, 3398, 3400, 3402, 3406, 3415, 3415, 3424, 3427, 3430, 3439, 3450, 3455, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3807, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3948, 3953, 3972, 3974, 3991, 3993, 4028, 4038, 4038, 4096, 4169, 4176, 4253, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4957, 4959, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5908, 5920, 5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003, 6016, 6099, 6103, 6103, 6108, 6109, 6112, 6121, 6155, 6157, 6160, 6169, 6176, 6263, 6272, 6314, 6320, 6389, 6400, 6428, 6432, 6443, 6448, 6459, 6470, 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6608, 6617, 6656, 6683, 6688, 6750, 6752, 6780, 6783, 6793, 6800, 6809, 6823, 6823, 6912, 6987, 6992, 7001, 7019, 7027, 7040, 7155, 7168, 7223, 7232, 7241, 7245, 7293, 7376, 7378, 7380, 7414, 7424, 7654, 7676, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8204, 8205, 8255, 8256, 8276, 8276, 8305, 8305, 8319, 8319, 8336, 8348, 8400, 8412, 8417, 8417, 8421, 8432, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11647, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11744, 11775, 11823, 11823, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12348, 12353, 12438, 12441, 12442, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42539, 42560, 42607, 42612, 42621, 42623, 42647, 42655, 42737, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43047, 43072, 43123, 43136, 43204, 43216, 43225, 43232, 43255, 43259, 43259, 43264, 43309, 43312, 43347, 43360, 43388, 43392, 43456, 43471, 43481, 43520, 43574, 43584, 43597, 43600, 43609, 43616, 43638, 43642, 43643, 43648, 43714, 43739, 43741, 43744, 43759, 43762, 43766, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44010, 44012, 44013, 44016, 44025, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65024, 65039, 65056, 65062, 65075, 65076, 65101, 65103, 65136, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, ];
273
274    /**
275     * Generated by scripts/regenerate-unicode-identifier-parts.js on node v12.4.0 with unicode 12.1
276     * based on http://www.unicode.org/reports/tr31/ and https://www.ecma-international.org/ecma-262/6.0/#sec-names-and-keywords
277     * unicodeESNextIdentifierStart corresponds to the ID_Start and Other_ID_Start property, and
278     * unicodeESNextIdentifierPart corresponds to ID_Continue, Other_ID_Continue, plus ID_Start and Other_ID_Start
279     */
280    const unicodeESNextIdentifierStart = [65, 90, 97, 122, 170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 880, 884, 886, 887, 890, 893, 895, 895, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1327, 1329, 1366, 1369, 1369, 1376, 1416, 1488, 1514, 1519, 1522, 1568, 1610, 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2144, 2154, 2208, 2228, 2230, 2237, 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2432, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545, 2556, 2556, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, 2809, 2809, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3129, 3133, 3133, 3160, 3162, 3168, 3169, 3200, 3200, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3389, 3406, 3406, 3412, 3414, 3423, 3425, 3450, 3455, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3718, 3722, 3724, 3747, 3749, 3749, 3751, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5109, 5112, 5117, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5880, 5888, 5900, 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6264, 6272, 6312, 6314, 6314, 6320, 6389, 6400, 6430, 6480, 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6656, 6678, 6688, 6740, 6823, 6823, 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245, 7247, 7258, 7293, 7296, 7304, 7312, 7354, 7357, 7359, 7401, 7404, 7406, 7411, 7413, 7414, 7418, 7418, 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8472, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11502, 11506, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438, 12443, 12447, 12449, 12538, 12540, 12543, 12549, 12591, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40943, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539, 42560, 42606, 42623, 42653, 42656, 42735, 42775, 42783, 42786, 42888, 42891, 42943, 42946, 42950, 42999, 43009, 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259, 43261, 43262, 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442, 43471, 43471, 43488, 43492, 43494, 43503, 43514, 43518, 43520, 43560, 43584, 43586, 43588, 43595, 43616, 43638, 43642, 43642, 43646, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43824, 43866, 43868, 43879, 43888, 44002, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594, 65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786, 65856, 65908, 66176, 66204, 66208, 66256, 66304, 66335, 66349, 66378, 66384, 66421, 66432, 66461, 66464, 66499, 66504, 66511, 66513, 66517, 66560, 66717, 66736, 66771, 66776, 66811, 66816, 66855, 66864, 66915, 67072, 67382, 67392, 67413, 67424, 67431, 67584, 67589, 67592, 67592, 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669, 67680, 67702, 67712, 67742, 67808, 67826, 67828, 67829, 67840, 67861, 67872, 67897, 67968, 68023, 68030, 68031, 68096, 68096, 68112, 68115, 68117, 68119, 68121, 68149, 68192, 68220, 68224, 68252, 68288, 68295, 68297, 68324, 68352, 68405, 68416, 68437, 68448, 68466, 68480, 68497, 68608, 68680, 68736, 68786, 68800, 68850, 68864, 68899, 69376, 69404, 69415, 69415, 69424, 69445, 69600, 69622, 69635, 69687, 69763, 69807, 69840, 69864, 69891, 69926, 69956, 69956, 69968, 70002, 70006, 70006, 70019, 70066, 70081, 70084, 70106, 70106, 70108, 70108, 70144, 70161, 70163, 70187, 70272, 70278, 70280, 70280, 70282, 70285, 70287, 70301, 70303, 70312, 70320, 70366, 70405, 70412, 70415, 70416, 70419, 70440, 70442, 70448, 70450, 70451, 70453, 70457, 70461, 70461, 70480, 70480, 70493, 70497, 70656, 70708, 70727, 70730, 70751, 70751, 70784, 70831, 70852, 70853, 70855, 70855, 71040, 71086, 71128, 71131, 71168, 71215, 71236, 71236, 71296, 71338, 71352, 71352, 71424, 71450, 71680, 71723, 71840, 71903, 71935, 71935, 72096, 72103, 72106, 72144, 72161, 72161, 72163, 72163, 72192, 72192, 72203, 72242, 72250, 72250, 72272, 72272, 72284, 72329, 72349, 72349, 72384, 72440, 72704, 72712, 72714, 72750, 72768, 72768, 72818, 72847, 72960, 72966, 72968, 72969, 72971, 73008, 73030, 73030, 73056, 73061, 73063, 73064, 73066, 73097, 73112, 73112, 73440, 73458, 73728, 74649, 74752, 74862, 74880, 75075, 77824, 78894, 82944, 83526, 92160, 92728, 92736, 92766, 92880, 92909, 92928, 92975, 92992, 92995, 93027, 93047, 93053, 93071, 93760, 93823, 93952, 94026, 94032, 94032, 94099, 94111, 94176, 94177, 94179, 94179, 94208, 100343, 100352, 101106, 110592, 110878, 110928, 110930, 110948, 110951, 110960, 111355, 113664, 113770, 113776, 113788, 113792, 113800, 113808, 113817, 119808, 119892, 119894, 119964, 119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980, 119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069, 120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121, 120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144, 120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570, 120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686, 120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779, 123136, 123180, 123191, 123197, 123214, 123214, 123584, 123627, 124928, 125124, 125184, 125251, 125259, 125259, 126464, 126467, 126469, 126495, 126497, 126498, 126500, 126500, 126503, 126503, 126505, 126514, 126516, 126519, 126521, 126521, 126523, 126523, 126530, 126530, 126535, 126535, 126537, 126537, 126539, 126539, 126541, 126543, 126545, 126546, 126548, 126548, 126551, 126551, 126553, 126553, 126555, 126555, 126557, 126557, 126559, 126559, 126561, 126562, 126564, 126564, 126567, 126570, 126572, 126578, 126580, 126583, 126585, 126588, 126590, 126590, 126592, 126601, 126603, 126619, 126625, 126627, 126629, 126633, 126635, 126651, 131072, 173782, 173824, 177972, 177984, 178205, 178208, 183969, 183984, 191456, 194560, 195101];
281    const unicodeESNextIdentifierPart = [48, 57, 65, 90, 95, 95, 97, 122, 170, 170, 181, 181, 183, 183, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 768, 884, 886, 887, 890, 893, 895, 895, 902, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1155, 1159, 1162, 1327, 1329, 1366, 1369, 1369, 1376, 1416, 1425, 1469, 1471, 1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1519, 1522, 1552, 1562, 1568, 1641, 1646, 1747, 1749, 1756, 1759, 1768, 1770, 1788, 1791, 1791, 1808, 1866, 1869, 1969, 1984, 2037, 2042, 2042, 2045, 2045, 2048, 2093, 2112, 2139, 2144, 2154, 2208, 2228, 2230, 2237, 2259, 2273, 2275, 2403, 2406, 2415, 2417, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2500, 2503, 2504, 2507, 2510, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2556, 2556, 2558, 2558, 2561, 2563, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652, 2654, 2654, 2662, 2677, 2689, 2691, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2787, 2790, 2799, 2809, 2815, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876, 2884, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2915, 2918, 2927, 2929, 2929, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3024, 3024, 3031, 3031, 3046, 3055, 3072, 3084, 3086, 3088, 3090, 3112, 3114, 3129, 3133, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3160, 3162, 3168, 3171, 3174, 3183, 3200, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3260, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3299, 3302, 3311, 3313, 3314, 3328, 3331, 3333, 3340, 3342, 3344, 3346, 3396, 3398, 3400, 3402, 3406, 3412, 3415, 3423, 3427, 3430, 3439, 3450, 3455, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3558, 3567, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3718, 3722, 3724, 3747, 3749, 3749, 3751, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3807, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3948, 3953, 3972, 3974, 3991, 3993, 4028, 4038, 4038, 4096, 4169, 4176, 4253, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4957, 4959, 4969, 4977, 4992, 5007, 5024, 5109, 5112, 5117, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5880, 5888, 5900, 5902, 5908, 5920, 5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003, 6016, 6099, 6103, 6103, 6108, 6109, 6112, 6121, 6155, 6157, 6160, 6169, 6176, 6264, 6272, 6314, 6320, 6389, 6400, 6430, 6432, 6443, 6448, 6459, 6470, 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6608, 6618, 6656, 6683, 6688, 6750, 6752, 6780, 6783, 6793, 6800, 6809, 6823, 6823, 6832, 6845, 6912, 6987, 6992, 7001, 7019, 7027, 7040, 7155, 7168, 7223, 7232, 7241, 7245, 7293, 7296, 7304, 7312, 7354, 7357, 7359, 7376, 7378, 7380, 7418, 7424, 7673, 7675, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8255, 8256, 8276, 8276, 8305, 8305, 8319, 8319, 8336, 8348, 8400, 8412, 8417, 8417, 8421, 8432, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8472, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11647, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11744, 11775, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12348, 12353, 12438, 12441, 12447, 12449, 12538, 12540, 12543, 12549, 12591, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40943, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42539, 42560, 42607, 42612, 42621, 42623, 42737, 42775, 42783, 42786, 42888, 42891, 42943, 42946, 42950, 42999, 43047, 43072, 43123, 43136, 43205, 43216, 43225, 43232, 43255, 43259, 43259, 43261, 43309, 43312, 43347, 43360, 43388, 43392, 43456, 43471, 43481, 43488, 43518, 43520, 43574, 43584, 43597, 43600, 43609, 43616, 43638, 43642, 43714, 43739, 43741, 43744, 43759, 43762, 43766, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43824, 43866, 43868, 43879, 43888, 44010, 44012, 44013, 44016, 44025, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65024, 65039, 65056, 65071, 65075, 65076, 65101, 65103, 65136, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594, 65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786, 65856, 65908, 66045, 66045, 66176, 66204, 66208, 66256, 66272, 66272, 66304, 66335, 66349, 66378, 66384, 66426, 66432, 66461, 66464, 66499, 66504, 66511, 66513, 66517, 66560, 66717, 66720, 66729, 66736, 66771, 66776, 66811, 66816, 66855, 66864, 66915, 67072, 67382, 67392, 67413, 67424, 67431, 67584, 67589, 67592, 67592, 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669, 67680, 67702, 67712, 67742, 67808, 67826, 67828, 67829, 67840, 67861, 67872, 67897, 67968, 68023, 68030, 68031, 68096, 68099, 68101, 68102, 68108, 68115, 68117, 68119, 68121, 68149, 68152, 68154, 68159, 68159, 68192, 68220, 68224, 68252, 68288, 68295, 68297, 68326, 68352, 68405, 68416, 68437, 68448, 68466, 68480, 68497, 68608, 68680, 68736, 68786, 68800, 68850, 68864, 68903, 68912, 68921, 69376, 69404, 69415, 69415, 69424, 69456, 69600, 69622, 69632, 69702, 69734, 69743, 69759, 69818, 69840, 69864, 69872, 69881, 69888, 69940, 69942, 69951, 69956, 69958, 69968, 70003, 70006, 70006, 70016, 70084, 70089, 70092, 70096, 70106, 70108, 70108, 70144, 70161, 70163, 70199, 70206, 70206, 70272, 70278, 70280, 70280, 70282, 70285, 70287, 70301, 70303, 70312, 70320, 70378, 70384, 70393, 70400, 70403, 70405, 70412, 70415, 70416, 70419, 70440, 70442, 70448, 70450, 70451, 70453, 70457, 70459, 70468, 70471, 70472, 70475, 70477, 70480, 70480, 70487, 70487, 70493, 70499, 70502, 70508, 70512, 70516, 70656, 70730, 70736, 70745, 70750, 70751, 70784, 70853, 70855, 70855, 70864, 70873, 71040, 71093, 71096, 71104, 71128, 71133, 71168, 71232, 71236, 71236, 71248, 71257, 71296, 71352, 71360, 71369, 71424, 71450, 71453, 71467, 71472, 71481, 71680, 71738, 71840, 71913, 71935, 71935, 72096, 72103, 72106, 72151, 72154, 72161, 72163, 72164, 72192, 72254, 72263, 72263, 72272, 72345, 72349, 72349, 72384, 72440, 72704, 72712, 72714, 72758, 72760, 72768, 72784, 72793, 72818, 72847, 72850, 72871, 72873, 72886, 72960, 72966, 72968, 72969, 72971, 73014, 73018, 73018, 73020, 73021, 73023, 73031, 73040, 73049, 73056, 73061, 73063, 73064, 73066, 73102, 73104, 73105, 73107, 73112, 73120, 73129, 73440, 73462, 73728, 74649, 74752, 74862, 74880, 75075, 77824, 78894, 82944, 83526, 92160, 92728, 92736, 92766, 92768, 92777, 92880, 92909, 92912, 92916, 92928, 92982, 92992, 92995, 93008, 93017, 93027, 93047, 93053, 93071, 93760, 93823, 93952, 94026, 94031, 94087, 94095, 94111, 94176, 94177, 94179, 94179, 94208, 100343, 100352, 101106, 110592, 110878, 110928, 110930, 110948, 110951, 110960, 111355, 113664, 113770, 113776, 113788, 113792, 113800, 113808, 113817, 113821, 113822, 119141, 119145, 119149, 119154, 119163, 119170, 119173, 119179, 119210, 119213, 119362, 119364, 119808, 119892, 119894, 119964, 119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980, 119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069, 120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121, 120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144, 120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570, 120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686, 120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779, 120782, 120831, 121344, 121398, 121403, 121452, 121461, 121461, 121476, 121476, 121499, 121503, 121505, 121519, 122880, 122886, 122888, 122904, 122907, 122913, 122915, 122916, 122918, 122922, 123136, 123180, 123184, 123197, 123200, 123209, 123214, 123214, 123584, 123641, 124928, 125124, 125136, 125142, 125184, 125259, 125264, 125273, 126464, 126467, 126469, 126495, 126497, 126498, 126500, 126500, 126503, 126503, 126505, 126514, 126516, 126519, 126521, 126521, 126523, 126523, 126530, 126530, 126535, 126535, 126537, 126537, 126539, 126539, 126541, 126543, 126545, 126546, 126548, 126548, 126551, 126551, 126553, 126553, 126555, 126555, 126557, 126557, 126559, 126559, 126561, 126562, 126564, 126564, 126567, 126570, 126572, 126578, 126580, 126583, 126585, 126588, 126590, 126590, 126592, 126601, 126603, 126619, 126625, 126627, 126629, 126633, 126635, 126651, 131072, 173782, 173824, 177972, 177984, 178205, 178208, 183969, 183984, 191456, 194560, 195101, 917760, 917999];
282
283    /**
284     * Test for whether a single line comment's text contains a directive.
285     */
286    const commentDirectiveRegExSingleLine = /^\s*\/\/\/?\s*@(ts-expect-error|ts-ignore)/;
287
288    /**
289     * Test for whether a multi-line comment's last line contains a directive.
290     */
291    const commentDirectiveRegExMultiLine = /^\s*(?:\/|\*)*\s*@(ts-expect-error|ts-ignore)/;
292
293    function lookupInUnicodeMap(code: number, map: readonly number[]): boolean {
294        // Bail out quickly if it couldn't possibly be in the map.
295        if (code < map[0]) {
296            return false;
297        }
298
299        // Perform binary search in one of the Unicode range maps
300        let lo = 0;
301        let hi: number = map.length;
302        let mid: number;
303
304        while (lo + 1 < hi) {
305            mid = lo + (hi - lo) / 2;
306            // mid has to be even to catch a range's beginning
307            mid -= mid % 2;
308            if (map[mid] <= code && code <= map[mid + 1]) {
309                return true;
310            }
311
312            if (code < map[mid]) {
313                hi = mid;
314            }
315            else {
316                lo = mid + 2;
317            }
318        }
319
320        return false;
321    }
322
323    /* @internal */ export function isUnicodeIdentifierStart(code: number, languageVersion: ScriptTarget | undefined) {
324        return languageVersion! >= ScriptTarget.ES2015 ?
325            lookupInUnicodeMap(code, unicodeESNextIdentifierStart) :
326            languageVersion === ScriptTarget.ES5 ? lookupInUnicodeMap(code, unicodeES5IdentifierStart) :
327                lookupInUnicodeMap(code, unicodeES3IdentifierStart);
328    }
329
330    function isUnicodeIdentifierPart(code: number, languageVersion: ScriptTarget | undefined) {
331        return languageVersion! >= ScriptTarget.ES2015 ?
332            lookupInUnicodeMap(code, unicodeESNextIdentifierPart) :
333            languageVersion === ScriptTarget.ES5 ? lookupInUnicodeMap(code, unicodeES5IdentifierPart) :
334                lookupInUnicodeMap(code, unicodeES3IdentifierPart);
335    }
336
337    function makeReverseMap(source: ESMap<string, number>): string[] {
338        const result: string[] = [];
339        source.forEach((value, name) => {
340            result[value] = name;
341        });
342        return result;
343    }
344
345    const tokenStrings = makeReverseMap(textToToken);
346    export function tokenToString(t: SyntaxKind): string | undefined {
347        return tokenStrings[t];
348    }
349
350    /* @internal */
351    export function stringToToken(s: string): SyntaxKind | undefined {
352        return textToToken.get(s);
353    }
354
355    /* @internal */
356    export function computeLineStarts(text: string): number[] {
357        const result: number[] = new Array();
358        let pos = 0;
359        let lineStart = 0;
360        while (pos < text.length) {
361            const ch = text.charCodeAt(pos);
362            pos++;
363            switch (ch) {
364                case CharacterCodes.carriageReturn:
365                    if (text.charCodeAt(pos) === CharacterCodes.lineFeed) {
366                        pos++;
367                    }
368                // falls through
369                case CharacterCodes.lineFeed:
370                    result.push(lineStart);
371                    lineStart = pos;
372                    break;
373                default:
374                    if (ch > CharacterCodes.maxAsciiCharacter && isLineBreak(ch)) {
375                        result.push(lineStart);
376                        lineStart = pos;
377                    }
378                    break;
379            }
380        }
381        result.push(lineStart);
382        return result;
383    }
384
385    export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number): number;
386    /* @internal */
387    export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number, allowEdits?: true): number; // eslint-disable-line @typescript-eslint/unified-signatures
388    export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number, allowEdits?: true): number {
389        return sourceFile.getPositionOfLineAndCharacter ?
390            sourceFile.getPositionOfLineAndCharacter(line, character, allowEdits) :
391            computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character, sourceFile.text, allowEdits);
392    }
393
394    /* @internal */
395    export function computePositionOfLineAndCharacter(lineStarts: readonly number[], line: number, character: number, debugText?: string, allowEdits?: true): number {
396        if (line < 0 || line >= lineStarts.length) {
397            if (allowEdits) {
398                // Clamp line to nearest allowable value
399                line = line < 0 ? 0 : line >= lineStarts.length ? lineStarts.length - 1 : line;
400            }
401            else {
402                Debug.fail(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length} , line map is correct? ${debugText !== undefined ? arraysEqual(lineStarts, computeLineStarts(debugText)) : "unknown"}`);
403            }
404        }
405
406        const res = lineStarts[line] + character;
407        if (allowEdits) {
408            // Clamp to nearest allowable values to allow the underlying to be edited without crashing (accuracy is lost, instead)
409            // TODO: Somehow track edits between file as it was during the creation of sourcemap we have and the current file and
410            // apply them to the computed position to improve accuracy
411            return res > lineStarts[line + 1] ? lineStarts[line + 1] : typeof debugText === "string" && res > debugText.length ? debugText.length : res;
412        }
413        if (line < lineStarts.length - 1) {
414            Debug.assert(res < lineStarts[line + 1]);
415        }
416        else if (debugText !== undefined) {
417            Debug.assert(res <= debugText.length); // Allow single character overflow for trailing newline
418        }
419        return res;
420    }
421
422    /* @internal */
423    export function getLineStarts(sourceFile: SourceFileLike): readonly number[] {
424        return sourceFile.lineMap || (sourceFile.lineMap = computeLineStarts(sourceFile.text));
425    }
426
427    /* @internal */
428    export function computeLineAndCharacterOfPosition(lineStarts: readonly number[], position: number): LineAndCharacter {
429        const lineNumber = computeLineOfPosition(lineStarts, position);
430        return {
431            line: lineNumber,
432            character: position - lineStarts[lineNumber]
433        };
434    }
435
436    /**
437     * @internal
438     * We assume the first line starts at position 0 and 'position' is non-negative.
439     */
440    export function computeLineOfPosition(lineStarts: readonly number[], position: number, lowerBound?: number) {
441        let lineNumber = binarySearch(lineStarts, position, identity, compareValues, lowerBound);
442        if (lineNumber < 0) {
443            // If the actual position was not found,
444            // the binary search returns the 2's-complement of the next line start
445            // e.g. if the line starts at [5, 10, 23, 80] and the position requested was 20
446            // then the search will return -2.
447            //
448            // We want the index of the previous line start, so we subtract 1.
449            // Review 2's-complement if this is confusing.
450            lineNumber = ~lineNumber - 1;
451            Debug.assert(lineNumber !== -1, "position cannot precede the beginning of the file");
452        }
453        return lineNumber;
454    }
455
456    /** @internal */
457    export function getLinesBetweenPositions(sourceFile: SourceFileLike, pos1: number, pos2: number) {
458        if (pos1 === pos2) return 0;
459        const lineStarts = getLineStarts(sourceFile);
460        const lower = Math.min(pos1, pos2);
461        const isNegative = lower === pos2;
462        const upper = isNegative ? pos1 : pos2;
463        const lowerLine = computeLineOfPosition(lineStarts, lower);
464        const upperLine = computeLineOfPosition(lineStarts, upper, lowerLine);
465        return isNegative ? lowerLine - upperLine : upperLine - lowerLine;
466    }
467
468    export function getLineAndCharacterOfPosition(sourceFile: SourceFileLike, position: number): LineAndCharacter {
469        return computeLineAndCharacterOfPosition(getLineStarts(sourceFile), position);
470    }
471
472    export function isWhiteSpaceLike(ch: number): boolean {
473        return isWhiteSpaceSingleLine(ch) || isLineBreak(ch);
474    }
475
476    /** Does not include line breaks. For that, see isWhiteSpaceLike. */
477    export function isWhiteSpaceSingleLine(ch: number): boolean {
478        // Note: nextLine is in the Zs space, and should be considered to be a whitespace.
479        // It is explicitly not a line-break as it isn't in the exact set specified by EcmaScript.
480        return ch === CharacterCodes.space ||
481            ch === CharacterCodes.tab ||
482            ch === CharacterCodes.verticalTab ||
483            ch === CharacterCodes.formFeed ||
484            ch === CharacterCodes.nonBreakingSpace ||
485            ch === CharacterCodes.nextLine ||
486            ch === CharacterCodes.ogham ||
487            ch >= CharacterCodes.enQuad && ch <= CharacterCodes.zeroWidthSpace ||
488            ch === CharacterCodes.narrowNoBreakSpace ||
489            ch === CharacterCodes.mathematicalSpace ||
490            ch === CharacterCodes.ideographicSpace ||
491            ch === CharacterCodes.byteOrderMark;
492    }
493
494    export function isLineBreak(ch: number): boolean {
495        // ES5 7.3:
496        // The ECMAScript line terminator characters are listed in Table 3.
497        //     Table 3: Line Terminator Characters
498        //     Code Unit Value     Name                    Formal Name
499        //     \u000A              Line Feed               <LF>
500        //     \u000D              Carriage Return         <CR>
501        //     \u2028              Line separator          <LS>
502        //     \u2029              Paragraph separator     <PS>
503        // Only the characters in Table 3 are treated as line terminators. Other new line or line
504        // breaking characters are treated as white space but not as line terminators.
505
506        return ch === CharacterCodes.lineFeed ||
507            ch === CharacterCodes.carriageReturn ||
508            ch === CharacterCodes.lineSeparator ||
509            ch === CharacterCodes.paragraphSeparator;
510    }
511
512    function isDigit(ch: number): boolean {
513        return ch >= CharacterCodes._0 && ch <= CharacterCodes._9;
514    }
515
516    function isHexDigit(ch: number): boolean {
517        return isDigit(ch) || ch >= CharacterCodes.A && ch <= CharacterCodes.F || ch >= CharacterCodes.a && ch <= CharacterCodes.f;
518    }
519
520    function isCodePoint(code: number): boolean {
521        return code <= 0x10FFFF;
522    }
523
524    /* @internal */
525    export function isOctalDigit(ch: number): boolean {
526        return ch >= CharacterCodes._0 && ch <= CharacterCodes._7;
527    }
528
529    export function couldStartTrivia(text: string, pos: number): boolean {
530        // Keep in sync with skipTrivia
531        const ch = text.charCodeAt(pos);
532        switch (ch) {
533            case CharacterCodes.carriageReturn:
534            case CharacterCodes.lineFeed:
535            case CharacterCodes.tab:
536            case CharacterCodes.verticalTab:
537            case CharacterCodes.formFeed:
538            case CharacterCodes.space:
539            case CharacterCodes.slash:
540            // starts of normal trivia
541            // falls through
542            case CharacterCodes.lessThan:
543            case CharacterCodes.bar:
544            case CharacterCodes.equals:
545            case CharacterCodes.greaterThan:
546                // Starts of conflict marker trivia
547                return true;
548            case CharacterCodes.hash:
549                // Only if its the beginning can we have #! trivia
550                return pos === 0;
551            default:
552                return ch > CharacterCodes.maxAsciiCharacter;
553        }
554    }
555
556    /* @internal */
557    export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean, stopAtComments = false): number {
558        if (positionIsSynthesized(pos)) {
559            return pos;
560        }
561
562        // Keep in sync with couldStartTrivia
563        while (true) {
564            const ch = text.charCodeAt(pos);
565            switch (ch) {
566                case CharacterCodes.carriageReturn:
567                    if (text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) {
568                        pos++;
569                    }
570                // falls through
571                case CharacterCodes.lineFeed:
572                    pos++;
573                    if (stopAfterLineBreak) {
574                        return pos;
575                    }
576                    continue;
577                case CharacterCodes.tab:
578                case CharacterCodes.verticalTab:
579                case CharacterCodes.formFeed:
580                case CharacterCodes.space:
581                    pos++;
582                    continue;
583                case CharacterCodes.slash:
584                    if (stopAtComments) {
585                        break;
586                    }
587                    if (text.charCodeAt(pos + 1) === CharacterCodes.slash) {
588                        pos += 2;
589                        while (pos < text.length) {
590                            if (isLineBreak(text.charCodeAt(pos))) {
591                                break;
592                            }
593                            pos++;
594                        }
595                        continue;
596                    }
597                    if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) {
598                        pos += 2;
599                        while (pos < text.length) {
600                            if (text.charCodeAt(pos) === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) {
601                                pos += 2;
602                                break;
603                            }
604                            pos++;
605                        }
606                        continue;
607                    }
608                    break;
609
610                case CharacterCodes.lessThan:
611                case CharacterCodes.bar:
612                case CharacterCodes.equals:
613                case CharacterCodes.greaterThan:
614                    if (isConflictMarkerTrivia(text, pos)) {
615                        pos = scanConflictMarkerTrivia(text, pos);
616                        continue;
617                    }
618                    break;
619
620                case CharacterCodes.hash:
621                    if (pos === 0 && isShebangTrivia(text, pos)) {
622                        pos = scanShebangTrivia(text, pos);
623                        continue;
624                    }
625                    break;
626
627                default:
628                    if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpaceLike(ch))) {
629                        pos++;
630                        continue;
631                    }
632                    break;
633            }
634            return pos;
635        }
636    }
637
638    // All conflict markers consist of the same character repeated seven times.  If it is
639    // a <<<<<<< or >>>>>>> marker then it is also followed by a space.
640    const mergeConflictMarkerLength = "<<<<<<<".length;
641
642    function isConflictMarkerTrivia(text: string, pos: number) {
643        Debug.assert(pos >= 0);
644
645        // Conflict markers must be at the start of a line.
646        if (pos === 0 || isLineBreak(text.charCodeAt(pos - 1))) {
647            const ch = text.charCodeAt(pos);
648
649            if ((pos + mergeConflictMarkerLength) < text.length) {
650                for (let i = 0; i < mergeConflictMarkerLength; i++) {
651                    if (text.charCodeAt(pos + i) !== ch) {
652                        return false;
653                    }
654                }
655
656                return ch === CharacterCodes.equals ||
657                    text.charCodeAt(pos + mergeConflictMarkerLength) === CharacterCodes.space;
658            }
659        }
660
661        return false;
662    }
663
664    function scanConflictMarkerTrivia(text: string, pos: number, error?: (diag: DiagnosticMessage, pos?: number, len?: number) => void) {
665        if (error) {
666            error(Diagnostics.Merge_conflict_marker_encountered, pos, mergeConflictMarkerLength);
667        }
668
669        const ch = text.charCodeAt(pos);
670        const len = text.length;
671
672        if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) {
673            while (pos < len && !isLineBreak(text.charCodeAt(pos))) {
674                pos++;
675            }
676        }
677        else {
678            Debug.assert(ch === CharacterCodes.bar || ch === CharacterCodes.equals);
679            // Consume everything from the start of a ||||||| or ======= marker to the start
680            // of the next ======= or >>>>>>> marker.
681            while (pos < len) {
682                const currentChar = text.charCodeAt(pos);
683                if ((currentChar === CharacterCodes.equals || currentChar === CharacterCodes.greaterThan) && currentChar !== ch && isConflictMarkerTrivia(text, pos)) {
684                    break;
685                }
686
687                pos++;
688            }
689        }
690
691        return pos;
692    }
693
694    const shebangTriviaRegex = /^#!.*/;
695
696    /*@internal*/
697    export function isShebangTrivia(text: string, pos: number) {
698        // Shebangs check must only be done at the start of the file
699        Debug.assert(pos === 0);
700        return shebangTriviaRegex.test(text);
701    }
702
703    /*@internal*/
704    export function scanShebangTrivia(text: string, pos: number) {
705        const shebang = shebangTriviaRegex.exec(text)![0];
706        pos = pos + shebang.length;
707        return pos;
708    }
709
710    /**
711     * Invokes a callback for each comment range following the provided position.
712     *
713     * Single-line comment ranges include the leading double-slash characters but not the ending
714     * line break. Multi-line comment ranges include the leading slash-asterisk and trailing
715     * asterisk-slash characters.
716     *
717     * @param reduce If true, accumulates the result of calling the callback in a fashion similar
718     *      to reduceLeft. If false, iteration stops when the callback returns a truthy value.
719     * @param text The source text to scan.
720     * @param pos The position at which to start scanning.
721     * @param trailing If false, whitespace is skipped until the first line break and comments
722     *      between that location and the next token are returned. If true, comments occurring
723     *      between the given position and the next line break are returned.
724     * @param cb The callback to execute as each comment range is encountered.
725     * @param state A state value to pass to each iteration of the callback.
726     * @param initial An initial value to pass when accumulating results (when "reduce" is true).
727     * @returns If "reduce" is true, the accumulated value. If "reduce" is false, the first truthy
728     *      return value of the callback.
729     */
730    function iterateCommentRanges<T, U>(reduce: boolean, text: string, pos: number, trailing: boolean, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U | undefined) => U, state: T, initial?: U): U | undefined {
731        let pendingPos!: number;
732        let pendingEnd!: number;
733        let pendingKind!: CommentKind;
734        let pendingHasTrailingNewLine!: boolean;
735        let hasPendingCommentRange = false;
736        let collecting = trailing;
737        let accumulator = initial;
738        if (pos === 0) {
739            collecting = true;
740            const shebang = getShebang(text);
741            if (shebang) {
742                pos = shebang.length;
743            }
744        }
745        scan: while (pos >= 0 && pos < text.length) {
746            const ch = text.charCodeAt(pos);
747            switch (ch) {
748                case CharacterCodes.carriageReturn:
749                    if (text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) {
750                        pos++;
751                    }
752                // falls through
753                case CharacterCodes.lineFeed:
754                    pos++;
755                    if (trailing) {
756                        break scan;
757                    }
758
759                    collecting = true;
760                    if (hasPendingCommentRange) {
761                        pendingHasTrailingNewLine = true;
762                    }
763
764                    continue;
765                case CharacterCodes.tab:
766                case CharacterCodes.verticalTab:
767                case CharacterCodes.formFeed:
768                case CharacterCodes.space:
769                    pos++;
770                    continue;
771                case CharacterCodes.slash:
772                    const nextChar = text.charCodeAt(pos + 1);
773                    let hasTrailingNewLine = false;
774                    if (nextChar === CharacterCodes.slash || nextChar === CharacterCodes.asterisk) {
775                        const kind = nextChar === CharacterCodes.slash ? SyntaxKind.SingleLineCommentTrivia : SyntaxKind.MultiLineCommentTrivia;
776                        const startPos = pos;
777                        pos += 2;
778                        if (nextChar === CharacterCodes.slash) {
779                            while (pos < text.length) {
780                                if (isLineBreak(text.charCodeAt(pos))) {
781                                    hasTrailingNewLine = true;
782                                    break;
783                                }
784                                pos++;
785                            }
786                        }
787                        else {
788                            while (pos < text.length) {
789                                if (text.charCodeAt(pos) === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) {
790                                    pos += 2;
791                                    break;
792                                }
793                                pos++;
794                            }
795                        }
796
797                        if (collecting) {
798                            if (hasPendingCommentRange) {
799                                accumulator = cb(pendingPos, pendingEnd, pendingKind, pendingHasTrailingNewLine, state, accumulator);
800                                if (!reduce && accumulator) {
801                                    // If we are not reducing and we have a truthy result, return it.
802                                    return accumulator;
803                                }
804                            }
805
806                            pendingPos = startPos;
807                            pendingEnd = pos;
808                            pendingKind = kind;
809                            pendingHasTrailingNewLine = hasTrailingNewLine;
810                            hasPendingCommentRange = true;
811                        }
812
813                        continue;
814                    }
815                    break scan;
816                default:
817                    if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpaceLike(ch))) {
818                        if (hasPendingCommentRange && isLineBreak(ch)) {
819                            pendingHasTrailingNewLine = true;
820                        }
821                        pos++;
822                        continue;
823                    }
824                    break scan;
825            }
826        }
827
828        if (hasPendingCommentRange) {
829            accumulator = cb(pendingPos, pendingEnd, pendingKind, pendingHasTrailingNewLine, state, accumulator);
830        }
831
832        return accumulator;
833    }
834
835    export function forEachLeadingCommentRange<U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U): U | undefined;
836    export function forEachLeadingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined;
837    export function forEachLeadingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U | undefined {
838        return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ false, cb, state);
839    }
840
841    export function forEachTrailingCommentRange<U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U): U | undefined;
842    export function forEachTrailingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined;
843    export function forEachTrailingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U | undefined {
844        return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ true, cb, state);
845    }
846
847    export function reduceEachLeadingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U) {
848        return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ false, cb, state, initial);
849    }
850
851    export function reduceEachTrailingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U) {
852        return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ true, cb, state, initial);
853    }
854
855    function appendCommentRange(pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, _state: any, comments: CommentRange[]) {
856        if (!comments) {
857            comments = [];
858        }
859
860        comments.push({ kind, pos, end, hasTrailingNewLine });
861        return comments;
862    }
863
864    export function getLeadingCommentRanges(text: string, pos: number): CommentRange[] | undefined {
865        return reduceEachLeadingCommentRange(text, pos, appendCommentRange, /*state*/ undefined, /*initial*/ undefined);
866    }
867
868    export function getTrailingCommentRanges(text: string, pos: number): CommentRange[] | undefined {
869        return reduceEachTrailingCommentRange(text, pos, appendCommentRange, /*state*/ undefined, /*initial*/ undefined);
870    }
871
872    /** Optionally, get the shebang */
873    export function getShebang(text: string): string | undefined {
874        const match = shebangTriviaRegex.exec(text);
875        if (match) {
876            return match[0];
877        }
878    }
879
880    export function isIdentifierStart(ch: number, languageVersion: ScriptTarget | undefined): boolean {
881        return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z ||
882            ch === CharacterCodes.$ || ch === CharacterCodes._ ||
883            ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierStart(ch, languageVersion);
884    }
885
886    export function isIdentifierPart(ch: number, languageVersion: ScriptTarget | undefined, identifierVariant?: LanguageVariant): boolean {
887        return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z ||
888            ch >= CharacterCodes._0 && ch <= CharacterCodes._9 || ch === CharacterCodes.$ || ch === CharacterCodes._ ||
889            // "-" and ":" are valid in JSX Identifiers
890            (identifierVariant === LanguageVariant.JSX ? (ch === CharacterCodes.minus || ch === CharacterCodes.colon) : false) ||
891            ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion);
892    }
893
894    /* @internal */
895    export function isIdentifierText(name: string, languageVersion: ScriptTarget | undefined, identifierVariant?: LanguageVariant): boolean {
896        let ch = codePointAt(name, 0);
897        if (!isIdentifierStart(ch, languageVersion)) {
898            return false;
899        }
900
901        for (let i = charSize(ch); i < name.length; i += charSize(ch)) {
902            if (!isIdentifierPart(ch = codePointAt(name, i), languageVersion, identifierVariant)) {
903                return false;
904            }
905        }
906
907        return true;
908    }
909
910    // Creates a scanner over a (possibly unspecified) range of a piece of text.
911    export function createScanner(languageVersion: ScriptTarget,
912        skipTrivia: boolean,
913        languageVariant = LanguageVariant.Standard,
914        textInitial?: string,
915        onError?: ErrorCallback,
916        start?: number,
917        length?: number): Scanner {
918
919        let text = textInitial!;
920
921        // Current position (end position of text of current token)
922        let pos: number;
923
924
925        // end of text
926        let end: number;
927
928        // Start position of whitespace before current token
929        let startPos: number;
930
931        // Start position of text of current token
932        let tokenPos: number;
933
934        let token: SyntaxKind;
935        let tokenValue!: string;
936        let tokenFlags: TokenFlags;
937
938        let commentDirectives: CommentDirective[] | undefined;
939        let inJSDocType = 0;
940
941        setText(text, start, length);
942
943        const scanner: Scanner = {
944            getStartPos: () => startPos,
945            getTextPos: () => pos,
946            getToken: () => token,
947            getTokenPos: () => tokenPos,
948            getTokenText: () => text.substring(tokenPos, pos),
949            getTokenValue: () => tokenValue,
950            hasUnicodeEscape: () => (tokenFlags & TokenFlags.UnicodeEscape) !== 0,
951            hasExtendedUnicodeEscape: () => (tokenFlags & TokenFlags.ExtendedUnicodeEscape) !== 0,
952            hasPrecedingLineBreak: () => (tokenFlags & TokenFlags.PrecedingLineBreak) !== 0,
953            hasPrecedingJSDocComment: () => (tokenFlags & TokenFlags.PrecedingJSDocComment) !== 0,
954            isIdentifier: () => token === SyntaxKind.Identifier || token > SyntaxKind.LastReservedWord,
955            isReservedWord: () => token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord,
956            isUnterminated: () => (tokenFlags & TokenFlags.Unterminated) !== 0,
957            getCommentDirectives: () => commentDirectives,
958            getNumericLiteralFlags: () => tokenFlags & TokenFlags.NumericLiteralFlags,
959            getTokenFlags: () => tokenFlags,
960            reScanGreaterToken,
961            reScanAsteriskEqualsToken,
962            reScanSlashToken,
963            reScanTemplateToken,
964            reScanTemplateHeadOrNoSubstitutionTemplate,
965            scanJsxIdentifier,
966            scanJsxAttributeValue,
967            reScanJsxAttributeValue,
968            reScanJsxToken,
969            reScanLessThanToken,
970            reScanQuestionToken,
971            reScanInvalidIdentifier,
972            scanJsxToken,
973            scanJsDocToken,
974            scan,
975            getText,
976            clearCommentDirectives,
977            setText,
978            setScriptTarget,
979            setLanguageVariant,
980            setOnError,
981            setTextPos,
982            setInJSDocType,
983            tryScan,
984            lookAhead,
985            scanRange,
986        };
987
988        if (Debug.isDebugging) {
989            Object.defineProperty(scanner, "__debugShowCurrentPositionInText", {
990                get: () => {
991                    const text = scanner.getText();
992                    return text.slice(0, scanner.getStartPos()) + "║" + text.slice(scanner.getStartPos());
993                },
994            });
995        }
996
997        return scanner;
998
999        function error(message: DiagnosticMessage): void;
1000        function error(message: DiagnosticMessage, errPos: number, length: number): void;
1001        function error(message: DiagnosticMessage, errPos: number = pos, length?: number): void {
1002            if (onError) {
1003                const oldPos = pos;
1004                pos = errPos;
1005                onError(message, length || 0);
1006                pos = oldPos;
1007            }
1008        }
1009
1010        function scanNumberFragment(): string {
1011            let start = pos;
1012            let allowSeparator = false;
1013            let isPreviousTokenSeparator = false;
1014            let result = "";
1015            while (true) {
1016                const ch = text.charCodeAt(pos);
1017                if (ch === CharacterCodes._) {
1018                    tokenFlags |= TokenFlags.ContainsSeparator;
1019                    if (allowSeparator) {
1020                        allowSeparator = false;
1021                        isPreviousTokenSeparator = true;
1022                        result += text.substring(start, pos);
1023                    }
1024                    else if (isPreviousTokenSeparator) {
1025                        error(Diagnostics.Multiple_consecutive_numeric_separators_are_not_permitted, pos, 1);
1026                    }
1027                    else {
1028                        error(Diagnostics.Numeric_separators_are_not_allowed_here, pos, 1);
1029                    }
1030                    pos++;
1031                    start = pos;
1032                    continue;
1033                }
1034                if (isDigit(ch)) {
1035                    allowSeparator = true;
1036                    isPreviousTokenSeparator = false;
1037                    pos++;
1038                    continue;
1039                }
1040                break;
1041            }
1042            if (text.charCodeAt(pos - 1) === CharacterCodes._) {
1043                error(Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1);
1044            }
1045            return result + text.substring(start, pos);
1046        }
1047
1048        function scanNumber(): { type: SyntaxKind, value: string } {
1049            const start = pos;
1050            const mainFragment = scanNumberFragment();
1051            let decimalFragment: string | undefined;
1052            let scientificFragment: string | undefined;
1053            if (text.charCodeAt(pos) === CharacterCodes.dot) {
1054                pos++;
1055                decimalFragment = scanNumberFragment();
1056            }
1057            let end = pos;
1058            if (text.charCodeAt(pos) === CharacterCodes.E || text.charCodeAt(pos) === CharacterCodes.e) {
1059                pos++;
1060                tokenFlags |= TokenFlags.Scientific;
1061                if (text.charCodeAt(pos) === CharacterCodes.plus || text.charCodeAt(pos) === CharacterCodes.minus) pos++;
1062                const preNumericPart = pos;
1063                const finalFragment = scanNumberFragment();
1064                if (!finalFragment) {
1065                    error(Diagnostics.Digit_expected);
1066                }
1067                else {
1068                    scientificFragment = text.substring(end, preNumericPart) + finalFragment;
1069                    end = pos;
1070                }
1071            }
1072            let result: string;
1073            if (tokenFlags & TokenFlags.ContainsSeparator) {
1074                result = mainFragment;
1075                if (decimalFragment) {
1076                    result += "." + decimalFragment;
1077                }
1078                if (scientificFragment) {
1079                    result += scientificFragment;
1080                }
1081            }
1082            else {
1083                result = text.substring(start, end); // No need to use all the fragments; no _ removal needed
1084            }
1085
1086            if (decimalFragment !== undefined || tokenFlags & TokenFlags.Scientific) {
1087                checkForIdentifierStartAfterNumericLiteral(start, decimalFragment === undefined && !!(tokenFlags & TokenFlags.Scientific));
1088                return {
1089                    type: SyntaxKind.NumericLiteral,
1090                    value: "" + +result // if value is not an integer, it can be safely coerced to a number
1091                };
1092            }
1093            else {
1094                tokenValue = result;
1095                const type = checkBigIntSuffix(); // if value is an integer, check whether it is a bigint
1096                checkForIdentifierStartAfterNumericLiteral(start);
1097                return { type, value: tokenValue };
1098            }
1099        }
1100
1101        function checkForIdentifierStartAfterNumericLiteral(numericStart: number, isScientific?: boolean) {
1102            if (!isIdentifierStart(codePointAt(text, pos), languageVersion)) {
1103                return;
1104            }
1105
1106            const identifierStart = pos;
1107            const { length } = scanIdentifierParts();
1108
1109            if (length === 1 && text[identifierStart] === "n") {
1110                if (isScientific) {
1111                    error(Diagnostics.A_bigint_literal_cannot_use_exponential_notation, numericStart, identifierStart - numericStart + 1);
1112                }
1113                else {
1114                    error(Diagnostics.A_bigint_literal_must_be_an_integer, numericStart, identifierStart - numericStart + 1);
1115                }
1116            }
1117            else {
1118                error(Diagnostics.An_identifier_or_keyword_cannot_immediately_follow_a_numeric_literal, identifierStart, length);
1119                pos = identifierStart;
1120            }
1121        }
1122
1123        function scanOctalDigits(): number {
1124            const start = pos;
1125            while (isOctalDigit(text.charCodeAt(pos))) {
1126                pos++;
1127            }
1128            return +(text.substring(start, pos));
1129        }
1130
1131        /**
1132         * Scans the given number of hexadecimal digits in the text,
1133         * returning -1 if the given number is unavailable.
1134         */
1135        function scanExactNumberOfHexDigits(count: number, canHaveSeparators: boolean): number {
1136            const valueString = scanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ false, canHaveSeparators);
1137            return valueString ? parseInt(valueString, 16) : -1;
1138        }
1139
1140        /**
1141         * Scans as many hexadecimal digits as are available in the text,
1142         * returning "" if the given number of digits was unavailable.
1143         */
1144        function scanMinimumNumberOfHexDigits(count: number, canHaveSeparators: boolean): string {
1145            return scanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ true, canHaveSeparators);
1146        }
1147
1148        function scanHexDigits(minCount: number, scanAsManyAsPossible: boolean, canHaveSeparators: boolean): string {
1149            let valueChars: number[] = [];
1150            let allowSeparator = false;
1151            let isPreviousTokenSeparator = false;
1152            while (valueChars.length < minCount || scanAsManyAsPossible) {
1153                let ch = text.charCodeAt(pos);
1154                if (canHaveSeparators && ch === CharacterCodes._) {
1155                    tokenFlags |= TokenFlags.ContainsSeparator;
1156                    if (allowSeparator) {
1157                        allowSeparator = false;
1158                        isPreviousTokenSeparator = true;
1159                    }
1160                    else if (isPreviousTokenSeparator) {
1161                        error(Diagnostics.Multiple_consecutive_numeric_separators_are_not_permitted, pos, 1);
1162                    }
1163                    else {
1164                        error(Diagnostics.Numeric_separators_are_not_allowed_here, pos, 1);
1165                    }
1166                    pos++;
1167                    continue;
1168                }
1169                allowSeparator = canHaveSeparators;
1170                if (ch >= CharacterCodes.A && ch <= CharacterCodes.F) {
1171                    ch += CharacterCodes.a - CharacterCodes.A; // standardize hex literals to lowercase
1172                }
1173                else if (!((ch >= CharacterCodes._0 && ch <= CharacterCodes._9) ||
1174                    (ch >= CharacterCodes.a && ch <= CharacterCodes.f)
1175                )) {
1176                    break;
1177                }
1178                valueChars.push(ch);
1179                pos++;
1180                isPreviousTokenSeparator = false;
1181            }
1182            if (valueChars.length < minCount) {
1183                valueChars = [];
1184            }
1185            if (text.charCodeAt(pos - 1) === CharacterCodes._) {
1186                error(Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1);
1187            }
1188            return String.fromCharCode(...valueChars);
1189        }
1190
1191        function scanString(jsxAttributeString = false): string {
1192            const quote = text.charCodeAt(pos);
1193            pos++;
1194            let result = "";
1195            let start = pos;
1196            while (true) {
1197                if (pos >= end) {
1198                    result += text.substring(start, pos);
1199                    tokenFlags |= TokenFlags.Unterminated;
1200                    error(Diagnostics.Unterminated_string_literal);
1201                    break;
1202                }
1203                const ch = text.charCodeAt(pos);
1204                if (ch === quote) {
1205                    result += text.substring(start, pos);
1206                    pos++;
1207                    break;
1208                }
1209                if (ch === CharacterCodes.backslash && !jsxAttributeString) {
1210                    result += text.substring(start, pos);
1211                    result += scanEscapeSequence();
1212                    start = pos;
1213                    continue;
1214                }
1215                if (isLineBreak(ch) && !jsxAttributeString) {
1216                    result += text.substring(start, pos);
1217                    tokenFlags |= TokenFlags.Unterminated;
1218                    error(Diagnostics.Unterminated_string_literal);
1219                    break;
1220                }
1221                pos++;
1222            }
1223            return result;
1224        }
1225
1226        /**
1227         * Sets the current 'tokenValue' and returns a NoSubstitutionTemplateLiteral or
1228         * a literal component of a TemplateExpression.
1229         */
1230        function scanTemplateAndSetTokenValue(isTaggedTemplate: boolean): SyntaxKind {
1231            const startedWithBacktick = text.charCodeAt(pos) === CharacterCodes.backtick;
1232
1233            pos++;
1234            let start = pos;
1235            let contents = "";
1236            let resultingToken: SyntaxKind;
1237
1238            while (true) {
1239                if (pos >= end) {
1240                    contents += text.substring(start, pos);
1241                    tokenFlags |= TokenFlags.Unterminated;
1242                    error(Diagnostics.Unterminated_template_literal);
1243                    resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail;
1244                    break;
1245                }
1246
1247                const currChar = text.charCodeAt(pos);
1248
1249                // '`'
1250                if (currChar === CharacterCodes.backtick) {
1251                    contents += text.substring(start, pos);
1252                    pos++;
1253                    resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail;
1254                    break;
1255                }
1256
1257                // '${'
1258                if (currChar === CharacterCodes.$ && pos + 1 < end && text.charCodeAt(pos + 1) === CharacterCodes.openBrace) {
1259                    contents += text.substring(start, pos);
1260                    pos += 2;
1261                    resultingToken = startedWithBacktick ? SyntaxKind.TemplateHead : SyntaxKind.TemplateMiddle;
1262                    break;
1263                }
1264
1265                // Escape character
1266                if (currChar === CharacterCodes.backslash) {
1267                    contents += text.substring(start, pos);
1268                    contents += scanEscapeSequence(isTaggedTemplate);
1269                    start = pos;
1270                    continue;
1271                }
1272
1273                // Speculated ECMAScript 6 Spec 11.8.6.1:
1274                // <CR><LF> and <CR> LineTerminatorSequences are normalized to <LF> for Template Values
1275                if (currChar === CharacterCodes.carriageReturn) {
1276                    contents += text.substring(start, pos);
1277                    pos++;
1278
1279                    if (pos < end && text.charCodeAt(pos) === CharacterCodes.lineFeed) {
1280                        pos++;
1281                    }
1282
1283                    contents += "\n";
1284                    start = pos;
1285                    continue;
1286                }
1287
1288                pos++;
1289            }
1290
1291            Debug.assert(resultingToken !== undefined);
1292
1293            tokenValue = contents;
1294            return resultingToken;
1295        }
1296
1297        function scanEscapeSequence(isTaggedTemplate?: boolean): string {
1298            const start = pos;
1299            pos++;
1300            if (pos >= end) {
1301                error(Diagnostics.Unexpected_end_of_text);
1302                return "";
1303            }
1304            const ch = text.charCodeAt(pos);
1305            pos++;
1306            switch (ch) {
1307                case CharacterCodes._0:
1308                    // '\01'
1309                    if (isTaggedTemplate && pos < end && isDigit(text.charCodeAt(pos))) {
1310                        pos++;
1311                        tokenFlags |= TokenFlags.ContainsInvalidEscape;
1312                        return text.substring(start, pos);
1313                    }
1314                    return "\0";
1315                case CharacterCodes.b:
1316                    return "\b";
1317                case CharacterCodes.t:
1318                    return "\t";
1319                case CharacterCodes.n:
1320                    return "\n";
1321                case CharacterCodes.v:
1322                    return "\v";
1323                case CharacterCodes.f:
1324                    return "\f";
1325                case CharacterCodes.r:
1326                    return "\r";
1327                case CharacterCodes.singleQuote:
1328                    return "\'";
1329                case CharacterCodes.doubleQuote:
1330                    return "\"";
1331                case CharacterCodes.u:
1332                    if (isTaggedTemplate) {
1333                        // '\u' or '\u0' or '\u00' or '\u000'
1334                        for (let escapePos = pos; escapePos < pos + 4; escapePos++) {
1335                            if (escapePos < end && !isHexDigit(text.charCodeAt(escapePos)) && text.charCodeAt(escapePos) !== CharacterCodes.openBrace) {
1336                                pos = escapePos;
1337                                tokenFlags |= TokenFlags.ContainsInvalidEscape;
1338                                return text.substring(start, pos);
1339                            }
1340                        }
1341                    }
1342                    // '\u{DDDDDDDD}'
1343                    if (pos < end && text.charCodeAt(pos) === CharacterCodes.openBrace) {
1344                        pos++;
1345
1346                        // '\u{'
1347                        if (isTaggedTemplate && !isHexDigit(text.charCodeAt(pos))) {
1348                            tokenFlags |= TokenFlags.ContainsInvalidEscape;
1349                            return text.substring(start, pos);
1350                        }
1351
1352                        if (isTaggedTemplate) {
1353                            const savePos = pos;
1354                            const escapedValueString = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false);
1355                            const escapedValue = escapedValueString ? parseInt(escapedValueString, 16) : -1;
1356
1357                            // '\u{Not Code Point' or '\u{CodePoint'
1358                            if (!isCodePoint(escapedValue) || text.charCodeAt(pos) !== CharacterCodes.closeBrace) {
1359                                tokenFlags |= TokenFlags.ContainsInvalidEscape;
1360                                return text.substring(start, pos);
1361                            }
1362                            else {
1363                                pos = savePos;
1364                            }
1365                        }
1366                        tokenFlags |= TokenFlags.ExtendedUnicodeEscape;
1367                        return scanExtendedUnicodeEscape();
1368                    }
1369
1370                    tokenFlags |= TokenFlags.UnicodeEscape;
1371                    // '\uDDDD'
1372                    return scanHexadecimalEscape(/*numDigits*/ 4);
1373
1374                case CharacterCodes.x:
1375                    if (isTaggedTemplate) {
1376                        if (!isHexDigit(text.charCodeAt(pos))) {
1377                            tokenFlags |= TokenFlags.ContainsInvalidEscape;
1378                            return text.substring(start, pos);
1379                        }
1380                        else if (!isHexDigit(text.charCodeAt(pos + 1))) {
1381                            pos++;
1382                            tokenFlags |= TokenFlags.ContainsInvalidEscape;
1383                            return text.substring(start, pos);
1384                        }
1385                    }
1386                    // '\xDD'
1387                    return scanHexadecimalEscape(/*numDigits*/ 2);
1388
1389                // when encountering a LineContinuation (i.e. a backslash and a line terminator sequence),
1390                // the line terminator is interpreted to be "the empty code unit sequence".
1391                case CharacterCodes.carriageReturn:
1392                    if (pos < end && text.charCodeAt(pos) === CharacterCodes.lineFeed) {
1393                        pos++;
1394                    }
1395                // falls through
1396                case CharacterCodes.lineFeed:
1397                case CharacterCodes.lineSeparator:
1398                case CharacterCodes.paragraphSeparator:
1399                    return "";
1400                default:
1401                    return String.fromCharCode(ch);
1402            }
1403        }
1404
1405        function scanHexadecimalEscape(numDigits: number): string {
1406            const escapedValue = scanExactNumberOfHexDigits(numDigits, /*canHaveSeparators*/ false);
1407
1408            if (escapedValue >= 0) {
1409                return String.fromCharCode(escapedValue);
1410            }
1411            else {
1412                error(Diagnostics.Hexadecimal_digit_expected);
1413                return "";
1414            }
1415        }
1416
1417        function scanExtendedUnicodeEscape(): string {
1418            const escapedValueString = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false);
1419            const escapedValue = escapedValueString ? parseInt(escapedValueString, 16) : -1;
1420            let isInvalidExtendedEscape = false;
1421
1422            // Validate the value of the digit
1423            if (escapedValue < 0) {
1424                error(Diagnostics.Hexadecimal_digit_expected);
1425                isInvalidExtendedEscape = true;
1426            }
1427            else if (escapedValue > 0x10FFFF) {
1428                error(Diagnostics.An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive);
1429                isInvalidExtendedEscape = true;
1430            }
1431
1432            if (pos >= end) {
1433                error(Diagnostics.Unexpected_end_of_text);
1434                isInvalidExtendedEscape = true;
1435            }
1436            else if (text.charCodeAt(pos) === CharacterCodes.closeBrace) {
1437                // Only swallow the following character up if it's a '}'.
1438                pos++;
1439            }
1440            else {
1441                error(Diagnostics.Unterminated_Unicode_escape_sequence);
1442                isInvalidExtendedEscape = true;
1443            }
1444
1445            if (isInvalidExtendedEscape) {
1446                return "";
1447            }
1448
1449            return utf16EncodeAsString(escapedValue);
1450        }
1451
1452        // Current character is known to be a backslash. Check for Unicode escape of the form '\uXXXX'
1453        // and return code point value if valid Unicode escape is found. Otherwise return -1.
1454        function peekUnicodeEscape(): number {
1455            if (pos + 5 < end && text.charCodeAt(pos + 1) === CharacterCodes.u) {
1456                const start = pos;
1457                pos += 2;
1458                const value = scanExactNumberOfHexDigits(4, /*canHaveSeparators*/ false);
1459                pos = start;
1460                return value;
1461            }
1462            return -1;
1463        }
1464
1465
1466        function peekExtendedUnicodeEscape(): number {
1467            if (languageVersion >= ScriptTarget.ES2015 && codePointAt(text, pos + 1) === CharacterCodes.u && codePointAt(text, pos + 2) === CharacterCodes.openBrace) {
1468                const start = pos;
1469                pos += 3;
1470                const escapedValueString = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false);
1471                const escapedValue = escapedValueString ? parseInt(escapedValueString, 16) : -1;
1472                pos = start;
1473                return escapedValue;
1474            }
1475            return -1;
1476        }
1477
1478        function scanIdentifierParts(): string {
1479            let result = "";
1480            let start = pos;
1481            while (pos < end) {
1482                let ch = codePointAt(text, pos);
1483                if (isIdentifierPart(ch, languageVersion)) {
1484                    pos += charSize(ch);
1485                }
1486                else if (ch === CharacterCodes.backslash) {
1487                    ch = peekExtendedUnicodeEscape();
1488                    if (ch >= 0 && isIdentifierPart(ch, languageVersion)) {
1489                        pos += 3;
1490                        tokenFlags |= TokenFlags.ExtendedUnicodeEscape;
1491                        result += scanExtendedUnicodeEscape();
1492                        start = pos;
1493                        continue;
1494                    }
1495                    ch = peekUnicodeEscape();
1496                    if (!(ch >= 0 && isIdentifierPart(ch, languageVersion))) {
1497                        break;
1498                    }
1499                    tokenFlags |= TokenFlags.UnicodeEscape;
1500                    result += text.substring(start, pos);
1501                    result += utf16EncodeAsString(ch);
1502                    // Valid Unicode escape is always six characters
1503                    pos += 6;
1504                    start = pos;
1505                }
1506                else {
1507                    break;
1508                }
1509            }
1510            result += text.substring(start, pos);
1511            return result;
1512        }
1513
1514        function getIdentifierToken(): SyntaxKind.Identifier | KeywordSyntaxKind {
1515            // Reserved words are between 2 and 12 characters long and start with a lowercase letter
1516            const len = tokenValue.length;
1517            if (len >= 2 && len <= 12) {
1518                const ch = tokenValue.charCodeAt(0);
1519                if (ch >= CharacterCodes.a && ch <= CharacterCodes.z) {
1520                    const keyword = textToKeyword.get(tokenValue);
1521                    if (keyword !== undefined) {
1522                        return token = keyword;
1523                    }
1524                }
1525            }
1526            return token = SyntaxKind.Identifier;
1527        }
1528
1529        function scanBinaryOrOctalDigits(base: 2 | 8): string {
1530            let value = "";
1531            // For counting number of digits; Valid binaryIntegerLiteral must have at least one binary digit following B or b.
1532            // Similarly valid octalIntegerLiteral must have at least one octal digit following o or O.
1533            let separatorAllowed = false;
1534            let isPreviousTokenSeparator = false;
1535            while (true) {
1536                const ch = text.charCodeAt(pos);
1537                // Numeric separators are allowed anywhere within a numeric literal, except not at the beginning, or following another separator
1538                if (ch === CharacterCodes._) {
1539                    tokenFlags |= TokenFlags.ContainsSeparator;
1540                    if (separatorAllowed) {
1541                        separatorAllowed = false;
1542                        isPreviousTokenSeparator = true;
1543                    }
1544                    else if (isPreviousTokenSeparator) {
1545                        error(Diagnostics.Multiple_consecutive_numeric_separators_are_not_permitted, pos, 1);
1546                    }
1547                    else {
1548                        error(Diagnostics.Numeric_separators_are_not_allowed_here, pos, 1);
1549                    }
1550                    pos++;
1551                    continue;
1552                }
1553                separatorAllowed = true;
1554                if (!isDigit(ch) || ch - CharacterCodes._0 >= base) {
1555                    break;
1556                }
1557                value += text[pos];
1558                pos++;
1559                isPreviousTokenSeparator = false;
1560            }
1561            if (text.charCodeAt(pos - 1) === CharacterCodes._) {
1562                // Literal ends with underscore - not allowed
1563                error(Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1);
1564            }
1565            return value;
1566        }
1567
1568        function checkBigIntSuffix(): SyntaxKind {
1569            if (text.charCodeAt(pos) === CharacterCodes.n) {
1570                tokenValue += "n";
1571                // Use base 10 instead of base 2 or base 8 for shorter literals
1572                if (tokenFlags & TokenFlags.BinaryOrOctalSpecifier) {
1573                    tokenValue = parsePseudoBigInt(tokenValue) + "n";
1574                }
1575                pos++;
1576                return SyntaxKind.BigIntLiteral;
1577            }
1578            else { // not a bigint, so can convert to number in simplified form
1579                // Number() may not support 0b or 0o, so use parseInt() instead
1580                const numericValue = tokenFlags & TokenFlags.BinarySpecifier
1581                    ? parseInt(tokenValue.slice(2), 2) // skip "0b"
1582                    : tokenFlags & TokenFlags.OctalSpecifier
1583                        ? parseInt(tokenValue.slice(2), 8) // skip "0o"
1584                        : +tokenValue;
1585                tokenValue = "" + numericValue;
1586                return SyntaxKind.NumericLiteral;
1587            }
1588        }
1589
1590        function scan(): SyntaxKind {
1591            startPos = pos;
1592            tokenFlags = TokenFlags.None;
1593            let asteriskSeen = false;
1594            while (true) {
1595                tokenPos = pos;
1596                if (pos >= end) {
1597                    return token = SyntaxKind.EndOfFileToken;
1598                }
1599                let ch = codePointAt(text, pos);
1600
1601                // Special handling for shebang
1602                if (ch === CharacterCodes.hash && pos === 0 && isShebangTrivia(text, pos)) {
1603                    pos = scanShebangTrivia(text, pos);
1604                    if (skipTrivia) {
1605                        continue;
1606                    }
1607                    else {
1608                        return token = SyntaxKind.ShebangTrivia;
1609                    }
1610                }
1611
1612                switch (ch) {
1613                    case CharacterCodes.lineFeed:
1614                    case CharacterCodes.carriageReturn:
1615                        tokenFlags |= TokenFlags.PrecedingLineBreak;
1616                        if (skipTrivia) {
1617                            pos++;
1618                            continue;
1619                        }
1620                        else {
1621                            if (ch === CharacterCodes.carriageReturn && pos + 1 < end && text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) {
1622                                // consume both CR and LF
1623                                pos += 2;
1624                            }
1625                            else {
1626                                pos++;
1627                            }
1628                            return token = SyntaxKind.NewLineTrivia;
1629                        }
1630                    case CharacterCodes.tab:
1631                    case CharacterCodes.verticalTab:
1632                    case CharacterCodes.formFeed:
1633                    case CharacterCodes.space:
1634                    case CharacterCodes.nonBreakingSpace:
1635                    case CharacterCodes.ogham:
1636                    case CharacterCodes.enQuad:
1637                    case CharacterCodes.emQuad:
1638                    case CharacterCodes.enSpace:
1639                    case CharacterCodes.emSpace:
1640                    case CharacterCodes.threePerEmSpace:
1641                    case CharacterCodes.fourPerEmSpace:
1642                    case CharacterCodes.sixPerEmSpace:
1643                    case CharacterCodes.figureSpace:
1644                    case CharacterCodes.punctuationSpace:
1645                    case CharacterCodes.thinSpace:
1646                    case CharacterCodes.hairSpace:
1647                    case CharacterCodes.zeroWidthSpace:
1648                    case CharacterCodes.narrowNoBreakSpace:
1649                    case CharacterCodes.mathematicalSpace:
1650                    case CharacterCodes.ideographicSpace:
1651                    case CharacterCodes.byteOrderMark:
1652                        if (skipTrivia) {
1653                            pos++;
1654                            continue;
1655                        }
1656                        else {
1657                            while (pos < end && isWhiteSpaceSingleLine(text.charCodeAt(pos))) {
1658                                pos++;
1659                            }
1660                            return token = SyntaxKind.WhitespaceTrivia;
1661                        }
1662                    case CharacterCodes.exclamation:
1663                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
1664                            if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
1665                                return pos += 3, token = SyntaxKind.ExclamationEqualsEqualsToken;
1666                            }
1667                            return pos += 2, token = SyntaxKind.ExclamationEqualsToken;
1668                        }
1669                        pos++;
1670                        return token = SyntaxKind.ExclamationToken;
1671                    case CharacterCodes.doubleQuote:
1672                    case CharacterCodes.singleQuote:
1673                        tokenValue = scanString();
1674                        return token = SyntaxKind.StringLiteral;
1675                    case CharacterCodes.backtick:
1676                        return token = scanTemplateAndSetTokenValue(/* isTaggedTemplate */ false);
1677                    case CharacterCodes.percent:
1678                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
1679                            return pos += 2, token = SyntaxKind.PercentEqualsToken;
1680                        }
1681                        pos++;
1682                        return token = SyntaxKind.PercentToken;
1683                    case CharacterCodes.ampersand:
1684                        if (text.charCodeAt(pos + 1) === CharacterCodes.ampersand) {
1685                            if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
1686                                return pos += 3, token = SyntaxKind.AmpersandAmpersandEqualsToken;
1687                            }
1688                            return pos += 2, token = SyntaxKind.AmpersandAmpersandToken;
1689                        }
1690                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
1691                            return pos += 2, token = SyntaxKind.AmpersandEqualsToken;
1692                        }
1693                        pos++;
1694                        return token = SyntaxKind.AmpersandToken;
1695                    case CharacterCodes.openParen:
1696                        pos++;
1697                        return token = SyntaxKind.OpenParenToken;
1698                    case CharacterCodes.closeParen:
1699                        pos++;
1700                        return token = SyntaxKind.CloseParenToken;
1701                    case CharacterCodes.asterisk:
1702                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
1703                            return pos += 2, token = SyntaxKind.AsteriskEqualsToken;
1704                        }
1705                        if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) {
1706                            if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
1707                                return pos += 3, token = SyntaxKind.AsteriskAsteriskEqualsToken;
1708                            }
1709                            return pos += 2, token = SyntaxKind.AsteriskAsteriskToken;
1710                        }
1711                        pos++;
1712                        if (inJSDocType && !asteriskSeen && (tokenFlags & TokenFlags.PrecedingLineBreak)) {
1713                            // decoration at the start of a JSDoc comment line
1714                            asteriskSeen = true;
1715                            continue;
1716                        }
1717                        return token = SyntaxKind.AsteriskToken;
1718                    case CharacterCodes.plus:
1719                        if (text.charCodeAt(pos + 1) === CharacterCodes.plus) {
1720                            return pos += 2, token = SyntaxKind.PlusPlusToken;
1721                        }
1722                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
1723                            return pos += 2, token = SyntaxKind.PlusEqualsToken;
1724                        }
1725                        pos++;
1726                        return token = SyntaxKind.PlusToken;
1727                    case CharacterCodes.comma:
1728                        pos++;
1729                        return token = SyntaxKind.CommaToken;
1730                    case CharacterCodes.minus:
1731                        if (text.charCodeAt(pos + 1) === CharacterCodes.minus) {
1732                            return pos += 2, token = SyntaxKind.MinusMinusToken;
1733                        }
1734                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
1735                            return pos += 2, token = SyntaxKind.MinusEqualsToken;
1736                        }
1737                        pos++;
1738                        return token = SyntaxKind.MinusToken;
1739                    case CharacterCodes.dot:
1740                        if (isDigit(text.charCodeAt(pos + 1))) {
1741                            tokenValue = scanNumber().value;
1742                            return token = SyntaxKind.NumericLiteral;
1743                        }
1744                        if (text.charCodeAt(pos + 1) === CharacterCodes.dot && text.charCodeAt(pos + 2) === CharacterCodes.dot) {
1745                            return pos += 3, token = SyntaxKind.DotDotDotToken;
1746                        }
1747                        pos++;
1748                        return token = SyntaxKind.DotToken;
1749                    case CharacterCodes.slash:
1750                        // Single-line comment
1751                        if (text.charCodeAt(pos + 1) === CharacterCodes.slash) {
1752                            pos += 2;
1753
1754                            while (pos < end) {
1755                                if (isLineBreak(text.charCodeAt(pos))) {
1756                                    break;
1757                                }
1758                                pos++;
1759                            }
1760
1761                            commentDirectives = appendIfCommentDirective(
1762                                commentDirectives,
1763                                text.slice(tokenPos, pos),
1764                                commentDirectiveRegExSingleLine,
1765                                tokenPos,
1766                            );
1767
1768                            if (skipTrivia) {
1769                                continue;
1770                            }
1771                            else {
1772                                return token = SyntaxKind.SingleLineCommentTrivia;
1773                            }
1774                        }
1775                        // Multi-line comment
1776                        if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) {
1777                            pos += 2;
1778                            if (text.charCodeAt(pos) === CharacterCodes.asterisk && text.charCodeAt(pos + 1) !== CharacterCodes.slash) {
1779                                tokenFlags |= TokenFlags.PrecedingJSDocComment;
1780                            }
1781
1782                            let commentClosed = false;
1783                            let lastLineStart = tokenPos;
1784                            while (pos < end) {
1785                                const ch = text.charCodeAt(pos);
1786
1787                                if (ch === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) {
1788                                    pos += 2;
1789                                    commentClosed = true;
1790                                    break;
1791                                }
1792
1793                                pos++;
1794
1795                                if (isLineBreak(ch)) {
1796                                    lastLineStart = pos;
1797                                    tokenFlags |= TokenFlags.PrecedingLineBreak;
1798                                }
1799                            }
1800
1801                            commentDirectives = appendIfCommentDirective(commentDirectives, text.slice(lastLineStart, pos), commentDirectiveRegExMultiLine, lastLineStart);
1802
1803                            if (!commentClosed) {
1804                                error(Diagnostics.Asterisk_Slash_expected);
1805                            }
1806
1807                            if (skipTrivia) {
1808                                continue;
1809                            }
1810                            else {
1811                                if (!commentClosed) {
1812                                    tokenFlags |= TokenFlags.Unterminated;
1813                                }
1814                                return token = SyntaxKind.MultiLineCommentTrivia;
1815                            }
1816                        }
1817
1818                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
1819                            return pos += 2, token = SyntaxKind.SlashEqualsToken;
1820                        }
1821
1822                        pos++;
1823                        return token = SyntaxKind.SlashToken;
1824
1825                    case CharacterCodes._0:
1826                        if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.X || text.charCodeAt(pos + 1) === CharacterCodes.x)) {
1827                            pos += 2;
1828                            tokenValue = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ true);
1829                            if (!tokenValue) {
1830                                error(Diagnostics.Hexadecimal_digit_expected);
1831                                tokenValue = "0";
1832                            }
1833                            tokenValue = "0x" + tokenValue;
1834                            tokenFlags |= TokenFlags.HexSpecifier;
1835                            return token = checkBigIntSuffix();
1836                        }
1837                        else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.B || text.charCodeAt(pos + 1) === CharacterCodes.b)) {
1838                            pos += 2;
1839                            tokenValue = scanBinaryOrOctalDigits(/* base */ 2);
1840                            if (!tokenValue) {
1841                                error(Diagnostics.Binary_digit_expected);
1842                                tokenValue = "0";
1843                            }
1844                            tokenValue = "0b" + tokenValue;
1845                            tokenFlags |= TokenFlags.BinarySpecifier;
1846                            return token = checkBigIntSuffix();
1847                        }
1848                        else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.O || text.charCodeAt(pos + 1) === CharacterCodes.o)) {
1849                            pos += 2;
1850                            tokenValue = scanBinaryOrOctalDigits(/* base */ 8);
1851                            if (!tokenValue) {
1852                                error(Diagnostics.Octal_digit_expected);
1853                                tokenValue = "0";
1854                            }
1855                            tokenValue = "0o" + tokenValue;
1856                            tokenFlags |= TokenFlags.OctalSpecifier;
1857                            return token = checkBigIntSuffix();
1858                        }
1859                        // Try to parse as an octal
1860                        if (pos + 1 < end && isOctalDigit(text.charCodeAt(pos + 1))) {
1861                            tokenValue = "" + scanOctalDigits();
1862                            tokenFlags |= TokenFlags.Octal;
1863                            return token = SyntaxKind.NumericLiteral;
1864                        }
1865                    // This fall-through is a deviation from the EcmaScript grammar. The grammar says that a leading zero
1866                    // can only be followed by an octal digit, a dot, or the end of the number literal. However, we are being
1867                    // permissive and allowing decimal digits of the form 08* and 09* (which many browsers also do).
1868                    // falls through
1869                    case CharacterCodes._1:
1870                    case CharacterCodes._2:
1871                    case CharacterCodes._3:
1872                    case CharacterCodes._4:
1873                    case CharacterCodes._5:
1874                    case CharacterCodes._6:
1875                    case CharacterCodes._7:
1876                    case CharacterCodes._8:
1877                    case CharacterCodes._9:
1878                        ({ type: token, value: tokenValue } = scanNumber());
1879                        return token;
1880                    case CharacterCodes.colon:
1881                        pos++;
1882                        return token = SyntaxKind.ColonToken;
1883                    case CharacterCodes.semicolon:
1884                        pos++;
1885                        return token = SyntaxKind.SemicolonToken;
1886                    case CharacterCodes.lessThan:
1887                        if (isConflictMarkerTrivia(text, pos)) {
1888                            pos = scanConflictMarkerTrivia(text, pos, error);
1889                            if (skipTrivia) {
1890                                continue;
1891                            }
1892                            else {
1893                                return token = SyntaxKind.ConflictMarkerTrivia;
1894                            }
1895                        }
1896
1897                        if (text.charCodeAt(pos + 1) === CharacterCodes.lessThan) {
1898                            if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
1899                                return pos += 3, token = SyntaxKind.LessThanLessThanEqualsToken;
1900                            }
1901                            return pos += 2, token = SyntaxKind.LessThanLessThanToken;
1902                        }
1903                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
1904                            return pos += 2, token = SyntaxKind.LessThanEqualsToken;
1905                        }
1906                        if (languageVariant === LanguageVariant.JSX &&
1907                            text.charCodeAt(pos + 1) === CharacterCodes.slash &&
1908                            text.charCodeAt(pos + 2) !== CharacterCodes.asterisk) {
1909                            return pos += 2, token = SyntaxKind.LessThanSlashToken;
1910                        }
1911                        pos++;
1912                        return token = SyntaxKind.LessThanToken;
1913                    case CharacterCodes.equals:
1914                        if (isConflictMarkerTrivia(text, pos)) {
1915                            pos = scanConflictMarkerTrivia(text, pos, error);
1916                            if (skipTrivia) {
1917                                continue;
1918                            }
1919                            else {
1920                                return token = SyntaxKind.ConflictMarkerTrivia;
1921                            }
1922                        }
1923
1924                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
1925                            if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
1926                                return pos += 3, token = SyntaxKind.EqualsEqualsEqualsToken;
1927                            }
1928                            return pos += 2, token = SyntaxKind.EqualsEqualsToken;
1929                        }
1930                        if (text.charCodeAt(pos + 1) === CharacterCodes.greaterThan) {
1931                            return pos += 2, token = SyntaxKind.EqualsGreaterThanToken;
1932                        }
1933                        pos++;
1934                        return token = SyntaxKind.EqualsToken;
1935                    case CharacterCodes.greaterThan:
1936                        if (isConflictMarkerTrivia(text, pos)) {
1937                            pos = scanConflictMarkerTrivia(text, pos, error);
1938                            if (skipTrivia) {
1939                                continue;
1940                            }
1941                            else {
1942                                return token = SyntaxKind.ConflictMarkerTrivia;
1943                            }
1944                        }
1945
1946                        pos++;
1947                        return token = SyntaxKind.GreaterThanToken;
1948                    case CharacterCodes.question:
1949                        if (text.charCodeAt(pos + 1) === CharacterCodes.dot && !isDigit(text.charCodeAt(pos + 2))) {
1950                            return pos += 2, token = SyntaxKind.QuestionDotToken;
1951                        }
1952                        if (text.charCodeAt(pos + 1) === CharacterCodes.question) {
1953                            if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
1954                                return pos += 3, token = SyntaxKind.QuestionQuestionEqualsToken;
1955                            }
1956                            return pos += 2, token = SyntaxKind.QuestionQuestionToken;
1957                        }
1958                        pos++;
1959                        return token = SyntaxKind.QuestionToken;
1960                    case CharacterCodes.openBracket:
1961                        pos++;
1962                        return token = SyntaxKind.OpenBracketToken;
1963                    case CharacterCodes.closeBracket:
1964                        pos++;
1965                        return token = SyntaxKind.CloseBracketToken;
1966                    case CharacterCodes.caret:
1967                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
1968                            return pos += 2, token = SyntaxKind.CaretEqualsToken;
1969                        }
1970                        pos++;
1971                        return token = SyntaxKind.CaretToken;
1972                    case CharacterCodes.openBrace:
1973                        pos++;
1974                        return token = SyntaxKind.OpenBraceToken;
1975                    case CharacterCodes.bar:
1976                        if (isConflictMarkerTrivia(text, pos)) {
1977                            pos = scanConflictMarkerTrivia(text, pos, error);
1978                            if (skipTrivia) {
1979                                continue;
1980                            }
1981                            else {
1982                                return token = SyntaxKind.ConflictMarkerTrivia;
1983                            }
1984                        }
1985
1986                        if (text.charCodeAt(pos + 1) === CharacterCodes.bar) {
1987                            if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
1988                                return pos += 3, token = SyntaxKind.BarBarEqualsToken;
1989                            }
1990                            return pos += 2, token = SyntaxKind.BarBarToken;
1991                        }
1992                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
1993                            return pos += 2, token = SyntaxKind.BarEqualsToken;
1994                        }
1995                        pos++;
1996                        return token = SyntaxKind.BarToken;
1997                    case CharacterCodes.closeBrace:
1998                        pos++;
1999                        return token = SyntaxKind.CloseBraceToken;
2000                    case CharacterCodes.tilde:
2001                        pos++;
2002                        return token = SyntaxKind.TildeToken;
2003                    case CharacterCodes.at:
2004                        pos++;
2005                        return token = SyntaxKind.AtToken;
2006                    case CharacterCodes.backslash:
2007                        const extendedCookedChar = peekExtendedUnicodeEscape();
2008                        if (extendedCookedChar >= 0 && isIdentifierStart(extendedCookedChar, languageVersion)) {
2009                            pos += 3;
2010                            tokenFlags |= TokenFlags.ExtendedUnicodeEscape;
2011                            tokenValue = scanExtendedUnicodeEscape() + scanIdentifierParts();
2012                            return token = getIdentifierToken();
2013                        }
2014
2015                        const cookedChar = peekUnicodeEscape();
2016                        if (cookedChar >= 0 && isIdentifierStart(cookedChar, languageVersion)) {
2017                            pos += 6;
2018                            tokenFlags |= TokenFlags.UnicodeEscape;
2019                            tokenValue = String.fromCharCode(cookedChar) + scanIdentifierParts();
2020                            return token = getIdentifierToken();
2021                        }
2022
2023                        error(Diagnostics.Invalid_character);
2024                        pos++;
2025                        return token = SyntaxKind.Unknown;
2026                    case CharacterCodes.hash:
2027                        if (pos !== 0 && text[pos + 1] === "!") {
2028                            error(Diagnostics.can_only_be_used_at_the_start_of_a_file);
2029                            pos++;
2030                            return token = SyntaxKind.Unknown;
2031                        }
2032                        pos++;
2033                        if (isIdentifierStart(ch = text.charCodeAt(pos), languageVersion)) {
2034                            pos++;
2035                            while (pos < end && isIdentifierPart(ch = text.charCodeAt(pos), languageVersion)) pos++;
2036                            tokenValue = text.substring(tokenPos, pos);
2037                            if (ch === CharacterCodes.backslash) {
2038                                tokenValue += scanIdentifierParts();
2039                            }
2040                        }
2041                        else {
2042                            tokenValue = "#";
2043                            error(Diagnostics.Invalid_character);
2044                        }
2045                        return token = SyntaxKind.PrivateIdentifier;
2046                    default:
2047                        const identifierKind = scanIdentifier(ch, languageVersion);
2048                        if (identifierKind) {
2049                            return token = identifierKind;
2050                        }
2051                        else if (isWhiteSpaceSingleLine(ch)) {
2052                            pos += charSize(ch);
2053                            continue;
2054                        }
2055                        else if (isLineBreak(ch)) {
2056                            tokenFlags |= TokenFlags.PrecedingLineBreak;
2057                            pos += charSize(ch);
2058                            continue;
2059                        }
2060                        error(Diagnostics.Invalid_character);
2061                        pos += charSize(ch);
2062                        return token = SyntaxKind.Unknown;
2063                }
2064            }
2065        }
2066
2067        function reScanInvalidIdentifier(): SyntaxKind {
2068            Debug.assert(token === SyntaxKind.Unknown, "'reScanInvalidIdentifier' should only be called when the current token is 'SyntaxKind.Unknown'.");
2069            pos = tokenPos = startPos;
2070            tokenFlags = 0;
2071            const ch = codePointAt(text, pos);
2072            const identifierKind = scanIdentifier(ch, ScriptTarget.ESNext);
2073            if (identifierKind) {
2074                return token = identifierKind;
2075            }
2076            pos += charSize(ch);
2077            return token; // Still `SyntaKind.Unknown`
2078        }
2079
2080        function scanIdentifier(startCharacter: number, languageVersion: ScriptTarget) {
2081            let ch = startCharacter;
2082            if (isIdentifierStart(ch, languageVersion)) {
2083                pos += charSize(ch);
2084                while (pos < end && isIdentifierPart(ch = codePointAt(text, pos), languageVersion)) pos += charSize(ch);
2085                tokenValue = text.substring(tokenPos, pos);
2086                if (ch === CharacterCodes.backslash) {
2087                    tokenValue += scanIdentifierParts();
2088                }
2089                return getIdentifierToken();
2090            }
2091        }
2092
2093        function reScanGreaterToken(): SyntaxKind {
2094            if (token === SyntaxKind.GreaterThanToken) {
2095                if (text.charCodeAt(pos) === CharacterCodes.greaterThan) {
2096                    if (text.charCodeAt(pos + 1) === CharacterCodes.greaterThan) {
2097                        if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
2098                            return pos += 3, token = SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken;
2099                        }
2100                        return pos += 2, token = SyntaxKind.GreaterThanGreaterThanGreaterThanToken;
2101                    }
2102                    if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
2103                        return pos += 2, token = SyntaxKind.GreaterThanGreaterThanEqualsToken;
2104                    }
2105                    pos++;
2106                    return token = SyntaxKind.GreaterThanGreaterThanToken;
2107                }
2108                if (text.charCodeAt(pos) === CharacterCodes.equals) {
2109                    pos++;
2110                    return token = SyntaxKind.GreaterThanEqualsToken;
2111                }
2112            }
2113            return token;
2114        }
2115
2116        function reScanAsteriskEqualsToken(): SyntaxKind {
2117            Debug.assert(token === SyntaxKind.AsteriskEqualsToken, "'reScanAsteriskEqualsToken' should only be called on a '*='");
2118            pos = tokenPos + 1;
2119            return token = SyntaxKind.EqualsToken;
2120        }
2121
2122        function reScanSlashToken(): SyntaxKind {
2123            if (token === SyntaxKind.SlashToken || token === SyntaxKind.SlashEqualsToken) {
2124                let p = tokenPos + 1;
2125                let inEscape = false;
2126                let inCharacterClass = false;
2127                while (true) {
2128                    // If we reach the end of a file, or hit a newline, then this is an unterminated
2129                    // regex.  Report error and return what we have so far.
2130                    if (p >= end) {
2131                        tokenFlags |= TokenFlags.Unterminated;
2132                        error(Diagnostics.Unterminated_regular_expression_literal);
2133                        break;
2134                    }
2135
2136                    const ch = text.charCodeAt(p);
2137                    if (isLineBreak(ch)) {
2138                        tokenFlags |= TokenFlags.Unterminated;
2139                        error(Diagnostics.Unterminated_regular_expression_literal);
2140                        break;
2141                    }
2142
2143                    if (inEscape) {
2144                        // Parsing an escape character;
2145                        // reset the flag and just advance to the next char.
2146                        inEscape = false;
2147                    }
2148                    else if (ch === CharacterCodes.slash && !inCharacterClass) {
2149                        // A slash within a character class is permissible,
2150                        // but in general it signals the end of the regexp literal.
2151                        p++;
2152                        break;
2153                    }
2154                    else if (ch === CharacterCodes.openBracket) {
2155                        inCharacterClass = true;
2156                    }
2157                    else if (ch === CharacterCodes.backslash) {
2158                        inEscape = true;
2159                    }
2160                    else if (ch === CharacterCodes.closeBracket) {
2161                        inCharacterClass = false;
2162                    }
2163                    p++;
2164                }
2165
2166                while (p < end && isIdentifierPart(text.charCodeAt(p), languageVersion)) {
2167                    p++;
2168                }
2169                pos = p;
2170                tokenValue = text.substring(tokenPos, pos);
2171                token = SyntaxKind.RegularExpressionLiteral;
2172            }
2173            return token;
2174        }
2175
2176        function appendIfCommentDirective(
2177            commentDirectives: CommentDirective[] | undefined,
2178            text: string,
2179            commentDirectiveRegEx: RegExp,
2180            lineStart: number,
2181        ) {
2182            const type = getDirectiveFromComment(text, commentDirectiveRegEx);
2183            if (type === undefined) {
2184                return commentDirectives;
2185            }
2186
2187            return append(
2188                commentDirectives,
2189                {
2190                    range: { pos: lineStart, end: pos },
2191                    type,
2192                },
2193            );
2194        }
2195
2196        function getDirectiveFromComment(text: string, commentDirectiveRegEx: RegExp) {
2197            const match = commentDirectiveRegEx.exec(text);
2198            if (!match) {
2199                return undefined;
2200            }
2201
2202            switch (match[1]) {
2203                case "ts-expect-error":
2204                    return CommentDirectiveType.ExpectError;
2205
2206                case "ts-ignore":
2207                    return CommentDirectiveType.Ignore;
2208            }
2209
2210            return undefined;
2211        }
2212
2213        /**
2214         * Unconditionally back up and scan a template expression portion.
2215         */
2216        function reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind {
2217            Debug.assert(token === SyntaxKind.CloseBraceToken, "'reScanTemplateToken' should only be called on a '}'");
2218            pos = tokenPos;
2219            return token = scanTemplateAndSetTokenValue(isTaggedTemplate);
2220        }
2221
2222        function reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind {
2223            pos = tokenPos;
2224            return token = scanTemplateAndSetTokenValue(/* isTaggedTemplate */ true);
2225        }
2226
2227        function reScanJsxToken(): JsxTokenSyntaxKind {
2228            pos = tokenPos = startPos;
2229            return token = scanJsxToken();
2230        }
2231
2232        function reScanLessThanToken(): SyntaxKind {
2233            if (token === SyntaxKind.LessThanLessThanToken) {
2234                pos = tokenPos + 1;
2235                return token = SyntaxKind.LessThanToken;
2236            }
2237            return token;
2238        }
2239
2240        function reScanQuestionToken(): SyntaxKind {
2241            Debug.assert(token === SyntaxKind.QuestionQuestionToken, "'reScanQuestionToken' should only be called on a '??'");
2242            pos = tokenPos + 1;
2243            return token = SyntaxKind.QuestionToken;
2244        }
2245
2246        function scanJsxToken(): JsxTokenSyntaxKind {
2247            startPos = tokenPos = pos;
2248
2249            if (pos >= end) {
2250                return token = SyntaxKind.EndOfFileToken;
2251            }
2252
2253            let char = text.charCodeAt(pos);
2254            if (char === CharacterCodes.lessThan) {
2255                if (text.charCodeAt(pos + 1) === CharacterCodes.slash) {
2256                    pos += 2;
2257                    return token = SyntaxKind.LessThanSlashToken;
2258                }
2259                pos++;
2260                return token = SyntaxKind.LessThanToken;
2261            }
2262
2263            if (char === CharacterCodes.openBrace) {
2264                pos++;
2265                return token = SyntaxKind.OpenBraceToken;
2266            }
2267
2268            // First non-whitespace character on this line.
2269            let firstNonWhitespace = 0;
2270            let lastNonWhitespace = -1;
2271
2272            // These initial values are special because the first line is:
2273            // firstNonWhitespace = 0 to indicate that we want leading whitespace,
2274
2275            while (pos < end) {
2276
2277                // We want to keep track of the last non-whitespace (but including
2278                // newlines character for hitting the end of the JSX Text region)
2279                if (!isWhiteSpaceSingleLine(char)) {
2280                    lastNonWhitespace = pos;
2281                }
2282
2283                char = text.charCodeAt(pos);
2284                if (char === CharacterCodes.openBrace) {
2285                    break;
2286                }
2287                if (char === CharacterCodes.lessThan) {
2288                    if (isConflictMarkerTrivia(text, pos)) {
2289                        pos = scanConflictMarkerTrivia(text, pos, error);
2290                        return token = SyntaxKind.ConflictMarkerTrivia;
2291                    }
2292                    break;
2293                }
2294                if (char === CharacterCodes.greaterThan) {
2295                    error(Diagnostics.Unexpected_token_Did_you_mean_or_gt, pos, 1);
2296                }
2297                if (char === CharacterCodes.closeBrace) {
2298                    error(Diagnostics.Unexpected_token_Did_you_mean_or_rbrace, pos, 1);
2299                }
2300
2301                if (lastNonWhitespace > 0) lastNonWhitespace++;
2302
2303                // FirstNonWhitespace is 0, then we only see whitespaces so far. If we see a linebreak, we want to ignore that whitespaces.
2304                // i.e (- : whitespace)
2305                //      <div>----
2306                //      </div> becomes <div></div>
2307                //
2308                //      <div>----</div> becomes <div>----</div>
2309                if (isLineBreak(char) && firstNonWhitespace === 0) {
2310                    firstNonWhitespace = -1;
2311                }
2312                else if (!isWhiteSpaceLike(char)) {
2313                    firstNonWhitespace = pos;
2314                }
2315
2316                pos++;
2317            }
2318
2319            const endPosition = lastNonWhitespace === -1 ? pos : lastNonWhitespace;
2320            tokenValue = text.substring(startPos, endPosition);
2321
2322            return firstNonWhitespace === -1 ? SyntaxKind.JsxTextAllWhiteSpaces : SyntaxKind.JsxText;
2323        }
2324
2325        // Scans a JSX identifier; these differ from normal identifiers in that
2326        // they allow dashes
2327        function scanJsxIdentifier(): SyntaxKind {
2328            if (tokenIsIdentifierOrKeyword(token)) {
2329                // An identifier or keyword has already been parsed - check for a `-` or a single instance of `:` and then append it and
2330                // everything after it to the token
2331                // Do note that this means that `scanJsxIdentifier` effectively _mutates_ the visible token without advancing to a new token
2332                // Any caller should be expecting this behavior and should only read the pos or token value after calling it.
2333                let namespaceSeparator = false;
2334                while (pos < end) {
2335                    const ch = text.charCodeAt(pos);
2336                    if (ch === CharacterCodes.minus) {
2337                        tokenValue += "-";
2338                        pos++;
2339                        continue;
2340                    }
2341                    else if (ch === CharacterCodes.colon && !namespaceSeparator) {
2342                        tokenValue += ":";
2343                        pos++;
2344                        namespaceSeparator = true;
2345                        continue;
2346                    }
2347                    const oldPos = pos;
2348                    tokenValue += scanIdentifierParts(); // reuse `scanIdentifierParts` so unicode escapes are handled
2349                    if (pos === oldPos) {
2350                        break;
2351                    }
2352                }
2353                // Do not include a trailing namespace separator in the token, since this is against the spec.
2354                if (tokenValue.slice(-1) === ":") {
2355                    tokenValue = tokenValue.slice(0, -1);
2356                    pos--;
2357                }
2358            }
2359            return token;
2360        }
2361
2362        function scanJsxAttributeValue(): SyntaxKind {
2363            startPos = pos;
2364
2365            switch (text.charCodeAt(pos)) {
2366                case CharacterCodes.doubleQuote:
2367                case CharacterCodes.singleQuote:
2368                    tokenValue = scanString(/*jsxAttributeString*/ true);
2369                    return token = SyntaxKind.StringLiteral;
2370                default:
2371                    // If this scans anything other than `{`, it's a parse error.
2372                    return scan();
2373            }
2374        }
2375
2376        function reScanJsxAttributeValue(): SyntaxKind {
2377            pos = tokenPos = startPos;
2378            return scanJsxAttributeValue();
2379        }
2380
2381        function scanJsDocToken(): JSDocSyntaxKind {
2382            startPos = tokenPos = pos;
2383            tokenFlags = TokenFlags.None;
2384            if (pos >= end) {
2385                return token = SyntaxKind.EndOfFileToken;
2386            }
2387
2388            const ch = codePointAt(text, pos);
2389            pos += charSize(ch);
2390            switch (ch) {
2391                case CharacterCodes.tab:
2392                case CharacterCodes.verticalTab:
2393                case CharacterCodes.formFeed:
2394                case CharacterCodes.space:
2395                    while (pos < end && isWhiteSpaceSingleLine(text.charCodeAt(pos))) {
2396                        pos++;
2397                    }
2398                    return token = SyntaxKind.WhitespaceTrivia;
2399                case CharacterCodes.at:
2400                    return token = SyntaxKind.AtToken;
2401                case CharacterCodes.carriageReturn:
2402                    if (text.charCodeAt(pos) === CharacterCodes.lineFeed) {
2403                        pos++;
2404                    }
2405                    // falls through
2406                case CharacterCodes.lineFeed:
2407                    tokenFlags |= TokenFlags.PrecedingLineBreak;
2408                    return token = SyntaxKind.NewLineTrivia;
2409                case CharacterCodes.asterisk:
2410                    return token = SyntaxKind.AsteriskToken;
2411                case CharacterCodes.openBrace:
2412                    return token = SyntaxKind.OpenBraceToken;
2413                case CharacterCodes.closeBrace:
2414                    return token = SyntaxKind.CloseBraceToken;
2415                case CharacterCodes.openBracket:
2416                    return token = SyntaxKind.OpenBracketToken;
2417                case CharacterCodes.closeBracket:
2418                    return token = SyntaxKind.CloseBracketToken;
2419                case CharacterCodes.lessThan:
2420                    return token = SyntaxKind.LessThanToken;
2421                case CharacterCodes.greaterThan:
2422                    return token = SyntaxKind.GreaterThanToken;
2423                case CharacterCodes.equals:
2424                    return token = SyntaxKind.EqualsToken;
2425                case CharacterCodes.comma:
2426                    return token = SyntaxKind.CommaToken;
2427                case CharacterCodes.dot:
2428                    return token = SyntaxKind.DotToken;
2429                case CharacterCodes.backtick:
2430                    return token = SyntaxKind.BacktickToken;
2431                case CharacterCodes.backslash:
2432                    pos--;
2433                    const extendedCookedChar = peekExtendedUnicodeEscape();
2434                    if (extendedCookedChar >= 0 && isIdentifierStart(extendedCookedChar, languageVersion)) {
2435                        pos += 3;
2436                        tokenFlags |= TokenFlags.ExtendedUnicodeEscape;
2437                        tokenValue = scanExtendedUnicodeEscape() + scanIdentifierParts();
2438                        return token = getIdentifierToken();
2439                    }
2440
2441                    const cookedChar = peekUnicodeEscape();
2442                    if (cookedChar >= 0 && isIdentifierStart(cookedChar, languageVersion)) {
2443                        pos += 6;
2444                        tokenFlags |= TokenFlags.UnicodeEscape;
2445                        tokenValue = String.fromCharCode(cookedChar) + scanIdentifierParts();
2446                        return token = getIdentifierToken();
2447                    }
2448                    pos++;
2449                    return token = SyntaxKind.Unknown;
2450            }
2451
2452            if (isIdentifierStart(ch, languageVersion)) {
2453                let char = ch;
2454                while (pos < end && isIdentifierPart(char = codePointAt(text, pos), languageVersion) || text.charCodeAt(pos) === CharacterCodes.minus) pos += charSize(char);
2455                tokenValue = text.substring(tokenPos, pos);
2456                if (char === CharacterCodes.backslash) {
2457                    tokenValue += scanIdentifierParts();
2458                }
2459                return token = getIdentifierToken();
2460            }
2461            else {
2462                return token = SyntaxKind.Unknown;
2463            }
2464        }
2465
2466        function speculationHelper<T>(callback: () => T, isLookahead: boolean): T {
2467            const savePos = pos;
2468            const saveStartPos = startPos;
2469            const saveTokenPos = tokenPos;
2470            const saveToken = token;
2471            const saveTokenValue = tokenValue;
2472            const saveTokenFlags = tokenFlags;
2473            const result = callback();
2474
2475            // If our callback returned something 'falsy' or we're just looking ahead,
2476            // then unconditionally restore us to where we were.
2477            if (!result || isLookahead) {
2478                pos = savePos;
2479                startPos = saveStartPos;
2480                tokenPos = saveTokenPos;
2481                token = saveToken;
2482                tokenValue = saveTokenValue;
2483                tokenFlags = saveTokenFlags;
2484            }
2485            return result;
2486        }
2487
2488        function scanRange<T>(start: number, length: number, callback: () => T): T {
2489            const saveEnd = end;
2490            const savePos = pos;
2491            const saveStartPos = startPos;
2492            const saveTokenPos = tokenPos;
2493            const saveToken = token;
2494            const saveTokenValue = tokenValue;
2495            const saveTokenFlags = tokenFlags;
2496            const saveErrorExpectations = commentDirectives;
2497
2498            setText(text, start, length);
2499            const result = callback();
2500
2501            end = saveEnd;
2502            pos = savePos;
2503            startPos = saveStartPos;
2504            tokenPos = saveTokenPos;
2505            token = saveToken;
2506            tokenValue = saveTokenValue;
2507            tokenFlags = saveTokenFlags;
2508            commentDirectives = saveErrorExpectations;
2509
2510            return result;
2511        }
2512
2513        function lookAhead<T>(callback: () => T): T {
2514            return speculationHelper(callback, /*isLookahead*/ true);
2515        }
2516
2517        function tryScan<T>(callback: () => T): T {
2518            return speculationHelper(callback, /*isLookahead*/ false);
2519        }
2520
2521        function getText(): string {
2522            return text;
2523        }
2524
2525        function clearCommentDirectives() {
2526            commentDirectives = undefined;
2527        }
2528
2529        function setText(newText: string | undefined, start: number | undefined, length: number | undefined) {
2530            text = newText || "";
2531            end = length === undefined ? text.length : start! + length;
2532            setTextPos(start || 0);
2533        }
2534
2535        function setOnError(errorCallback: ErrorCallback | undefined) {
2536            onError = errorCallback;
2537        }
2538
2539        function setScriptTarget(scriptTarget: ScriptTarget) {
2540            languageVersion = scriptTarget;
2541        }
2542
2543        function setLanguageVariant(variant: LanguageVariant) {
2544            languageVariant = variant;
2545        }
2546
2547        function setTextPos(textPos: number) {
2548            Debug.assert(textPos >= 0);
2549            pos = textPos;
2550            startPos = textPos;
2551            tokenPos = textPos;
2552            token = SyntaxKind.Unknown;
2553            tokenValue = undefined!;
2554            tokenFlags = TokenFlags.None;
2555        }
2556
2557        function setInJSDocType(inType: boolean) {
2558            inJSDocType += inType ? 1 : -1;
2559        }
2560    }
2561
2562    /* @internal */
2563    const codePointAt: (s: string, i: number) => number = (String.prototype as any).codePointAt ? (s, i) => (s as any).codePointAt(i) : function codePointAt(str, i): number {
2564        // from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt
2565        const size = str.length;
2566        // Account for out-of-bounds indices:
2567        if (i < 0 || i >= size) {
2568            return undefined!; // String.codePointAt returns `undefined` for OOB indexes
2569        }
2570        // Get the first code unit
2571        const first = str.charCodeAt(i);
2572        // check if it’s the start of a surrogate pair
2573        if (first >= 0xD800 && first <= 0xDBFF && size > i + 1) { // high surrogate and there is a next code unit
2574            const second = str.charCodeAt(i + 1);
2575            if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate
2576                // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
2577                return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
2578            }
2579        }
2580        return first;
2581    };
2582
2583    /* @internal */
2584    function charSize(ch: number) {
2585        if (ch >= 0x10000) {
2586            return 2;
2587        }
2588        return 1;
2589    }
2590
2591    // Derived from the 10.1.1 UTF16Encoding of the ES6 Spec.
2592    function utf16EncodeAsStringFallback(codePoint: number) {
2593        Debug.assert(0x0 <= codePoint && codePoint <= 0x10FFFF);
2594
2595        if (codePoint <= 65535) {
2596            return String.fromCharCode(codePoint);
2597        }
2598
2599        const codeUnit1 = Math.floor((codePoint - 65536) / 1024) + 0xD800;
2600        const codeUnit2 = ((codePoint - 65536) % 1024) + 0xDC00;
2601
2602        return String.fromCharCode(codeUnit1, codeUnit2);
2603    }
2604
2605    const utf16EncodeAsStringWorker: (codePoint: number) => string = (String as any).fromCodePoint ? codePoint => (String as any).fromCodePoint(codePoint) : utf16EncodeAsStringFallback;
2606
2607    /* @internal */
2608    export function utf16EncodeAsString(codePoint: number) {
2609        return utf16EncodeAsStringWorker(codePoint);
2610    }
2611}
2612