1/// <reference path="utilities.ts"/>
2/// <reference path="scanner.ts"/>
3
4namespace ts {
5    const enum SignatureFlags {
6        None = 0,
7        Yield = 1 << 0,
8        Await = 1 << 1,
9        Type  = 1 << 2,
10        RequireCompleteParameterList = 1 << 3,
11        IgnoreMissingOpenBrace = 1 << 4,
12        JSDoc = 1 << 5,
13    }
14
15    // tslint:disable variable-name
16    let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
17    let TokenConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
18    let IdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
19    let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
20    // tslint:enable variable-name
21
22    export function createNode(kind: SyntaxKind, pos?: number, end?: number): Node {
23        if (kind === SyntaxKind.SourceFile) {
24            return new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, pos, end);
25        }
26        else if (kind === SyntaxKind.Identifier) {
27            return new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))(kind, pos, end);
28        }
29        else if (!isNodeKind(kind)) {
30            return new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind, pos, end);
31        }
32        else {
33            return new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, pos, end);
34        }
35    }
36
37    function visitNode<T>(cbNode: (node: Node) => T, node: Node): T | undefined {
38        return node && cbNode(node);
39    }
40
41    function visitNodes<T>(cbNode: (node: Node) => T, cbNodes: (node: NodeArray<Node>) => T | undefined, nodes: NodeArray<Node>): T | undefined {
42        if (nodes) {
43            if (cbNodes) {
44                return cbNodes(nodes);
45            }
46            for (const node of nodes) {
47                const result = cbNode(node);
48                if (result) {
49                    return result;
50                }
51            }
52        }
53    }
54
55    /**
56     * Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
57     * stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
58     * embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
59     * a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
60     *
61     * @param node a given node to visit its children
62     * @param cbNode a callback to be invoked for all child nodes
63     * @param cbNodes a callback to be invoked for embedded array
64     *
65     * @remarks `forEachChild` must visit the children of a node in the order
66     * that they appear in the source code. The language service depends on this property to locate nodes by position.
67     */
68    export function forEachChild<T>(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
69        if (!node || node.kind <= SyntaxKind.LastToken) {
70            return;
71        }
72        switch (node.kind) {
73            case SyntaxKind.QualifiedName:
74                return visitNode(cbNode, (<QualifiedName>node).left) ||
75                    visitNode(cbNode, (<QualifiedName>node).right);
76            case SyntaxKind.TypeParameter:
77                return visitNode(cbNode, (<TypeParameterDeclaration>node).name) ||
78                    visitNode(cbNode, (<TypeParameterDeclaration>node).constraint) ||
79                    visitNode(cbNode, (<TypeParameterDeclaration>node).default) ||
80                    visitNode(cbNode, (<TypeParameterDeclaration>node).expression);
81            case SyntaxKind.ShorthandPropertyAssignment:
82                return visitNodes(cbNode, cbNodes, node.decorators) ||
83                    visitNodes(cbNode, cbNodes, node.modifiers) ||
84                    visitNode(cbNode, (<ShorthandPropertyAssignment>node).name) ||
85                    visitNode(cbNode, (<ShorthandPropertyAssignment>node).questionToken) ||
86                    visitNode(cbNode, (<ShorthandPropertyAssignment>node).equalsToken) ||
87                    visitNode(cbNode, (<ShorthandPropertyAssignment>node).objectAssignmentInitializer);
88            case SyntaxKind.SpreadAssignment:
89                return visitNode(cbNode, (<SpreadAssignment>node).expression);
90            case SyntaxKind.Parameter:
91                return visitNodes(cbNode, cbNodes, node.decorators) ||
92                    visitNodes(cbNode, cbNodes, node.modifiers) ||
93                    visitNode(cbNode, (<ParameterDeclaration>node).dotDotDotToken) ||
94                    visitNode(cbNode, (<ParameterDeclaration>node).name) ||
95                    visitNode(cbNode, (<ParameterDeclaration>node).questionToken) ||
96                    visitNode(cbNode, (<ParameterDeclaration>node).type) ||
97                    visitNode(cbNode, (<ParameterDeclaration>node).initializer);
98            case SyntaxKind.PropertyDeclaration:
99                return visitNodes(cbNode, cbNodes, node.decorators) ||
100                    visitNodes(cbNode, cbNodes, node.modifiers) ||
101                    visitNode(cbNode, (<PropertyDeclaration>node).name) ||
102                    visitNode(cbNode, (<PropertyDeclaration>node).questionToken) ||
103                    visitNode(cbNode, (<PropertyDeclaration>node).exclamationToken) ||
104                    visitNode(cbNode, (<PropertyDeclaration>node).type) ||
105                    visitNode(cbNode, (<PropertyDeclaration>node).initializer);
106            case SyntaxKind.PropertySignature:
107                return visitNodes(cbNode, cbNodes, node.decorators) ||
108                    visitNodes(cbNode, cbNodes, node.modifiers) ||
109                    visitNode(cbNode, (<PropertySignature>node).name) ||
110                    visitNode(cbNode, (<PropertySignature>node).questionToken) ||
111                    visitNode(cbNode, (<PropertySignature>node).type) ||
112                    visitNode(cbNode, (<PropertySignature>node).initializer);
113            case SyntaxKind.PropertyAssignment:
114                return visitNodes(cbNode, cbNodes, node.decorators) ||
115                    visitNodes(cbNode, cbNodes, node.modifiers) ||
116                    visitNode(cbNode, (<PropertyAssignment>node).name) ||
117                    visitNode(cbNode, (<PropertyAssignment>node).questionToken) ||
118                    visitNode(cbNode, (<PropertyAssignment>node).initializer);
119            case SyntaxKind.VariableDeclaration:
120                return visitNodes(cbNode, cbNodes, node.decorators) ||
121                    visitNodes(cbNode, cbNodes, node.modifiers) ||
122                    visitNode(cbNode, (<VariableDeclaration>node).name) ||
123                    visitNode(cbNode, (<VariableDeclaration>node).exclamationToken) ||
124                    visitNode(cbNode, (<VariableDeclaration>node).type) ||
125                    visitNode(cbNode, (<VariableDeclaration>node).initializer);
126            case SyntaxKind.BindingElement:
127                return visitNodes(cbNode, cbNodes, node.decorators) ||
128                    visitNodes(cbNode, cbNodes, node.modifiers) ||
129                    visitNode(cbNode, (<BindingElement>node).dotDotDotToken) ||
130                    visitNode(cbNode, (<BindingElement>node).propertyName) ||
131                    visitNode(cbNode, (<BindingElement>node).name) ||
132                    visitNode(cbNode, (<BindingElement>node).initializer);
133            case SyntaxKind.FunctionType:
134            case SyntaxKind.ConstructorType:
135            case SyntaxKind.CallSignature:
136            case SyntaxKind.ConstructSignature:
137            case SyntaxKind.IndexSignature:
138                return visitNodes(cbNode, cbNodes, node.decorators) ||
139                    visitNodes(cbNode, cbNodes, node.modifiers) ||
140                    visitNodes(cbNode, cbNodes, (<SignatureDeclaration>node).typeParameters) ||
141                    visitNodes(cbNode, cbNodes, (<SignatureDeclaration>node).parameters) ||
142                    visitNode(cbNode, (<SignatureDeclaration>node).type);
143            case SyntaxKind.MethodDeclaration:
144            case SyntaxKind.MethodSignature:
145            case SyntaxKind.Constructor:
146            case SyntaxKind.GetAccessor:
147            case SyntaxKind.SetAccessor:
148            case SyntaxKind.FunctionExpression:
149            case SyntaxKind.FunctionDeclaration:
150            case SyntaxKind.ArrowFunction:
151                return visitNodes(cbNode, cbNodes, node.decorators) ||
152                    visitNodes(cbNode, cbNodes, node.modifiers) ||
153                    visitNode(cbNode, (<FunctionLikeDeclaration>node).asteriskToken) ||
154                    visitNode(cbNode, (<FunctionLikeDeclaration>node).name) ||
155                    visitNode(cbNode, (<FunctionLikeDeclaration>node).questionToken) ||
156                    visitNodes(cbNode, cbNodes, (<FunctionLikeDeclaration>node).typeParameters) ||
157                    visitNodes(cbNode, cbNodes, (<FunctionLikeDeclaration>node).parameters) ||
158                    visitNode(cbNode, (<FunctionLikeDeclaration>node).type) ||
159                    visitNode(cbNode, (<ArrowFunction>node).equalsGreaterThanToken) ||
160                    visitNode(cbNode, (<FunctionLikeDeclaration>node).body);
161            case SyntaxKind.TypeReference:
162                return visitNode(cbNode, (<TypeReferenceNode>node).typeName) ||
163                    visitNodes(cbNode, cbNodes, (<TypeReferenceNode>node).typeArguments);
164            case SyntaxKind.TypePredicate:
165                return visitNode(cbNode, (<TypePredicateNode>node).parameterName) ||
166                    visitNode(cbNode, (<TypePredicateNode>node).type);
167            case SyntaxKind.TypeQuery:
168                return visitNode(cbNode, (<TypeQueryNode>node).exprName);
169            case SyntaxKind.TypeLiteral:
170                return visitNodes(cbNode, cbNodes, (<TypeLiteralNode>node).members);
171            case SyntaxKind.ArrayType:
172                return visitNode(cbNode, (<ArrayTypeNode>node).elementType);
173            case SyntaxKind.TupleType:
174                return visitNodes(cbNode, cbNodes, (<TupleTypeNode>node).elementTypes);
175            case SyntaxKind.UnionType:
176            case SyntaxKind.IntersectionType:
177                return visitNodes(cbNode, cbNodes, (<UnionOrIntersectionTypeNode>node).types);
178            case SyntaxKind.ConditionalType:
179                return visitNode(cbNode, (<ConditionalTypeNode>node).checkType) ||
180                    visitNode(cbNode, (<ConditionalTypeNode>node).extendsType) ||
181                    visitNode(cbNode, (<ConditionalTypeNode>node).trueType) ||
182                    visitNode(cbNode, (<ConditionalTypeNode>node).falseType);
183            case SyntaxKind.InferType:
184                return visitNode(cbNode, (<InferTypeNode>node).typeParameter);
185            case SyntaxKind.ParenthesizedType:
186            case SyntaxKind.TypeOperator:
187                return visitNode(cbNode, (<ParenthesizedTypeNode | TypeOperatorNode>node).type);
188            case SyntaxKind.IndexedAccessType:
189                return visitNode(cbNode, (<IndexedAccessTypeNode>node).objectType) ||
190                    visitNode(cbNode, (<IndexedAccessTypeNode>node).indexType);
191            case SyntaxKind.MappedType:
192                return visitNode(cbNode, (<MappedTypeNode>node).readonlyToken) ||
193                    visitNode(cbNode, (<MappedTypeNode>node).typeParameter) ||
194                    visitNode(cbNode, (<MappedTypeNode>node).questionToken) ||
195                    visitNode(cbNode, (<MappedTypeNode>node).type);
196            case SyntaxKind.LiteralType:
197                return visitNode(cbNode, (<LiteralTypeNode>node).literal);
198            case SyntaxKind.ObjectBindingPattern:
199            case SyntaxKind.ArrayBindingPattern:
200                return visitNodes(cbNode, cbNodes, (<BindingPattern>node).elements);
201            case SyntaxKind.ArrayLiteralExpression:
202                return visitNodes(cbNode, cbNodes, (<ArrayLiteralExpression>node).elements);
203            case SyntaxKind.ObjectLiteralExpression:
204                return visitNodes(cbNode, cbNodes, (<ObjectLiteralExpression>node).properties);
205            case SyntaxKind.PropertyAccessExpression:
206                return visitNode(cbNode, (<PropertyAccessExpression>node).expression) ||
207                    visitNode(cbNode, (<PropertyAccessExpression>node).name);
208            case SyntaxKind.ElementAccessExpression:
209                return visitNode(cbNode, (<ElementAccessExpression>node).expression) ||
210                    visitNode(cbNode, (<ElementAccessExpression>node).argumentExpression);
211            case SyntaxKind.CallExpression:
212            case SyntaxKind.NewExpression:
213                return visitNode(cbNode, (<CallExpression>node).expression) ||
214                    visitNodes(cbNode, cbNodes, (<CallExpression>node).typeArguments) ||
215                    visitNodes(cbNode, cbNodes, (<CallExpression>node).arguments);
216            case SyntaxKind.TaggedTemplateExpression:
217                return visitNode(cbNode, (<TaggedTemplateExpression>node).tag) ||
218                    visitNode(cbNode, (<TaggedTemplateExpression>node).template);
219            case SyntaxKind.TypeAssertionExpression:
220                return visitNode(cbNode, (<TypeAssertion>node).type) ||
221                    visitNode(cbNode, (<TypeAssertion>node).expression);
222            case SyntaxKind.ParenthesizedExpression:
223                return visitNode(cbNode, (<ParenthesizedExpression>node).expression);
224            case SyntaxKind.DeleteExpression:
225                return visitNode(cbNode, (<DeleteExpression>node).expression);
226            case SyntaxKind.TypeOfExpression:
227                return visitNode(cbNode, (<TypeOfExpression>node).expression);
228            case SyntaxKind.VoidExpression:
229                return visitNode(cbNode, (<VoidExpression>node).expression);
230            case SyntaxKind.PrefixUnaryExpression:
231                return visitNode(cbNode, (<PrefixUnaryExpression>node).operand);
232            case SyntaxKind.YieldExpression:
233                return visitNode(cbNode, (<YieldExpression>node).asteriskToken) ||
234                    visitNode(cbNode, (<YieldExpression>node).expression);
235            case SyntaxKind.AwaitExpression:
236                return visitNode(cbNode, (<AwaitExpression>node).expression);
237            case SyntaxKind.PostfixUnaryExpression:
238                return visitNode(cbNode, (<PostfixUnaryExpression>node).operand);
239            case SyntaxKind.BinaryExpression:
240                return visitNode(cbNode, (<BinaryExpression>node).left) ||
241                    visitNode(cbNode, (<BinaryExpression>node).operatorToken) ||
242                    visitNode(cbNode, (<BinaryExpression>node).right);
243            case SyntaxKind.AsExpression:
244                return visitNode(cbNode, (<AsExpression>node).expression) ||
245                    visitNode(cbNode, (<AsExpression>node).type);
246            case SyntaxKind.NonNullExpression:
247                return visitNode(cbNode, (<NonNullExpression>node).expression);
248            case SyntaxKind.MetaProperty:
249                return visitNode(cbNode, (<MetaProperty>node).name);
250            case SyntaxKind.ConditionalExpression:
251                return visitNode(cbNode, (<ConditionalExpression>node).condition) ||
252                    visitNode(cbNode, (<ConditionalExpression>node).questionToken) ||
253                    visitNode(cbNode, (<ConditionalExpression>node).whenTrue) ||
254                    visitNode(cbNode, (<ConditionalExpression>node).colonToken) ||
255                    visitNode(cbNode, (<ConditionalExpression>node).whenFalse);
256            case SyntaxKind.SpreadElement:
257                return visitNode(cbNode, (<SpreadElement>node).expression);
258            case SyntaxKind.Block:
259            case SyntaxKind.ModuleBlock:
260                return visitNodes(cbNode, cbNodes, (<Block>node).statements);
261            case SyntaxKind.SourceFile:
262                return visitNodes(cbNode, cbNodes, (<SourceFile>node).statements) ||
263                    visitNode(cbNode, (<SourceFile>node).endOfFileToken);
264            case SyntaxKind.VariableStatement:
265                return visitNodes(cbNode, cbNodes, node.decorators) ||
266                    visitNodes(cbNode, cbNodes, node.modifiers) ||
267                    visitNode(cbNode, (<VariableStatement>node).declarationList);
268            case SyntaxKind.VariableDeclarationList:
269                return visitNodes(cbNode, cbNodes, (<VariableDeclarationList>node).declarations);
270            case SyntaxKind.ExpressionStatement:
271                return visitNode(cbNode, (<ExpressionStatement>node).expression);
272            case SyntaxKind.IfStatement:
273                return visitNode(cbNode, (<IfStatement>node).expression) ||
274                    visitNode(cbNode, (<IfStatement>node).thenStatement) ||
275                    visitNode(cbNode, (<IfStatement>node).elseStatement);
276            case SyntaxKind.DoStatement:
277                return visitNode(cbNode, (<DoStatement>node).statement) ||
278                    visitNode(cbNode, (<DoStatement>node).expression);
279            case SyntaxKind.WhileStatement:
280                return visitNode(cbNode, (<WhileStatement>node).expression) ||
281                    visitNode(cbNode, (<WhileStatement>node).statement);
282            case SyntaxKind.ForStatement:
283                return visitNode(cbNode, (<ForStatement>node).initializer) ||
284                    visitNode(cbNode, (<ForStatement>node).condition) ||
285                    visitNode(cbNode, (<ForStatement>node).incrementor) ||
286                    visitNode(cbNode, (<ForStatement>node).statement);
287            case SyntaxKind.ForInStatement:
288                return visitNode(cbNode, (<ForInStatement>node).initializer) ||
289                    visitNode(cbNode, (<ForInStatement>node).expression) ||
290                    visitNode(cbNode, (<ForInStatement>node).statement);
291            case SyntaxKind.ForOfStatement:
292                return visitNode(cbNode, (<ForOfStatement>node).awaitModifier) ||
293                    visitNode(cbNode, (<ForOfStatement>node).initializer) ||
294                    visitNode(cbNode, (<ForOfStatement>node).expression) ||
295                    visitNode(cbNode, (<ForOfStatement>node).statement);
296            case SyntaxKind.ContinueStatement:
297            case SyntaxKind.BreakStatement:
298                return visitNode(cbNode, (<BreakOrContinueStatement>node).label);
299            case SyntaxKind.ReturnStatement:
300                return visitNode(cbNode, (<ReturnStatement>node).expression);
301            case SyntaxKind.WithStatement:
302                return visitNode(cbNode, (<WithStatement>node).expression) ||
303                    visitNode(cbNode, (<WithStatement>node).statement);
304            case SyntaxKind.SwitchStatement:
305                return visitNode(cbNode, (<SwitchStatement>node).expression) ||
306                    visitNode(cbNode, (<SwitchStatement>node).caseBlock);
307            case SyntaxKind.CaseBlock:
308                return visitNodes(cbNode, cbNodes, (<CaseBlock>node).clauses);
309            case SyntaxKind.CaseClause:
310                return visitNode(cbNode, (<CaseClause>node).expression) ||
311                    visitNodes(cbNode, cbNodes, (<CaseClause>node).statements);
312            case SyntaxKind.DefaultClause:
313                return visitNodes(cbNode, cbNodes, (<DefaultClause>node).statements);
314            case SyntaxKind.LabeledStatement:
315                return visitNode(cbNode, (<LabeledStatement>node).label) ||
316                    visitNode(cbNode, (<LabeledStatement>node).statement);
317            case SyntaxKind.ThrowStatement:
318                return visitNode(cbNode, (<ThrowStatement>node).expression);
319            case SyntaxKind.TryStatement:
320                return visitNode(cbNode, (<TryStatement>node).tryBlock) ||
321                    visitNode(cbNode, (<TryStatement>node).catchClause) ||
322                    visitNode(cbNode, (<TryStatement>node).finallyBlock);
323            case SyntaxKind.CatchClause:
324                return visitNode(cbNode, (<CatchClause>node).variableDeclaration) ||
325                    visitNode(cbNode, (<CatchClause>node).block);
326            case SyntaxKind.Decorator:
327                return visitNode(cbNode, (<Decorator>node).expression);
328            case SyntaxKind.ClassDeclaration:
329            case SyntaxKind.ClassExpression:
330                return visitNodes(cbNode, cbNodes, node.decorators) ||
331                    visitNodes(cbNode, cbNodes, node.modifiers) ||
332                    visitNode(cbNode, (<ClassLikeDeclaration>node).name) ||
333                    visitNodes(cbNode, cbNodes, (<ClassLikeDeclaration>node).typeParameters) ||
334                    visitNodes(cbNode, cbNodes, (<ClassLikeDeclaration>node).heritageClauses) ||
335                    visitNodes(cbNode, cbNodes, (<ClassLikeDeclaration>node).members);
336            case SyntaxKind.InterfaceDeclaration:
337                return visitNodes(cbNode, cbNodes, node.decorators) ||
338                    visitNodes(cbNode, cbNodes, node.modifiers) ||
339                    visitNode(cbNode, (<InterfaceDeclaration>node).name) ||
340                    visitNodes(cbNode, cbNodes, (<InterfaceDeclaration>node).typeParameters) ||
341                    visitNodes(cbNode, cbNodes, (<ClassDeclaration>node).heritageClauses) ||
342                    visitNodes(cbNode, cbNodes, (<InterfaceDeclaration>node).members);
343            case SyntaxKind.TypeAliasDeclaration:
344                return visitNodes(cbNode, cbNodes, node.decorators) ||
345                    visitNodes(cbNode, cbNodes, node.modifiers) ||
346                    visitNode(cbNode, (<TypeAliasDeclaration>node).name) ||
347                    visitNodes(cbNode, cbNodes, (<TypeAliasDeclaration>node).typeParameters) ||
348                    visitNode(cbNode, (<TypeAliasDeclaration>node).type);
349            case SyntaxKind.EnumDeclaration:
350                return visitNodes(cbNode, cbNodes, node.decorators) ||
351                    visitNodes(cbNode, cbNodes, node.modifiers) ||
352                    visitNode(cbNode, (<EnumDeclaration>node).name) ||
353                    visitNodes(cbNode, cbNodes, (<EnumDeclaration>node).members);
354            case SyntaxKind.EnumMember:
355                return visitNode(cbNode, (<EnumMember>node).name) ||
356                    visitNode(cbNode, (<EnumMember>node).initializer);
357            case SyntaxKind.ModuleDeclaration:
358                return visitNodes(cbNode, cbNodes, node.decorators) ||
359                    visitNodes(cbNode, cbNodes, node.modifiers) ||
360                    visitNode(cbNode, (<ModuleDeclaration>node).name) ||
361                    visitNode(cbNode, (<ModuleDeclaration>node).body);
362            case SyntaxKind.ImportEqualsDeclaration:
363                return visitNodes(cbNode, cbNodes, node.decorators) ||
364                    visitNodes(cbNode, cbNodes, node.modifiers) ||
365                    visitNode(cbNode, (<ImportEqualsDeclaration>node).name) ||
366                    visitNode(cbNode, (<ImportEqualsDeclaration>node).moduleReference);
367            case SyntaxKind.ImportDeclaration:
368                return visitNodes(cbNode, cbNodes, node.decorators) ||
369                    visitNodes(cbNode, cbNodes, node.modifiers) ||
370                    visitNode(cbNode, (<ImportDeclaration>node).importClause) ||
371                    visitNode(cbNode, (<ImportDeclaration>node).moduleSpecifier);
372            case SyntaxKind.ImportClause:
373                return visitNode(cbNode, (<ImportClause>node).name) ||
374                    visitNode(cbNode, (<ImportClause>node).namedBindings);
375            case SyntaxKind.NamespaceExportDeclaration:
376                return visitNode(cbNode, (<NamespaceExportDeclaration>node).name);
377
378            case SyntaxKind.NamespaceImport:
379                return visitNode(cbNode, (<NamespaceImport>node).name);
380            case SyntaxKind.NamedImports:
381            case SyntaxKind.NamedExports:
382                return visitNodes(cbNode, cbNodes, (<NamedImportsOrExports>node).elements);
383            case SyntaxKind.ExportDeclaration:
384                return visitNodes(cbNode, cbNodes, node.decorators) ||
385                    visitNodes(cbNode, cbNodes, node.modifiers) ||
386                    visitNode(cbNode, (<ExportDeclaration>node).exportClause) ||
387                    visitNode(cbNode, (<ExportDeclaration>node).moduleSpecifier);
388            case SyntaxKind.ImportSpecifier:
389            case SyntaxKind.ExportSpecifier:
390                return visitNode(cbNode, (<ImportOrExportSpecifier>node).propertyName) ||
391                    visitNode(cbNode, (<ImportOrExportSpecifier>node).name);
392            case SyntaxKind.ExportAssignment:
393                return visitNodes(cbNode, cbNodes, node.decorators) ||
394                    visitNodes(cbNode, cbNodes, node.modifiers) ||
395                    visitNode(cbNode, (<ExportAssignment>node).expression);
396            case SyntaxKind.TemplateExpression:
397                return visitNode(cbNode, (<TemplateExpression>node).head) || visitNodes(cbNode, cbNodes, (<TemplateExpression>node).templateSpans);
398            case SyntaxKind.TemplateSpan:
399                return visitNode(cbNode, (<TemplateSpan>node).expression) || visitNode(cbNode, (<TemplateSpan>node).literal);
400            case SyntaxKind.ComputedPropertyName:
401                return visitNode(cbNode, (<ComputedPropertyName>node).expression);
402            case SyntaxKind.HeritageClause:
403                return visitNodes(cbNode, cbNodes, (<HeritageClause>node).types);
404            case SyntaxKind.ExpressionWithTypeArguments:
405                return visitNode(cbNode, (<ExpressionWithTypeArguments>node).expression) ||
406                    visitNodes(cbNode, cbNodes, (<ExpressionWithTypeArguments>node).typeArguments);
407            case SyntaxKind.ExternalModuleReference:
408                return visitNode(cbNode, (<ExternalModuleReference>node).expression);
409            case SyntaxKind.MissingDeclaration:
410                return visitNodes(cbNode, cbNodes, node.decorators);
411            case SyntaxKind.CommaListExpression:
412                return visitNodes(cbNode, cbNodes, (<CommaListExpression>node).elements);
413
414            case SyntaxKind.JsxElement:
415                return visitNode(cbNode, (<JsxElement>node).openingElement) ||
416                    visitNodes(cbNode, cbNodes, (<JsxElement>node).children) ||
417                    visitNode(cbNode, (<JsxElement>node).closingElement);
418            case SyntaxKind.JsxFragment:
419                return visitNode(cbNode, (<JsxFragment>node).openingFragment) ||
420                    visitNodes(cbNode, cbNodes, (<JsxFragment>node).children) ||
421                    visitNode(cbNode, (<JsxFragment>node).closingFragment);
422            case SyntaxKind.JsxSelfClosingElement:
423            case SyntaxKind.JsxOpeningElement:
424                return visitNode(cbNode, (<JsxOpeningLikeElement>node).tagName) ||
425                    visitNode(cbNode, (<JsxOpeningLikeElement>node).attributes);
426            case SyntaxKind.JsxAttributes:
427                return visitNodes(cbNode, cbNodes, (<JsxAttributes>node).properties);
428            case SyntaxKind.JsxAttribute:
429                return visitNode(cbNode, (<JsxAttribute>node).name) ||
430                    visitNode(cbNode, (<JsxAttribute>node).initializer);
431            case SyntaxKind.JsxSpreadAttribute:
432                return visitNode(cbNode, (<JsxSpreadAttribute>node).expression);
433            case SyntaxKind.JsxExpression:
434                return visitNode(cbNode, (node as JsxExpression).dotDotDotToken) ||
435                    visitNode(cbNode, (node as JsxExpression).expression);
436            case SyntaxKind.JsxClosingElement:
437                return visitNode(cbNode, (<JsxClosingElement>node).tagName);
438
439            case SyntaxKind.JSDocTypeExpression:
440                return visitNode(cbNode, (<JSDocTypeExpression>node).type);
441            case SyntaxKind.JSDocNonNullableType:
442                return visitNode(cbNode, (<JSDocNonNullableType>node).type);
443            case SyntaxKind.JSDocNullableType:
444                return visitNode(cbNode, (<JSDocNullableType>node).type);
445            case SyntaxKind.JSDocOptionalType:
446                return visitNode(cbNode, (<JSDocOptionalType>node).type);
447            case SyntaxKind.JSDocFunctionType:
448                return visitNodes(cbNode, cbNodes, (<JSDocFunctionType>node).parameters) ||
449                    visitNode(cbNode, (<JSDocFunctionType>node).type);
450            case SyntaxKind.JSDocVariadicType:
451                return visitNode(cbNode, (<JSDocVariadicType>node).type);
452            case SyntaxKind.JSDocComment:
453                return visitNodes(cbNode, cbNodes, (<JSDoc>node).tags);
454            case SyntaxKind.JSDocParameterTag:
455            case SyntaxKind.JSDocPropertyTag:
456                if ((node as JSDocPropertyLikeTag).isNameFirst) {
457                    return visitNode(cbNode, (<JSDocPropertyLikeTag>node).name) ||
458                        visitNode(cbNode, (<JSDocPropertyLikeTag>node).typeExpression);
459                }
460                else {
461                    return visitNode(cbNode, (<JSDocPropertyLikeTag>node).typeExpression) ||
462                        visitNode(cbNode, (<JSDocPropertyLikeTag>node).name);
463                }
464            case SyntaxKind.JSDocReturnTag:
465                return visitNode(cbNode, (<JSDocReturnTag>node).typeExpression);
466            case SyntaxKind.JSDocTypeTag:
467                return visitNode(cbNode, (<JSDocTypeTag>node).typeExpression);
468            case SyntaxKind.JSDocAugmentsTag:
469                return visitNode(cbNode, (<JSDocAugmentsTag>node).class);
470            case SyntaxKind.JSDocTemplateTag:
471                return visitNodes(cbNode, cbNodes, (<JSDocTemplateTag>node).typeParameters);
472            case SyntaxKind.JSDocTypedefTag:
473                if ((node as JSDocTypedefTag).typeExpression &&
474                    (node as JSDocTypedefTag).typeExpression.kind === SyntaxKind.JSDocTypeExpression) {
475                    return visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression) ||
476                        visitNode(cbNode, (<JSDocTypedefTag>node).fullName);
477                }
478                else {
479                    return visitNode(cbNode, (<JSDocTypedefTag>node).fullName) ||
480                        visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression);
481                }
482            case SyntaxKind.JSDocTypeLiteral:
483                if ((node as JSDocTypeLiteral).jsDocPropertyTags) {
484                    for (const tag of (node as JSDocTypeLiteral).jsDocPropertyTags) {
485                        visitNode(cbNode, tag);
486                    }
487                }
488                return;
489            case SyntaxKind.PartiallyEmittedExpression:
490                return visitNode(cbNode, (<PartiallyEmittedExpression>node).expression);
491        }
492    }
493
494    export function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false, scriptKind?: ScriptKind): SourceFile {
495        performance.mark("beforeParse");
496        const result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind);
497        performance.mark("afterParse");
498        performance.measure("Parse", "beforeParse", "afterParse");
499        return result;
500    }
501
502    export function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName {
503        return Parser.parseIsolatedEntityName(text, languageVersion);
504    }
505
506    /**
507     * Parse json text into SyntaxTree and return node and parse errors if any
508     * @param fileName
509     * @param sourceText
510     */
511    export function parseJsonText(fileName: string, sourceText: string): JsonSourceFile {
512        return Parser.parseJsonText(fileName, sourceText);
513    }
514
515    // See also `isExternalOrCommonJsModule` in utilities.ts
516    export function isExternalModule(file: SourceFile): boolean {
517        return file.externalModuleIndicator !== undefined;
518    }
519
520    // Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter
521    // indicates what changed between the 'text' that this SourceFile has and the 'newText'.
522    // The SourceFile will be created with the compiler attempting to reuse as many nodes from
523    // this file as possible.
524    //
525    // Note: this function mutates nodes from this SourceFile. That means any existing nodes
526    // from this SourceFile that are being held onto may change as a result (including
527    // becoming detached from any SourceFile).  It is recommended that this SourceFile not
528    // be used once 'update' is called on it.
529    export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile {
530        const newSourceFile = IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks);
531        // Because new source file node is created, it may not have the flag PossiblyContainDynamicImport. This is the case if there is no new edit to add dynamic import.
532        // We will manually port the flag to the new source file.
533        newSourceFile.flags |= (sourceFile.flags & NodeFlags.PossiblyContainsDynamicImport);
534        return newSourceFile;
535    }
536
537    /* @internal */
538    export function parseIsolatedJSDocComment(content: string, start?: number, length?: number) {
539        const result = Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length);
540        if (result && result.jsDoc) {
541            // because the jsDocComment was parsed out of the source file, it might
542            // not be covered by the fixupParentReferences.
543            Parser.fixupParentReferences(result.jsDoc);
544        }
545
546        return result;
547    }
548
549    /* @internal */
550    // Exposed only for testing.
551    export function parseJSDocTypeExpressionForTests(content: string, start?: number, length?: number) {
552        return Parser.JSDocParser.parseJSDocTypeExpressionForTests(content, start, length);
553    }
554
555    // Implement the parser as a singleton module.  We do this for perf reasons because creating
556    // parser instances can actually be expensive enough to impact us on projects with many source
557    // files.
558    namespace Parser {
559        // Share a single scanner across all calls to parse a source file.  This helps speed things
560        // up by avoiding the cost of creating/compiling scanners over and over again.
561        const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true);
562        const disallowInAndDecoratorContext = NodeFlags.DisallowInContext | NodeFlags.DecoratorContext;
563
564        // capture constructors in 'initializeState' to avoid null checks
565        // tslint:disable variable-name
566        let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
567        let TokenConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
568        let IdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
569        let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
570        // tslint:enable variable-name
571
572        let sourceFile: SourceFile;
573        let parseDiagnostics: Diagnostic[];
574        let syntaxCursor: IncrementalParser.SyntaxCursor;
575
576        let currentToken: SyntaxKind;
577        let sourceText: string;
578        let nodeCount: number;
579        let identifiers: Map<string>;
580        let identifierCount: number;
581
582        let parsingContext: ParsingContext;
583
584        // Flags that dictate what parsing context we're in.  For example:
585        // Whether or not we are in strict parsing mode.  All that changes in strict parsing mode is
586        // that some tokens that would be considered identifiers may be considered keywords.
587        //
588        // When adding more parser context flags, consider which is the more common case that the
589        // flag will be in.  This should be the 'false' state for that flag.  The reason for this is
590        // that we don't store data in our nodes unless the value is in the *non-default* state.  So,
591        // for example, more often than code 'allows-in' (or doesn't 'disallow-in').  We opt for
592        // 'disallow-in' set to 'false'.  Otherwise, if we had 'allowsIn' set to 'true', then almost
593        // all nodes would need extra state on them to store this info.
594        //
595        // Note: 'allowIn' and 'allowYield' track 1:1 with the [in] and [yield] concepts in the ES6
596        // grammar specification.
597        //
598        // An important thing about these context concepts.  By default they are effectively inherited
599        // while parsing through every grammar production.  i.e. if you don't change them, then when
600        // you parse a sub-production, it will have the same context values as the parent production.
601        // This is great most of the time.  After all, consider all the 'expression' grammar productions
602        // and how nearly all of them pass along the 'in' and 'yield' context values:
603        //
604        // EqualityExpression[In, Yield] :
605        //      RelationalExpression[?In, ?Yield]
606        //      EqualityExpression[?In, ?Yield] == RelationalExpression[?In, ?Yield]
607        //      EqualityExpression[?In, ?Yield] != RelationalExpression[?In, ?Yield]
608        //      EqualityExpression[?In, ?Yield] === RelationalExpression[?In, ?Yield]
609        //      EqualityExpression[?In, ?Yield] !== RelationalExpression[?In, ?Yield]
610        //
611        // Where you have to be careful is then understanding what the points are in the grammar
612        // where the values are *not* passed along.  For example:
613        //
614        // SingleNameBinding[Yield,GeneratorParameter]
615        //      [+GeneratorParameter]BindingIdentifier[Yield] Initializer[In]opt
616        //      [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
617        //
618        // Here this is saying that if the GeneratorParameter context flag is set, that we should
619        // explicitly set the 'yield' context flag to false before calling into the BindingIdentifier
620        // and we should explicitly unset the 'yield' context flag before calling into the Initializer.
621        // production.  Conversely, if the GeneratorParameter context flag is not set, then we
622        // should leave the 'yield' context flag alone.
623        //
624        // Getting this all correct is tricky and requires careful reading of the grammar to
625        // understand when these values should be changed versus when they should be inherited.
626        //
627        // Note: it should not be necessary to save/restore these flags during speculative/lookahead
628        // parsing.  These context flags are naturally stored and restored through normal recursive
629        // descent parsing and unwinding.
630        let contextFlags: NodeFlags;
631
632        // Whether or not we've had a parse error since creating the last AST node.  If we have
633        // encountered an error, it will be stored on the next AST node we create.  Parse errors
634        // can be broken down into three categories:
635        //
636        // 1) An error that occurred during scanning.  For example, an unterminated literal, or a
637        //    character that was completely not understood.
638        //
639        // 2) A token was expected, but was not present.  This type of error is commonly produced
640        //    by the 'parseExpected' function.
641        //
642        // 3) A token was present that no parsing function was able to consume.  This type of error
643        //    only occurs in the 'abortParsingListOrMoveToNextToken' function when the parser
644        //    decides to skip the token.
645        //
646        // In all of these cases, we want to mark the next node as having had an error before it.
647        // With this mark, we can know in incremental settings if this node can be reused, or if
648        // we have to reparse it.  If we don't keep this information around, we may just reuse the
649        // node.  in that event we would then not produce the same errors as we did before, causing
650        // significant confusion problems.
651        //
652        // Note: it is necessary that this value be saved/restored during speculative/lookahead
653        // parsing.  During lookahead parsing, we will often create a node.  That node will have
654        // this value attached, and then this value will be set back to 'false'.  If we decide to
655        // rewind, we must get back to the same value we had prior to the lookahead.
656        //
657        // Note: any errors at the end of the file that do not precede a regular node, should get
658        // attached to the EOF token.
659        let parseErrorBeforeNextFinishedNode = false;
660
661        export function parseSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile {
662            scriptKind = ensureScriptKind(fileName, scriptKind);
663
664            initializeState(sourceText, languageVersion, syntaxCursor, scriptKind);
665
666            const result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind);
667
668            clearState();
669
670            return result;
671        }
672
673        export function parseIsolatedEntityName(content: string, languageVersion: ScriptTarget): EntityName {
674            // Choice of `isDeclarationFile` should be arbitrary
675            initializeState(content, languageVersion, /*syntaxCursor*/ undefined, ScriptKind.JS);
676            // Prime the scanner.
677            nextToken();
678            const entityName = parseEntityName(/*allowReservedWords*/ true);
679            const isInvalid = token() === SyntaxKind.EndOfFileToken && !parseDiagnostics.length;
680            clearState();
681            return isInvalid ? entityName : undefined;
682        }
683
684        export function parseJsonText(fileName: string, sourceText: string): JsonSourceFile {
685            initializeState(sourceText, ScriptTarget.ES2015, /*syntaxCursor*/ undefined, ScriptKind.JSON);
686            // Set source file so that errors will be reported with this file name
687            sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, /*isDeclaration*/ false);
688            const result = <JsonSourceFile>sourceFile;
689
690            // Prime the scanner.
691            nextToken();
692            if (token() === SyntaxKind.EndOfFileToken) {
693                sourceFile.endOfFileToken = <EndOfFileToken>parseTokenNode();
694            }
695            else if (token() === SyntaxKind.OpenBraceToken ||
696                lookAhead(() => token() === SyntaxKind.StringLiteral)) {
697                result.jsonObject = parseObjectLiteralExpression();
698                sourceFile.endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, Diagnostics.Unexpected_token);
699            }
700            else {
701                parseExpected(SyntaxKind.OpenBraceToken);
702            }
703
704            sourceFile.parseDiagnostics = parseDiagnostics;
705            clearState();
706            return result;
707        }
708
709        function getLanguageVariant(scriptKind: ScriptKind) {
710            // .tsx and .jsx files are treated as jsx language variant.
711            return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSON ? LanguageVariant.JSX : LanguageVariant.Standard;
712        }
713
714        function initializeState(_sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, scriptKind: ScriptKind) {
715            NodeConstructor = objectAllocator.getNodeConstructor();
716            TokenConstructor = objectAllocator.getTokenConstructor();
717            IdentifierConstructor = objectAllocator.getIdentifierConstructor();
718            SourceFileConstructor = objectAllocator.getSourceFileConstructor();
719
720            sourceText = _sourceText;
721            syntaxCursor = _syntaxCursor;
722
723            parseDiagnostics = [];
724            parsingContext = 0;
725            identifiers = createMap<string>();
726            identifierCount = 0;
727            nodeCount = 0;
728
729            switch (scriptKind) {
730                case ScriptKind.JS:
731                case ScriptKind.JSX:
732                case ScriptKind.JSON:
733                    contextFlags = NodeFlags.JavaScriptFile;
734                    break;
735                default:
736                    contextFlags = NodeFlags.None;
737                    break;
738            }
739            parseErrorBeforeNextFinishedNode = false;
740
741            // Initialize and prime the scanner before parsing the source elements.
742            scanner.setText(sourceText);
743            scanner.setOnError(scanError);
744            scanner.setScriptTarget(languageVersion);
745            scanner.setLanguageVariant(getLanguageVariant(scriptKind));
746        }
747
748        function clearState() {
749            // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily.
750            scanner.setText("");
751            scanner.setOnError(undefined);
752
753            // Clear any data.  We don't want to accidentally hold onto it for too long.
754            parseDiagnostics = undefined;
755            sourceFile = undefined;
756            identifiers = undefined;
757            syntaxCursor = undefined;
758            sourceText = undefined;
759        }
760
761        function parseSourceFileWorker(fileName: string, languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind): SourceFile {
762            const isDeclarationFile = isDeclarationFileName(fileName);
763            if (isDeclarationFile) {
764                contextFlags |= NodeFlags.Ambient;
765            }
766
767            sourceFile = createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile);
768            sourceFile.flags = contextFlags;
769
770            // Prime the scanner.
771            nextToken();
772            processReferenceComments(sourceFile);
773
774            sourceFile.statements = parseList(ParsingContext.SourceElements, parseStatement);
775            Debug.assert(token() === SyntaxKind.EndOfFileToken);
776            sourceFile.endOfFileToken = addJSDocComment(parseTokenNode() as EndOfFileToken);
777
778            setExternalModuleIndicator(sourceFile);
779
780            sourceFile.nodeCount = nodeCount;
781            sourceFile.identifierCount = identifierCount;
782            sourceFile.identifiers = identifiers;
783            sourceFile.parseDiagnostics = parseDiagnostics;
784
785            if (setParentNodes) {
786                fixupParentReferences(sourceFile);
787            }
788
789            return sourceFile;
790        }
791
792        function addJSDocComment<T extends HasJSDoc>(node: T): T {
793            const comments = getJSDocCommentRanges(node, sourceFile.text);
794            if (comments) {
795                for (const comment of comments) {
796                    node.jsDoc = append(node.jsDoc, JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos));
797                }
798            }
799
800            return node;
801        }
802
803        export function fixupParentReferences(rootNode: Node) {
804            // normally parent references are set during binding. However, for clients that only need
805            // a syntax tree, and no semantic features, then the binding process is an unnecessary
806            // overhead.  This functions allows us to set all the parents, without all the expense of
807            // binding.
808
809            let parent: Node = rootNode;
810            forEachChild(rootNode, visitNode);
811            return;
812
813            function visitNode(n: Node): void {
814                // walk down setting parents that differ from the parent we think it should be.  This
815                // allows us to quickly bail out of setting parents for subtrees during incremental
816                // parsing
817                if (n.parent !== parent) {
818                    n.parent = parent;
819
820                    const saveParent = parent;
821                    parent = n;
822                    forEachChild(n, visitNode);
823                    if (hasJSDocNodes(n)) {
824                        for (const jsDoc of n.jsDoc) {
825                            jsDoc.parent = n;
826                            parent = jsDoc;
827                            forEachChild(jsDoc, visitNode);
828                        }
829                    }
830                    parent = saveParent;
831                }
832            }
833        }
834
835        function createSourceFile(fileName: string, languageVersion: ScriptTarget, scriptKind: ScriptKind, isDeclarationFile: boolean): SourceFile {
836            // code from createNode is inlined here so createNode won't have to deal with special case of creating source files
837            // this is quite rare comparing to other nodes and createNode should be as fast as possible
838            const sourceFile = <SourceFile>new SourceFileConstructor(SyntaxKind.SourceFile, /*pos*/ 0, /* end */ sourceText.length);
839            nodeCount++;
840
841            sourceFile.text = sourceText;
842            sourceFile.bindDiagnostics = [];
843            sourceFile.languageVersion = languageVersion;
844            sourceFile.fileName = normalizePath(fileName);
845            sourceFile.languageVariant = getLanguageVariant(scriptKind);
846            sourceFile.isDeclarationFile = isDeclarationFile;
847            sourceFile.scriptKind = scriptKind;
848
849            return sourceFile;
850        }
851
852        function setContextFlag(val: boolean, flag: NodeFlags) {
853            if (val) {
854                contextFlags |= flag;
855            }
856            else {
857                contextFlags &= ~flag;
858            }
859        }
860
861        function setDisallowInContext(val: boolean) {
862            setContextFlag(val, NodeFlags.DisallowInContext);
863        }
864
865        function setYieldContext(val: boolean) {
866            setContextFlag(val, NodeFlags.YieldContext);
867        }
868
869        function setDecoratorContext(val: boolean) {
870            setContextFlag(val, NodeFlags.DecoratorContext);
871        }
872
873        function setAwaitContext(val: boolean) {
874            setContextFlag(val, NodeFlags.AwaitContext);
875        }
876
877        function doOutsideOfContext<T>(context: NodeFlags, func: () => T): T {
878            // contextFlagsToClear will contain only the context flags that are
879            // currently set that we need to temporarily clear
880            // We don't just blindly reset to the previous flags to ensure
881            // that we do not mutate cached flags for the incremental
882            // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and
883            // HasAggregatedChildData).
884            const contextFlagsToClear = context & contextFlags;
885            if (contextFlagsToClear) {
886                // clear the requested context flags
887                setContextFlag(/*val*/ false, contextFlagsToClear);
888                const result = func();
889                // restore the context flags we just cleared
890                setContextFlag(/*val*/ true, contextFlagsToClear);
891                return result;
892            }
893
894            // no need to do anything special as we are not in any of the requested contexts
895            return func();
896        }
897
898        function doInsideOfContext<T>(context: NodeFlags, func: () => T): T {
899            // contextFlagsToSet will contain only the context flags that
900            // are not currently set that we need to temporarily enable.
901            // We don't just blindly reset to the previous flags to ensure
902            // that we do not mutate cached flags for the incremental
903            // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and
904            // HasAggregatedChildData).
905            const contextFlagsToSet = context & ~contextFlags;
906            if (contextFlagsToSet) {
907                // set the requested context flags
908                setContextFlag(/*val*/ true, contextFlagsToSet);
909                const result = func();
910                // reset the context flags we just set
911                setContextFlag(/*val*/ false, contextFlagsToSet);
912                return result;
913            }
914
915            // no need to do anything special as we are already in all of the requested contexts
916            return func();
917        }
918
919        function allowInAnd<T>(func: () => T): T {
920            return doOutsideOfContext(NodeFlags.DisallowInContext, func);
921        }
922
923        function disallowInAnd<T>(func: () => T): T {
924            return doInsideOfContext(NodeFlags.DisallowInContext, func);
925        }
926
927        function doInYieldContext<T>(func: () => T): T {
928            return doInsideOfContext(NodeFlags.YieldContext, func);
929        }
930
931        function doInDecoratorContext<T>(func: () => T): T {
932            return doInsideOfContext(NodeFlags.DecoratorContext, func);
933        }
934
935        function doInAwaitContext<T>(func: () => T): T {
936            return doInsideOfContext(NodeFlags.AwaitContext, func);
937        }
938
939        function doOutsideOfAwaitContext<T>(func: () => T): T {
940            return doOutsideOfContext(NodeFlags.AwaitContext, func);
941        }
942
943        function doInYieldAndAwaitContext<T>(func: () => T): T {
944            return doInsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext, func);
945        }
946
947        function inContext(flags: NodeFlags) {
948            return (contextFlags & flags) !== 0;
949        }
950
951        function inYieldContext() {
952            return inContext(NodeFlags.YieldContext);
953        }
954
955        function inDisallowInContext() {
956            return inContext(NodeFlags.DisallowInContext);
957        }
958
959        function inDecoratorContext() {
960            return inContext(NodeFlags.DecoratorContext);
961        }
962
963        function inAwaitContext() {
964            return inContext(NodeFlags.AwaitContext);
965        }
966
967        function parseErrorAtCurrentToken(message: DiagnosticMessage, arg0?: any): void {
968            const start = scanner.getTokenPos();
969            const length = scanner.getTextPos() - start;
970
971            parseErrorAtPosition(start, length, message, arg0);
972        }
973
974        function parseErrorAtPosition(start: number, length: number, message: DiagnosticMessage, arg0?: any): void {
975            // Don't report another error if it would just be at the same position as the last error.
976            const lastError = lastOrUndefined(parseDiagnostics);
977            if (!lastError || start !== lastError.start) {
978                parseDiagnostics.push(createFileDiagnostic(sourceFile, start, length, message, arg0));
979            }
980
981            // Mark that we've encountered an error.  We'll set an appropriate bit on the next
982            // node we finish so that it can't be reused incrementally.
983            parseErrorBeforeNextFinishedNode = true;
984        }
985
986        function scanError(message: DiagnosticMessage, length?: number) {
987            const pos = scanner.getTextPos();
988            parseErrorAtPosition(pos, length || 0, message);
989        }
990
991        function getNodePos(): number {
992            return scanner.getStartPos();
993        }
994
995        // Use this function to access the current token instead of reading the currentToken
996        // variable. Since function results aren't narrowed in control flow analysis, this ensures
997        // that the type checker doesn't make wrong assumptions about the type of the current
998        // token (e.g. a call to nextToken() changes the current token but the checker doesn't
999        // reason about this side effect).  Mainstream VMs inline simple functions like this, so
1000        // there is no performance penalty.
1001        function token(): SyntaxKind {
1002            return currentToken;
1003        }
1004
1005        function nextToken(): SyntaxKind {
1006            return currentToken = scanner.scan();
1007        }
1008
1009        function reScanGreaterToken(): SyntaxKind {
1010            return currentToken = scanner.reScanGreaterToken();
1011        }
1012
1013        function reScanSlashToken(): SyntaxKind {
1014            return currentToken = scanner.reScanSlashToken();
1015        }
1016
1017        function reScanTemplateToken(): SyntaxKind {
1018            return currentToken = scanner.reScanTemplateToken();
1019        }
1020
1021        function scanJsxIdentifier(): SyntaxKind {
1022            return currentToken = scanner.scanJsxIdentifier();
1023        }
1024
1025        function scanJsxText(): SyntaxKind {
1026            return currentToken = scanner.scanJsxToken();
1027        }
1028
1029        function scanJsxAttributeValue(): SyntaxKind {
1030            return currentToken = scanner.scanJsxAttributeValue();
1031        }
1032
1033        function speculationHelper<T>(callback: () => T, isLookAhead: boolean): T {
1034            // Keep track of the state we'll need to rollback to if lookahead fails (or if the
1035            // caller asked us to always reset our state).
1036            const saveToken = currentToken;
1037            const saveParseDiagnosticsLength = parseDiagnostics.length;
1038            const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
1039
1040            // Note: it is not actually necessary to save/restore the context flags here.  That's
1041            // because the saving/restoring of these flags happens naturally through the recursive
1042            // descent nature of our parser.  However, we still store this here just so we can
1043            // assert that invariant holds.
1044            const saveContextFlags = contextFlags;
1045
1046            // If we're only looking ahead, then tell the scanner to only lookahead as well.
1047            // Otherwise, if we're actually speculatively parsing, then tell the scanner to do the
1048            // same.
1049            const result = isLookAhead
1050                ? scanner.lookAhead(callback)
1051                : scanner.tryScan(callback);
1052
1053            Debug.assert(saveContextFlags === contextFlags);
1054
1055            // If our callback returned something 'falsy' or we're just looking ahead,
1056            // then unconditionally restore us to where we were.
1057            if (!result || isLookAhead) {
1058                currentToken = saveToken;
1059                parseDiagnostics.length = saveParseDiagnosticsLength;
1060                parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode;
1061            }
1062
1063            return result;
1064        }
1065
1066        /** Invokes the provided callback then unconditionally restores the parser to the state it
1067         * was in immediately prior to invoking the callback.  The result of invoking the callback
1068         * is returned from this function.
1069         */
1070        function lookAhead<T>(callback: () => T): T {
1071            return speculationHelper(callback, /*isLookAhead*/ true);
1072        }
1073
1074        /** Invokes the provided callback.  If the callback returns something falsy, then it restores
1075         * the parser to the state it was in immediately prior to invoking the callback.  If the
1076         * callback returns something truthy, then the parser state is not rolled back.  The result
1077         * of invoking the callback is returned from this function.
1078         */
1079        function tryParse<T>(callback: () => T): T {
1080            return speculationHelper(callback, /*isLookAhead*/ false);
1081        }
1082
1083        // Ignore strict mode flag because we will report an error in type checker instead.
1084        function isIdentifier(): boolean {
1085            if (token() === SyntaxKind.Identifier) {
1086                return true;
1087            }
1088
1089            // If we have a 'yield' keyword, and we're in the [yield] context, then 'yield' is
1090            // considered a keyword and is not an identifier.
1091            if (token() === SyntaxKind.YieldKeyword && inYieldContext()) {
1092                return false;
1093            }
1094
1095            // If we have a 'await' keyword, and we're in the [Await] context, then 'await' is
1096            // considered a keyword and is not an identifier.
1097            if (token() === SyntaxKind.AwaitKeyword && inAwaitContext()) {
1098                return false;
1099            }
1100
1101            return token() > SyntaxKind.LastReservedWord;
1102        }
1103
1104        function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage, shouldAdvance = true): boolean {
1105            if (token() === kind) {
1106                if (shouldAdvance) {
1107                    nextToken();
1108                }
1109                return true;
1110            }
1111
1112            // Report specific message if provided with one.  Otherwise, report generic fallback message.
1113            if (diagnosticMessage) {
1114                parseErrorAtCurrentToken(diagnosticMessage);
1115            }
1116            else {
1117                parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(kind));
1118            }
1119            return false;
1120        }
1121
1122        function parseOptional(t: SyntaxKind): boolean {
1123            if (token() === t) {
1124                nextToken();
1125                return true;
1126            }
1127            return false;
1128        }
1129
1130        function parseOptionalToken<TKind extends SyntaxKind>(t: TKind): Token<TKind>;
1131        function parseOptionalToken(t: SyntaxKind): Node {
1132            if (token() === t) {
1133                return parseTokenNode();
1134            }
1135            return undefined;
1136        }
1137
1138        function parseExpectedToken<TKind extends SyntaxKind>(t: TKind, diagnosticMessage?: DiagnosticMessage, arg0?: any): Token<TKind>;
1139        function parseExpectedToken(t: SyntaxKind, diagnosticMessage?: DiagnosticMessage, arg0?: any): Node {
1140            return parseOptionalToken(t) ||
1141                createMissingNode(t, /*reportAtCurrentPosition*/ false, diagnosticMessage || Diagnostics._0_expected, arg0 || tokenToString(t));
1142        }
1143
1144        function parseTokenNode<T extends Node>(): T {
1145            const node = <T>createNode(token());
1146            nextToken();
1147            return finishNode(node);
1148        }
1149
1150        function canParseSemicolon() {
1151            // If there's a real semicolon, then we can always parse it out.
1152            if (token() === SyntaxKind.SemicolonToken) {
1153                return true;
1154            }
1155
1156            // We can parse out an optional semicolon in ASI cases in the following cases.
1157            return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.EndOfFileToken || scanner.hasPrecedingLineBreak();
1158        }
1159
1160        function parseSemicolon(): boolean {
1161            if (canParseSemicolon()) {
1162                if (token() === SyntaxKind.SemicolonToken) {
1163                    // consume the semicolon if it was explicitly provided.
1164                    nextToken();
1165                }
1166
1167                return true;
1168            }
1169            else {
1170                return parseExpected(SyntaxKind.SemicolonToken);
1171            }
1172        }
1173
1174        function createNode(kind: SyntaxKind, pos?: number): Node {
1175            nodeCount++;
1176            const p = pos >= 0 ? pos : scanner.getStartPos();
1177            return isNodeKind(kind) || kind === SyntaxKind.Unknown ? new NodeConstructor(kind, p, p) :
1178                kind === SyntaxKind.Identifier ? new IdentifierConstructor(kind, p, p) :
1179                new TokenConstructor(kind, p, p);
1180        }
1181
1182        function createNodeWithJSDoc(kind: SyntaxKind): Node {
1183            const node = createNode(kind);
1184            if (scanner.getTokenFlags() & TokenFlags.PrecedingJSDocComment) {
1185                addJSDocComment(<HasJSDoc>node);
1186            }
1187            return node;
1188        }
1189
1190        function createNodeArray<T extends Node>(elements: T[], pos: number, end?: number): NodeArray<T> {
1191            // Since the element list of a node array is typically created by starting with an empty array and
1192            // repeatedly calling push(), the list may not have the optimal memory layout. We invoke slice() for
1193            // small arrays (1 to 4 elements) to give the VM a chance to allocate an optimal representation.
1194            const length = elements.length;
1195            const array = <MutableNodeArray<T>>(length >= 1 && length <= 4 ? elements.slice() : elements);
1196            array.pos = pos;
1197            array.end = end === undefined ? scanner.getStartPos() : end;
1198            return array;
1199        }
1200
1201        function finishNode<T extends Node>(node: T, end?: number): T {
1202            node.end = end === undefined ? scanner.getStartPos() : end;
1203
1204            if (contextFlags) {
1205                node.flags |= contextFlags;
1206            }
1207
1208            // Keep track on the node if we encountered an error while parsing it.  If we did, then
1209            // we cannot reuse the node incrementally.  Once we've marked this node, clear out the
1210            // flag so that we don't mark any subsequent nodes.
1211            if (parseErrorBeforeNextFinishedNode) {
1212                parseErrorBeforeNextFinishedNode = false;
1213                node.flags |= NodeFlags.ThisNodeHasError;
1214            }
1215
1216            return node;
1217        }
1218
1219        function createMissingNode<T extends Node>(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, arg0?: any): T {
1220            if (reportAtCurrentPosition) {
1221                parseErrorAtPosition(scanner.getStartPos(), 0, diagnosticMessage, arg0);
1222            }
1223            else {
1224                parseErrorAtCurrentToken(diagnosticMessage, arg0);
1225            }
1226
1227            const result = createNode(kind);
1228
1229            if (kind === SyntaxKind.Identifier) {
1230                (result as Identifier).escapedText = "" as __String;
1231            }
1232            else if (isLiteralKind(kind) || isTemplateLiteralKind(kind)) {
1233                (result as LiteralLikeNode).text = "";
1234            }
1235
1236            return finishNode(result) as T;
1237        }
1238
1239        function internIdentifier(text: string): string {
1240            let identifier = identifiers.get(text);
1241            if (identifier === undefined) {
1242                identifiers.set(text, identifier = text);
1243            }
1244            return identifier;
1245        }
1246
1247        // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues
1248        // with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for
1249        // each identifier in order to reduce memory consumption.
1250        function createIdentifier(isIdentifier: boolean, diagnosticMessage?: DiagnosticMessage): Identifier {
1251            identifierCount++;
1252            if (isIdentifier) {
1253                const node = <Identifier>createNode(SyntaxKind.Identifier);
1254
1255                // Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker
1256                if (token() !== SyntaxKind.Identifier) {
1257                    node.originalKeywordKind = token();
1258                }
1259                node.escapedText = escapeLeadingUnderscores(internIdentifier(scanner.getTokenValue()));
1260                nextToken();
1261                return finishNode(node);
1262            }
1263
1264            // Only for end of file because the error gets reported incorrectly on embedded script tags.
1265            const reportAtCurrentPosition = token() === SyntaxKind.EndOfFileToken;
1266
1267            return createMissingNode<Identifier>(SyntaxKind.Identifier, reportAtCurrentPosition, diagnosticMessage || Diagnostics.Identifier_expected);
1268        }
1269
1270        function parseIdentifier(diagnosticMessage?: DiagnosticMessage): Identifier {
1271            return createIdentifier(isIdentifier(), diagnosticMessage);
1272        }
1273
1274        function parseIdentifierName(diagnosticMessage?: DiagnosticMessage): Identifier {
1275            return createIdentifier(tokenIsIdentifierOrKeyword(token()), diagnosticMessage);
1276        }
1277
1278        function isLiteralPropertyName(): boolean {
1279            return tokenIsIdentifierOrKeyword(token()) ||
1280                token() === SyntaxKind.StringLiteral ||
1281                token() === SyntaxKind.NumericLiteral;
1282        }
1283
1284        function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName {
1285            if (token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral) {
1286                const node = <StringLiteral | NumericLiteral>parseLiteralNode();
1287                node.text = internIdentifier(node.text);
1288                return node;
1289            }
1290            if (allowComputedPropertyNames && token() === SyntaxKind.OpenBracketToken) {
1291                return parseComputedPropertyName();
1292            }
1293            return parseIdentifierName();
1294        }
1295
1296        function parsePropertyName(): PropertyName {
1297            return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true);
1298        }
1299
1300        function parseComputedPropertyName(): ComputedPropertyName {
1301            // PropertyName [Yield]:
1302            //      LiteralPropertyName
1303            //      ComputedPropertyName[?Yield]
1304            const node = <ComputedPropertyName>createNode(SyntaxKind.ComputedPropertyName);
1305            parseExpected(SyntaxKind.OpenBracketToken);
1306
1307            // We parse any expression (including a comma expression). But the grammar
1308            // says that only an assignment expression is allowed, so the grammar checker
1309            // will error if it sees a comma expression.
1310            node.expression = allowInAnd(parseExpression);
1311
1312            parseExpected(SyntaxKind.CloseBracketToken);
1313            return finishNode(node);
1314        }
1315
1316        function parseContextualModifier(t: SyntaxKind): boolean {
1317            return token() === t && tryParse(nextTokenCanFollowModifier);
1318        }
1319
1320        function nextTokenIsOnSameLineAndCanFollowModifier() {
1321            nextToken();
1322            if (scanner.hasPrecedingLineBreak()) {
1323                return false;
1324            }
1325            return canFollowModifier();
1326        }
1327
1328        function nextTokenCanFollowModifier() {
1329            if (token() === SyntaxKind.ConstKeyword) {
1330                // 'const' is only a modifier if followed by 'enum'.
1331                return nextToken() === SyntaxKind.EnumKeyword;
1332            }
1333            if (token() === SyntaxKind.ExportKeyword) {
1334                nextToken();
1335                if (token() === SyntaxKind.DefaultKeyword) {
1336                    return lookAhead(nextTokenCanFollowDefaultKeyword);
1337                }
1338                return token() !== SyntaxKind.AsteriskToken && token() !== SyntaxKind.AsKeyword && token() !== SyntaxKind.OpenBraceToken && canFollowModifier();
1339            }
1340            if (token() === SyntaxKind.DefaultKeyword) {
1341                return nextTokenCanFollowDefaultKeyword();
1342            }
1343            if (token() === SyntaxKind.StaticKeyword) {
1344                nextToken();
1345                return canFollowModifier();
1346            }
1347
1348            return nextTokenIsOnSameLineAndCanFollowModifier();
1349        }
1350
1351        function parseAnyContextualModifier(): boolean {
1352            return isModifierKind(token()) && tryParse(nextTokenCanFollowModifier);
1353        }
1354
1355        function canFollowModifier(): boolean {
1356            return token() === SyntaxKind.OpenBracketToken
1357                || token() === SyntaxKind.OpenBraceToken
1358                || token() === SyntaxKind.AsteriskToken
1359                || token() === SyntaxKind.DotDotDotToken
1360                || isLiteralPropertyName();
1361        }
1362
1363        function nextTokenCanFollowDefaultKeyword(): boolean {
1364            nextToken();
1365            return token() === SyntaxKind.ClassKeyword || token() === SyntaxKind.FunctionKeyword ||
1366                token() === SyntaxKind.InterfaceKeyword ||
1367                (token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine)) ||
1368                (token() === SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine));
1369        }
1370
1371        // True if positioned at the start of a list element
1372        function isListElement(parsingContext: ParsingContext, inErrorRecovery: boolean): boolean {
1373            const node = currentNode(parsingContext);
1374            if (node) {
1375                return true;
1376            }
1377
1378            switch (parsingContext) {
1379                case ParsingContext.SourceElements:
1380                case ParsingContext.BlockStatements:
1381                case ParsingContext.SwitchClauseStatements:
1382                    // If we're in error recovery, then we don't want to treat ';' as an empty statement.
1383                    // The problem is that ';' can show up in far too many contexts, and if we see one
1384                    // and assume it's a statement, then we may bail out inappropriately from whatever
1385                    // we're parsing.  For example, if we have a semicolon in the middle of a class, then
1386                    // we really don't want to assume the class is over and we're on a statement in the
1387                    // outer module.  We just want to consume and move on.
1388                    return !(token() === SyntaxKind.SemicolonToken && inErrorRecovery) && isStartOfStatement();
1389                case ParsingContext.SwitchClauses:
1390                    return token() === SyntaxKind.CaseKeyword || token() === SyntaxKind.DefaultKeyword;
1391                case ParsingContext.TypeMembers:
1392                    return lookAhead(isTypeMemberStart);
1393                case ParsingContext.ClassMembers:
1394                    // We allow semicolons as class elements (as specified by ES6) as long as we're
1395                    // not in error recovery.  If we're in error recovery, we don't want an errant
1396                    // semicolon to be treated as a class member (since they're almost always used
1397                    // for statements.
1398                    return lookAhead(isClassMemberStart) || (token() === SyntaxKind.SemicolonToken && !inErrorRecovery);
1399                case ParsingContext.EnumMembers:
1400                    // Include open bracket computed properties. This technically also lets in indexers,
1401                    // which would be a candidate for improved error reporting.
1402                    return token() === SyntaxKind.OpenBracketToken || isLiteralPropertyName();
1403                case ParsingContext.ObjectLiteralMembers:
1404                    return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
1405                case ParsingContext.RestProperties:
1406                    return isLiteralPropertyName();
1407                case ParsingContext.ObjectBindingElements:
1408                    return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
1409                case ParsingContext.HeritageClauseElement:
1410                    // If we see `{ ... }` then only consume it as an expression if it is followed by `,` or `{`
1411                    // That way we won't consume the body of a class in its heritage clause.
1412                    if (token() === SyntaxKind.OpenBraceToken) {
1413                        return lookAhead(isValidHeritageClauseObjectLiteral);
1414                    }
1415
1416                    if (!inErrorRecovery) {
1417                        return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword();
1418                    }
1419                    else {
1420                        // If we're in error recovery we tighten up what we're willing to match.
1421                        // That way we don't treat something like "this" as a valid heritage clause
1422                        // element during recovery.
1423                        return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword();
1424                    }
1425                case ParsingContext.VariableDeclarations:
1426                    return isIdentifierOrPattern();
1427                case ParsingContext.ArrayBindingElements:
1428                    return token() === SyntaxKind.CommaToken || token() === SyntaxKind.DotDotDotToken || isIdentifierOrPattern();
1429                case ParsingContext.TypeParameters:
1430                    return isIdentifier();
1431                case ParsingContext.ArrayLiteralMembers:
1432                    if (token() === SyntaxKind.CommaToken) {
1433                        return true;
1434                    }
1435                    // falls through
1436                case ParsingContext.ArgumentExpressions:
1437                    return token() === SyntaxKind.DotDotDotToken || isStartOfExpression();
1438                case ParsingContext.Parameters:
1439                    return isStartOfParameter();
1440                case ParsingContext.TypeArguments:
1441                case ParsingContext.TupleElementTypes:
1442                    return token() === SyntaxKind.CommaToken || isStartOfType();
1443                case ParsingContext.HeritageClauses:
1444                    return isHeritageClause();
1445                case ParsingContext.ImportOrExportSpecifiers:
1446                    return tokenIsIdentifierOrKeyword(token());
1447                case ParsingContext.JsxAttributes:
1448                    return tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.OpenBraceToken;
1449                case ParsingContext.JsxChildren:
1450                    return true;
1451            }
1452
1453            Debug.fail("Non-exhaustive case in 'isListElement'.");
1454        }
1455
1456        function isValidHeritageClauseObjectLiteral() {
1457            Debug.assert(token() === SyntaxKind.OpenBraceToken);
1458            if (nextToken() === SyntaxKind.CloseBraceToken) {
1459                // if we see "extends {}" then only treat the {} as what we're extending (and not
1460                // the class body) if we have:
1461                //
1462                //      extends {} {
1463                //      extends {},
1464                //      extends {} extends
1465                //      extends {} implements
1466
1467                const next = nextToken();
1468                return next === SyntaxKind.CommaToken || next === SyntaxKind.OpenBraceToken || next === SyntaxKind.ExtendsKeyword || next === SyntaxKind.ImplementsKeyword;
1469            }
1470
1471            return true;
1472        }
1473
1474        function nextTokenIsIdentifier() {
1475            nextToken();
1476            return isIdentifier();
1477        }
1478
1479        function nextTokenIsIdentifierOrKeyword() {
1480            nextToken();
1481            return tokenIsIdentifierOrKeyword(token());
1482        }
1483
1484        function nextTokenIsIdentifierOrKeywordOrGreaterThan() {
1485            nextToken();
1486            return tokenIsIdentifierOrKeywordOrGreaterThan(token());
1487        }
1488
1489        function isHeritageClauseExtendsOrImplementsKeyword(): boolean {
1490            if (token() === SyntaxKind.ImplementsKeyword ||
1491                token() === SyntaxKind.ExtendsKeyword) {
1492
1493                return lookAhead(nextTokenIsStartOfExpression);
1494            }
1495
1496            return false;
1497        }
1498
1499        function nextTokenIsStartOfExpression() {
1500            nextToken();
1501            return isStartOfExpression();
1502        }
1503
1504        function nextTokenIsStartOfType() {
1505            nextToken();
1506            return isStartOfType();
1507        }
1508
1509        // True if positioned at a list terminator
1510        function isListTerminator(kind: ParsingContext): boolean {
1511            if (token() === SyntaxKind.EndOfFileToken) {
1512                // Being at the end of the file ends all lists.
1513                return true;
1514            }
1515
1516            switch (kind) {
1517                case ParsingContext.BlockStatements:
1518                case ParsingContext.SwitchClauses:
1519                case ParsingContext.TypeMembers:
1520                case ParsingContext.ClassMembers:
1521                case ParsingContext.EnumMembers:
1522                case ParsingContext.ObjectLiteralMembers:
1523                case ParsingContext.ObjectBindingElements:
1524                case ParsingContext.ImportOrExportSpecifiers:
1525                    return token() === SyntaxKind.CloseBraceToken;
1526                case ParsingContext.SwitchClauseStatements:
1527                    return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.CaseKeyword || token() === SyntaxKind.DefaultKeyword;
1528                case ParsingContext.HeritageClauseElement:
1529                    return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
1530                case ParsingContext.VariableDeclarations:
1531                    return isVariableDeclaratorListTerminator();
1532                case ParsingContext.TypeParameters:
1533                    // Tokens other than '>' are here for better error recovery
1534                    return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
1535                case ParsingContext.ArgumentExpressions:
1536                    // Tokens other than ')' are here for better error recovery
1537                    return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.SemicolonToken;
1538                case ParsingContext.ArrayLiteralMembers:
1539                case ParsingContext.TupleElementTypes:
1540                case ParsingContext.ArrayBindingElements:
1541                    return token() === SyntaxKind.CloseBracketToken;
1542                case ParsingContext.Parameters:
1543                case ParsingContext.RestProperties:
1544                    // Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery
1545                    return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.CloseBracketToken /*|| token === SyntaxKind.OpenBraceToken*/;
1546                case ParsingContext.TypeArguments:
1547                    // All other tokens should cause the type-argument to terminate except comma token
1548                    return token() !== SyntaxKind.CommaToken;
1549                case ParsingContext.HeritageClauses:
1550                    return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.CloseBraceToken;
1551                case ParsingContext.JsxAttributes:
1552                    return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.SlashToken;
1553                case ParsingContext.JsxChildren:
1554                    return token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsSlash);
1555            }
1556        }
1557
1558        function isVariableDeclaratorListTerminator(): boolean {
1559            // If we can consume a semicolon (either explicitly, or with ASI), then consider us done
1560            // with parsing the list of variable declarators.
1561            if (canParseSemicolon()) {
1562                return true;
1563            }
1564
1565            // in the case where we're parsing the variable declarator of a 'for-in' statement, we
1566            // are done if we see an 'in' keyword in front of us. Same with for-of
1567            if (isInOrOfKeyword(token())) {
1568                return true;
1569            }
1570
1571            // ERROR RECOVERY TWEAK:
1572            // For better error recovery, if we see an '=>' then we just stop immediately.  We've got an
1573            // arrow function here and it's going to be very unlikely that we'll resynchronize and get
1574            // another variable declaration.
1575            if (token() === SyntaxKind.EqualsGreaterThanToken) {
1576                return true;
1577            }
1578
1579            // Keep trying to parse out variable declarators.
1580            return false;
1581        }
1582
1583        // True if positioned at element or terminator of the current list or any enclosing list
1584        function isInSomeParsingContext(): boolean {
1585            for (let kind = 0; kind < ParsingContext.Count; kind++) {
1586                if (parsingContext & (1 << kind)) {
1587                    if (isListElement(kind, /*inErrorRecovery*/ true) || isListTerminator(kind)) {
1588                        return true;
1589                    }
1590                }
1591            }
1592
1593            return false;
1594        }
1595
1596        // Parses a list of elements
1597        function parseList<T extends Node>(kind: ParsingContext, parseElement: () => T): NodeArray<T> {
1598            const saveParsingContext = parsingContext;
1599            parsingContext |= 1 << kind;
1600            const list = [];
1601            const listPos = getNodePos();
1602
1603            while (!isListTerminator(kind)) {
1604                if (isListElement(kind, /*inErrorRecovery*/ false)) {
1605                    const element = parseListElement(kind, parseElement);
1606                    list.push(element);
1607
1608                    continue;
1609                }
1610
1611                if (abortParsingListOrMoveToNextToken(kind)) {
1612                    break;
1613                }
1614            }
1615
1616            parsingContext = saveParsingContext;
1617            return createNodeArray(list, listPos);
1618        }
1619
1620        function parseListElement<T extends Node>(parsingContext: ParsingContext, parseElement: () => T): T {
1621            const node = currentNode(parsingContext);
1622            if (node) {
1623                return <T>consumeNode(node);
1624            }
1625
1626            return parseElement();
1627        }
1628
1629        function currentNode(parsingContext: ParsingContext): Node {
1630            // If there is an outstanding parse error that we've encountered, but not attached to
1631            // some node, then we cannot get a node from the old source tree.  This is because we
1632            // want to mark the next node we encounter as being unusable.
1633            //
1634            // Note: This may be too conservative.  Perhaps we could reuse the node and set the bit
1635            // on it (or its leftmost child) as having the error.  For now though, being conservative
1636            // is nice and likely won't ever affect perf.
1637            if (parseErrorBeforeNextFinishedNode) {
1638                return undefined;
1639            }
1640
1641            if (!syntaxCursor) {
1642                // if we don't have a cursor, we could never return a node from the old tree.
1643                return undefined;
1644            }
1645
1646            const node = syntaxCursor.currentNode(scanner.getStartPos());
1647
1648            // Can't reuse a missing node.
1649            if (nodeIsMissing(node)) {
1650                return undefined;
1651            }
1652
1653            // Can't reuse a node that intersected the change range.
1654            if (node.intersectsChange) {
1655                return undefined;
1656            }
1657
1658            // Can't reuse a node that contains a parse error.  This is necessary so that we
1659            // produce the same set of errors again.
1660            if (containsParseError(node)) {
1661                return undefined;
1662            }
1663
1664            // We can only reuse a node if it was parsed under the same strict mode that we're
1665            // currently in.  i.e. if we originally parsed a node in non-strict mode, but then
1666            // the user added 'using strict' at the top of the file, then we can't use that node
1667            // again as the presence of strict mode may cause us to parse the tokens in the file
1668            // differently.
1669            //
1670            // Note: we *can* reuse tokens when the strict mode changes.  That's because tokens
1671            // are unaffected by strict mode.  It's just the parser will decide what to do with it
1672            // differently depending on what mode it is in.
1673            //
1674            // This also applies to all our other context flags as well.
1675            const nodeContextFlags = node.flags & NodeFlags.ContextFlags;
1676            if (nodeContextFlags !== contextFlags) {
1677                return undefined;
1678            }
1679
1680            // Ok, we have a node that looks like it could be reused.  Now verify that it is valid
1681            // in the current list parsing context that we're currently at.
1682            if (!canReuseNode(node, parsingContext)) {
1683                return undefined;
1684            }
1685
1686            if ((node as JSDocContainer).jsDocCache) {
1687                // jsDocCache may include tags from parent nodes, which might have been modified.
1688                (node as JSDocContainer).jsDocCache = undefined;
1689            }
1690
1691            return node;
1692        }
1693
1694        function consumeNode(node: Node) {
1695            // Move the scanner so it is after the node we just consumed.
1696            scanner.setTextPos(node.end);
1697            nextToken();
1698            return node;
1699        }
1700
1701        function canReuseNode(node: Node, parsingContext: ParsingContext): boolean {
1702            switch (parsingContext) {
1703                case ParsingContext.ClassMembers:
1704                    return isReusableClassMember(node);
1705
1706                case ParsingContext.SwitchClauses:
1707                    return isReusableSwitchClause(node);
1708
1709                case ParsingContext.SourceElements:
1710                case ParsingContext.BlockStatements:
1711                case ParsingContext.SwitchClauseStatements:
1712                    return isReusableStatement(node);
1713
1714                case ParsingContext.EnumMembers:
1715                    return isReusableEnumMember(node);
1716
1717                case ParsingContext.TypeMembers:
1718                    return isReusableTypeMember(node);
1719
1720                case ParsingContext.VariableDeclarations:
1721                    return isReusableVariableDeclaration(node);
1722
1723                case ParsingContext.Parameters:
1724                    return isReusableParameter(node);
1725
1726                case ParsingContext.RestProperties:
1727                    return false;
1728
1729                // Any other lists we do not care about reusing nodes in.  But feel free to add if
1730                // you can do so safely.  Danger areas involve nodes that may involve speculative
1731                // parsing.  If speculative parsing is involved with the node, then the range the
1732                // parser reached while looking ahead might be in the edited range (see the example
1733                // in canReuseVariableDeclaratorNode for a good case of this).
1734                case ParsingContext.HeritageClauses:
1735                // This would probably be safe to reuse.  There is no speculative parsing with
1736                // heritage clauses.
1737
1738                case ParsingContext.TypeParameters:
1739                // This would probably be safe to reuse.  There is no speculative parsing with
1740                // type parameters.  Note that that's because type *parameters* only occur in
1741                // unambiguous *type* contexts.  While type *arguments* occur in very ambiguous
1742                // *expression* contexts.
1743
1744                case ParsingContext.TupleElementTypes:
1745                // This would probably be safe to reuse.  There is no speculative parsing with
1746                // tuple types.
1747
1748                // Technically, type argument list types are probably safe to reuse.  While
1749                // speculative parsing is involved with them (since type argument lists are only
1750                // produced from speculative parsing a < as a type argument list), we only have
1751                // the types because speculative parsing succeeded.  Thus, the lookahead never
1752                // went past the end of the list and rewound.
1753                case ParsingContext.TypeArguments:
1754
1755                // Note: these are almost certainly not safe to ever reuse.  Expressions commonly
1756                // need a large amount of lookahead, and we should not reuse them as they may
1757                // have actually intersected the edit.
1758                case ParsingContext.ArgumentExpressions:
1759
1760                // This is not safe to reuse for the same reason as the 'AssignmentExpression'
1761                // cases.  i.e. a property assignment may end with an expression, and thus might
1762                // have lookahead far beyond it's old node.
1763                case ParsingContext.ObjectLiteralMembers:
1764
1765                // This is probably not safe to reuse.  There can be speculative parsing with
1766                // type names in a heritage clause.  There can be generic names in the type
1767                // name list, and there can be left hand side expressions (which can have type
1768                // arguments.)
1769                case ParsingContext.HeritageClauseElement:
1770
1771                // Perhaps safe to reuse, but it's unlikely we'd see more than a dozen attributes
1772                // on any given element. Same for children.
1773                case ParsingContext.JsxAttributes:
1774                case ParsingContext.JsxChildren:
1775
1776            }
1777
1778            return false;
1779        }
1780
1781        function isReusableClassMember(node: Node) {
1782            if (node) {
1783                switch (node.kind) {
1784                    case SyntaxKind.Constructor:
1785                    case SyntaxKind.IndexSignature:
1786                    case SyntaxKind.GetAccessor:
1787                    case SyntaxKind.SetAccessor:
1788                    case SyntaxKind.PropertyDeclaration:
1789                    case SyntaxKind.SemicolonClassElement:
1790                        return true;
1791                    case SyntaxKind.MethodDeclaration:
1792                        // Method declarations are not necessarily reusable.  An object-literal
1793                        // may have a method calls "constructor(...)" and we must reparse that
1794                        // into an actual .ConstructorDeclaration.
1795                        const methodDeclaration = <MethodDeclaration>node;
1796                        const nameIsConstructor = methodDeclaration.name.kind === SyntaxKind.Identifier &&
1797                            (<Identifier>methodDeclaration.name).originalKeywordKind === SyntaxKind.ConstructorKeyword;
1798
1799                        return !nameIsConstructor;
1800                }
1801            }
1802
1803            return false;
1804        }
1805
1806        function isReusableSwitchClause(node: Node) {
1807            if (node) {
1808                switch (node.kind) {
1809                    case SyntaxKind.CaseClause:
1810                    case SyntaxKind.DefaultClause:
1811                        return true;
1812                }
1813            }
1814
1815            return false;
1816        }
1817
1818        function isReusableStatement(node: Node) {
1819            if (node) {
1820                switch (node.kind) {
1821                    case SyntaxKind.FunctionDeclaration:
1822                    case SyntaxKind.VariableStatement:
1823                    case SyntaxKind.Block:
1824                    case SyntaxKind.IfStatement:
1825                    case SyntaxKind.ExpressionStatement:
1826                    case SyntaxKind.ThrowStatement:
1827                    case SyntaxKind.ReturnStatement:
1828                    case SyntaxKind.SwitchStatement:
1829                    case SyntaxKind.BreakStatement:
1830                    case SyntaxKind.ContinueStatement:
1831                    case SyntaxKind.ForInStatement:
1832                    case SyntaxKind.ForOfStatement:
1833                    case SyntaxKind.ForStatement:
1834                    case SyntaxKind.WhileStatement:
1835                    case SyntaxKind.WithStatement:
1836                    case SyntaxKind.EmptyStatement:
1837                    case SyntaxKind.TryStatement:
1838                    case SyntaxKind.LabeledStatement:
1839                    case SyntaxKind.DoStatement:
1840                    case SyntaxKind.DebuggerStatement:
1841                    case SyntaxKind.ImportDeclaration:
1842                    case SyntaxKind.ImportEqualsDeclaration:
1843                    case SyntaxKind.ExportDeclaration:
1844                    case SyntaxKind.ExportAssignment:
1845                    case SyntaxKind.ModuleDeclaration:
1846                    case SyntaxKind.ClassDeclaration:
1847                    case SyntaxKind.InterfaceDeclaration:
1848                    case SyntaxKind.EnumDeclaration:
1849                    case SyntaxKind.TypeAliasDeclaration:
1850                        return true;
1851                }
1852            }
1853
1854            return false;
1855        }
1856
1857        function isReusableEnumMember(node: Node) {
1858            return node.kind === SyntaxKind.EnumMember;
1859        }
1860
1861        function isReusableTypeMember(node: Node) {
1862            if (node) {
1863                switch (node.kind) {
1864                    case SyntaxKind.ConstructSignature:
1865                    case SyntaxKind.MethodSignature:
1866                    case SyntaxKind.IndexSignature:
1867                    case SyntaxKind.PropertySignature:
1868                    case SyntaxKind.CallSignature:
1869                        return true;
1870                }
1871            }
1872
1873            return false;
1874        }
1875
1876        function isReusableVariableDeclaration(node: Node) {
1877            if (node.kind !== SyntaxKind.VariableDeclaration) {
1878                return false;
1879            }
1880
1881            // Very subtle incremental parsing bug.  Consider the following code:
1882            //
1883            //      let v = new List < A, B
1884            //
1885            // This is actually legal code.  It's a list of variable declarators "v = new List<A"
1886            // on one side and "B" on the other. If you then change that to:
1887            //
1888            //      let v = new List < A, B >()
1889            //
1890            // then we have a problem.  "v = new List<A" doesn't intersect the change range, so we
1891            // start reparsing at "B" and we completely fail to handle this properly.
1892            //
1893            // In order to prevent this, we do not allow a variable declarator to be reused if it
1894            // has an initializer.
1895            const variableDeclarator = <VariableDeclaration>node;
1896            return variableDeclarator.initializer === undefined;
1897        }
1898
1899        function isReusableParameter(node: Node) {
1900            if (node.kind !== SyntaxKind.Parameter) {
1901                return false;
1902            }
1903
1904            // See the comment in isReusableVariableDeclaration for why we do this.
1905            const parameter = <ParameterDeclaration>node;
1906            return parameter.initializer === undefined;
1907        }
1908
1909        // Returns true if we should abort parsing.
1910        function abortParsingListOrMoveToNextToken(kind: ParsingContext) {
1911            parseErrorAtCurrentToken(parsingContextErrors(kind));
1912            if (isInSomeParsingContext()) {
1913                return true;
1914            }
1915
1916            nextToken();
1917            return false;
1918        }
1919
1920        function parsingContextErrors(context: ParsingContext): DiagnosticMessage {
1921            switch (context) {
1922                case ParsingContext.SourceElements: return Diagnostics.Declaration_or_statement_expected;
1923                case ParsingContext.BlockStatements: return Diagnostics.Declaration_or_statement_expected;
1924                case ParsingContext.SwitchClauses: return Diagnostics.case_or_default_expected;
1925                case ParsingContext.SwitchClauseStatements: return Diagnostics.Statement_expected;
1926                case ParsingContext.RestProperties: // fallthrough
1927                case ParsingContext.TypeMembers: return Diagnostics.Property_or_signature_expected;
1928                case ParsingContext.ClassMembers: return Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected;
1929                case ParsingContext.EnumMembers: return Diagnostics.Enum_member_expected;
1930                case ParsingContext.HeritageClauseElement: return Diagnostics.Expression_expected;
1931                case ParsingContext.VariableDeclarations: return Diagnostics.Variable_declaration_expected;
1932                case ParsingContext.ObjectBindingElements: return Diagnostics.Property_destructuring_pattern_expected;
1933                case ParsingContext.ArrayBindingElements: return Diagnostics.Array_element_destructuring_pattern_expected;
1934                case ParsingContext.ArgumentExpressions: return Diagnostics.Argument_expression_expected;
1935                case ParsingContext.ObjectLiteralMembers: return Diagnostics.Property_assignment_expected;
1936                case ParsingContext.ArrayLiteralMembers: return Diagnostics.Expression_or_comma_expected;
1937                case ParsingContext.Parameters: return Diagnostics.Parameter_declaration_expected;
1938                case ParsingContext.TypeParameters: return Diagnostics.Type_parameter_declaration_expected;
1939                case ParsingContext.TypeArguments: return Diagnostics.Type_argument_expected;
1940                case ParsingContext.TupleElementTypes: return Diagnostics.Type_expected;
1941                case ParsingContext.HeritageClauses: return Diagnostics.Unexpected_token_expected;
1942                case ParsingContext.ImportOrExportSpecifiers: return Diagnostics.Identifier_expected;
1943                case ParsingContext.JsxAttributes: return Diagnostics.Identifier_expected;
1944                case ParsingContext.JsxChildren: return Diagnostics.Identifier_expected;
1945            }
1946        }
1947
1948        // Parses a comma-delimited list of elements
1949        function parseDelimitedList<T extends Node>(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray<T> {
1950            const saveParsingContext = parsingContext;
1951            parsingContext |= 1 << kind;
1952            const list = [];
1953            const listPos = getNodePos();
1954
1955            let commaStart = -1; // Meaning the previous token was not a comma
1956            while (true) {
1957                if (isListElement(kind, /*inErrorRecovery*/ false)) {
1958                    const startPos = scanner.getStartPos();
1959                    list.push(parseListElement(kind, parseElement));
1960                    commaStart = scanner.getTokenPos();
1961
1962                    if (parseOptional(SyntaxKind.CommaToken)) {
1963                        // No need to check for a zero length node since we know we parsed a comma
1964                        continue;
1965                    }
1966
1967                    commaStart = -1; // Back to the state where the last token was not a comma
1968                    if (isListTerminator(kind)) {
1969                        break;
1970                    }
1971
1972                    // We didn't get a comma, and the list wasn't terminated, explicitly parse
1973                    // out a comma so we give a good error message.
1974                    parseExpected(SyntaxKind.CommaToken);
1975
1976                    // If the token was a semicolon, and the caller allows that, then skip it and
1977                    // continue.  This ensures we get back on track and don't result in tons of
1978                    // parse errors.  For example, this can happen when people do things like use
1979                    // a semicolon to delimit object literal members.   Note: we'll have already
1980                    // reported an error when we called parseExpected above.
1981                    if (considerSemicolonAsDelimiter && token() === SyntaxKind.SemicolonToken && !scanner.hasPrecedingLineBreak()) {
1982                        nextToken();
1983                    }
1984                    if (startPos === scanner.getStartPos()) {
1985                        // What we're parsing isn't actually remotely recognizable as a element and we've consumed no tokens whatsoever
1986                        // Consume a token to advance the parser in some way and avoid an infinite loop
1987                        // This can happen when we're speculatively parsing parenthesized expressions which we think may be arrow functions,
1988                        // or when a modifier keyword which is disallowed as a parameter name (ie, `static` in strict mode) is supplied
1989                        nextToken();
1990                    }
1991                    continue;
1992                }
1993
1994                if (isListTerminator(kind)) {
1995                    break;
1996                }
1997
1998                if (abortParsingListOrMoveToNextToken(kind)) {
1999                    break;
2000                }
2001            }
2002
2003            parsingContext = saveParsingContext;
2004            const result = createNodeArray(list, listPos);
2005            // Recording the trailing comma is deliberately done after the previous
2006            // loop, and not just if we see a list terminator. This is because the list
2007            // may have ended incorrectly, but it is still important to know if there
2008            // was a trailing comma.
2009            // Check if the last token was a comma.
2010            if (commaStart >= 0) {
2011                // Always preserve a trailing comma by marking it on the NodeArray
2012                result.hasTrailingComma = true;
2013            }
2014            return result;
2015        }
2016
2017        function createMissingList<T extends Node>(): NodeArray<T> {
2018            return createNodeArray<T>([], getNodePos());
2019        }
2020
2021        function parseBracketedList<T extends Node>(kind: ParsingContext, parseElement: () => T, open: SyntaxKind, close: SyntaxKind): NodeArray<T> {
2022            if (parseExpected(open)) {
2023                const result = parseDelimitedList(kind, parseElement);
2024                parseExpected(close);
2025                return result;
2026            }
2027
2028            return createMissingList<T>();
2029        }
2030
2031        function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: DiagnosticMessage): EntityName {
2032            let entity: EntityName = allowReservedWords ? parseIdentifierName(diagnosticMessage) : parseIdentifier(diagnosticMessage);
2033            let dotPos = scanner.getStartPos();
2034            while (parseOptional(SyntaxKind.DotToken)) {
2035                if (token() === SyntaxKind.LessThanToken) {
2036                    // the entity is part of a JSDoc-style generic, so record the trailing dot for later error reporting
2037                    entity.jsdocDotPos = dotPos;
2038                    break;
2039                }
2040                dotPos = scanner.getStartPos();
2041                entity = createQualifiedName(entity, parseRightSideOfDot(allowReservedWords));
2042            }
2043            return entity;
2044        }
2045
2046        function createQualifiedName(entity: EntityName, name: Identifier): QualifiedName {
2047            const node = createNode(SyntaxKind.QualifiedName, entity.pos) as QualifiedName;
2048            node.left = entity;
2049            node.right = name;
2050            return finishNode(node);
2051        }
2052
2053        function parseRightSideOfDot(allowIdentifierNames: boolean): Identifier {
2054            // Technically a keyword is valid here as all identifiers and keywords are identifier names.
2055            // However, often we'll encounter this in error situations when the identifier or keyword
2056            // is actually starting another valid construct.
2057            //
2058            // So, we check for the following specific case:
2059            //
2060            //      name.
2061            //      identifierOrKeyword identifierNameOrKeyword
2062            //
2063            // Note: the newlines are important here.  For example, if that above code
2064            // were rewritten into:
2065            //
2066            //      name.identifierOrKeyword
2067            //      identifierNameOrKeyword
2068            //
2069            // Then we would consider it valid.  That's because ASI would take effect and
2070            // the code would be implicitly: "name.identifierOrKeyword; identifierNameOrKeyword".
2071            // In the first case though, ASI will not take effect because there is not a
2072            // line terminator after the identifier or keyword.
2073            if (scanner.hasPrecedingLineBreak() && tokenIsIdentifierOrKeyword(token())) {
2074                const matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine);
2075
2076                if (matchesPattern) {
2077                    // Report that we need an identifier.  However, report it right after the dot,
2078                    // and not on the next token.  This is because the next token might actually
2079                    // be an identifier and the error would be quite confusing.
2080                    return createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected);
2081                }
2082            }
2083
2084            return allowIdentifierNames ? parseIdentifierName() : parseIdentifier();
2085        }
2086
2087        function parseTemplateExpression(): TemplateExpression {
2088            const template = <TemplateExpression>createNode(SyntaxKind.TemplateExpression);
2089
2090            template.head = parseTemplateHead();
2091            Debug.assert(template.head.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind");
2092
2093            const list = [];
2094            const listPos = getNodePos();
2095
2096            do {
2097                list.push(parseTemplateSpan());
2098            }
2099            while (lastOrUndefined(list).literal.kind === SyntaxKind.TemplateMiddle);
2100
2101            template.templateSpans = createNodeArray(list, listPos);
2102
2103            return finishNode(template);
2104        }
2105
2106        function parseTemplateSpan(): TemplateSpan {
2107            const span = <TemplateSpan>createNode(SyntaxKind.TemplateSpan);
2108            span.expression = allowInAnd(parseExpression);
2109
2110            let literal: TemplateMiddle | TemplateTail;
2111            if (token() === SyntaxKind.CloseBraceToken) {
2112                reScanTemplateToken();
2113                literal = parseTemplateMiddleOrTemplateTail();
2114            }
2115            else {
2116                literal = <TemplateTail>parseExpectedToken(SyntaxKind.TemplateTail, Diagnostics._0_expected, tokenToString(SyntaxKind.CloseBraceToken));
2117            }
2118
2119            span.literal = literal;
2120            return finishNode(span);
2121        }
2122
2123        function parseLiteralNode(): LiteralExpression {
2124            return <LiteralExpression>parseLiteralLikeNode(token());
2125        }
2126
2127        function parseTemplateHead(): TemplateHead {
2128            const fragment = parseLiteralLikeNode(token());
2129            Debug.assert(fragment.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind");
2130            return <TemplateHead>fragment;
2131        }
2132
2133        function parseTemplateMiddleOrTemplateTail(): TemplateMiddle | TemplateTail {
2134            const fragment = parseLiteralLikeNode(token());
2135            Debug.assert(fragment.kind === SyntaxKind.TemplateMiddle || fragment.kind === SyntaxKind.TemplateTail, "Template fragment has wrong token kind");
2136            return <TemplateMiddle | TemplateTail>fragment;
2137        }
2138
2139        function parseLiteralLikeNode(kind: SyntaxKind): LiteralExpression | LiteralLikeNode {
2140            const node = <LiteralExpression>createNode(kind);
2141            const text = scanner.getTokenValue();
2142            node.text = text;
2143
2144            if (scanner.hasExtendedUnicodeEscape()) {
2145                node.hasExtendedUnicodeEscape = true;
2146            }
2147
2148            if (scanner.isUnterminated()) {
2149                node.isUnterminated = true;
2150            }
2151
2152            // Octal literals are not allowed in strict mode or ES5
2153            // Note that theoretically the following condition would hold true literals like 009,
2154            // which is not octal.But because of how the scanner separates the tokens, we would
2155            // never get a token like this. Instead, we would get 00 and 9 as two separate tokens.
2156            // We also do not need to check for negatives because any prefix operator would be part of a
2157            // parent unary expression.
2158            if (node.kind === SyntaxKind.NumericLiteral) {
2159                (<NumericLiteral>node).numericLiteralFlags = scanner.getTokenFlags() & TokenFlags.NumericLiteralFlags;
2160            }
2161
2162            nextToken();
2163            finishNode(node);
2164
2165            return node;
2166        }
2167
2168        // TYPES
2169
2170        function parseTypeReference(): TypeReferenceNode {
2171            const node = <TypeReferenceNode>createNode(SyntaxKind.TypeReference);
2172            node.typeName = parseEntityName(/*allowReservedWords*/ true, Diagnostics.Type_expected);
2173            if (!scanner.hasPrecedingLineBreak() && token() === SyntaxKind.LessThanToken) {
2174                node.typeArguments = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
2175            }
2176            return finishNode(node);
2177        }
2178
2179        function parseThisTypePredicate(lhs: ThisTypeNode): TypePredicateNode {
2180            nextToken();
2181            const node = createNode(SyntaxKind.TypePredicate, lhs.pos) as TypePredicateNode;
2182            node.parameterName = lhs;
2183            node.type = parseType();
2184            return finishNode(node);
2185        }
2186
2187        function parseThisTypeNode(): ThisTypeNode {
2188            const node = createNode(SyntaxKind.ThisType) as ThisTypeNode;
2189            nextToken();
2190            return finishNode(node);
2191        }
2192
2193        function parseJSDocAllType(): JSDocAllType {
2194            const result = <JSDocAllType>createNode(SyntaxKind.JSDocAllType);
2195            nextToken();
2196            return finishNode(result);
2197        }
2198
2199        function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType {
2200            const pos = scanner.getStartPos();
2201            // skip the ?
2202            nextToken();
2203
2204            // Need to lookahead to decide if this is a nullable or unknown type.
2205
2206            // Here are cases where we'll pick the unknown type:
2207            //
2208            //      Foo(?,
2209            //      { a: ? }
2210            //      Foo(?)
2211            //      Foo<?>
2212            //      Foo(?=
2213            //      (?|
2214            if (token() === SyntaxKind.CommaToken ||
2215                token() === SyntaxKind.CloseBraceToken ||
2216                token() === SyntaxKind.CloseParenToken ||
2217                token() === SyntaxKind.GreaterThanToken ||
2218                token() === SyntaxKind.EqualsToken ||
2219                token() === SyntaxKind.BarToken) {
2220
2221                const result = <JSDocUnknownType>createNode(SyntaxKind.JSDocUnknownType, pos);
2222                return finishNode(result);
2223            }
2224            else {
2225                const result = <JSDocNullableType>createNode(SyntaxKind.JSDocNullableType, pos);
2226                result.type = parseType();
2227                return finishNode(result);
2228            }
2229        }
2230
2231        function parseJSDocFunctionType(): JSDocFunctionType | TypeReferenceNode {
2232            if (lookAhead(nextTokenIsOpenParen)) {
2233                const result = <JSDocFunctionType>createNodeWithJSDoc(SyntaxKind.JSDocFunctionType);
2234                nextToken();
2235                fillSignature(SyntaxKind.ColonToken, SignatureFlags.Type | SignatureFlags.JSDoc, result);
2236                return finishNode(result);
2237            }
2238            const node = <TypeReferenceNode>createNode(SyntaxKind.TypeReference);
2239            node.typeName = parseIdentifierName();
2240            return finishNode(node);
2241        }
2242
2243        function parseJSDocParameter(): ParameterDeclaration {
2244            const parameter = createNode(SyntaxKind.Parameter) as ParameterDeclaration;
2245            if (token() === SyntaxKind.ThisKeyword || token() === SyntaxKind.NewKeyword) {
2246                parameter.name = parseIdentifierName();
2247                parseExpected(SyntaxKind.ColonToken);
2248            }
2249            parameter.type = parseType();
2250            return finishNode(parameter);
2251        }
2252
2253        function parseJSDocNodeWithType(kind: SyntaxKind.JSDocVariadicType | SyntaxKind.JSDocNonNullableType): TypeNode {
2254            const result = createNode(kind) as JSDocVariadicType | JSDocNonNullableType;
2255            nextToken();
2256            result.type = parseNonArrayType();
2257            return finishNode(result);
2258        }
2259
2260        function parseTypeQuery(): TypeQueryNode {
2261            const node = <TypeQueryNode>createNode(SyntaxKind.TypeQuery);
2262            parseExpected(SyntaxKind.TypeOfKeyword);
2263            node.exprName = parseEntityName(/*allowReservedWords*/ true);
2264            return finishNode(node);
2265        }
2266
2267        function parseTypeParameter(): TypeParameterDeclaration {
2268            const node = <TypeParameterDeclaration>createNode(SyntaxKind.TypeParameter);
2269            node.name = parseIdentifier();
2270            if (parseOptional(SyntaxKind.ExtendsKeyword)) {
2271                // It's not uncommon for people to write improper constraints to a generic.  If the
2272                // user writes a constraint that is an expression and not an actual type, then parse
2273                // it out as an expression (so we can recover well), but report that a type is needed
2274                // instead.
2275                if (isStartOfType() || !isStartOfExpression()) {
2276                    node.constraint = parseType();
2277                }
2278                else {
2279                    // It was not a type, and it looked like an expression.  Parse out an expression
2280                    // here so we recover well.  Note: it is important that we call parseUnaryExpression
2281                    // and not parseExpression here.  If the user has:
2282                    //
2283                    //      <T extends "">
2284                    //
2285                    // We do *not* want to consume the `>` as we're consuming the expression for "".
2286                    node.expression = parseUnaryExpressionOrHigher();
2287                }
2288            }
2289
2290            if (parseOptional(SyntaxKind.EqualsToken)) {
2291                node.default = parseType();
2292            }
2293
2294            return finishNode(node);
2295        }
2296
2297        function parseTypeParameters(): NodeArray<TypeParameterDeclaration> | undefined {
2298            if (token() === SyntaxKind.LessThanToken) {
2299                return parseBracketedList(ParsingContext.TypeParameters, parseTypeParameter, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
2300            }
2301        }
2302
2303        function parseParameterType(): TypeNode {
2304            if (parseOptional(SyntaxKind.ColonToken)) {
2305                return parseType();
2306            }
2307
2308            return undefined;
2309        }
2310
2311        function isStartOfParameter(): boolean {
2312            return token() === SyntaxKind.DotDotDotToken ||
2313                isIdentifierOrPattern() ||
2314                isModifierKind(token()) ||
2315                token() === SyntaxKind.AtToken ||
2316                isStartOfType(/*inStartOfParameter*/ true);
2317        }
2318
2319        function parseParameter(): ParameterDeclaration {
2320            const node = <ParameterDeclaration>createNodeWithJSDoc(SyntaxKind.Parameter);
2321            if (token() === SyntaxKind.ThisKeyword) {
2322                node.name = createIdentifier(/*isIdentifier*/ true);
2323                node.type = parseParameterType();
2324                return finishNode(node);
2325            }
2326
2327            node.decorators = parseDecorators();
2328            node.modifiers = parseModifiers();
2329            node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
2330
2331            // FormalParameter [Yield,Await]:
2332            //      BindingElement[?Yield,?Await]
2333            node.name = parseIdentifierOrPattern();
2334            if (getFullWidth(node.name) === 0 && !hasModifiers(node) && isModifierKind(token())) {
2335                // in cases like
2336                // 'use strict'
2337                // function foo(static)
2338                // isParameter('static') === true, because of isModifier('static')
2339                // however 'static' is not a legal identifier in a strict mode.
2340                // so result of this function will be ParameterDeclaration (flags = 0, name = missing, type = undefined, initializer = undefined)
2341                // and current token will not change => parsing of the enclosing parameter list will last till the end of time (or OOM)
2342                // to avoid this we'll advance cursor to the next token.
2343                nextToken();
2344            }
2345
2346            node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
2347            node.type = parseParameterType();
2348            node.initializer = parseInitializer();
2349
2350            return finishNode(node);
2351        }
2352
2353        function fillSignature(
2354            returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken,
2355            flags: SignatureFlags,
2356            signature: SignatureDeclaration): void {
2357            if (!(flags & SignatureFlags.JSDoc)) {
2358                signature.typeParameters = parseTypeParameters();
2359            }
2360            signature.parameters = parseParameterList(flags);
2361            signature.type = parseReturnType(returnToken, !!(flags & SignatureFlags.Type));
2362        }
2363
2364        function parseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean): TypeNode | undefined {
2365            return shouldParseReturnType(returnToken, isType) ? parseTypeOrTypePredicate() : undefined;
2366        }
2367        function shouldParseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean): boolean {
2368            if (returnToken === SyntaxKind.EqualsGreaterThanToken) {
2369                parseExpected(returnToken);
2370                return true;
2371            }
2372            else if (parseOptional(SyntaxKind.ColonToken)) {
2373                return true;
2374            }
2375            else if (isType && token() === SyntaxKind.EqualsGreaterThanToken) {
2376                // This is easy to get backward, especially in type contexts, so parse the type anyway
2377                parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken));
2378                nextToken();
2379                return true;
2380            }
2381            return false;
2382        }
2383
2384        function parseParameterList(flags: SignatureFlags) {
2385            // FormalParameters [Yield,Await]: (modified)
2386            //      [empty]
2387            //      FormalParameterList[?Yield,Await]
2388            //
2389            // FormalParameter[Yield,Await]: (modified)
2390            //      BindingElement[?Yield,Await]
2391            //
2392            // BindingElement [Yield,Await]: (modified)
2393            //      SingleNameBinding[?Yield,?Await]
2394            //      BindingPattern[?Yield,?Await]Initializer [In, ?Yield,?Await] opt
2395            //
2396            // SingleNameBinding [Yield,Await]:
2397            //      BindingIdentifier[?Yield,?Await]Initializer [In, ?Yield,?Await] opt
2398            if (parseExpected(SyntaxKind.OpenParenToken)) {
2399                const savedYieldContext = inYieldContext();
2400                const savedAwaitContext = inAwaitContext();
2401
2402                setYieldContext(!!(flags & SignatureFlags.Yield));
2403                setAwaitContext(!!(flags & SignatureFlags.Await));
2404
2405                const result = parseDelimitedList(ParsingContext.Parameters, flags & SignatureFlags.JSDoc ? parseJSDocParameter : parseParameter);
2406
2407                setYieldContext(savedYieldContext);
2408                setAwaitContext(savedAwaitContext);
2409
2410                if (!parseExpected(SyntaxKind.CloseParenToken) && (flags & SignatureFlags.RequireCompleteParameterList)) {
2411                    // Caller insisted that we had to end with a )   We didn't.  So just return
2412                    // undefined here.
2413                    return undefined;
2414                }
2415
2416                return result;
2417            }
2418
2419            // We didn't even have an open paren.  If the caller requires a complete parameter list,
2420            // we definitely can't provide that.  However, if they're ok with an incomplete one,
2421            // then just return an empty set of parameters.
2422            return (flags & SignatureFlags.RequireCompleteParameterList) ? undefined : createMissingList<ParameterDeclaration>();
2423        }
2424
2425        function parseTypeMemberSemicolon() {
2426            // We allow type members to be separated by commas or (possibly ASI) semicolons.
2427            // First check if it was a comma.  If so, we're done with the member.
2428            if (parseOptional(SyntaxKind.CommaToken)) {
2429                return;
2430            }
2431
2432            // Didn't have a comma.  We must have a (possible ASI) semicolon.
2433            parseSemicolon();
2434        }
2435
2436        function parseSignatureMember(kind: SyntaxKind.CallSignature | SyntaxKind.ConstructSignature): CallSignatureDeclaration | ConstructSignatureDeclaration {
2437            const node = <CallSignatureDeclaration | ConstructSignatureDeclaration>createNodeWithJSDoc(kind);
2438            if (kind === SyntaxKind.ConstructSignature) {
2439                parseExpected(SyntaxKind.NewKeyword);
2440            }
2441            fillSignature(SyntaxKind.ColonToken, SignatureFlags.Type, node);
2442            parseTypeMemberSemicolon();
2443            return finishNode(node);
2444        }
2445
2446        function isIndexSignature(): boolean {
2447            return token() === SyntaxKind.OpenBracketToken && lookAhead(isUnambiguouslyIndexSignature);
2448        }
2449
2450        function isUnambiguouslyIndexSignature() {
2451            // The only allowed sequence is:
2452            //
2453            //   [id:
2454            //
2455            // However, for error recovery, we also check the following cases:
2456            //
2457            //   [...
2458            //   [id,
2459            //   [id?,
2460            //   [id?:
2461            //   [id?]
2462            //   [public id
2463            //   [private id
2464            //   [protected id
2465            //   []
2466            //
2467            nextToken();
2468            if (token() === SyntaxKind.DotDotDotToken || token() === SyntaxKind.CloseBracketToken) {
2469                return true;
2470            }
2471
2472            if (isModifierKind(token())) {
2473                nextToken();
2474                if (isIdentifier()) {
2475                    return true;
2476                }
2477            }
2478            else if (!isIdentifier()) {
2479                return false;
2480            }
2481            else {
2482                // Skip the identifier
2483                nextToken();
2484            }
2485
2486            // A colon signifies a well formed indexer
2487            // A comma should be a badly formed indexer because comma expressions are not allowed
2488            // in computed properties.
2489            if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken) {
2490                return true;
2491            }
2492
2493            // Question mark could be an indexer with an optional property,
2494            // or it could be a conditional expression in a computed property.
2495            if (token() !== SyntaxKind.QuestionToken) {
2496                return false;
2497            }
2498
2499            // If any of the following tokens are after the question mark, it cannot
2500            // be a conditional expression, so treat it as an indexer.
2501            nextToken();
2502            return token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.CloseBracketToken;
2503        }
2504
2505        function parseIndexSignatureDeclaration(node: IndexSignatureDeclaration): IndexSignatureDeclaration {
2506            node.kind = SyntaxKind.IndexSignature;
2507            node.parameters = parseBracketedList(ParsingContext.Parameters, parseParameter, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
2508            node.type = parseTypeAnnotation();
2509            parseTypeMemberSemicolon();
2510            return finishNode(node);
2511        }
2512
2513        function parsePropertyOrMethodSignature(node: PropertySignature | MethodSignature): PropertySignature | MethodSignature {
2514            node.name = parsePropertyName();
2515            node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
2516            if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
2517                node.kind = SyntaxKind.MethodSignature;
2518                // Method signatures don't exist in expression contexts.  So they have neither
2519                // [Yield] nor [Await]
2520                fillSignature(SyntaxKind.ColonToken, SignatureFlags.Type, <MethodSignature>node);
2521            }
2522            else {
2523                node.kind = SyntaxKind.PropertySignature;
2524                node.type = parseTypeAnnotation();
2525                if (token() === SyntaxKind.EqualsToken) {
2526                    // Although type literal properties cannot not have initializers, we attempt
2527                    // to parse an initializer so we can report in the checker that an interface
2528                    // property or type literal property cannot have an initializer.
2529                    (<PropertySignature>node).initializer = parseInitializer();
2530                }
2531            }
2532            parseTypeMemberSemicolon();
2533            return finishNode(node);
2534        }
2535
2536        function isTypeMemberStart(): boolean {
2537            // Return true if we have the start of a signature member
2538            if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
2539                return true;
2540            }
2541            let idToken: boolean;
2542            // Eat up all modifiers, but hold on to the last one in case it is actually an identifier
2543            while (isModifierKind(token())) {
2544                idToken = true;
2545                nextToken();
2546            }
2547            // Index signatures and computed property names are type members
2548            if (token() === SyntaxKind.OpenBracketToken) {
2549                return true;
2550            }
2551            // Try to get the first property-like token following all modifiers
2552            if (isLiteralPropertyName()) {
2553                idToken = true;
2554                nextToken();
2555            }
2556            // If we were able to get any potential identifier, check that it is
2557            // the start of a member declaration
2558            if (idToken) {
2559                return token() === SyntaxKind.OpenParenToken ||
2560                    token() === SyntaxKind.LessThanToken ||
2561                    token() === SyntaxKind.QuestionToken ||
2562                    token() === SyntaxKind.ColonToken ||
2563                    token() === SyntaxKind.CommaToken ||
2564                    canParseSemicolon();
2565            }
2566            return false;
2567        }
2568
2569        function parseTypeMember(): TypeElement {
2570            if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
2571                return parseSignatureMember(SyntaxKind.CallSignature);
2572            }
2573            if (token() === SyntaxKind.NewKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) {
2574                return parseSignatureMember(SyntaxKind.ConstructSignature);
2575            }
2576            const node = <TypeElement>createNodeWithJSDoc(SyntaxKind.Unknown);
2577            node.modifiers = parseModifiers();
2578            if (isIndexSignature()) {
2579                return parseIndexSignatureDeclaration(<IndexSignatureDeclaration>node);
2580            }
2581            return parsePropertyOrMethodSignature(<PropertySignature | MethodSignature>node);
2582        }
2583
2584        function nextTokenIsOpenParenOrLessThan() {
2585            nextToken();
2586            return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken;
2587        }
2588
2589        function parseTypeLiteral(): TypeLiteralNode {
2590            const node = <TypeLiteralNode>createNode(SyntaxKind.TypeLiteral);
2591            node.members = parseObjectTypeMembers();
2592            return finishNode(node);
2593        }
2594
2595        function parseObjectTypeMembers(): NodeArray<TypeElement> {
2596            let members: NodeArray<TypeElement>;
2597            if (parseExpected(SyntaxKind.OpenBraceToken)) {
2598                members = parseList(ParsingContext.TypeMembers, parseTypeMember);
2599                parseExpected(SyntaxKind.CloseBraceToken);
2600            }
2601            else {
2602                members = createMissingList<TypeElement>();
2603            }
2604
2605            return members;
2606        }
2607
2608        function isStartOfMappedType() {
2609            nextToken();
2610            if (token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) {
2611                return nextToken() === SyntaxKind.ReadonlyKeyword;
2612            }
2613            if (token() === SyntaxKind.ReadonlyKeyword) {
2614                nextToken();
2615            }
2616            return token() === SyntaxKind.OpenBracketToken && nextTokenIsIdentifier() && nextToken() === SyntaxKind.InKeyword;
2617        }
2618
2619        function parseMappedTypeParameter() {
2620            const node = <TypeParameterDeclaration>createNode(SyntaxKind.TypeParameter);
2621            node.name = parseIdentifier();
2622            parseExpected(SyntaxKind.InKeyword);
2623            node.constraint = parseType();
2624            return finishNode(node);
2625        }
2626
2627        function parseMappedType() {
2628            const node = <MappedTypeNode>createNode(SyntaxKind.MappedType);
2629            parseExpected(SyntaxKind.OpenBraceToken);
2630            if (token() === SyntaxKind.ReadonlyKeyword || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) {
2631                node.readonlyToken = parseTokenNode();
2632                if (node.readonlyToken.kind !== SyntaxKind.ReadonlyKeyword) {
2633                    parseExpectedToken(SyntaxKind.ReadonlyKeyword);
2634                }
2635            }
2636            parseExpected(SyntaxKind.OpenBracketToken);
2637            node.typeParameter = parseMappedTypeParameter();
2638            parseExpected(SyntaxKind.CloseBracketToken);
2639            if (token() === SyntaxKind.QuestionToken || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) {
2640                node.questionToken = parseTokenNode();
2641                if (node.questionToken.kind !== SyntaxKind.QuestionToken) {
2642                    parseExpectedToken(SyntaxKind.QuestionToken);
2643                }
2644            }
2645            node.type = parseTypeAnnotation();
2646            parseSemicolon();
2647            parseExpected(SyntaxKind.CloseBraceToken);
2648            return finishNode(node);
2649        }
2650
2651        function parseTupleType(): TupleTypeNode {
2652            const node = <TupleTypeNode>createNode(SyntaxKind.TupleType);
2653            node.elementTypes = parseBracketedList(ParsingContext.TupleElementTypes, parseType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
2654            return finishNode(node);
2655        }
2656
2657        function parseParenthesizedType(): ParenthesizedTypeNode {
2658            const node = <ParenthesizedTypeNode>createNode(SyntaxKind.ParenthesizedType);
2659            parseExpected(SyntaxKind.OpenParenToken);
2660            node.type = parseType();
2661            parseExpected(SyntaxKind.CloseParenToken);
2662            return finishNode(node);
2663        }
2664
2665        function parseFunctionOrConstructorType(kind: SyntaxKind): FunctionOrConstructorTypeNode {
2666            const node = <FunctionOrConstructorTypeNode>createNodeWithJSDoc(kind);
2667            if (kind === SyntaxKind.ConstructorType) {
2668                parseExpected(SyntaxKind.NewKeyword);
2669            }
2670            fillSignature(SyntaxKind.EqualsGreaterThanToken, SignatureFlags.Type, node);
2671            return finishNode(node);
2672        }
2673
2674        function parseKeywordAndNoDot(): TypeNode | undefined {
2675            const node = parseTokenNode<TypeNode>();
2676            return token() === SyntaxKind.DotToken ? undefined : node;
2677        }
2678
2679        function parseLiteralTypeNode(negative?: boolean): LiteralTypeNode {
2680            const node = createNode(SyntaxKind.LiteralType) as LiteralTypeNode;
2681            let unaryMinusExpression: PrefixUnaryExpression;
2682            if (negative) {
2683                unaryMinusExpression = createNode(SyntaxKind.PrefixUnaryExpression) as PrefixUnaryExpression;
2684                unaryMinusExpression.operator = SyntaxKind.MinusToken;
2685                nextToken();
2686            }
2687            let expression: BooleanLiteral | LiteralExpression | PrefixUnaryExpression = token() === SyntaxKind.TrueKeyword || token() === SyntaxKind.FalseKeyword
2688                ? parseTokenNode<BooleanLiteral>()
2689                : parseLiteralLikeNode(token()) as LiteralExpression;
2690            if (negative) {
2691                unaryMinusExpression.operand = expression;
2692                finishNode(unaryMinusExpression);
2693                expression = unaryMinusExpression;
2694            }
2695            node.literal = expression;
2696            return finishNode(node);
2697        }
2698
2699        function nextTokenIsNumericLiteral() {
2700            return nextToken() === SyntaxKind.NumericLiteral;
2701        }
2702
2703        function parseNonArrayType(): TypeNode {
2704            switch (token()) {
2705                case SyntaxKind.AnyKeyword:
2706                case SyntaxKind.StringKeyword:
2707                case SyntaxKind.NumberKeyword:
2708                case SyntaxKind.SymbolKeyword:
2709                case SyntaxKind.BooleanKeyword:
2710                case SyntaxKind.UndefinedKeyword:
2711                case SyntaxKind.NeverKeyword:
2712                case SyntaxKind.ObjectKeyword:
2713                    // If these are followed by a dot, then parse these out as a dotted type reference instead.
2714                    return tryParse(parseKeywordAndNoDot) || parseTypeReference();
2715                case SyntaxKind.AsteriskToken:
2716                    return parseJSDocAllType();
2717                case SyntaxKind.QuestionToken:
2718                    return parseJSDocUnknownOrNullableType();
2719                case SyntaxKind.FunctionKeyword:
2720                    return parseJSDocFunctionType();
2721                case SyntaxKind.ExclamationToken:
2722                    return parseJSDocNodeWithType(SyntaxKind.JSDocNonNullableType);
2723                case SyntaxKind.NoSubstitutionTemplateLiteral:
2724                case SyntaxKind.StringLiteral:
2725                case SyntaxKind.NumericLiteral:
2726                case SyntaxKind.TrueKeyword:
2727                case SyntaxKind.FalseKeyword:
2728                    return parseLiteralTypeNode();
2729                case SyntaxKind.MinusToken:
2730                    return lookAhead(nextTokenIsNumericLiteral) ? parseLiteralTypeNode(/*negative*/ true) : parseTypeReference();
2731                case SyntaxKind.VoidKeyword:
2732                case SyntaxKind.NullKeyword:
2733                    return parseTokenNode<TypeNode>();
2734                case SyntaxKind.ThisKeyword: {
2735                    const thisKeyword = parseThisTypeNode();
2736                    if (token() === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) {
2737                        return parseThisTypePredicate(thisKeyword);
2738                    }
2739                    else {
2740                        return thisKeyword;
2741                    }
2742                }
2743                case SyntaxKind.TypeOfKeyword:
2744                    return parseTypeQuery();
2745                case SyntaxKind.OpenBraceToken:
2746                    return lookAhead(isStartOfMappedType) ? parseMappedType() : parseTypeLiteral();
2747                case SyntaxKind.OpenBracketToken:
2748                    return parseTupleType();
2749                case SyntaxKind.OpenParenToken:
2750                    return parseParenthesizedType();
2751                default:
2752                    return parseTypeReference();
2753            }
2754        }
2755
2756        function isStartOfType(inStartOfParameter?: boolean): boolean {
2757            switch (token()) {
2758                case SyntaxKind.AnyKeyword:
2759                case SyntaxKind.StringKeyword:
2760                case SyntaxKind.NumberKeyword:
2761                case SyntaxKind.BooleanKeyword:
2762                case SyntaxKind.SymbolKeyword:
2763                case SyntaxKind.UniqueKeyword:
2764                case SyntaxKind.VoidKeyword:
2765                case SyntaxKind.UndefinedKeyword:
2766                case SyntaxKind.NullKeyword:
2767                case SyntaxKind.ThisKeyword:
2768                case SyntaxKind.TypeOfKeyword:
2769                case SyntaxKind.NeverKeyword:
2770                case SyntaxKind.OpenBraceToken:
2771                case SyntaxKind.OpenBracketToken:
2772                case SyntaxKind.LessThanToken:
2773                case SyntaxKind.BarToken:
2774                case SyntaxKind.AmpersandToken:
2775                case SyntaxKind.NewKeyword:
2776                case SyntaxKind.StringLiteral:
2777                case SyntaxKind.NumericLiteral:
2778                case SyntaxKind.TrueKeyword:
2779                case SyntaxKind.FalseKeyword:
2780                case SyntaxKind.ObjectKeyword:
2781                case SyntaxKind.AsteriskToken:
2782                case SyntaxKind.QuestionToken:
2783                case SyntaxKind.ExclamationToken:
2784                case SyntaxKind.DotDotDotToken:
2785                case SyntaxKind.InferKeyword:
2786                    return true;
2787                case SyntaxKind.MinusToken:
2788                    return !inStartOfParameter && lookAhead(nextTokenIsNumericLiteral);
2789                case SyntaxKind.OpenParenToken:
2790                    // Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier,
2791                    // or something that starts a type. We don't want to consider things like '(1)' a type.
2792                    return !inStartOfParameter && lookAhead(isStartOfParenthesizedOrFunctionType);
2793                default:
2794                    return isIdentifier();
2795            }
2796        }
2797
2798        function isStartOfParenthesizedOrFunctionType() {
2799            nextToken();
2800            return token() === SyntaxKind.CloseParenToken || isStartOfParameter() || isStartOfType();
2801        }
2802
2803        function parsePostfixTypeOrHigher(): TypeNode {
2804            let type = parseNonArrayType();
2805            while (!scanner.hasPrecedingLineBreak()) {
2806                switch (token()) {
2807                    case SyntaxKind.EqualsToken:
2808                        // only parse postfix = inside jsdoc, because it's ambiguous elsewhere
2809                        if (!(contextFlags & NodeFlags.JSDoc)) {
2810                            return type;
2811                        }
2812                        type = createJSDocPostfixType(SyntaxKind.JSDocOptionalType, type);
2813                        break;
2814                    case SyntaxKind.ExclamationToken:
2815                        type = createJSDocPostfixType(SyntaxKind.JSDocNonNullableType, type);
2816                        break;
2817                    case SyntaxKind.QuestionToken:
2818                        // If not in JSDoc and next token is start of a type we have a conditional type
2819                        if (!(contextFlags & NodeFlags.JSDoc) && lookAhead(nextTokenIsStartOfType)) {
2820                            return type;
2821                        }
2822                        type = createJSDocPostfixType(SyntaxKind.JSDocNullableType, type);
2823                        break;
2824                    case SyntaxKind.OpenBracketToken:
2825                        parseExpected(SyntaxKind.OpenBracketToken);
2826                        if (isStartOfType()) {
2827                            const node = createNode(SyntaxKind.IndexedAccessType, type.pos) as IndexedAccessTypeNode;
2828                            node.objectType = type;
2829                            node.indexType = parseType();
2830                            parseExpected(SyntaxKind.CloseBracketToken);
2831                            type = finishNode(node);
2832                        }
2833                        else {
2834                            const node = createNode(SyntaxKind.ArrayType, type.pos) as ArrayTypeNode;
2835                            node.elementType = type;
2836                            parseExpected(SyntaxKind.CloseBracketToken);
2837                            type = finishNode(node);
2838                        }
2839                        break;
2840                    default:
2841                        return type;
2842                }
2843            }
2844            return type;
2845        }
2846
2847        function createJSDocPostfixType(kind: SyntaxKind, type: TypeNode) {
2848            nextToken();
2849            const postfix = createNode(kind, type.pos) as JSDocOptionalType | JSDocNonNullableType | JSDocNullableType;
2850            postfix.type = type;
2851            return finishNode(postfix);
2852        }
2853
2854        function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword) {
2855            const node = <TypeOperatorNode>createNode(SyntaxKind.TypeOperator);
2856            parseExpected(operator);
2857            node.operator = operator;
2858            node.type = parseTypeOperatorOrHigher();
2859            return finishNode(node);
2860        }
2861
2862        function parseInferType(): InferTypeNode {
2863            const node = <InferTypeNode>createNode(SyntaxKind.InferType);
2864            parseExpected(SyntaxKind.InferKeyword);
2865            const typeParameter = <TypeParameterDeclaration>createNode(SyntaxKind.TypeParameter);
2866            typeParameter.name = parseIdentifier();
2867            node.typeParameter = finishNode(typeParameter);
2868            return finishNode(node);
2869        }
2870
2871        function parseTypeOperatorOrHigher(): TypeNode {
2872            const operator = token();
2873            switch (operator) {
2874                case SyntaxKind.KeyOfKeyword:
2875                case SyntaxKind.UniqueKeyword:
2876                    return parseTypeOperator(operator);
2877                case SyntaxKind.InferKeyword:
2878                    return parseInferType();
2879                case SyntaxKind.DotDotDotToken: {
2880                    const result = createNode(SyntaxKind.JSDocVariadicType) as JSDocVariadicType;
2881                    nextToken();
2882                    result.type = parsePostfixTypeOrHigher();
2883                    return finishNode(result);
2884                }
2885            }
2886            return parsePostfixTypeOrHigher();
2887        }
2888
2889        function parseUnionOrIntersectionType(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, parseConstituentType: () => TypeNode, operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken): TypeNode {
2890            parseOptional(operator);
2891            let type = parseConstituentType();
2892            if (token() === operator) {
2893                const types = [type];
2894                while (parseOptional(operator)) {
2895                    types.push(parseConstituentType());
2896                }
2897                const node = <UnionOrIntersectionTypeNode>createNode(kind, type.pos);
2898                node.types = createNodeArray(types, type.pos);
2899                type = finishNode(node);
2900            }
2901            return type;
2902        }
2903
2904        function parseIntersectionTypeOrHigher(): TypeNode {
2905            return parseUnionOrIntersectionType(SyntaxKind.IntersectionType, parseTypeOperatorOrHigher, SyntaxKind.AmpersandToken);
2906        }
2907
2908        function parseUnionTypeOrHigher(): TypeNode {
2909            return parseUnionOrIntersectionType(SyntaxKind.UnionType, parseIntersectionTypeOrHigher, SyntaxKind.BarToken);
2910        }
2911
2912        function isStartOfFunctionType(): boolean {
2913            if (token() === SyntaxKind.LessThanToken) {
2914                return true;
2915            }
2916            return token() === SyntaxKind.OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType);
2917        }
2918
2919        function skipParameterStart(): boolean {
2920            if (isModifierKind(token())) {
2921                // Skip modifiers
2922                parseModifiers();
2923            }
2924            if (isIdentifier() || token() === SyntaxKind.ThisKeyword) {
2925                nextToken();
2926                return true;
2927            }
2928            if (token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.OpenBraceToken) {
2929                // Return true if we can parse an array or object binding pattern with no errors
2930                const previousErrorCount = parseDiagnostics.length;
2931                parseIdentifierOrPattern();
2932                return previousErrorCount === parseDiagnostics.length;
2933            }
2934            return false;
2935        }
2936
2937        function isUnambiguouslyStartOfFunctionType() {
2938            nextToken();
2939            if (token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.DotDotDotToken) {
2940                // ( )
2941                // ( ...
2942                return true;
2943            }
2944            if (skipParameterStart()) {
2945                // We successfully skipped modifiers (if any) and an identifier or binding pattern,
2946                // now see if we have something that indicates a parameter declaration
2947                if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken ||
2948                    token() === SyntaxKind.QuestionToken || token() === SyntaxKind.EqualsToken) {
2949                    // ( xxx :
2950                    // ( xxx ,
2951                    // ( xxx ?
2952                    // ( xxx =
2953                    return true;
2954                }
2955                if (token() === SyntaxKind.CloseParenToken) {
2956                    nextToken();
2957                    if (token() === SyntaxKind.EqualsGreaterThanToken) {
2958                        // ( xxx ) =>
2959                        return true;
2960                    }
2961                }
2962            }
2963            return false;
2964        }
2965
2966        function parseTypeOrTypePredicate(): TypeNode {
2967            const typePredicateVariable = isIdentifier() && tryParse(parseTypePredicatePrefix);
2968            const type = parseType();
2969            if (typePredicateVariable) {
2970                const node = <TypePredicateNode>createNode(SyntaxKind.TypePredicate, typePredicateVariable.pos);
2971                node.parameterName = typePredicateVariable;
2972                node.type = type;
2973                return finishNode(node);
2974            }
2975            else {
2976                return type;
2977            }
2978        }
2979
2980        function parseTypePredicatePrefix() {
2981            const id = parseIdentifier();
2982            if (token() === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) {
2983                nextToken();
2984                return id;
2985            }
2986        }
2987
2988        function parseType(): TypeNode {
2989            // The rules about 'yield' only apply to actual code/expression contexts.  They don't
2990            // apply to 'type' contexts.  So we disable these parameters here before moving on.
2991            return doOutsideOfContext(NodeFlags.TypeExcludesFlags, parseTypeWorker);
2992        }
2993
2994        function parseTypeWorker(noConditionalTypes?: boolean): TypeNode {
2995            if (isStartOfFunctionType()) {
2996                return parseFunctionOrConstructorType(SyntaxKind.FunctionType);
2997            }
2998            if (token() === SyntaxKind.NewKeyword) {
2999                return parseFunctionOrConstructorType(SyntaxKind.ConstructorType);
3000            }
3001            const type = parseUnionTypeOrHigher();
3002            if (!noConditionalTypes && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.ExtendsKeyword)) {
3003                const node = <ConditionalTypeNode>createNode(SyntaxKind.ConditionalType, type.pos);
3004                node.checkType = type;
3005                // The type following 'extends' is not permitted to be another conditional type
3006                node.extendsType = parseTypeWorker(/*noConditionalTypes*/ true);
3007                parseExpected(SyntaxKind.QuestionToken);
3008                node.trueType = parseTypeWorker();
3009                parseExpected(SyntaxKind.ColonToken);
3010                node.falseType = parseTypeWorker();
3011                return finishNode(node);
3012            }
3013            return type;
3014        }
3015
3016        function parseTypeAnnotation(): TypeNode {
3017            return parseOptional(SyntaxKind.ColonToken) ? parseType() : undefined;
3018        }
3019
3020        // EXPRESSIONS
3021        function isStartOfLeftHandSideExpression(): boolean {
3022            switch (token()) {
3023                case SyntaxKind.ThisKeyword:
3024                case SyntaxKind.SuperKeyword:
3025                case SyntaxKind.NullKeyword:
3026                case SyntaxKind.TrueKeyword:
3027                case SyntaxKind.FalseKeyword:
3028                case SyntaxKind.NumericLiteral:
3029                case SyntaxKind.StringLiteral:
3030                case SyntaxKind.NoSubstitutionTemplateLiteral:
3031                case SyntaxKind.TemplateHead:
3032                case SyntaxKind.OpenParenToken:
3033                case SyntaxKind.OpenBracketToken:
3034                case SyntaxKind.OpenBraceToken:
3035                case SyntaxKind.FunctionKeyword:
3036                case SyntaxKind.ClassKeyword:
3037                case SyntaxKind.NewKeyword:
3038                case SyntaxKind.SlashToken:
3039                case SyntaxKind.SlashEqualsToken:
3040                case SyntaxKind.Identifier:
3041                    return true;
3042                case SyntaxKind.ImportKeyword:
3043                    return lookAhead(nextTokenIsOpenParenOrLessThan);
3044                default:
3045                    return isIdentifier();
3046            }
3047        }
3048
3049        function isStartOfExpression(): boolean {
3050            if (isStartOfLeftHandSideExpression()) {
3051                return true;
3052            }
3053
3054            switch (token()) {
3055                case SyntaxKind.PlusToken:
3056                case SyntaxKind.MinusToken:
3057                case SyntaxKind.TildeToken:
3058                case SyntaxKind.ExclamationToken:
3059                case SyntaxKind.DeleteKeyword:
3060                case SyntaxKind.TypeOfKeyword:
3061                case SyntaxKind.VoidKeyword:
3062                case SyntaxKind.PlusPlusToken:
3063                case SyntaxKind.MinusMinusToken:
3064                case SyntaxKind.LessThanToken:
3065                case SyntaxKind.AwaitKeyword:
3066                case SyntaxKind.YieldKeyword:
3067                    // Yield/await always starts an expression.  Either it is an identifier (in which case
3068                    // it is definitely an expression).  Or it's a keyword (either because we're in
3069                    // a generator or async function, or in strict mode (or both)) and it started a yield or await expression.
3070                    return true;
3071                default:
3072                    // Error tolerance.  If we see the start of some binary operator, we consider
3073                    // that the start of an expression.  That way we'll parse out a missing identifier,
3074                    // give a good message about an identifier being missing, and then consume the
3075                    // rest of the binary expression.
3076                    if (isBinaryOperator()) {
3077                        return true;
3078                    }
3079
3080                    return isIdentifier();
3081            }
3082        }
3083
3084        function isStartOfExpressionStatement(): boolean {
3085            // As per the grammar, none of '{' or 'function' or 'class' can start an expression statement.
3086            return token() !== SyntaxKind.OpenBraceToken &&
3087                token() !== SyntaxKind.FunctionKeyword &&
3088                token() !== SyntaxKind.ClassKeyword &&
3089                token() !== SyntaxKind.AtToken &&
3090                isStartOfExpression();
3091        }
3092
3093        function parseExpression(): Expression {
3094            // Expression[in]:
3095            //      AssignmentExpression[in]
3096            //      Expression[in] , AssignmentExpression[in]
3097
3098            // clear the decorator context when parsing Expression, as it should be unambiguous when parsing a decorator
3099            const saveDecoratorContext = inDecoratorContext();
3100            if (saveDecoratorContext) {
3101                setDecoratorContext(/*val*/ false);
3102            }
3103
3104            let expr = parseAssignmentExpressionOrHigher();
3105            let operatorToken: BinaryOperatorToken;
3106            while ((operatorToken = parseOptionalToken(SyntaxKind.CommaToken))) {
3107                expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher());
3108            }
3109
3110            if (saveDecoratorContext) {
3111                setDecoratorContext(/*val*/ true);
3112            }
3113            return expr;
3114        }
3115
3116        function parseInitializer(): Expression | undefined {
3117            return parseOptional(SyntaxKind.EqualsToken) ? parseAssignmentExpressionOrHigher() : undefined;
3118        }
3119
3120        function parseAssignmentExpressionOrHigher(): Expression {
3121            //  AssignmentExpression[in,yield]:
3122            //      1) ConditionalExpression[?in,?yield]
3123            //      2) LeftHandSideExpression = AssignmentExpression[?in,?yield]
3124            //      3) LeftHandSideExpression AssignmentOperator AssignmentExpression[?in,?yield]
3125            //      4) ArrowFunctionExpression[?in,?yield]
3126            //      5) AsyncArrowFunctionExpression[in,yield,await]
3127            //      6) [+Yield] YieldExpression[?In]
3128            //
3129            // Note: for ease of implementation we treat productions '2' and '3' as the same thing.
3130            // (i.e. they're both BinaryExpressions with an assignment operator in it).
3131
3132            // First, do the simple check if we have a YieldExpression (production '6').
3133            if (isYieldExpression()) {
3134                return parseYieldExpression();
3135            }
3136
3137            // Then, check if we have an arrow function (production '4' and '5') that starts with a parenthesized
3138            // parameter list or is an async arrow function.
3139            // AsyncArrowFunctionExpression:
3140            //      1) async[no LineTerminator here]AsyncArrowBindingIdentifier[?Yield][no LineTerminator here]=>AsyncConciseBody[?In]
3141            //      2) CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await][no LineTerminator here]=>AsyncConciseBody[?In]
3142            // Production (1) of AsyncArrowFunctionExpression is parsed in "tryParseAsyncSimpleArrowFunctionExpression".
3143            // And production (2) is parsed in "tryParseParenthesizedArrowFunctionExpression".
3144            //
3145            // If we do successfully parse arrow-function, we must *not* recurse for productions 1, 2 or 3. An ArrowFunction is
3146            // not a LeftHandSideExpression, nor does it start a ConditionalExpression.  So we are done
3147            // with AssignmentExpression if we see one.
3148            const arrowExpression = tryParseParenthesizedArrowFunctionExpression() || tryParseAsyncSimpleArrowFunctionExpression();
3149            if (arrowExpression) {
3150                return arrowExpression;
3151            }
3152
3153            // Now try to see if we're in production '1', '2' or '3'.  A conditional expression can
3154            // start with a LogicalOrExpression, while the assignment productions can only start with
3155            // LeftHandSideExpressions.
3156            //
3157            // So, first, we try to just parse out a BinaryExpression.  If we get something that is a
3158            // LeftHandSide or higher, then we can try to parse out the assignment expression part.
3159            // Otherwise, we try to parse out the conditional expression bit.  We want to allow any
3160            // binary expression here, so we pass in the 'lowest' precedence here so that it matches
3161            // and consumes anything.
3162            const expr = parseBinaryExpressionOrHigher(/*precedence*/ 0);
3163
3164            // To avoid a look-ahead, we did not handle the case of an arrow function with a single un-parenthesized
3165            // parameter ('x => ...') above. We handle it here by checking if the parsed expression was a single
3166            // identifier and the current token is an arrow.
3167            if (expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) {
3168                return parseSimpleArrowFunctionExpression(<Identifier>expr);
3169            }
3170
3171            // Now see if we might be in cases '2' or '3'.
3172            // If the expression was a LHS expression, and we have an assignment operator, then
3173            // we're in '2' or '3'. Consume the assignment and return.
3174            //
3175            // Note: we call reScanGreaterToken so that we get an appropriately merged token
3176            // for cases like `> > =` becoming `>>=`
3177            if (isLeftHandSideExpression(expr) && isAssignmentOperator(reScanGreaterToken())) {
3178                return makeBinaryExpression(expr, <BinaryOperatorToken>parseTokenNode(), parseAssignmentExpressionOrHigher());
3179            }
3180
3181            // It wasn't an assignment or a lambda.  This is a conditional expression:
3182            return parseConditionalExpressionRest(expr);
3183        }
3184
3185        function isYieldExpression(): boolean {
3186            if (token() === SyntaxKind.YieldKeyword) {
3187                // If we have a 'yield' keyword, and this is a context where yield expressions are
3188                // allowed, then definitely parse out a yield expression.
3189                if (inYieldContext()) {
3190                    return true;
3191                }
3192
3193                // We're in a context where 'yield expr' is not allowed.  However, if we can
3194                // definitely tell that the user was trying to parse a 'yield expr' and not
3195                // just a normal expr that start with a 'yield' identifier, then parse out
3196                // a 'yield expr'.  We can then report an error later that they are only
3197                // allowed in generator expressions.
3198                //
3199                // for example, if we see 'yield(foo)', then we'll have to treat that as an
3200                // invocation expression of something called 'yield'.  However, if we have
3201                // 'yield foo' then that is not legal as a normal expression, so we can
3202                // definitely recognize this as a yield expression.
3203                //
3204                // for now we just check if the next token is an identifier.  More heuristics
3205                // can be added here later as necessary.  We just need to make sure that we
3206                // don't accidentally consume something legal.
3207                return lookAhead(nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine);
3208            }
3209
3210            return false;
3211        }
3212
3213        function nextTokenIsIdentifierOnSameLine() {
3214            nextToken();
3215            return !scanner.hasPrecedingLineBreak() && isIdentifier();
3216        }
3217
3218        function parseYieldExpression(): YieldExpression {
3219            const node = <YieldExpression>createNode(SyntaxKind.YieldExpression);
3220
3221            // YieldExpression[In] :
3222            //      yield
3223            //      yield [no LineTerminator here] [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield]
3224            //      yield [no LineTerminator here] * [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield]
3225            nextToken();
3226
3227            if (!scanner.hasPrecedingLineBreak() &&
3228                (token() === SyntaxKind.AsteriskToken || isStartOfExpression())) {
3229                node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
3230                node.expression = parseAssignmentExpressionOrHigher();
3231                return finishNode(node);
3232            }
3233            else {
3234                // if the next token is not on the same line as yield.  or we don't have an '*' or
3235                // the start of an expression, then this is just a simple "yield" expression.
3236                return finishNode(node);
3237            }
3238        }
3239
3240        function parseSimpleArrowFunctionExpression(identifier: Identifier, asyncModifier?: NodeArray<Modifier>): ArrowFunction {
3241            Debug.assert(token() === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>");
3242
3243            let node: ArrowFunction;
3244            if (asyncModifier) {
3245                node = <ArrowFunction>createNode(SyntaxKind.ArrowFunction, asyncModifier.pos);
3246                node.modifiers = asyncModifier;
3247            }
3248            else {
3249                node = <ArrowFunction>createNode(SyntaxKind.ArrowFunction, identifier.pos);
3250            }
3251
3252            const parameter = <ParameterDeclaration>createNode(SyntaxKind.Parameter, identifier.pos);
3253            parameter.name = identifier;
3254            finishNode(parameter);
3255
3256            node.parameters = createNodeArray<ParameterDeclaration>([parameter], parameter.pos, parameter.end);
3257
3258            node.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken);
3259            node.body = parseArrowFunctionExpressionBody(/*isAsync*/ !!asyncModifier);
3260
3261            return addJSDocComment(finishNode(node));
3262        }
3263
3264        function tryParseParenthesizedArrowFunctionExpression(): Expression | undefined {
3265            const triState = isParenthesizedArrowFunctionExpression();
3266            if (triState === Tristate.False) {
3267                // It's definitely not a parenthesized arrow function expression.
3268                return undefined;
3269            }
3270
3271            // If we definitely have an arrow function, then we can just parse one, not requiring a
3272            // following => or { token. Otherwise, we *might* have an arrow function.  Try to parse
3273            // it out, but don't allow any ambiguity, and return 'undefined' if this could be an
3274            // expression instead.
3275            const arrowFunction = triState === Tristate.True
3276                ? parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ true)
3277                : tryParse(parsePossibleParenthesizedArrowFunctionExpressionHead);
3278
3279            if (!arrowFunction) {
3280                // Didn't appear to actually be a parenthesized arrow function.  Just bail out.
3281                return undefined;
3282            }
3283
3284            const isAsync = hasModifier(arrowFunction, ModifierFlags.Async);
3285
3286            // If we have an arrow, then try to parse the body. Even if not, try to parse if we
3287            // have an opening brace, just in case we're in an error state.
3288            const lastToken = token();
3289            arrowFunction.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken);
3290            arrowFunction.body = (lastToken === SyntaxKind.EqualsGreaterThanToken || lastToken === SyntaxKind.OpenBraceToken)
3291                ? parseArrowFunctionExpressionBody(isAsync)
3292                : parseIdentifier();
3293
3294            return finishNode(arrowFunction);
3295        }
3296
3297        //  True        -> We definitely expect a parenthesized arrow function here.
3298        //  False       -> There *cannot* be a parenthesized arrow function here.
3299        //  Unknown     -> There *might* be a parenthesized arrow function here.
3300        //                 Speculatively look ahead to be sure, and rollback if not.
3301        function isParenthesizedArrowFunctionExpression(): Tristate {
3302            if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken || token() === SyntaxKind.AsyncKeyword) {
3303                return lookAhead(isParenthesizedArrowFunctionExpressionWorker);
3304            }
3305
3306            if (token() === SyntaxKind.EqualsGreaterThanToken) {
3307                // ERROR RECOVERY TWEAK:
3308                // If we see a standalone => try to parse it as an arrow function expression as that's
3309                // likely what the user intended to write.
3310                return Tristate.True;
3311            }
3312            // Definitely not a parenthesized arrow function.
3313            return Tristate.False;
3314        }
3315
3316        function isParenthesizedArrowFunctionExpressionWorker() {
3317            if (token() === SyntaxKind.AsyncKeyword) {
3318                nextToken();
3319                if (scanner.hasPrecedingLineBreak()) {
3320                    return Tristate.False;
3321                }
3322                if (token() !== SyntaxKind.OpenParenToken && token() !== SyntaxKind.LessThanToken) {
3323                    return Tristate.False;
3324                }
3325            }
3326
3327            const first = token();
3328            const second = nextToken();
3329
3330            if (first === SyntaxKind.OpenParenToken) {
3331                if (second === SyntaxKind.CloseParenToken) {
3332                    // Simple cases: "() =>", "(): ", and "() {".
3333                    // This is an arrow function with no parameters.
3334                    // The last one is not actually an arrow function,
3335                    // but this is probably what the user intended.
3336                    const third = nextToken();
3337                    switch (third) {
3338                        case SyntaxKind.EqualsGreaterThanToken:
3339                        case SyntaxKind.ColonToken:
3340                        case SyntaxKind.OpenBraceToken:
3341                            return Tristate.True;
3342                        default:
3343                            return Tristate.False;
3344                    }
3345                }
3346
3347                // If encounter "([" or "({", this could be the start of a binding pattern.
3348                // Examples:
3349                //      ([ x ]) => { }
3350                //      ({ x }) => { }
3351                //      ([ x ])
3352                //      ({ x })
3353                if (second === SyntaxKind.OpenBracketToken || second === SyntaxKind.OpenBraceToken) {
3354                    return Tristate.Unknown;
3355                }
3356
3357                // Simple case: "(..."
3358                // This is an arrow function with a rest parameter.
3359                if (second === SyntaxKind.DotDotDotToken) {
3360                    return Tristate.True;
3361                }
3362
3363                // Check for "(xxx yyy", where xxx is a modifier and yyy is an identifier. This
3364                // isn't actually allowed, but we want to treat it as a lambda so we can provide
3365                // a good error message.
3366                if (isModifierKind(second) && second !== SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsIdentifier)) {
3367                    return Tristate.True;
3368                }
3369
3370                // If we had "(" followed by something that's not an identifier,
3371                // then this definitely doesn't look like a lambda.
3372                if (!isIdentifier()) {
3373                    return Tristate.False;
3374                }
3375
3376                switch (nextToken()) {
3377                    case SyntaxKind.ColonToken:
3378                        // If we have something like "(a:", then we must have a
3379                        // type-annotated parameter in an arrow function expression.
3380                        return Tristate.True;
3381                    case SyntaxKind.QuestionToken:
3382                        nextToken();
3383                        // If we have "(a?:" or "(a?," or "(a?=" or "(a?)" then it is definitely a lambda.
3384                        if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.EqualsToken || token() === SyntaxKind.CloseParenToken) {
3385                            return Tristate.True;
3386                        }
3387                        // Otherwise it is definitely not a lambda.
3388                        return Tristate.False;
3389                    case SyntaxKind.CommaToken:
3390                    case SyntaxKind.EqualsToken:
3391                    case SyntaxKind.CloseParenToken:
3392                        // If we have "(a," or "(a=" or "(a)" this *could* be an arrow function
3393                        return Tristate.Unknown;
3394                }
3395                // It is definitely not an arrow function
3396                return Tristate.False;
3397            }
3398            else {
3399                Debug.assert(first === SyntaxKind.LessThanToken);
3400
3401                // If we have "<" not followed by an identifier,
3402                // then this definitely is not an arrow function.
3403                if (!isIdentifier()) {
3404                    return Tristate.False;
3405                }
3406
3407                // JSX overrides
3408                if (sourceFile.languageVariant === LanguageVariant.JSX) {
3409                    const isArrowFunctionInJsx = lookAhead(() => {
3410                        const third = nextToken();
3411                        if (third === SyntaxKind.ExtendsKeyword) {
3412                            const fourth = nextToken();
3413                            switch (fourth) {
3414                                case SyntaxKind.EqualsToken:
3415                                case SyntaxKind.GreaterThanToken:
3416                                    return false;
3417                                default:
3418                                    return true;
3419                            }
3420                        }
3421                        else if (third === SyntaxKind.CommaToken) {
3422                            return true;
3423                        }
3424                        return false;
3425                    });
3426
3427                    if (isArrowFunctionInJsx) {
3428                        return Tristate.True;
3429                    }
3430
3431                    return Tristate.False;
3432                }
3433
3434                // This *could* be a parenthesized arrow function.
3435                return Tristate.Unknown;
3436            }
3437        }
3438
3439        function parsePossibleParenthesizedArrowFunctionExpressionHead(): ArrowFunction {
3440            return parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ false);
3441        }
3442
3443        function tryParseAsyncSimpleArrowFunctionExpression(): ArrowFunction | undefined {
3444            // We do a check here so that we won't be doing unnecessarily call to "lookAhead"
3445            if (token() === SyntaxKind.AsyncKeyword) {
3446                if (lookAhead(isUnParenthesizedAsyncArrowFunctionWorker) === Tristate.True) {
3447                    const asyncModifier = parseModifiersForArrowFunction();
3448                    const expr = parseBinaryExpressionOrHigher(/*precedence*/ 0);
3449                    return parseSimpleArrowFunctionExpression(<Identifier>expr, asyncModifier);
3450                }
3451            }
3452            return undefined;
3453        }
3454
3455        function isUnParenthesizedAsyncArrowFunctionWorker(): Tristate {
3456            // AsyncArrowFunctionExpression:
3457            //      1) async[no LineTerminator here]AsyncArrowBindingIdentifier[?Yield][no LineTerminator here]=>AsyncConciseBody[?In]
3458            //      2) CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await][no LineTerminator here]=>AsyncConciseBody[?In]
3459            if (token() === SyntaxKind.AsyncKeyword) {
3460                nextToken();
3461                // If the "async" is followed by "=>" token then it is not a begining of an async arrow-function
3462                // but instead a simple arrow-function which will be parsed inside "parseAssignmentExpressionOrHigher"
3463                if (scanner.hasPrecedingLineBreak() || token() === SyntaxKind.EqualsGreaterThanToken) {
3464                    return Tristate.False;
3465                }
3466                // Check for un-parenthesized AsyncArrowFunction
3467                const expr = parseBinaryExpressionOrHigher(/*precedence*/ 0);
3468                if (!scanner.hasPrecedingLineBreak() && expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) {
3469                    return Tristate.True;
3470                }
3471            }
3472
3473            return Tristate.False;
3474        }
3475
3476        function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunction {
3477            const node = <ArrowFunction>createNodeWithJSDoc(SyntaxKind.ArrowFunction);
3478            node.modifiers = parseModifiersForArrowFunction();
3479            const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None;
3480            // Arrow functions are never generators.
3481            //
3482            // If we're speculatively parsing a signature for a parenthesized arrow function, then
3483            // we have to have a complete parameter list.  Otherwise we might see something like
3484            // a => (b => c)
3485            // And think that "(b =>" was actually a parenthesized arrow function with a missing
3486            // close paren.
3487            fillSignature(SyntaxKind.ColonToken, isAsync | (allowAmbiguity ? SignatureFlags.None : SignatureFlags.RequireCompleteParameterList), node);
3488
3489            // If we couldn't get parameters, we definitely could not parse out an arrow function.
3490            if (!node.parameters) {
3491                return undefined;
3492            }
3493
3494            // Parsing a signature isn't enough.
3495            // Parenthesized arrow signatures often look like other valid expressions.
3496            // For instance:
3497            //  - "(x = 10)" is an assignment expression parsed as a signature with a default parameter value.
3498            //  - "(x,y)" is a comma expression parsed as a signature with two parameters.
3499            //  - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation.
3500            //
3501            // So we need just a bit of lookahead to ensure that it can only be a signature.
3502            if (!allowAmbiguity && token() !== SyntaxKind.EqualsGreaterThanToken && token() !== SyntaxKind.OpenBraceToken) {
3503                // Returning undefined here will cause our caller to rewind to where we started from.
3504                return undefined;
3505            }
3506
3507            return node;
3508        }
3509
3510        function parseArrowFunctionExpressionBody(isAsync: boolean): Block | Expression {
3511            if (token() === SyntaxKind.OpenBraceToken) {
3512                return parseFunctionBlock(isAsync ? SignatureFlags.Await : SignatureFlags.None);
3513            }
3514
3515            if (token() !== SyntaxKind.SemicolonToken &&
3516                token() !== SyntaxKind.FunctionKeyword &&
3517                token() !== SyntaxKind.ClassKeyword &&
3518                isStartOfStatement() &&
3519                !isStartOfExpressionStatement()) {
3520                // Check if we got a plain statement (i.e. no expression-statements, no function/class expressions/declarations)
3521                //
3522                // Here we try to recover from a potential error situation in the case where the
3523                // user meant to supply a block. For example, if the user wrote:
3524                //
3525                //  a =>
3526                //      let v = 0;
3527                //  }
3528                //
3529                // they may be missing an open brace.  Check to see if that's the case so we can
3530                // try to recover better.  If we don't do this, then the next close curly we see may end
3531                // up preemptively closing the containing construct.
3532                //
3533                // Note: even when 'IgnoreMissingOpenBrace' is passed, parseBody will still error.
3534                return parseFunctionBlock(SignatureFlags.IgnoreMissingOpenBrace | (isAsync ? SignatureFlags.Await : SignatureFlags.None));
3535            }
3536
3537            return isAsync
3538                ? doInAwaitContext(parseAssignmentExpressionOrHigher)
3539                : doOutsideOfAwaitContext(parseAssignmentExpressionOrHigher);
3540        }
3541
3542        function parseConditionalExpressionRest(leftOperand: Expression): Expression {
3543            // Note: we are passed in an expression which was produced from parseBinaryExpressionOrHigher.
3544            const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
3545            if (!questionToken) {
3546                return leftOperand;
3547            }
3548
3549            // Note: we explicitly 'allowIn' in the whenTrue part of the condition expression, and
3550            // we do not that for the 'whenFalse' part.
3551            const node = <ConditionalExpression>createNode(SyntaxKind.ConditionalExpression, leftOperand.pos);
3552            node.condition = leftOperand;
3553            node.questionToken = questionToken;
3554            node.whenTrue = doOutsideOfContext(disallowInAndDecoratorContext, parseAssignmentExpressionOrHigher);
3555            node.colonToken = parseExpectedToken(SyntaxKind.ColonToken);
3556            node.whenFalse = nodeIsPresent(node.colonToken)
3557                ? parseAssignmentExpressionOrHigher()
3558                : createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken));
3559            return finishNode(node);
3560        }
3561
3562        function parseBinaryExpressionOrHigher(precedence: number): Expression {
3563            const leftOperand = parseUnaryExpressionOrHigher();
3564            return parseBinaryExpressionRest(precedence, leftOperand);
3565        }
3566
3567        function isInOrOfKeyword(t: SyntaxKind) {
3568            return t === SyntaxKind.InKeyword || t === SyntaxKind.OfKeyword;
3569        }
3570
3571        function parseBinaryExpressionRest(precedence: number, leftOperand: Expression): Expression {
3572            while (true) {
3573                // We either have a binary operator here, or we're finished.  We call
3574                // reScanGreaterToken so that we merge token sequences like > and = into >=
3575
3576                reScanGreaterToken();
3577                const newPrecedence = getBinaryOperatorPrecedence();
3578
3579                // Check the precedence to see if we should "take" this operator
3580                // - For left associative operator (all operator but **), consume the operator,
3581                //   recursively call the function below, and parse binaryExpression as a rightOperand
3582                //   of the caller if the new precedence of the operator is greater then or equal to the current precedence.
3583                //   For example:
3584                //      a - b - c;
3585                //            ^token; leftOperand = b. Return b to the caller as a rightOperand
3586                //      a * b - c
3587                //            ^token; leftOperand = b. Return b to the caller as a rightOperand
3588                //      a - b * c;
3589                //            ^token; leftOperand = b. Return b * c to the caller as a rightOperand
3590                // - For right associative operator (**), consume the operator, recursively call the function
3591                //   and parse binaryExpression as a rightOperand of the caller if the new precedence of
3592                //   the operator is strictly grater than the current precedence
3593                //   For example:
3594                //      a ** b ** c;
3595                //             ^^token; leftOperand = b. Return b ** c to the caller as a rightOperand
3596                //      a - b ** c;
3597                //            ^^token; leftOperand = b. Return b ** c to the caller as a rightOperand
3598                //      a ** b - c
3599                //             ^token; leftOperand = b. Return b to the caller as a rightOperand
3600                const consumeCurrentOperator = token() === SyntaxKind.AsteriskAsteriskToken ?
3601                    newPrecedence >= precedence :
3602                    newPrecedence > precedence;
3603
3604                if (!consumeCurrentOperator) {
3605                    break;
3606                }
3607
3608                if (token() === SyntaxKind.InKeyword && inDisallowInContext()) {
3609                    break;
3610                }
3611
3612                if (token() === SyntaxKind.AsKeyword) {
3613                    // Make sure we *do* perform ASI for constructs like this:
3614                    //    var x = foo
3615                    //    as (Bar)
3616                    // This should be parsed as an initialized variable, followed
3617                    // by a function call to 'as' with the argument 'Bar'
3618                    if (scanner.hasPrecedingLineBreak()) {
3619                        break;
3620                    }
3621                    else {
3622                        nextToken();
3623                        leftOperand = makeAsExpression(leftOperand, parseType());
3624                    }
3625                }
3626                else {
3627                    leftOperand = makeBinaryExpression(leftOperand, <BinaryOperatorToken>parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence));
3628                }
3629            }
3630
3631            return leftOperand;
3632        }
3633
3634        function isBinaryOperator() {
3635            if (inDisallowInContext() && token() === SyntaxKind.InKeyword) {
3636                return false;
3637            }
3638
3639            return getBinaryOperatorPrecedence() > 0;
3640        }
3641
3642        function getBinaryOperatorPrecedence(): number {
3643            switch (token()) {
3644                case SyntaxKind.BarBarToken:
3645                    return 1;
3646                case SyntaxKind.AmpersandAmpersandToken:
3647                    return 2;
3648                case SyntaxKind.BarToken:
3649                    return 3;
3650                case SyntaxKind.CaretToken:
3651                    return 4;
3652                case SyntaxKind.AmpersandToken:
3653                    return 5;
3654                case SyntaxKind.EqualsEqualsToken:
3655                case SyntaxKind.ExclamationEqualsToken:
3656                case SyntaxKind.EqualsEqualsEqualsToken:
3657                case SyntaxKind.ExclamationEqualsEqualsToken:
3658                    return 6;
3659                case SyntaxKind.LessThanToken:
3660                case SyntaxKind.GreaterThanToken:
3661                case SyntaxKind.LessThanEqualsToken:
3662                case SyntaxKind.GreaterThanEqualsToken:
3663                case SyntaxKind.InstanceOfKeyword:
3664                case SyntaxKind.InKeyword:
3665                case SyntaxKind.AsKeyword:
3666                    return 7;
3667                case SyntaxKind.LessThanLessThanToken:
3668                case SyntaxKind.GreaterThanGreaterThanToken:
3669                case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
3670                    return 8;
3671                case SyntaxKind.PlusToken:
3672                case SyntaxKind.MinusToken:
3673                    return 9;
3674                case SyntaxKind.AsteriskToken:
3675                case SyntaxKind.SlashToken:
3676                case SyntaxKind.PercentToken:
3677                    return 10;
3678                case SyntaxKind.AsteriskAsteriskToken:
3679                    return 11;
3680            }
3681
3682            // -1 is lower than all other precedences.  Returning it will cause binary expression
3683            // parsing to stop.
3684            return -1;
3685        }
3686
3687        function makeBinaryExpression(left: Expression, operatorToken: BinaryOperatorToken, right: Expression): BinaryExpression {
3688            const node = <BinaryExpression>createNode(SyntaxKind.BinaryExpression, left.pos);
3689            node.left = left;
3690            node.operatorToken = operatorToken;
3691            node.right = right;
3692            return finishNode(node);
3693        }
3694
3695        function makeAsExpression(left: Expression, right: TypeNode): AsExpression {
3696            const node = <AsExpression>createNode(SyntaxKind.AsExpression, left.pos);
3697            node.expression = left;
3698            node.type = right;
3699            return finishNode(node);
3700        }
3701
3702        function parsePrefixUnaryExpression() {
3703            const node = <PrefixUnaryExpression>createNode(SyntaxKind.PrefixUnaryExpression);
3704            node.operator = <PrefixUnaryOperator>token();
3705            nextToken();
3706            node.operand = parseSimpleUnaryExpression();
3707
3708            return finishNode(node);
3709        }
3710
3711        function parseDeleteExpression() {
3712            const node = <DeleteExpression>createNode(SyntaxKind.DeleteExpression);
3713            nextToken();
3714            node.expression = parseSimpleUnaryExpression();
3715            return finishNode(node);
3716        }
3717
3718        function parseTypeOfExpression() {
3719            const node = <TypeOfExpression>createNode(SyntaxKind.TypeOfExpression);
3720            nextToken();
3721            node.expression = parseSimpleUnaryExpression();
3722            return finishNode(node);
3723        }
3724
3725        function parseVoidExpression() {
3726            const node = <VoidExpression>createNode(SyntaxKind.VoidExpression);
3727            nextToken();
3728            node.expression = parseSimpleUnaryExpression();
3729            return finishNode(node);
3730        }
3731
3732        function isAwaitExpression(): boolean {
3733            if (token() === SyntaxKind.AwaitKeyword) {
3734                if (inAwaitContext()) {
3735                    return true;
3736                }
3737
3738                // here we are using similar heuristics as 'isYieldExpression'
3739                return lookAhead(nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine);
3740            }
3741
3742            return false;
3743        }
3744
3745        function parseAwaitExpression() {
3746            const node = <AwaitExpression>createNode(SyntaxKind.AwaitExpression);
3747            nextToken();
3748            node.expression = parseSimpleUnaryExpression();
3749            return finishNode(node);
3750        }
3751
3752        /**
3753         * Parse ES7 exponential expression and await expression
3754         *
3755         * ES7 ExponentiationExpression:
3756         *      1) UnaryExpression[?Yield]
3757         *      2) UpdateExpression[?Yield] ** ExponentiationExpression[?Yield]
3758         *
3759         */
3760        function parseUnaryExpressionOrHigher(): UnaryExpression | BinaryExpression {
3761            /**
3762             * ES7 UpdateExpression:
3763             *      1) LeftHandSideExpression[?Yield]
3764             *      2) LeftHandSideExpression[?Yield][no LineTerminator here]++
3765             *      3) LeftHandSideExpression[?Yield][no LineTerminator here]--
3766             *      4) ++UnaryExpression[?Yield]
3767             *      5) --UnaryExpression[?Yield]
3768             */
3769            if (isUpdateExpression()) {
3770                const updateExpression = parseUpdateExpression();
3771                return token() === SyntaxKind.AsteriskAsteriskToken ?
3772                    <BinaryExpression>parseBinaryExpressionRest(getBinaryOperatorPrecedence(), updateExpression) :
3773                    updateExpression;
3774            }
3775
3776            /**
3777             * ES7 UnaryExpression:
3778             *      1) UpdateExpression[?yield]
3779             *      2) delete UpdateExpression[?yield]
3780             *      3) void UpdateExpression[?yield]
3781             *      4) typeof UpdateExpression[?yield]
3782             *      5) + UpdateExpression[?yield]
3783             *      6) - UpdateExpression[?yield]
3784             *      7) ~ UpdateExpression[?yield]
3785             *      8) ! UpdateExpression[?yield]
3786             */
3787            const unaryOperator = token();
3788            const simpleUnaryExpression = parseSimpleUnaryExpression();
3789            if (token() === SyntaxKind.AsteriskAsteriskToken) {
3790                const start = skipTrivia(sourceText, simpleUnaryExpression.pos);
3791                if (simpleUnaryExpression.kind === SyntaxKind.TypeAssertionExpression) {
3792                    parseErrorAtPosition(start, simpleUnaryExpression.end - start, Diagnostics.A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses);
3793                }
3794                else {
3795                    parseErrorAtPosition(start, simpleUnaryExpression.end - start, Diagnostics.An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses, tokenToString(unaryOperator));
3796                }
3797            }
3798            return simpleUnaryExpression;
3799        }
3800
3801        /**
3802         * Parse ES7 simple-unary expression or higher:
3803         *
3804         * ES7 UnaryExpression:
3805         *      1) UpdateExpression[?yield]
3806         *      2) delete UnaryExpression[?yield]
3807         *      3) void UnaryExpression[?yield]
3808         *      4) typeof UnaryExpression[?yield]
3809         *      5) + UnaryExpression[?yield]
3810         *      6) - UnaryExpression[?yield]
3811         *      7) ~ UnaryExpression[?yield]
3812         *      8) ! UnaryExpression[?yield]
3813         *      9) [+Await] await UnaryExpression[?yield]
3814         */
3815        function parseSimpleUnaryExpression(): UnaryExpression {
3816            switch (token()) {
3817                case SyntaxKind.PlusToken:
3818                case SyntaxKind.MinusToken:
3819                case SyntaxKind.TildeToken:
3820                case SyntaxKind.ExclamationToken:
3821                    return parsePrefixUnaryExpression();
3822                case SyntaxKind.DeleteKeyword:
3823                    return parseDeleteExpression();
3824                case SyntaxKind.TypeOfKeyword:
3825                    return parseTypeOfExpression();
3826                case SyntaxKind.VoidKeyword:
3827                    return parseVoidExpression();
3828                case SyntaxKind.LessThanToken:
3829                    // This is modified UnaryExpression grammar in TypeScript
3830                    //  UnaryExpression (modified):
3831                    //      < type > UnaryExpression
3832                    return parseTypeAssertion();
3833                case SyntaxKind.AwaitKeyword:
3834                    if (isAwaitExpression()) {
3835                        return parseAwaitExpression();
3836                    }
3837                    // falls through
3838                default:
3839                    return parseUpdateExpression();
3840            }
3841        }
3842
3843        /**
3844         * Check if the current token can possibly be an ES7 increment expression.
3845         *
3846         * ES7 UpdateExpression:
3847         *      LeftHandSideExpression[?Yield]
3848         *      LeftHandSideExpression[?Yield][no LineTerminator here]++
3849         *      LeftHandSideExpression[?Yield][no LineTerminator here]--
3850         *      ++LeftHandSideExpression[?Yield]
3851         *      --LeftHandSideExpression[?Yield]
3852         */
3853        function isUpdateExpression(): boolean {
3854            // This function is called inside parseUnaryExpression to decide
3855            // whether to call parseSimpleUnaryExpression or call parseUpdateExpression directly
3856            switch (token()) {
3857                case SyntaxKind.PlusToken:
3858                case SyntaxKind.MinusToken:
3859                case SyntaxKind.TildeToken:
3860                case SyntaxKind.ExclamationToken:
3861                case SyntaxKind.DeleteKeyword:
3862                case SyntaxKind.TypeOfKeyword:
3863                case SyntaxKind.VoidKeyword:
3864                case SyntaxKind.AwaitKeyword:
3865                    return false;
3866                case SyntaxKind.LessThanToken:
3867                    // If we are not in JSX context, we are parsing TypeAssertion which is an UnaryExpression
3868                    if (sourceFile.languageVariant !== LanguageVariant.JSX) {
3869                        return false;
3870                    }
3871                    // We are in JSX context and the token is part of JSXElement.
3872                    // falls through
3873                default:
3874                    return true;
3875            }
3876        }
3877
3878        /**
3879         * Parse ES7 UpdateExpression. UpdateExpression is used instead of ES6's PostFixExpression.
3880         *
3881         * ES7 UpdateExpression[yield]:
3882         *      1) LeftHandSideExpression[?yield]
3883         *      2) LeftHandSideExpression[?yield] [[no LineTerminator here]]++
3884         *      3) LeftHandSideExpression[?yield] [[no LineTerminator here]]--
3885         *      4) ++LeftHandSideExpression[?yield]
3886         *      5) --LeftHandSideExpression[?yield]
3887         * In TypeScript (2), (3) are parsed as PostfixUnaryExpression. (4), (5) are parsed as PrefixUnaryExpression
3888         */
3889        function parseUpdateExpression(): UpdateExpression {
3890            if (token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) {
3891                const node = <PrefixUnaryExpression>createNode(SyntaxKind.PrefixUnaryExpression);
3892                node.operator = <PrefixUnaryOperator>token();
3893                nextToken();
3894                node.operand = parseLeftHandSideExpressionOrHigher();
3895                return finishNode(node);
3896            }
3897            else if (sourceFile.languageVariant === LanguageVariant.JSX && token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) {
3898                // JSXElement is part of primaryExpression
3899                return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true);
3900            }
3901
3902            const expression = parseLeftHandSideExpressionOrHigher();
3903
3904            Debug.assert(isLeftHandSideExpression(expression));
3905            if ((token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) && !scanner.hasPrecedingLineBreak()) {
3906                const node = <PostfixUnaryExpression>createNode(SyntaxKind.PostfixUnaryExpression, expression.pos);
3907                node.operand = expression;
3908                node.operator = <PostfixUnaryOperator>token();
3909                nextToken();
3910                return finishNode(node);
3911            }
3912
3913            return expression;
3914        }
3915
3916        function parseLeftHandSideExpressionOrHigher(): LeftHandSideExpression {
3917            // Original Ecma:
3918            // LeftHandSideExpression: See 11.2
3919            //      NewExpression
3920            //      CallExpression
3921            //
3922            // Our simplification:
3923            //
3924            // LeftHandSideExpression: See 11.2
3925            //      MemberExpression
3926            //      CallExpression
3927            //
3928            // See comment in parseMemberExpressionOrHigher on how we replaced NewExpression with
3929            // MemberExpression to make our lives easier.
3930            //
3931            // to best understand the below code, it's important to see how CallExpression expands
3932            // out into its own productions:
3933            //
3934            // CallExpression:
3935            //      MemberExpression Arguments
3936            //      CallExpression Arguments
3937            //      CallExpression[Expression]
3938            //      CallExpression.IdentifierName
3939            //      import (AssignmentExpression)
3940            //      super Arguments
3941            //      super.IdentifierName
3942            //
3943            // Because of the recursion in these calls, we need to bottom out first. There are three
3944            // bottom out states we can run into: 1) We see 'super' which must start either of
3945            // the last two CallExpression productions. 2) We see 'import' which must start import call.
3946            // 3)we have a MemberExpression which either completes the LeftHandSideExpression,
3947            // or starts the beginning of the first four CallExpression productions.
3948            let expression: MemberExpression;
3949            if (token() === SyntaxKind.ImportKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) {
3950                // We don't want to eagerly consume all import keyword as import call expression so we look a head to find "("
3951                // For example:
3952                //      var foo3 = require("subfolder
3953                //      import * as foo1 from "module-from-node
3954                // We want this import to be a statement rather than import call expression
3955                sourceFile.flags |= NodeFlags.PossiblyContainsDynamicImport;
3956                expression = parseTokenNode<PrimaryExpression>();
3957            }
3958            else {
3959                expression = token() === SyntaxKind.SuperKeyword ? parseSuperExpression() : parseMemberExpressionOrHigher();
3960            }
3961
3962            // Now, we *may* be complete.  However, we might have consumed the start of a
3963            // CallExpression.  As such, we need to consume the rest of it here to be complete.
3964            return parseCallExpressionRest(expression);
3965        }
3966
3967        function parseMemberExpressionOrHigher(): MemberExpression {
3968            // Note: to make our lives simpler, we decompose the NewExpression productions and
3969            // place ObjectCreationExpression and FunctionExpression into PrimaryExpression.
3970            // like so:
3971            //
3972            //   PrimaryExpression : See 11.1
3973            //      this
3974            //      Identifier
3975            //      Literal
3976            //      ArrayLiteral
3977            //      ObjectLiteral
3978            //      (Expression)
3979            //      FunctionExpression
3980            //      new MemberExpression Arguments?
3981            //
3982            //   MemberExpression : See 11.2
3983            //      PrimaryExpression
3984            //      MemberExpression[Expression]
3985            //      MemberExpression.IdentifierName
3986            //
3987            //   CallExpression : See 11.2
3988            //      MemberExpression
3989            //      CallExpression Arguments
3990            //      CallExpression[Expression]
3991            //      CallExpression.IdentifierName
3992            //
3993            // Technically this is ambiguous.  i.e. CallExpression defines:
3994            //
3995            //   CallExpression:
3996            //      CallExpression Arguments
3997            //
3998            // If you see: "new Foo()"
3999            //
4000            // Then that could be treated as a single ObjectCreationExpression, or it could be
4001            // treated as the invocation of "new Foo".  We disambiguate that in code (to match
4002            // the original grammar) by making sure that if we see an ObjectCreationExpression
4003            // we always consume arguments if they are there. So we treat "new Foo()" as an
4004            // object creation only, and not at all as an invocation.  Another way to think
4005            // about this is that for every "new" that we see, we will consume an argument list if
4006            // it is there as part of the *associated* object creation node.  Any additional
4007            // argument lists we see, will become invocation expressions.
4008            //
4009            // Because there are no other places in the grammar now that refer to FunctionExpression
4010            // or ObjectCreationExpression, it is safe to push down into the PrimaryExpression
4011            // production.
4012            //
4013            // Because CallExpression and MemberExpression are left recursive, we need to bottom out
4014            // of the recursion immediately.  So we parse out a primary expression to start with.
4015            const expression = parsePrimaryExpression();
4016            return parseMemberExpressionRest(expression);
4017        }
4018
4019        function parseSuperExpression(): MemberExpression {
4020            const expression = parseTokenNode<PrimaryExpression>();
4021            if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.DotToken || token() === SyntaxKind.OpenBracketToken) {
4022                return expression;
4023            }
4024
4025            // If we have seen "super" it must be followed by '(' or '.'.
4026            // If it wasn't then just try to parse out a '.' and report an error.
4027            const node = <PropertyAccessExpression>createNode(SyntaxKind.PropertyAccessExpression, expression.pos);
4028            node.expression = expression;
4029            parseExpectedToken(SyntaxKind.DotToken, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access);
4030            node.name = parseRightSideOfDot(/*allowIdentifierNames*/ true);
4031            return finishNode(node);
4032        }
4033
4034        function tagNamesAreEquivalent(lhs: JsxTagNameExpression, rhs: JsxTagNameExpression): boolean {
4035            if (lhs.kind !== rhs.kind) {
4036                return false;
4037            }
4038
4039            if (lhs.kind === SyntaxKind.Identifier) {
4040                return (<Identifier>lhs).escapedText === (<Identifier>rhs).escapedText;
4041            }
4042
4043            if (lhs.kind === SyntaxKind.ThisKeyword) {
4044                return true;
4045            }
4046
4047            // If we are at this statement then we must have PropertyAccessExpression and because tag name in Jsx element can only
4048            // take forms of JsxTagNameExpression which includes an identifier, "this" expression, or another propertyAccessExpression
4049            // it is safe to case the expression property as such. See parseJsxElementName for how we parse tag name in Jsx element
4050            return (<PropertyAccessExpression>lhs).name.escapedText === (<PropertyAccessExpression>rhs).name.escapedText &&
4051                tagNamesAreEquivalent((<PropertyAccessExpression>lhs).expression as JsxTagNameExpression, (<PropertyAccessExpression>rhs).expression as JsxTagNameExpression);
4052        }
4053
4054
4055        function parseJsxElementOrSelfClosingElementOrFragment(inExpressionContext: boolean): JsxElement | JsxSelfClosingElement | JsxFragment {
4056            const opening = parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext);
4057            let result: JsxElement | JsxSelfClosingElement | JsxFragment;
4058            if (opening.kind === SyntaxKind.JsxOpeningElement) {
4059                const node = <JsxElement>createNode(SyntaxKind.JsxElement, opening.pos);
4060                node.openingElement = opening;
4061
4062                node.children = parseJsxChildren(node.openingElement);
4063                node.closingElement = parseJsxClosingElement(inExpressionContext);
4064
4065                if (!tagNamesAreEquivalent(node.openingElement.tagName, node.closingElement.tagName)) {
4066                    parseErrorAtPosition(node.closingElement.pos, node.closingElement.end - node.closingElement.pos, Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, getTextOfNodeFromSourceText(sourceText, node.openingElement.tagName));
4067                }
4068
4069                result = finishNode(node);
4070            }
4071            else if (opening.kind === SyntaxKind.JsxOpeningFragment) {
4072                const node = <JsxFragment>createNode(SyntaxKind.JsxFragment, opening.pos);
4073                node.openingFragment = opening;
4074                node.children = parseJsxChildren(node.openingFragment);
4075                node.closingFragment = parseJsxClosingFragment(inExpressionContext);
4076
4077                result = finishNode(node);
4078            }
4079            else {
4080                Debug.assert(opening.kind === SyntaxKind.JsxSelfClosingElement);
4081                // Nothing else to do for self-closing elements
4082                result = <JsxSelfClosingElement>opening;
4083            }
4084
4085            // If the user writes the invalid code '<div></div><div></div>' in an expression context (i.e. not wrapped in
4086            // an enclosing tag), we'll naively try to parse   ^ this as a 'less than' operator and the remainder of the tag
4087            // as garbage, which will cause the formatter to badly mangle the JSX. Perform a speculative parse of a JSX
4088            // element if we see a < token so that we can wrap it in a synthetic binary expression so the formatter
4089            // does less damage and we can report a better error.
4090            // Since JSX elements are invalid < operands anyway, this lookahead parse will only occur in error scenarios
4091            // of one sort or another.
4092            if (inExpressionContext && token() === SyntaxKind.LessThanToken) {
4093                const invalidElement = tryParse(() => parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true));
4094                if (invalidElement) {
4095                    parseErrorAtCurrentToken(Diagnostics.JSX_expressions_must_have_one_parent_element);
4096                    const badNode = <BinaryExpression>createNode(SyntaxKind.BinaryExpression, result.pos);
4097                    badNode.end = invalidElement.end;
4098                    badNode.left = result;
4099                    badNode.right = invalidElement;
4100                    badNode.operatorToken = <BinaryOperatorToken>createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false, /*diagnosticMessage*/ undefined);
4101                    badNode.operatorToken.pos = badNode.operatorToken.end = badNode.right.pos;
4102                    return <JsxElement><Node>badNode;
4103                }
4104            }
4105
4106            return result;
4107        }
4108
4109        function parseJsxText(): JsxText {
4110            const node = <JsxText>createNode(SyntaxKind.JsxText);
4111            node.containsOnlyWhiteSpaces = currentToken === SyntaxKind.JsxTextAllWhiteSpaces;
4112            currentToken = scanner.scanJsxToken();
4113            return finishNode(node);
4114        }
4115
4116        function parseJsxChild(): JsxChild {
4117            switch (token()) {
4118                case SyntaxKind.JsxText:
4119                case SyntaxKind.JsxTextAllWhiteSpaces:
4120                    return parseJsxText();
4121                case SyntaxKind.OpenBraceToken:
4122                    return parseJsxExpression(/*inExpressionContext*/ false);
4123                case SyntaxKind.LessThanToken:
4124                    return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ false);
4125            }
4126            Debug.fail("Unknown JSX child kind " + token());
4127        }
4128
4129        function parseJsxChildren(openingTag: JsxOpeningElement | JsxOpeningFragment): NodeArray<JsxChild> {
4130            const list = [];
4131            const listPos = getNodePos();
4132            const saveParsingContext = parsingContext;
4133            parsingContext |= 1 << ParsingContext.JsxChildren;
4134
4135            while (true) {
4136                currentToken = scanner.reScanJsxToken();
4137                if (token() === SyntaxKind.LessThanSlashToken) {
4138                    // Closing tag
4139                    break;
4140                }
4141                else if (token() === SyntaxKind.EndOfFileToken) {
4142                    // If we hit EOF, issue the error at the tag that lacks the closing element
4143                    // rather than at the end of the file (which is useless)
4144                    if (isJsxOpeningFragment(openingTag)) {
4145                        parseErrorAtPosition(openingTag.pos, openingTag.end - openingTag.pos, Diagnostics.JSX_fragment_has_no_corresponding_closing_tag);
4146                    }
4147                    else {
4148                        const openingTagName = openingTag.tagName;
4149                        parseErrorAtPosition(openingTagName.pos, openingTagName.end - openingTagName.pos, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTagName));
4150                    }
4151                    break;
4152                }
4153                else if (token() === SyntaxKind.ConflictMarkerTrivia) {
4154                    break;
4155                }
4156                const child = parseJsxChild();
4157                if (child) {
4158                    list.push(child);
4159                }
4160            }
4161
4162            parsingContext = saveParsingContext;
4163
4164            return createNodeArray(list, listPos);
4165        }
4166
4167        function parseJsxAttributes(): JsxAttributes {
4168            const jsxAttributes = <JsxAttributes>createNode(SyntaxKind.JsxAttributes);
4169            jsxAttributes.properties = parseList(ParsingContext.JsxAttributes, parseJsxAttribute);
4170            return finishNode(jsxAttributes);
4171        }
4172
4173        function parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext: boolean): JsxOpeningElement | JsxSelfClosingElement | JsxOpeningFragment {
4174            const fullStart = scanner.getStartPos();
4175
4176            parseExpected(SyntaxKind.LessThanToken);
4177
4178            if (token() === SyntaxKind.GreaterThanToken) {
4179                parseExpected(SyntaxKind.GreaterThanToken);
4180                const node: JsxOpeningFragment = <JsxOpeningFragment>createNode(SyntaxKind.JsxOpeningFragment, fullStart);
4181                return finishNode(node);
4182            }
4183
4184            const tagName = parseJsxElementName();
4185            const attributes = parseJsxAttributes();
4186
4187            let node: JsxOpeningLikeElement;
4188
4189            if (token() === SyntaxKind.GreaterThanToken) {
4190                // Closing tag, so scan the immediately-following text with the JSX scanning instead
4191                // of regular scanning to avoid treating illegal characters (e.g. '#') as immediate
4192                // scanning errors
4193                node = <JsxOpeningElement>createNode(SyntaxKind.JsxOpeningElement, fullStart);
4194                scanJsxText();
4195            }
4196            else {
4197                parseExpected(SyntaxKind.SlashToken);
4198                if (inExpressionContext) {
4199                    parseExpected(SyntaxKind.GreaterThanToken);
4200                }
4201                else {
4202                    parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false);
4203                    scanJsxText();
4204                }
4205                node = <JsxSelfClosingElement>createNode(SyntaxKind.JsxSelfClosingElement, fullStart);
4206            }
4207
4208            node.tagName = tagName;
4209            node.attributes = attributes;
4210
4211            return finishNode(node);
4212        }
4213
4214        function parseJsxElementName(): JsxTagNameExpression {
4215            scanJsxIdentifier();
4216            // JsxElement can have name in the form of
4217            //      propertyAccessExpression
4218            //      primaryExpression in the form of an identifier and "this" keyword
4219            // We can't just simply use parseLeftHandSideExpressionOrHigher because then we will start consider class,function etc as a keyword
4220            // We only want to consider "this" as a primaryExpression
4221            let expression: JsxTagNameExpression = token() === SyntaxKind.ThisKeyword ?
4222                parseTokenNode<PrimaryExpression>() : parseIdentifierName();
4223            while (parseOptional(SyntaxKind.DotToken)) {
4224                const propertyAccess: PropertyAccessExpression = <PropertyAccessExpression>createNode(SyntaxKind.PropertyAccessExpression, expression.pos);
4225                propertyAccess.expression = expression;
4226                propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true);
4227                expression = finishNode(propertyAccess);
4228            }
4229            return expression;
4230        }
4231
4232        function parseJsxExpression(inExpressionContext: boolean): JsxExpression {
4233            const node = <JsxExpression>createNode(SyntaxKind.JsxExpression);
4234
4235            parseExpected(SyntaxKind.OpenBraceToken);
4236            if (token() !== SyntaxKind.CloseBraceToken) {
4237                node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
4238                node.expression = parseAssignmentExpressionOrHigher();
4239            }
4240            if (inExpressionContext) {
4241                parseExpected(SyntaxKind.CloseBraceToken);
4242            }
4243            else {
4244                parseExpected(SyntaxKind.CloseBraceToken, /*message*/ undefined, /*shouldAdvance*/ false);
4245                scanJsxText();
4246            }
4247
4248            return finishNode(node);
4249        }
4250
4251        function parseJsxAttribute(): JsxAttribute | JsxSpreadAttribute {
4252            if (token() === SyntaxKind.OpenBraceToken) {
4253                return parseJsxSpreadAttribute();
4254            }
4255
4256            scanJsxIdentifier();
4257            const node = <JsxAttribute>createNode(SyntaxKind.JsxAttribute);
4258            node.name = parseIdentifierName();
4259            if (token() === SyntaxKind.EqualsToken) {
4260                switch (scanJsxAttributeValue()) {
4261                    case SyntaxKind.StringLiteral:
4262                        node.initializer = <StringLiteral>parseLiteralNode();
4263                        break;
4264                    default:
4265                        node.initializer = parseJsxExpression(/*inExpressionContext*/ true);
4266                        break;
4267                }
4268            }
4269            return finishNode(node);
4270        }
4271
4272        function parseJsxSpreadAttribute(): JsxSpreadAttribute {
4273            const node = <JsxSpreadAttribute>createNode(SyntaxKind.JsxSpreadAttribute);
4274            parseExpected(SyntaxKind.OpenBraceToken);
4275            parseExpected(SyntaxKind.DotDotDotToken);
4276            node.expression = parseExpression();
4277            parseExpected(SyntaxKind.CloseBraceToken);
4278            return finishNode(node);
4279        }
4280
4281        function parseJsxClosingElement(inExpressionContext: boolean): JsxClosingElement {
4282            const node = <JsxClosingElement>createNode(SyntaxKind.JsxClosingElement);
4283            parseExpected(SyntaxKind.LessThanSlashToken);
4284            node.tagName = parseJsxElementName();
4285            if (inExpressionContext) {
4286                parseExpected(SyntaxKind.GreaterThanToken);
4287            }
4288            else {
4289                parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false);
4290                scanJsxText();
4291            }
4292            return finishNode(node);
4293        }
4294
4295        function parseJsxClosingFragment(inExpressionContext: boolean): JsxClosingFragment {
4296            const node = <JsxClosingFragment>createNode(SyntaxKind.JsxClosingFragment);
4297            parseExpected(SyntaxKind.LessThanSlashToken);
4298            if (tokenIsIdentifierOrKeyword(token())) {
4299                const unexpectedTagName = parseJsxElementName();
4300                parseErrorAtPosition(unexpectedTagName.pos, unexpectedTagName.end - unexpectedTagName.pos, Diagnostics.Expected_corresponding_closing_tag_for_JSX_fragment);
4301            }
4302            if (inExpressionContext) {
4303                parseExpected(SyntaxKind.GreaterThanToken);
4304            }
4305            else {
4306                parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false);
4307                scanJsxText();
4308            }
4309            return finishNode(node);
4310        }
4311
4312        function parseTypeAssertion(): TypeAssertion {
4313            const node = <TypeAssertion>createNode(SyntaxKind.TypeAssertionExpression);
4314            parseExpected(SyntaxKind.LessThanToken);
4315            node.type = parseType();
4316            parseExpected(SyntaxKind.GreaterThanToken);
4317            node.expression = parseSimpleUnaryExpression();
4318            return finishNode(node);
4319        }
4320
4321        function parseMemberExpressionRest(expression: LeftHandSideExpression): MemberExpression {
4322            while (true) {
4323                const dotToken = parseOptionalToken(SyntaxKind.DotToken);
4324                if (dotToken) {
4325                    const propertyAccess = <PropertyAccessExpression>createNode(SyntaxKind.PropertyAccessExpression, expression.pos);
4326                    propertyAccess.expression = expression;
4327                    propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true);
4328                    expression = finishNode(propertyAccess);
4329                    continue;
4330                }
4331
4332                if (token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
4333                    nextToken();
4334                    const nonNullExpression = <NonNullExpression>createNode(SyntaxKind.NonNullExpression, expression.pos);
4335                    nonNullExpression.expression = expression;
4336                    expression = finishNode(nonNullExpression);
4337                    continue;
4338                }
4339
4340                // when in the [Decorator] context, we do not parse ElementAccess as it could be part of a ComputedPropertyName
4341                if (!inDecoratorContext() && parseOptional(SyntaxKind.OpenBracketToken)) {
4342                    const indexedAccess = <ElementAccessExpression>createNode(SyntaxKind.ElementAccessExpression, expression.pos);
4343                    indexedAccess.expression = expression;
4344
4345                    // It's not uncommon for a user to write: "new Type[]".
4346                    // Check for that common pattern and report a better error message.
4347                    if (token() !== SyntaxKind.CloseBracketToken) {
4348                        indexedAccess.argumentExpression = allowInAnd(parseExpression);
4349                        if (indexedAccess.argumentExpression.kind === SyntaxKind.StringLiteral || indexedAccess.argumentExpression.kind === SyntaxKind.NumericLiteral) {
4350                            const literal = <LiteralExpression>indexedAccess.argumentExpression;
4351                            literal.text = internIdentifier(literal.text);
4352                        }
4353                    }
4354
4355                    parseExpected(SyntaxKind.CloseBracketToken);
4356                    expression = finishNode(indexedAccess);
4357                    continue;
4358                }
4359
4360                if (token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead) {
4361                    const tagExpression = <TaggedTemplateExpression>createNode(SyntaxKind.TaggedTemplateExpression, expression.pos);
4362                    tagExpression.tag = expression;
4363                    tagExpression.template = token() === SyntaxKind.NoSubstitutionTemplateLiteral
4364                        ? <NoSubstitutionTemplateLiteral>parseLiteralNode()
4365                        : parseTemplateExpression();
4366                    expression = finishNode(tagExpression);
4367                    continue;
4368                }
4369
4370                return <MemberExpression>expression;
4371            }
4372        }
4373
4374        function parseCallExpressionRest(expression: LeftHandSideExpression): LeftHandSideExpression {
4375            while (true) {
4376                expression = parseMemberExpressionRest(expression);
4377                if (token() === SyntaxKind.LessThanToken) {
4378                    // See if this is the start of a generic invocation.  If so, consume it and
4379                    // keep checking for postfix expressions.  Otherwise, it's just a '<' that's
4380                    // part of an arithmetic expression.  Break out so we consume it higher in the
4381                    // stack.
4382                    const typeArguments = tryParse(parseTypeArgumentsInExpression);
4383                    if (!typeArguments) {
4384                        return expression;
4385                    }
4386
4387                    const callExpr = <CallExpression>createNode(SyntaxKind.CallExpression, expression.pos);
4388                    callExpr.expression = expression;
4389                    callExpr.typeArguments = typeArguments;
4390                    callExpr.arguments = parseArgumentList();
4391                    expression = finishNode(callExpr);
4392                    continue;
4393                }
4394                else if (token() === SyntaxKind.OpenParenToken) {
4395                    const callExpr = <CallExpression>createNode(SyntaxKind.CallExpression, expression.pos);
4396                    callExpr.expression = expression;
4397                    callExpr.arguments = parseArgumentList();
4398                    expression = finishNode(callExpr);
4399                    continue;
4400                }
4401
4402                return expression;
4403            }
4404        }
4405
4406        function parseArgumentList() {
4407            parseExpected(SyntaxKind.OpenParenToken);
4408            const result = parseDelimitedList(ParsingContext.ArgumentExpressions, parseArgumentExpression);
4409            parseExpected(SyntaxKind.CloseParenToken);
4410            return result;
4411        }
4412
4413        function parseTypeArgumentsInExpression() {
4414            if (!parseOptional(SyntaxKind.LessThanToken)) {
4415                return undefined;
4416            }
4417
4418            const typeArguments = parseDelimitedList(ParsingContext.TypeArguments, parseType);
4419            if (!parseExpected(SyntaxKind.GreaterThanToken)) {
4420                // If it doesn't have the closing `>` then it's definitely not an type argument list.
4421                return undefined;
4422            }
4423
4424            // If we have a '<', then only parse this as a argument list if the type arguments
4425            // are complete and we have an open paren.  if we don't, rewind and return nothing.
4426            return typeArguments && canFollowTypeArgumentsInExpression()
4427                ? typeArguments
4428                : undefined;
4429        }
4430
4431        function canFollowTypeArgumentsInExpression(): boolean {
4432            switch (token()) {
4433                case SyntaxKind.OpenParenToken:                 // foo<x>(
4434                // this case are the only case where this token can legally follow a type argument
4435                // list.  So we definitely want to treat this as a type arg list.
4436
4437                case SyntaxKind.DotToken:                       // foo<x>.
4438                case SyntaxKind.CloseParenToken:                // foo<x>)
4439                case SyntaxKind.CloseBracketToken:              // foo<x>]
4440                case SyntaxKind.ColonToken:                     // foo<x>:
4441                case SyntaxKind.SemicolonToken:                 // foo<x>;
4442                case SyntaxKind.QuestionToken:                  // foo<x>?
4443                case SyntaxKind.EqualsEqualsToken:              // foo<x> ==
4444                case SyntaxKind.EqualsEqualsEqualsToken:        // foo<x> ===
4445                case SyntaxKind.ExclamationEqualsToken:         // foo<x> !=
4446                case SyntaxKind.ExclamationEqualsEqualsToken:   // foo<x> !==
4447                case SyntaxKind.AmpersandAmpersandToken:        // foo<x> &&
4448                case SyntaxKind.BarBarToken:                    // foo<x> ||
4449                case SyntaxKind.CaretToken:                     // foo<x> ^
4450                case SyntaxKind.AmpersandToken:                 // foo<x> &
4451                case SyntaxKind.BarToken:                       // foo<x> |
4452                case SyntaxKind.CloseBraceToken:                // foo<x> }
4453                case SyntaxKind.EndOfFileToken:                 // foo<x>
4454                    // these cases can't legally follow a type arg list.  However, they're not legal
4455                    // expressions either.  The user is probably in the middle of a generic type. So
4456                    // treat it as such.
4457                    return true;
4458
4459                case SyntaxKind.CommaToken:                     // foo<x>,
4460                case SyntaxKind.OpenBraceToken:                 // foo<x> {
4461                // We don't want to treat these as type arguments.  Otherwise we'll parse this
4462                // as an invocation expression.  Instead, we want to parse out the expression
4463                // in isolation from the type arguments.
4464
4465                default:
4466                    // Anything else treat as an expression.
4467                    return false;
4468            }
4469        }
4470
4471        function parsePrimaryExpression(): PrimaryExpression {
4472            switch (token()) {
4473                case SyntaxKind.NumericLiteral:
4474                case SyntaxKind.StringLiteral:
4475                case SyntaxKind.NoSubstitutionTemplateLiteral:
4476                    return parseLiteralNode();
4477                case SyntaxKind.ThisKeyword:
4478                case SyntaxKind.SuperKeyword:
4479                case SyntaxKind.NullKeyword:
4480                case SyntaxKind.TrueKeyword:
4481                case SyntaxKind.FalseKeyword:
4482                    return parseTokenNode<PrimaryExpression>();
4483                case SyntaxKind.OpenParenToken:
4484                    return parseParenthesizedExpression();
4485                case SyntaxKind.OpenBracketToken:
4486                    return parseArrayLiteralExpression();
4487                case SyntaxKind.OpenBraceToken:
4488                    return parseObjectLiteralExpression();
4489                case SyntaxKind.AsyncKeyword:
4490                    // Async arrow functions are parsed earlier in parseAssignmentExpressionOrHigher.
4491                    // If we encounter `async [no LineTerminator here] function` then this is an async
4492                    // function; otherwise, its an identifier.
4493                    if (!lookAhead(nextTokenIsFunctionKeywordOnSameLine)) {
4494                        break;
4495                    }
4496
4497                    return parseFunctionExpression();
4498                case SyntaxKind.ClassKeyword:
4499                    return parseClassExpression();
4500                case SyntaxKind.FunctionKeyword:
4501                    return parseFunctionExpression();
4502                case SyntaxKind.NewKeyword:
4503                    return parseNewExpression();
4504                case SyntaxKind.SlashToken:
4505                case SyntaxKind.SlashEqualsToken:
4506                    if (reScanSlashToken() === SyntaxKind.RegularExpressionLiteral) {
4507                        return parseLiteralNode();
4508                    }
4509                    break;
4510                case SyntaxKind.TemplateHead:
4511                    return parseTemplateExpression();
4512            }
4513
4514            return parseIdentifier(Diagnostics.Expression_expected);
4515        }
4516
4517        function parseParenthesizedExpression(): ParenthesizedExpression {
4518            const node = <ParenthesizedExpression>createNodeWithJSDoc(SyntaxKind.ParenthesizedExpression);
4519            parseExpected(SyntaxKind.OpenParenToken);
4520            node.expression = allowInAnd(parseExpression);
4521            parseExpected(SyntaxKind.CloseParenToken);
4522            return finishNode(node);
4523        }
4524
4525        function parseSpreadElement(): Expression {
4526            const node = <SpreadElement>createNode(SyntaxKind.SpreadElement);
4527            parseExpected(SyntaxKind.DotDotDotToken);
4528            node.expression = parseAssignmentExpressionOrHigher();
4529            return finishNode(node);
4530        }
4531
4532        function parseArgumentOrArrayLiteralElement(): Expression {
4533            return token() === SyntaxKind.DotDotDotToken ? parseSpreadElement() :
4534                token() === SyntaxKind.CommaToken ? <Expression>createNode(SyntaxKind.OmittedExpression) :
4535                    parseAssignmentExpressionOrHigher();
4536        }
4537
4538        function parseArgumentExpression(): Expression {
4539            return doOutsideOfContext(disallowInAndDecoratorContext, parseArgumentOrArrayLiteralElement);
4540        }
4541
4542        function parseArrayLiteralExpression(): ArrayLiteralExpression {
4543            const node = <ArrayLiteralExpression>createNode(SyntaxKind.ArrayLiteralExpression);
4544            parseExpected(SyntaxKind.OpenBracketToken);
4545            if (scanner.hasPrecedingLineBreak()) {
4546                node.multiLine = true;
4547            }
4548            node.elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers, parseArgumentOrArrayLiteralElement);
4549            parseExpected(SyntaxKind.CloseBracketToken);
4550            return finishNode(node);
4551        }
4552
4553        function parseObjectLiteralElement(): ObjectLiteralElementLike {
4554            const node = <ObjectLiteralElementLike>createNodeWithJSDoc(SyntaxKind.Unknown);
4555
4556            if (parseOptionalToken(SyntaxKind.DotDotDotToken)) {
4557                node.kind = SyntaxKind.SpreadAssignment;
4558                (<SpreadAssignment>node).expression = parseAssignmentExpressionOrHigher();
4559                return finishNode(node);
4560            }
4561
4562            node.decorators = parseDecorators();
4563            node.modifiers = parseModifiers();
4564
4565            if (parseContextualModifier(SyntaxKind.GetKeyword)) {
4566                return parseAccessorDeclaration(<AccessorDeclaration>node, SyntaxKind.GetAccessor);
4567            }
4568            if (parseContextualModifier(SyntaxKind.SetKeyword)) {
4569                return parseAccessorDeclaration(<AccessorDeclaration>node, SyntaxKind.SetAccessor);
4570            }
4571
4572            const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
4573            const tokenIsIdentifier = isIdentifier();
4574            node.name = parsePropertyName();
4575            // Disallowing of optional property assignments happens in the grammar checker.
4576            (<MethodDeclaration>node).questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
4577            if (asteriskToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
4578                return parseMethodDeclaration(<MethodDeclaration>node, asteriskToken);
4579            }
4580
4581            // check if it is short-hand property assignment or normal property assignment
4582            // NOTE: if token is EqualsToken it is interpreted as CoverInitializedName production
4583            // CoverInitializedName[Yield] :
4584            //     IdentifierReference[?Yield] Initializer[In, ?Yield]
4585            // this is necessary because ObjectLiteral productions are also used to cover grammar for ObjectAssignmentPattern
4586            const isShorthandPropertyAssignment =
4587                tokenIsIdentifier && (token() === SyntaxKind.CommaToken || token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.EqualsToken);
4588            if (isShorthandPropertyAssignment) {
4589                node.kind = SyntaxKind.ShorthandPropertyAssignment;
4590                const equalsToken = parseOptionalToken(SyntaxKind.EqualsToken);
4591                if (equalsToken) {
4592                    (<ShorthandPropertyAssignment>node).equalsToken = equalsToken;
4593                    (<ShorthandPropertyAssignment>node).objectAssignmentInitializer = allowInAnd(parseAssignmentExpressionOrHigher);
4594                }
4595            }
4596            else {
4597                node.kind = SyntaxKind.PropertyAssignment;
4598                parseExpected(SyntaxKind.ColonToken);
4599                (<PropertyAssignment>node).initializer = allowInAnd(parseAssignmentExpressionOrHigher);
4600            }
4601            return finishNode(node);
4602        }
4603
4604        function parseObjectLiteralExpression(): ObjectLiteralExpression {
4605            const node = <ObjectLiteralExpression>createNode(SyntaxKind.ObjectLiteralExpression);
4606            parseExpected(SyntaxKind.OpenBraceToken);
4607            if (scanner.hasPrecedingLineBreak()) {
4608                node.multiLine = true;
4609            }
4610
4611            node.properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralElement, /*considerSemicolonAsDelimiter*/ true);
4612            parseExpected(SyntaxKind.CloseBraceToken);
4613            return finishNode(node);
4614        }
4615
4616        function parseFunctionExpression(): FunctionExpression {
4617            // GeneratorExpression:
4618            //      function* BindingIdentifier [Yield][opt](FormalParameters[Yield]){ GeneratorBody }
4619            //
4620            // FunctionExpression:
4621            //      function BindingIdentifier[opt](FormalParameters){ FunctionBody }
4622            const saveDecoratorContext = inDecoratorContext();
4623            if (saveDecoratorContext) {
4624                setDecoratorContext(/*val*/ false);
4625            }
4626
4627            const node = <FunctionExpression>createNodeWithJSDoc(SyntaxKind.FunctionExpression);
4628            node.modifiers = parseModifiers();
4629            parseExpected(SyntaxKind.FunctionKeyword);
4630            node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
4631
4632            const isGenerator = node.asteriskToken ? SignatureFlags.Yield : SignatureFlags.None;
4633            const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None;
4634            node.name =
4635                isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalIdentifier) :
4636                    isGenerator ? doInYieldContext(parseOptionalIdentifier) :
4637                        isAsync ? doInAwaitContext(parseOptionalIdentifier) :
4638                            parseOptionalIdentifier();
4639
4640            fillSignature(SyntaxKind.ColonToken, isGenerator | isAsync, node);
4641            node.body = parseFunctionBlock(isGenerator | isAsync);
4642
4643            if (saveDecoratorContext) {
4644                setDecoratorContext(/*val*/ true);
4645            }
4646
4647            return finishNode(node);
4648        }
4649
4650        function parseOptionalIdentifier(): Identifier | undefined {
4651            return isIdentifier() ? parseIdentifier() : undefined;
4652        }
4653
4654        function parseNewExpression(): NewExpression | MetaProperty {
4655            const fullStart = scanner.getStartPos();
4656            parseExpected(SyntaxKind.NewKeyword);
4657            if (parseOptional(SyntaxKind.DotToken)) {
4658                const node = <MetaProperty>createNode(SyntaxKind.MetaProperty, fullStart);
4659                node.keywordToken = SyntaxKind.NewKeyword;
4660                node.name = parseIdentifierName();
4661                return finishNode(node);
4662            }
4663
4664            const node = <NewExpression>createNode(SyntaxKind.NewExpression, fullStart);
4665            node.expression = parseMemberExpressionOrHigher();
4666            node.typeArguments = tryParse(parseTypeArgumentsInExpression);
4667            if (node.typeArguments || token() === SyntaxKind.OpenParenToken) {
4668                node.arguments = parseArgumentList();
4669            }
4670            return finishNode(node);
4671        }
4672
4673        // STATEMENTS
4674        function parseBlock(ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): Block {
4675            const node = <Block>createNode(SyntaxKind.Block);
4676            if (parseExpected(SyntaxKind.OpenBraceToken, diagnosticMessage) || ignoreMissingOpenBrace) {
4677                if (scanner.hasPrecedingLineBreak()) {
4678                    node.multiLine = true;
4679                }
4680
4681                node.statements = parseList(ParsingContext.BlockStatements, parseStatement);
4682                parseExpected(SyntaxKind.CloseBraceToken);
4683            }
4684            else {
4685                node.statements = createMissingList<Statement>();
4686            }
4687            return finishNode(node);
4688        }
4689
4690        function parseFunctionBlock(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block {
4691            const savedYieldContext = inYieldContext();
4692            setYieldContext(!!(flags & SignatureFlags.Yield));
4693
4694            const savedAwaitContext = inAwaitContext();
4695            setAwaitContext(!!(flags & SignatureFlags.Await));
4696
4697            // We may be in a [Decorator] context when parsing a function expression or
4698            // arrow function. The body of the function is not in [Decorator] context.
4699            const saveDecoratorContext = inDecoratorContext();
4700            if (saveDecoratorContext) {
4701                setDecoratorContext(/*val*/ false);
4702            }
4703
4704            const block = parseBlock(!!(flags & SignatureFlags.IgnoreMissingOpenBrace), diagnosticMessage);
4705
4706            if (saveDecoratorContext) {
4707                setDecoratorContext(/*val*/ true);
4708            }
4709
4710            setYieldContext(savedYieldContext);
4711            setAwaitContext(savedAwaitContext);
4712
4713            return block;
4714        }
4715
4716        function parseEmptyStatement(): Statement {
4717            const node = <Statement>createNode(SyntaxKind.EmptyStatement);
4718            parseExpected(SyntaxKind.SemicolonToken);
4719            return finishNode(node);
4720        }
4721
4722        function parseIfStatement(): IfStatement {
4723            const node = <IfStatement>createNode(SyntaxKind.IfStatement);
4724            parseExpected(SyntaxKind.IfKeyword);
4725            parseExpected(SyntaxKind.OpenParenToken);
4726            node.expression = allowInAnd(parseExpression);
4727            parseExpected(SyntaxKind.CloseParenToken);
4728            node.thenStatement = parseStatement();
4729            node.elseStatement = parseOptional(SyntaxKind.ElseKeyword) ? parseStatement() : undefined;
4730            return finishNode(node);
4731        }
4732
4733        function parseDoStatement(): DoStatement {
4734            const node = <DoStatement>createNode(SyntaxKind.DoStatement);
4735            parseExpected(SyntaxKind.DoKeyword);
4736            node.statement = parseStatement();
4737            parseExpected(SyntaxKind.WhileKeyword);
4738            parseExpected(SyntaxKind.OpenParenToken);
4739            node.expression = allowInAnd(parseExpression);
4740            parseExpected(SyntaxKind.CloseParenToken);
4741
4742            // From: https://mail.mozilla.org/pipermail/es-discuss/2011-August/016188.html
4743            // 157 min --- All allen at wirfs-brock.com CONF --- "do{;}while(false)false" prohibited in
4744            // spec but allowed in consensus reality. Approved -- this is the de-facto standard whereby
4745            //  do;while(0)x will have a semicolon inserted before x.
4746            parseOptional(SyntaxKind.SemicolonToken);
4747            return finishNode(node);
4748        }
4749
4750        function parseWhileStatement(): WhileStatement {
4751            const node = <WhileStatement>createNode(SyntaxKind.WhileStatement);
4752            parseExpected(SyntaxKind.WhileKeyword);
4753            parseExpected(SyntaxKind.OpenParenToken);
4754            node.expression = allowInAnd(parseExpression);
4755            parseExpected(SyntaxKind.CloseParenToken);
4756            node.statement = parseStatement();
4757            return finishNode(node);
4758        }
4759
4760        function parseForOrForInOrForOfStatement(): Statement {
4761            const pos = getNodePos();
4762            parseExpected(SyntaxKind.ForKeyword);
4763            const awaitToken = parseOptionalToken(SyntaxKind.AwaitKeyword);
4764            parseExpected(SyntaxKind.OpenParenToken);
4765
4766            let initializer: VariableDeclarationList | Expression = undefined;
4767            if (token() !== SyntaxKind.SemicolonToken) {
4768                if (token() === SyntaxKind.VarKeyword || token() === SyntaxKind.LetKeyword || token() === SyntaxKind.ConstKeyword) {
4769                    initializer = parseVariableDeclarationList(/*inForStatementInitializer*/ true);
4770                }
4771                else {
4772                    initializer = disallowInAnd(parseExpression);
4773                }
4774            }
4775            let forOrForInOrForOfStatement: IterationStatement;
4776            if (awaitToken ? parseExpected(SyntaxKind.OfKeyword) : parseOptional(SyntaxKind.OfKeyword)) {
4777                const forOfStatement = <ForOfStatement>createNode(SyntaxKind.ForOfStatement, pos);
4778                forOfStatement.awaitModifier = awaitToken;
4779                forOfStatement.initializer = initializer;
4780                forOfStatement.expression = allowInAnd(parseAssignmentExpressionOrHigher);
4781                parseExpected(SyntaxKind.CloseParenToken);
4782                forOrForInOrForOfStatement = forOfStatement;
4783            }
4784            else if (parseOptional(SyntaxKind.InKeyword)) {
4785                const forInStatement = <ForInStatement>createNode(SyntaxKind.ForInStatement, pos);
4786                forInStatement.initializer = initializer;
4787                forInStatement.expression = allowInAnd(parseExpression);
4788                parseExpected(SyntaxKind.CloseParenToken);
4789                forOrForInOrForOfStatement = forInStatement;
4790            }
4791            else {
4792                const forStatement = <ForStatement>createNode(SyntaxKind.ForStatement, pos);
4793                forStatement.initializer = initializer;
4794                parseExpected(SyntaxKind.SemicolonToken);
4795                if (token() !== SyntaxKind.SemicolonToken && token() !== SyntaxKind.CloseParenToken) {
4796                    forStatement.condition = allowInAnd(parseExpression);
4797                }
4798                parseExpected(SyntaxKind.SemicolonToken);
4799                if (token() !== SyntaxKind.CloseParenToken) {
4800                    forStatement.incrementor = allowInAnd(parseExpression);
4801                }
4802                parseExpected(SyntaxKind.CloseParenToken);
4803                forOrForInOrForOfStatement = forStatement;
4804            }
4805
4806            forOrForInOrForOfStatement.statement = parseStatement();
4807
4808            return finishNode(forOrForInOrForOfStatement);
4809        }
4810
4811        function parseBreakOrContinueStatement(kind: SyntaxKind): BreakOrContinueStatement {
4812            const node = <BreakOrContinueStatement>createNode(kind);
4813
4814            parseExpected(kind === SyntaxKind.BreakStatement ? SyntaxKind.BreakKeyword : SyntaxKind.ContinueKeyword);
4815            if (!canParseSemicolon()) {
4816                node.label = parseIdentifier();
4817            }
4818
4819            parseSemicolon();
4820            return finishNode(node);
4821        }
4822
4823        function parseReturnStatement(): ReturnStatement {
4824            const node = <ReturnStatement>createNode(SyntaxKind.ReturnStatement);
4825
4826            parseExpected(SyntaxKind.ReturnKeyword);
4827            if (!canParseSemicolon()) {
4828                node.expression = allowInAnd(parseExpression);
4829            }
4830
4831            parseSemicolon();
4832            return finishNode(node);
4833        }
4834
4835        function parseWithStatement(): WithStatement {
4836            const node = <WithStatement>createNode(SyntaxKind.WithStatement);
4837            parseExpected(SyntaxKind.WithKeyword);
4838            parseExpected(SyntaxKind.OpenParenToken);
4839            node.expression = allowInAnd(parseExpression);
4840            parseExpected(SyntaxKind.CloseParenToken);
4841            node.statement = doInsideOfContext(NodeFlags.InWithStatement, parseStatement);
4842            return finishNode(node);
4843        }
4844
4845        function parseCaseClause(): CaseClause {
4846            const node = <CaseClause>createNode(SyntaxKind.CaseClause);
4847            parseExpected(SyntaxKind.CaseKeyword);
4848            node.expression = allowInAnd(parseExpression);
4849            parseExpected(SyntaxKind.ColonToken);
4850            node.statements = parseList(ParsingContext.SwitchClauseStatements, parseStatement);
4851            return finishNode(node);
4852        }
4853
4854        function parseDefaultClause(): DefaultClause {
4855            const node = <DefaultClause>createNode(SyntaxKind.DefaultClause);
4856            parseExpected(SyntaxKind.DefaultKeyword);
4857            parseExpected(SyntaxKind.ColonToken);
4858            node.statements = parseList(ParsingContext.SwitchClauseStatements, parseStatement);
4859            return finishNode(node);
4860        }
4861
4862        function parseCaseOrDefaultClause(): CaseOrDefaultClause {
4863            return token() === SyntaxKind.CaseKeyword ? parseCaseClause() : parseDefaultClause();
4864        }
4865
4866        function parseSwitchStatement(): SwitchStatement {
4867            const node = <SwitchStatement>createNode(SyntaxKind.SwitchStatement);
4868            parseExpected(SyntaxKind.SwitchKeyword);
4869            parseExpected(SyntaxKind.OpenParenToken);
4870            node.expression = allowInAnd(parseExpression);
4871            parseExpected(SyntaxKind.CloseParenToken);
4872            const caseBlock = <CaseBlock>createNode(SyntaxKind.CaseBlock);
4873            parseExpected(SyntaxKind.OpenBraceToken);
4874            caseBlock.clauses = parseList(ParsingContext.SwitchClauses, parseCaseOrDefaultClause);
4875            parseExpected(SyntaxKind.CloseBraceToken);
4876            node.caseBlock = finishNode(caseBlock);
4877            return finishNode(node);
4878        }
4879
4880        function parseThrowStatement(): ThrowStatement {
4881            // ThrowStatement[Yield] :
4882            //      throw [no LineTerminator here]Expression[In, ?Yield];
4883
4884            // Because of automatic semicolon insertion, we need to report error if this
4885            // throw could be terminated with a semicolon.  Note: we can't call 'parseExpression'
4886            // directly as that might consume an expression on the following line.
4887            // We just return 'undefined' in that case.  The actual error will be reported in the
4888            // grammar walker.
4889            const node = <ThrowStatement>createNode(SyntaxKind.ThrowStatement);
4890            parseExpected(SyntaxKind.ThrowKeyword);
4891            node.expression = scanner.hasPrecedingLineBreak() ? undefined : allowInAnd(parseExpression);
4892            parseSemicolon();
4893            return finishNode(node);
4894        }
4895
4896        // TODO: Review for error recovery
4897        function parseTryStatement(): TryStatement {
4898            const node = <TryStatement>createNode(SyntaxKind.TryStatement);
4899
4900            parseExpected(SyntaxKind.TryKeyword);
4901            node.tryBlock = parseBlock(/*ignoreMissingOpenBrace*/ false);
4902            node.catchClause = token() === SyntaxKind.CatchKeyword ? parseCatchClause() : undefined;
4903
4904            // If we don't have a catch clause, then we must have a finally clause.  Try to parse
4905            // one out no matter what.
4906            if (!node.catchClause || token() === SyntaxKind.FinallyKeyword) {
4907                parseExpected(SyntaxKind.FinallyKeyword);
4908                node.finallyBlock = parseBlock(/*ignoreMissingOpenBrace*/ false);
4909            }
4910
4911            return finishNode(node);
4912        }
4913
4914        function parseCatchClause(): CatchClause {
4915            const result = <CatchClause>createNode(SyntaxKind.CatchClause);
4916            parseExpected(SyntaxKind.CatchKeyword);
4917
4918            if (parseOptional(SyntaxKind.OpenParenToken)) {
4919                result.variableDeclaration = parseVariableDeclaration();
4920                parseExpected(SyntaxKind.CloseParenToken);
4921            }
4922            else {
4923                // Keep shape of node to avoid degrading performance.
4924                result.variableDeclaration = undefined;
4925            }
4926
4927            result.block = parseBlock(/*ignoreMissingOpenBrace*/ false);
4928            return finishNode(result);
4929        }
4930
4931        function parseDebuggerStatement(): Statement {
4932            const node = <Statement>createNode(SyntaxKind.DebuggerStatement);
4933            parseExpected(SyntaxKind.DebuggerKeyword);
4934            parseSemicolon();
4935            return finishNode(node);
4936        }
4937
4938        function parseExpressionOrLabeledStatement(): ExpressionStatement | LabeledStatement {
4939            // Avoiding having to do the lookahead for a labeled statement by just trying to parse
4940            // out an expression, seeing if it is identifier and then seeing if it is followed by
4941            // a colon.
4942            const node = <ExpressionStatement | LabeledStatement>createNodeWithJSDoc(SyntaxKind.Unknown);
4943            const expression = allowInAnd(parseExpression);
4944            if (expression.kind === SyntaxKind.Identifier && parseOptional(SyntaxKind.ColonToken)) {
4945                node.kind = SyntaxKind.LabeledStatement;
4946                (<LabeledStatement>node).label = <Identifier>expression;
4947                (<LabeledStatement>node).statement = parseStatement();
4948            }
4949            else {
4950                node.kind = SyntaxKind.ExpressionStatement;
4951                (<ExpressionStatement>node).expression = expression;
4952                parseSemicolon();
4953            }
4954            return finishNode(node);
4955        }
4956
4957        function nextTokenIsIdentifierOrKeywordOnSameLine() {
4958            nextToken();
4959            return tokenIsIdentifierOrKeyword(token()) && !scanner.hasPrecedingLineBreak();
4960        }
4961
4962        function nextTokenIsClassKeywordOnSameLine() {
4963            nextToken();
4964            return token() === SyntaxKind.ClassKeyword && !scanner.hasPrecedingLineBreak();
4965        }
4966
4967        function nextTokenIsFunctionKeywordOnSameLine() {
4968            nextToken();
4969            return token() === SyntaxKind.FunctionKeyword && !scanner.hasPrecedingLineBreak();
4970        }
4971
4972        function nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine() {
4973            nextToken();
4974            return (tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.StringLiteral) && !scanner.hasPrecedingLineBreak();
4975        }
4976
4977        function isDeclaration(): boolean {
4978            while (true) {
4979                switch (token()) {
4980                    case SyntaxKind.VarKeyword:
4981                    case SyntaxKind.LetKeyword:
4982                    case SyntaxKind.ConstKeyword:
4983                    case SyntaxKind.FunctionKeyword:
4984                    case SyntaxKind.ClassKeyword:
4985                    case SyntaxKind.EnumKeyword:
4986                        return true;
4987
4988                    // 'declare', 'module', 'namespace', 'interface'* and 'type' are all legal JavaScript identifiers;
4989                    // however, an identifier cannot be followed by another identifier on the same line. This is what we
4990                    // count on to parse out the respective declarations. For instance, we exploit this to say that
4991                    //
4992                    //    namespace n
4993                    //
4994                    // can be none other than the beginning of a namespace declaration, but need to respect that JavaScript sees
4995                    //
4996                    //    namespace
4997                    //    n
4998                    //
4999                    // as the identifier 'namespace' on one line followed by the identifier 'n' on another.
5000                    // We need to look one token ahead to see if it permissible to try parsing a declaration.
5001                    //
5002                    // *Note*: 'interface' is actually a strict mode reserved word. So while
5003                    //
5004                    //   "use strict"
5005                    //   interface
5006                    //   I {}
5007                    //
5008                    // could be legal, it would add complexity for very little gain.
5009                    case SyntaxKind.InterfaceKeyword:
5010                    case SyntaxKind.TypeKeyword:
5011                        return nextTokenIsIdentifierOnSameLine();
5012                    case SyntaxKind.ModuleKeyword:
5013                    case SyntaxKind.NamespaceKeyword:
5014                        return nextTokenIsIdentifierOrStringLiteralOnSameLine();
5015                    case SyntaxKind.AbstractKeyword:
5016                    case SyntaxKind.AsyncKeyword:
5017                    case SyntaxKind.DeclareKeyword:
5018                    case SyntaxKind.PrivateKeyword:
5019                    case SyntaxKind.ProtectedKeyword:
5020                    case SyntaxKind.PublicKeyword:
5021                    case SyntaxKind.ReadonlyKeyword:
5022                        nextToken();
5023                        // ASI takes effect for this modifier.
5024                        if (scanner.hasPrecedingLineBreak()) {
5025                            return false;
5026                        }
5027                        continue;
5028
5029                    case SyntaxKind.GlobalKeyword:
5030                        nextToken();
5031                        return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.Identifier || token() === SyntaxKind.ExportKeyword;
5032
5033                    case SyntaxKind.ImportKeyword:
5034                        nextToken();
5035                        return token() === SyntaxKind.StringLiteral || token() === SyntaxKind.AsteriskToken ||
5036                            token() === SyntaxKind.OpenBraceToken || tokenIsIdentifierOrKeyword(token());
5037                    case SyntaxKind.ExportKeyword:
5038                        nextToken();
5039                        if (token() === SyntaxKind.EqualsToken || token() === SyntaxKind.AsteriskToken ||
5040                            token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.DefaultKeyword ||
5041                            token() === SyntaxKind.AsKeyword) {
5042                            return true;
5043                        }
5044                        continue;
5045
5046                    case SyntaxKind.StaticKeyword:
5047                        nextToken();
5048                        continue;
5049                    default:
5050                        return false;
5051                }
5052            }
5053        }
5054
5055        function isStartOfDeclaration(): boolean {
5056            return lookAhead(isDeclaration);
5057        }
5058
5059        function isStartOfStatement(): boolean {
5060            switch (token()) {
5061                case SyntaxKind.AtToken:
5062                case SyntaxKind.SemicolonToken:
5063                case SyntaxKind.OpenBraceToken:
5064                case SyntaxKind.VarKeyword:
5065                case SyntaxKind.LetKeyword:
5066                case SyntaxKind.FunctionKeyword:
5067                case SyntaxKind.ClassKeyword:
5068                case SyntaxKind.EnumKeyword:
5069                case SyntaxKind.IfKeyword:
5070                case SyntaxKind.DoKeyword:
5071                case SyntaxKind.WhileKeyword:
5072                case SyntaxKind.ForKeyword:
5073                case SyntaxKind.ContinueKeyword:
5074                case SyntaxKind.BreakKeyword:
5075                case SyntaxKind.ReturnKeyword:
5076                case SyntaxKind.WithKeyword:
5077                case SyntaxKind.SwitchKeyword:
5078                case SyntaxKind.ThrowKeyword:
5079                case SyntaxKind.TryKeyword:
5080                case SyntaxKind.DebuggerKeyword:
5081                // 'catch' and 'finally' do not actually indicate that the code is part of a statement,
5082                // however, we say they are here so that we may gracefully parse them and error later.
5083                case SyntaxKind.CatchKeyword:
5084                case SyntaxKind.FinallyKeyword:
5085                    return true;
5086
5087                case SyntaxKind.ImportKeyword:
5088                    return isStartOfDeclaration() || lookAhead(nextTokenIsOpenParenOrLessThan);
5089
5090                case SyntaxKind.ConstKeyword:
5091                case SyntaxKind.ExportKeyword:
5092                    return isStartOfDeclaration();
5093
5094                case SyntaxKind.AsyncKeyword:
5095                case SyntaxKind.DeclareKeyword:
5096                case SyntaxKind.InterfaceKeyword:
5097                case SyntaxKind.ModuleKeyword:
5098                case SyntaxKind.NamespaceKeyword:
5099                case SyntaxKind.TypeKeyword:
5100                case SyntaxKind.GlobalKeyword:
5101                    // When these don't start a declaration, they're an identifier in an expression statement
5102                    return true;
5103
5104                case SyntaxKind.PublicKeyword:
5105                case SyntaxKind.PrivateKeyword:
5106                case SyntaxKind.ProtectedKeyword:
5107                case SyntaxKind.StaticKeyword:
5108                case SyntaxKind.ReadonlyKeyword:
5109                    // When these don't start a declaration, they may be the start of a class member if an identifier
5110                    // immediately follows. Otherwise they're an identifier in an expression statement.
5111                    return isStartOfDeclaration() || !lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine);
5112
5113                default:
5114                    return isStartOfExpression();
5115            }
5116        }
5117
5118        function nextTokenIsIdentifierOrStartOfDestructuring() {
5119            nextToken();
5120            return isIdentifier() || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.OpenBracketToken;
5121        }
5122
5123        function isLetDeclaration() {
5124            // In ES6 'let' always starts a lexical declaration if followed by an identifier or {
5125            // or [.
5126            return lookAhead(nextTokenIsIdentifierOrStartOfDestructuring);
5127        }
5128
5129        function parseStatement(): Statement {
5130            switch (token()) {
5131                case SyntaxKind.SemicolonToken:
5132                    return parseEmptyStatement();
5133                case SyntaxKind.OpenBraceToken:
5134                    return parseBlock(/*ignoreMissingOpenBrace*/ false);
5135                case SyntaxKind.VarKeyword:
5136                    return parseVariableStatement(<VariableStatement>createNodeWithJSDoc(SyntaxKind.VariableDeclaration));
5137                case SyntaxKind.LetKeyword:
5138                    if (isLetDeclaration()) {
5139                        return parseVariableStatement(<VariableStatement>createNodeWithJSDoc(SyntaxKind.VariableDeclaration));
5140                    }
5141                    break;
5142                case SyntaxKind.FunctionKeyword:
5143                    return parseFunctionDeclaration(<FunctionDeclaration>createNodeWithJSDoc(SyntaxKind.FunctionDeclaration));
5144                case SyntaxKind.ClassKeyword:
5145                    return parseClassDeclaration(<ClassDeclaration>createNodeWithJSDoc(SyntaxKind.ClassDeclaration));
5146                case SyntaxKind.IfKeyword:
5147                    return parseIfStatement();
5148                case SyntaxKind.DoKeyword:
5149                    return parseDoStatement();
5150                case SyntaxKind.WhileKeyword:
5151                    return parseWhileStatement();
5152                case SyntaxKind.ForKeyword:
5153                    return parseForOrForInOrForOfStatement();
5154                case SyntaxKind.ContinueKeyword:
5155                    return parseBreakOrContinueStatement(SyntaxKind.ContinueStatement);
5156                case SyntaxKind.BreakKeyword:
5157                    return parseBreakOrContinueStatement(SyntaxKind.BreakStatement);
5158                case SyntaxKind.ReturnKeyword:
5159                    return parseReturnStatement();
5160                case SyntaxKind.WithKeyword:
5161                    return parseWithStatement();
5162                case SyntaxKind.SwitchKeyword:
5163                    return parseSwitchStatement();
5164                case SyntaxKind.ThrowKeyword:
5165                    return parseThrowStatement();
5166                case SyntaxKind.TryKeyword:
5167                // Include 'catch' and 'finally' for error recovery.
5168                case SyntaxKind.CatchKeyword:
5169                case SyntaxKind.FinallyKeyword:
5170                    return parseTryStatement();
5171                case SyntaxKind.DebuggerKeyword:
5172                    return parseDebuggerStatement();
5173                case SyntaxKind.AtToken:
5174                    return parseDeclaration();
5175                case SyntaxKind.AsyncKeyword:
5176                case SyntaxKind.InterfaceKeyword:
5177                case SyntaxKind.TypeKeyword:
5178                case SyntaxKind.ModuleKeyword:
5179                case SyntaxKind.NamespaceKeyword:
5180                case SyntaxKind.DeclareKeyword:
5181                case SyntaxKind.ConstKeyword:
5182                case SyntaxKind.EnumKeyword:
5183                case SyntaxKind.ExportKeyword:
5184                case SyntaxKind.ImportKeyword:
5185                case SyntaxKind.PrivateKeyword:
5186                case SyntaxKind.ProtectedKeyword:
5187                case SyntaxKind.PublicKeyword:
5188                case SyntaxKind.AbstractKeyword:
5189                case SyntaxKind.StaticKeyword:
5190                case SyntaxKind.ReadonlyKeyword:
5191                case SyntaxKind.GlobalKeyword:
5192                    if (isStartOfDeclaration()) {
5193                        return parseDeclaration();
5194                    }
5195                    break;
5196            }
5197            return parseExpressionOrLabeledStatement();
5198        }
5199
5200        function isDeclareModifier(modifier: Modifier) {
5201            return modifier.kind === SyntaxKind.DeclareKeyword;
5202        }
5203
5204        function parseDeclaration(): Statement {
5205            const node = <Statement>createNodeWithJSDoc(SyntaxKind.Unknown);
5206            node.decorators = parseDecorators();
5207            node.modifiers = parseModifiers();
5208            if (some(node.modifiers, isDeclareModifier)) {
5209                for (const m of node.modifiers) {
5210                    m.flags |= NodeFlags.Ambient;
5211                }
5212                return doInsideOfContext(NodeFlags.Ambient, () => parseDeclarationWorker(node));
5213            }
5214            else {
5215                return parseDeclarationWorker(node);
5216            }
5217        }
5218
5219        function parseDeclarationWorker(node: Statement): Statement {
5220            switch (token()) {
5221                case SyntaxKind.VarKeyword:
5222                case SyntaxKind.LetKeyword:
5223                case SyntaxKind.ConstKeyword:
5224                    return parseVariableStatement(<VariableStatement>node);
5225                case SyntaxKind.FunctionKeyword:
5226                    return parseFunctionDeclaration(<FunctionDeclaration>node);
5227                case SyntaxKind.ClassKeyword:
5228                    return parseClassDeclaration(<ClassDeclaration>node);
5229                case SyntaxKind.InterfaceKeyword:
5230                    return parseInterfaceDeclaration(<InterfaceDeclaration>node);
5231                case SyntaxKind.TypeKeyword:
5232                    return parseTypeAliasDeclaration(<TypeAliasDeclaration>node);
5233                case SyntaxKind.EnumKeyword:
5234                    return parseEnumDeclaration(<EnumDeclaration>node);
5235                case SyntaxKind.GlobalKeyword:
5236                case SyntaxKind.ModuleKeyword:
5237                case SyntaxKind.NamespaceKeyword:
5238                    return parseModuleDeclaration(<ModuleDeclaration>node);
5239                case SyntaxKind.ImportKeyword:
5240                    return parseImportDeclarationOrImportEqualsDeclaration(<ImportDeclaration | ImportEqualsDeclaration>node);
5241                case SyntaxKind.ExportKeyword:
5242                    nextToken();
5243                    switch (token()) {
5244                        case SyntaxKind.DefaultKeyword:
5245                        case SyntaxKind.EqualsToken:
5246                            return parseExportAssignment(<ExportAssignment>node);
5247                        case SyntaxKind.AsKeyword:
5248                            return parseNamespaceExportDeclaration(<NamespaceExportDeclaration>node);
5249                        default:
5250                            return parseExportDeclaration(<ExportDeclaration>node);
5251                    }
5252                default:
5253                    if (node.decorators || node.modifiers) {
5254                        // We reached this point because we encountered decorators and/or modifiers and assumed a declaration
5255                        // would follow. For recovery and error reporting purposes, return an incomplete declaration.
5256                        const missing = <Statement>createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected);
5257                        missing.pos = node.pos;
5258                        missing.decorators = node.decorators;
5259                        missing.modifiers = node.modifiers;
5260                        return finishNode(missing);
5261                    }
5262            }
5263        }
5264
5265        function nextTokenIsIdentifierOrStringLiteralOnSameLine() {
5266            nextToken();
5267            return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() === SyntaxKind.StringLiteral);
5268        }
5269
5270        function parseFunctionBlockOrSemicolon(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block {
5271            if (token() !== SyntaxKind.OpenBraceToken && canParseSemicolon()) {
5272                parseSemicolon();
5273                return;
5274            }
5275
5276            return parseFunctionBlock(flags, diagnosticMessage);
5277        }
5278
5279        // DECLARATIONS
5280
5281        function parseArrayBindingElement(): ArrayBindingElement {
5282            if (token() === SyntaxKind.CommaToken) {
5283                return <OmittedExpression>createNode(SyntaxKind.OmittedExpression);
5284            }
5285            const node = <BindingElement>createNode(SyntaxKind.BindingElement);
5286            node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
5287            node.name = parseIdentifierOrPattern();
5288            node.initializer = parseInitializer();
5289            return finishNode(node);
5290        }
5291
5292        function parseObjectBindingElement(): BindingElement {
5293            const node = <BindingElement>createNode(SyntaxKind.BindingElement);
5294            node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
5295            const tokenIsIdentifier = isIdentifier();
5296            const propertyName = parsePropertyName();
5297            if (tokenIsIdentifier && token() !== SyntaxKind.ColonToken) {
5298                node.name = <Identifier>propertyName;
5299            }
5300            else {
5301                parseExpected(SyntaxKind.ColonToken);
5302                node.propertyName = propertyName;
5303                node.name = parseIdentifierOrPattern();
5304            }
5305            node.initializer = parseInitializer();
5306            return finishNode(node);
5307        }
5308
5309        function parseObjectBindingPattern(): ObjectBindingPattern {
5310            const node = <ObjectBindingPattern>createNode(SyntaxKind.ObjectBindingPattern);
5311            parseExpected(SyntaxKind.OpenBraceToken);
5312            node.elements = parseDelimitedList(ParsingContext.ObjectBindingElements, parseObjectBindingElement);
5313            parseExpected(SyntaxKind.CloseBraceToken);
5314            return finishNode(node);
5315        }
5316
5317        function parseArrayBindingPattern(): ArrayBindingPattern {
5318            const node = <ArrayBindingPattern>createNode(SyntaxKind.ArrayBindingPattern);
5319            parseExpected(SyntaxKind.OpenBracketToken);
5320            node.elements = parseDelimitedList(ParsingContext.ArrayBindingElements, parseArrayBindingElement);
5321            parseExpected(SyntaxKind.CloseBracketToken);
5322            return finishNode(node);
5323        }
5324
5325        function isIdentifierOrPattern() {
5326            return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.OpenBracketToken || isIdentifier();
5327        }
5328
5329        function parseIdentifierOrPattern(): Identifier | BindingPattern {
5330            if (token() === SyntaxKind.OpenBracketToken) {
5331                return parseArrayBindingPattern();
5332            }
5333            if (token() === SyntaxKind.OpenBraceToken) {
5334                return parseObjectBindingPattern();
5335            }
5336            return parseIdentifier();
5337        }
5338
5339        function parseVariableDeclarationAllowExclamation() {
5340            return parseVariableDeclaration(/*allowExclamation*/ true);
5341        }
5342
5343        function parseVariableDeclaration(allowExclamation?: boolean): VariableDeclaration {
5344            const node = <VariableDeclaration>createNode(SyntaxKind.VariableDeclaration);
5345            node.name = parseIdentifierOrPattern();
5346            if (allowExclamation && node.name.kind === SyntaxKind.Identifier &&
5347                token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
5348                node.exclamationToken = parseTokenNode();
5349            }
5350            node.type = parseTypeAnnotation();
5351            if (!isInOrOfKeyword(token())) {
5352                node.initializer = parseInitializer();
5353            }
5354            return finishNode(node);
5355        }
5356
5357        function parseVariableDeclarationList(inForStatementInitializer: boolean): VariableDeclarationList {
5358            const node = <VariableDeclarationList>createNode(SyntaxKind.VariableDeclarationList);
5359
5360            switch (token()) {
5361                case SyntaxKind.VarKeyword:
5362                    break;
5363                case SyntaxKind.LetKeyword:
5364                    node.flags |= NodeFlags.Let;
5365                    break;
5366                case SyntaxKind.ConstKeyword:
5367                    node.flags |= NodeFlags.Const;
5368                    break;
5369                default:
5370                    Debug.fail();
5371            }
5372
5373            nextToken();
5374
5375            // The user may have written the following:
5376            //
5377            //    for (let of X) { }
5378            //
5379            // In this case, we want to parse an empty declaration list, and then parse 'of'
5380            // as a keyword. The reason this is not automatic is that 'of' is a valid identifier.
5381            // So we need to look ahead to determine if 'of' should be treated as a keyword in
5382            // this context.
5383            // The checker will then give an error that there is an empty declaration list.
5384            if (token() === SyntaxKind.OfKeyword && lookAhead(canFollowContextualOfKeyword)) {
5385                node.declarations = createMissingList<VariableDeclaration>();
5386            }
5387            else {
5388                const savedDisallowIn = inDisallowInContext();
5389                setDisallowInContext(inForStatementInitializer);
5390
5391                node.declarations = parseDelimitedList(ParsingContext.VariableDeclarations,
5392                    inForStatementInitializer ? parseVariableDeclaration : parseVariableDeclarationAllowExclamation);
5393
5394                setDisallowInContext(savedDisallowIn);
5395            }
5396
5397            return finishNode(node);
5398        }
5399
5400        function canFollowContextualOfKeyword(): boolean {
5401            return nextTokenIsIdentifier() && nextToken() === SyntaxKind.CloseParenToken;
5402        }
5403
5404        function parseVariableStatement(node: VariableStatement): VariableStatement {
5405            node.kind = SyntaxKind.VariableStatement;
5406            node.declarationList = parseVariableDeclarationList(/*inForStatementInitializer*/ false);
5407            parseSemicolon();
5408            return finishNode(node);
5409        }
5410
5411        function parseFunctionDeclaration(node: FunctionDeclaration): FunctionDeclaration {
5412            node.kind = SyntaxKind.FunctionDeclaration;
5413            parseExpected(SyntaxKind.FunctionKeyword);
5414            node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
5415            node.name = hasModifier(node, ModifierFlags.Default) ? parseOptionalIdentifier() : parseIdentifier();
5416            const isGenerator = node.asteriskToken ? SignatureFlags.Yield : SignatureFlags.None;
5417            const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None;
5418            fillSignature(SyntaxKind.ColonToken, isGenerator | isAsync, node);
5419            node.body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, Diagnostics.or_expected);
5420            return finishNode(node);
5421        }
5422
5423        function parseConstructorDeclaration(node: ConstructorDeclaration): ConstructorDeclaration {
5424            node.kind = SyntaxKind.Constructor;
5425            parseExpected(SyntaxKind.ConstructorKeyword);
5426            fillSignature(SyntaxKind.ColonToken, SignatureFlags.None, node);
5427            node.body = parseFunctionBlockOrSemicolon(SignatureFlags.None, Diagnostics.or_expected);
5428            return finishNode(node);
5429        }
5430
5431        function parseMethodDeclaration(node: MethodDeclaration, asteriskToken: AsteriskToken, diagnosticMessage?: DiagnosticMessage): MethodDeclaration {
5432            node.kind = SyntaxKind.MethodDeclaration;
5433            node.asteriskToken = asteriskToken;
5434            const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None;
5435            const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None;
5436            fillSignature(SyntaxKind.ColonToken, isGenerator | isAsync, node);
5437            node.body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, diagnosticMessage);
5438            return finishNode(node);
5439        }
5440
5441        function parsePropertyDeclaration(node: PropertyDeclaration): PropertyDeclaration {
5442            node.kind = SyntaxKind.PropertyDeclaration;
5443            if (!node.questionToken && token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
5444                node.exclamationToken = parseTokenNode();
5445            }
5446            node.type = parseTypeAnnotation();
5447
5448            // For instance properties specifically, since they are evaluated inside the constructor,
5449            // we do *not * want to parse yield expressions, so we specifically turn the yield context
5450            // off. The grammar would look something like this:
5451            //
5452            //    MemberVariableDeclaration[Yield]:
5453            //        AccessibilityModifier_opt PropertyName TypeAnnotation_opt Initializer_opt[In];
5454            //        AccessibilityModifier_opt static_opt PropertyName TypeAnnotation_opt Initializer_opt[In, ?Yield];
5455            //
5456            // The checker may still error in the static case to explicitly disallow the yield expression.
5457            node.initializer = hasModifier(node, ModifierFlags.Static)
5458                ? allowInAnd(parseInitializer)
5459                : doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.DisallowInContext, parseInitializer);
5460
5461            parseSemicolon();
5462            return finishNode(node);
5463        }
5464
5465        function parsePropertyOrMethodDeclaration(node: PropertyDeclaration | MethodDeclaration): PropertyDeclaration | MethodDeclaration {
5466            const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
5467            node.name = parsePropertyName();
5468            // Note: this is not legal as per the grammar.  But we allow it in the parser and
5469            // report an error in the grammar checker.
5470            node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
5471            if (asteriskToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
5472                return parseMethodDeclaration(<MethodDeclaration>node, asteriskToken, Diagnostics.or_expected);
5473            }
5474            return parsePropertyDeclaration(<PropertyDeclaration>node);
5475        }
5476
5477        function parseAccessorDeclaration(node: AccessorDeclaration, kind: AccessorDeclaration["kind"]): AccessorDeclaration {
5478            node.kind = kind;
5479            node.name = parsePropertyName();
5480            fillSignature(SyntaxKind.ColonToken, SignatureFlags.None, node);
5481            node.body = parseFunctionBlockOrSemicolon(SignatureFlags.None);
5482            return finishNode(node);
5483        }
5484
5485        function isClassMemberModifier(idToken: SyntaxKind) {
5486            switch (idToken) {
5487                case SyntaxKind.PublicKeyword:
5488                case SyntaxKind.PrivateKeyword:
5489                case SyntaxKind.ProtectedKeyword:
5490                case SyntaxKind.StaticKeyword:
5491                case SyntaxKind.ReadonlyKeyword:
5492                    return true;
5493                default:
5494                    return false;
5495            }
5496        }
5497
5498        function isClassMemberStart(): boolean {
5499            let idToken: SyntaxKind;
5500
5501            if (token() === SyntaxKind.AtToken) {
5502                return true;
5503            }
5504
5505            // Eat up all modifiers, but hold on to the last one in case it is actually an identifier.
5506            while (isModifierKind(token())) {
5507                idToken = token();
5508                // If the idToken is a class modifier (protected, private, public, and static), it is
5509                // certain that we are starting to parse class member. This allows better error recovery
5510                // Example:
5511                //      public foo() ...     // true
5512                //      public @dec blah ... // true; we will then report an error later
5513                //      export public ...    // true; we will then report an error later
5514                if (isClassMemberModifier(idToken)) {
5515                    return true;
5516                }
5517
5518                nextToken();
5519            }
5520
5521            if (token() === SyntaxKind.AsteriskToken) {
5522                return true;
5523            }
5524
5525            // Try to get the first property-like token following all modifiers.
5526            // This can either be an identifier or the 'get' or 'set' keywords.
5527            if (isLiteralPropertyName()) {
5528                idToken = token();
5529                nextToken();
5530            }
5531
5532            // Index signatures and computed properties are class members; we can parse.
5533            if (token() === SyntaxKind.OpenBracketToken) {
5534                return true;
5535            }
5536
5537            // If we were able to get any potential identifier...
5538            if (idToken !== undefined) {
5539                // If we have a non-keyword identifier, or if we have an accessor, then it's safe to parse.
5540                if (!isKeyword(idToken) || idToken === SyntaxKind.SetKeyword || idToken === SyntaxKind.GetKeyword) {
5541                    return true;
5542                }
5543
5544                // If it *is* a keyword, but not an accessor, check a little farther along
5545                // to see if it should actually be parsed as a class member.
5546                switch (token()) {
5547                    case SyntaxKind.OpenParenToken:     // Method declaration
5548                    case SyntaxKind.LessThanToken:      // Generic Method declaration
5549                    case SyntaxKind.ExclamationToken:   // Non-null assertion on property name
5550                    case SyntaxKind.ColonToken:         // Type Annotation for declaration
5551                    case SyntaxKind.EqualsToken:        // Initializer for declaration
5552                    case SyntaxKind.QuestionToken:      // Not valid, but permitted so that it gets caught later on.
5553                        return true;
5554                    default:
5555                        // Covers
5556                        //  - Semicolons     (declaration termination)
5557                        //  - Closing braces (end-of-class, must be declaration)
5558                        //  - End-of-files   (not valid, but permitted so that it gets caught later on)
5559                        //  - Line-breaks    (enabling *automatic semicolon insertion*)
5560                        return canParseSemicolon();
5561                }
5562            }
5563
5564            return false;
5565        }
5566
5567        function parseDecorators(): NodeArray<Decorator> | undefined {
5568            let list: Decorator[] | undefined;
5569            const listPos = getNodePos();
5570            while (true) {
5571                const decoratorStart = getNodePos();
5572                if (!parseOptional(SyntaxKind.AtToken)) {
5573                    break;
5574                }
5575                const decorator = <Decorator>createNode(SyntaxKind.Decorator, decoratorStart);
5576                decorator.expression = doInDecoratorContext(parseLeftHandSideExpressionOrHigher);
5577                finishNode(decorator);
5578                (list || (list = [])).push(decorator);
5579            }
5580            return list && createNodeArray(list, listPos);
5581        }
5582
5583        /*
5584         * There are situations in which a modifier like 'const' will appear unexpectedly, such as on a class member.
5585         * In those situations, if we are entirely sure that 'const' is not valid on its own (such as when ASI takes effect
5586         * and turns it into a standalone declaration), then it is better to parse it and report an error later.
5587         *
5588         * In such situations, 'permitInvalidConstAsModifier' should be set to true.
5589         */
5590        function parseModifiers(permitInvalidConstAsModifier?: boolean): NodeArray<Modifier> | undefined {
5591            let list: Modifier[];
5592            const listPos = getNodePos();
5593            while (true) {
5594                const modifierStart = scanner.getStartPos();
5595                const modifierKind = token();
5596
5597                if (token() === SyntaxKind.ConstKeyword && permitInvalidConstAsModifier) {
5598                    // We need to ensure that any subsequent modifiers appear on the same line
5599                    // so that when 'const' is a standalone declaration, we don't issue an error.
5600                    if (!tryParse(nextTokenIsOnSameLineAndCanFollowModifier)) {
5601                        break;
5602                    }
5603                }
5604                else {
5605                    if (!parseAnyContextualModifier()) {
5606                        break;
5607                    }
5608                }
5609
5610                const modifier = finishNode(<Modifier>createNode(modifierKind, modifierStart));
5611                (list || (list = [])).push(modifier);
5612            }
5613            return list && createNodeArray(list, listPos);
5614        }
5615
5616        function parseModifiersForArrowFunction(): NodeArray<Modifier> {
5617            let modifiers: NodeArray<Modifier>;
5618            if (token() === SyntaxKind.AsyncKeyword) {
5619                const modifierStart = scanner.getStartPos();
5620                const modifierKind = token();
5621                nextToken();
5622                const modifier = finishNode(<Modifier>createNode(modifierKind, modifierStart));
5623                modifiers = createNodeArray<Modifier>([modifier], modifierStart);
5624            }
5625            return modifiers;
5626        }
5627
5628        function parseClassElement(): ClassElement {
5629            if (token() === SyntaxKind.SemicolonToken) {
5630                const result = <SemicolonClassElement>createNode(SyntaxKind.SemicolonClassElement);
5631                nextToken();
5632                return finishNode(result);
5633            }
5634
5635            const node = <ClassElement>createNodeWithJSDoc(SyntaxKind.Unknown);
5636            node.decorators = parseDecorators();
5637            node.modifiers = parseModifiers(/*permitInvalidConstAsModifier*/ true);
5638
5639            if (parseContextualModifier(SyntaxKind.GetKeyword)) {
5640                return parseAccessorDeclaration(<AccessorDeclaration>node, SyntaxKind.GetAccessor);
5641            }
5642
5643            if (parseContextualModifier(SyntaxKind.SetKeyword)) {
5644                return parseAccessorDeclaration(<AccessorDeclaration>node, SyntaxKind.SetAccessor);
5645            }
5646
5647            if (token() === SyntaxKind.ConstructorKeyword) {
5648                return parseConstructorDeclaration(<ConstructorDeclaration>node);
5649            }
5650
5651            if (isIndexSignature()) {
5652                return parseIndexSignatureDeclaration(<IndexSignatureDeclaration>node);
5653            }
5654
5655            // It is very important that we check this *after* checking indexers because
5656            // the [ token can start an index signature or a computed property name
5657            if (tokenIsIdentifierOrKeyword(token()) ||
5658                token() === SyntaxKind.StringLiteral ||
5659                token() === SyntaxKind.NumericLiteral ||
5660                token() === SyntaxKind.AsteriskToken ||
5661                token() === SyntaxKind.OpenBracketToken) {
5662
5663                return parsePropertyOrMethodDeclaration(<PropertyDeclaration | MethodDeclaration>node);
5664            }
5665
5666            if (node.decorators || node.modifiers) {
5667                // treat this as a property declaration with a missing name.
5668                node.name = createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected);
5669                return parsePropertyDeclaration(<PropertyDeclaration>node);
5670            }
5671
5672            // 'isClassMemberStart' should have hinted not to attempt parsing.
5673            Debug.fail("Should not have attempted to parse class member declaration.");
5674        }
5675
5676        function parseClassExpression(): ClassExpression {
5677            return <ClassExpression>parseClassDeclarationOrExpression(<ClassLikeDeclaration>createNodeWithJSDoc(SyntaxKind.Unknown), SyntaxKind.ClassExpression);
5678        }
5679
5680        function parseClassDeclaration(node: ClassLikeDeclaration): ClassDeclaration {
5681            return <ClassDeclaration>parseClassDeclarationOrExpression(node, SyntaxKind.ClassDeclaration);
5682        }
5683
5684        function parseClassDeclarationOrExpression(node: ClassLikeDeclaration, kind: ClassLikeDeclaration["kind"]): ClassLikeDeclaration {
5685            node.kind = kind;
5686            parseExpected(SyntaxKind.ClassKeyword);
5687            node.name = parseNameOfClassDeclarationOrExpression();
5688            node.typeParameters = parseTypeParameters();
5689            node.heritageClauses = parseHeritageClauses();
5690
5691            if (parseExpected(SyntaxKind.OpenBraceToken)) {
5692                // ClassTail[Yield,Await] : (Modified) See 14.5
5693                //      ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }
5694                node.members = parseClassMembers();
5695                parseExpected(SyntaxKind.CloseBraceToken);
5696            }
5697            else {
5698                node.members = createMissingList<ClassElement>();
5699            }
5700
5701            return finishNode(node);
5702        }
5703
5704        function parseNameOfClassDeclarationOrExpression(): Identifier | undefined {
5705            // implements is a future reserved word so
5706            // 'class implements' might mean either
5707            // - class expression with omitted name, 'implements' starts heritage clause
5708            // - class with name 'implements'
5709            // 'isImplementsClause' helps to disambiguate between these two cases
5710            return isIdentifier() && !isImplementsClause()
5711                ? parseIdentifier()
5712                : undefined;
5713        }
5714
5715        function isImplementsClause() {
5716            return token() === SyntaxKind.ImplementsKeyword && lookAhead(nextTokenIsIdentifierOrKeyword);
5717        }
5718
5719        function parseHeritageClauses(): NodeArray<HeritageClause> | undefined {
5720            // ClassTail[Yield,Await] : (Modified) See 14.5
5721            //      ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }
5722
5723            if (isHeritageClause()) {
5724                return parseList(ParsingContext.HeritageClauses, parseHeritageClause);
5725            }
5726
5727            return undefined;
5728        }
5729
5730        function parseHeritageClause(): HeritageClause | undefined {
5731            const tok = token();
5732            if (tok === SyntaxKind.ExtendsKeyword || tok === SyntaxKind.ImplementsKeyword) {
5733                const node = <HeritageClause>createNode(SyntaxKind.HeritageClause);
5734                node.token = tok;
5735                nextToken();
5736                node.types = parseDelimitedList(ParsingContext.HeritageClauseElement, parseExpressionWithTypeArguments);
5737                return finishNode(node);
5738            }
5739
5740            return undefined;
5741        }
5742
5743        function parseExpressionWithTypeArguments(): ExpressionWithTypeArguments {
5744            const node = <ExpressionWithTypeArguments>createNode(SyntaxKind.ExpressionWithTypeArguments);
5745            node.expression = parseLeftHandSideExpressionOrHigher();
5746            node.typeArguments = tryParseTypeArguments();
5747            return finishNode(node);
5748        }
5749
5750        function tryParseTypeArguments(): NodeArray<TypeNode> | undefined {
5751            return token() === SyntaxKind.LessThanToken
5752               ? parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken)
5753               : undefined;
5754        }
5755
5756        function isHeritageClause(): boolean {
5757            return token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
5758        }
5759
5760        function parseClassMembers(): NodeArray<ClassElement> {
5761            return parseList(ParsingContext.ClassMembers, parseClassElement);
5762        }
5763
5764        function parseInterfaceDeclaration(node: InterfaceDeclaration): InterfaceDeclaration {
5765            node.kind = SyntaxKind.InterfaceDeclaration;
5766            parseExpected(SyntaxKind.InterfaceKeyword);
5767            node.name = parseIdentifier();
5768            node.typeParameters = parseTypeParameters();
5769            node.heritageClauses = parseHeritageClauses();
5770            node.members = parseObjectTypeMembers();
5771            return finishNode(node);
5772        }
5773
5774        function parseTypeAliasDeclaration(node: TypeAliasDeclaration): TypeAliasDeclaration {
5775            node.kind = SyntaxKind.TypeAliasDeclaration;
5776            parseExpected(SyntaxKind.TypeKeyword);
5777            node.name = parseIdentifier();
5778            node.typeParameters = parseTypeParameters();
5779            parseExpected(SyntaxKind.EqualsToken);
5780            node.type = parseType();
5781            parseSemicolon();
5782            return finishNode(node);
5783        }
5784
5785        // In an ambient declaration, the grammar only allows integer literals as initializers.
5786        // In a non-ambient declaration, the grammar allows uninitialized members only in a
5787        // ConstantEnumMemberSection, which starts at the beginning of an enum declaration
5788        // or any time an integer literal initializer is encountered.
5789        function parseEnumMember(): EnumMember {
5790            const node = <EnumMember>createNodeWithJSDoc(SyntaxKind.EnumMember);
5791            node.name = parsePropertyName();
5792            node.initializer = allowInAnd(parseInitializer);
5793            return finishNode(node);
5794        }
5795
5796        function parseEnumDeclaration(node: EnumDeclaration): EnumDeclaration {
5797            node.kind = SyntaxKind.EnumDeclaration;
5798            parseExpected(SyntaxKind.EnumKeyword);
5799            node.name = parseIdentifier();
5800            if (parseExpected(SyntaxKind.OpenBraceToken)) {
5801                node.members = parseDelimitedList(ParsingContext.EnumMembers, parseEnumMember);
5802                parseExpected(SyntaxKind.CloseBraceToken);
5803            }
5804            else {
5805                node.members = createMissingList<EnumMember>();
5806            }
5807            return finishNode(node);
5808        }
5809
5810        function parseModuleBlock(): ModuleBlock {
5811            const node = <ModuleBlock>createNode(SyntaxKind.ModuleBlock);
5812            if (parseExpected(SyntaxKind.OpenBraceToken)) {
5813                node.statements = parseList(ParsingContext.BlockStatements, parseStatement);
5814                parseExpected(SyntaxKind.CloseBraceToken);
5815            }
5816            else {
5817                node.statements = createMissingList<Statement>();
5818            }
5819            return finishNode(node);
5820        }
5821
5822        function parseModuleOrNamespaceDeclaration(node: ModuleDeclaration, flags: NodeFlags): ModuleDeclaration {
5823            node.kind = SyntaxKind.ModuleDeclaration;
5824            // If we are parsing a dotted namespace name, we want to
5825            // propagate the 'Namespace' flag across the names if set.
5826            const namespaceFlag = flags & NodeFlags.Namespace;
5827            node.flags |= flags;
5828            node.name = parseIdentifier();
5829            node.body = parseOptional(SyntaxKind.DotToken)
5830                ? <NamespaceDeclaration>parseModuleOrNamespaceDeclaration(<ModuleDeclaration>createNode(SyntaxKind.Unknown), NodeFlags.NestedNamespace | namespaceFlag)
5831                : parseModuleBlock();
5832            return finishNode(node);
5833        }
5834
5835        function parseAmbientExternalModuleDeclaration(node: ModuleDeclaration): ModuleDeclaration {
5836            node.kind = SyntaxKind.ModuleDeclaration;
5837            if (token() === SyntaxKind.GlobalKeyword) {
5838                // parse 'global' as name of global scope augmentation
5839                node.name = parseIdentifier();
5840                node.flags |= NodeFlags.GlobalAugmentation;
5841            }
5842            else {
5843                node.name = <StringLiteral>parseLiteralNode();
5844                node.name.text = internIdentifier(node.name.text);
5845            }
5846            if (token() === SyntaxKind.OpenBraceToken) {
5847                node.body = parseModuleBlock();
5848            }
5849            else {
5850                parseSemicolon();
5851            }
5852            return finishNode(node);
5853        }
5854
5855        function parseModuleDeclaration(node: ModuleDeclaration): ModuleDeclaration {
5856            let flags: NodeFlags = 0;
5857            if (token() === SyntaxKind.GlobalKeyword) {
5858                // global augmentation
5859                return parseAmbientExternalModuleDeclaration(node);
5860            }
5861            else if (parseOptional(SyntaxKind.NamespaceKeyword)) {
5862                flags |= NodeFlags.Namespace;
5863            }
5864            else {
5865                parseExpected(SyntaxKind.ModuleKeyword);
5866                if (token() === SyntaxKind.StringLiteral) {
5867                    return parseAmbientExternalModuleDeclaration(node);
5868                }
5869            }
5870            return parseModuleOrNamespaceDeclaration(node, flags);
5871        }
5872
5873        function isExternalModuleReference() {
5874            return token() === SyntaxKind.RequireKeyword &&
5875                lookAhead(nextTokenIsOpenParen);
5876        }
5877
5878        function nextTokenIsOpenParen() {
5879            return nextToken() === SyntaxKind.OpenParenToken;
5880        }
5881
5882        function nextTokenIsSlash() {
5883            return nextToken() === SyntaxKind.SlashToken;
5884        }
5885
5886        function parseNamespaceExportDeclaration(node: NamespaceExportDeclaration): NamespaceExportDeclaration {
5887            node.kind = SyntaxKind.NamespaceExportDeclaration;
5888            parseExpected(SyntaxKind.AsKeyword);
5889            parseExpected(SyntaxKind.NamespaceKeyword);
5890            node.name = parseIdentifier();
5891            parseSemicolon();
5892            return finishNode(node);
5893        }
5894
5895        function parseImportDeclarationOrImportEqualsDeclaration(node: ImportEqualsDeclaration | ImportDeclaration): ImportEqualsDeclaration | ImportDeclaration {
5896            parseExpected(SyntaxKind.ImportKeyword);
5897            const afterImportPos = scanner.getStartPos();
5898
5899            let identifier: Identifier;
5900            if (isIdentifier()) {
5901                identifier = parseIdentifier();
5902                if (token() !== SyntaxKind.CommaToken && token() !== SyntaxKind.FromKeyword) {
5903                    return parseImportEqualsDeclaration(<ImportEqualsDeclaration>node, identifier);
5904                }
5905            }
5906
5907            // Import statement
5908            node.kind = SyntaxKind.ImportDeclaration;
5909            // ImportDeclaration:
5910            //  import ImportClause from ModuleSpecifier ;
5911            //  import ModuleSpecifier;
5912            if (identifier || // import id
5913                token() === SyntaxKind.AsteriskToken || // import *
5914                token() === SyntaxKind.OpenBraceToken) { // import {
5915                (<ImportDeclaration>node).importClause = parseImportClause(identifier, afterImportPos);
5916                parseExpected(SyntaxKind.FromKeyword);
5917            }
5918
5919            (<ImportDeclaration>node).moduleSpecifier = parseModuleSpecifier();
5920            parseSemicolon();
5921            return finishNode(node);
5922        }
5923
5924        function parseImportEqualsDeclaration(node: ImportEqualsDeclaration, identifier: ts.Identifier): ImportEqualsDeclaration {
5925            node.kind = SyntaxKind.ImportEqualsDeclaration;
5926            node.name = identifier;
5927            parseExpected(SyntaxKind.EqualsToken);
5928            node.moduleReference = parseModuleReference();
5929            parseSemicolon();
5930            return finishNode(node);
5931        }
5932
5933        function parseImportClause(identifier: Identifier, fullStart: number) {
5934            // ImportClause:
5935            //  ImportedDefaultBinding
5936            //  NameSpaceImport
5937            //  NamedImports
5938            //  ImportedDefaultBinding, NameSpaceImport
5939            //  ImportedDefaultBinding, NamedImports
5940
5941            const importClause = <ImportClause>createNode(SyntaxKind.ImportClause, fullStart);
5942            if (identifier) {
5943                // ImportedDefaultBinding:
5944                //  ImportedBinding
5945                importClause.name = identifier;
5946            }
5947
5948            // If there was no default import or if there is comma token after default import
5949            // parse namespace or named imports
5950            if (!importClause.name ||
5951                parseOptional(SyntaxKind.CommaToken)) {
5952                importClause.namedBindings = token() === SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImportsOrExports(SyntaxKind.NamedImports);
5953            }
5954
5955            return finishNode(importClause);
5956        }
5957
5958        function parseModuleReference() {
5959            return isExternalModuleReference()
5960                ? parseExternalModuleReference()
5961                : parseEntityName(/*allowReservedWords*/ false);
5962        }
5963
5964        function parseExternalModuleReference() {
5965            const node = <ExternalModuleReference>createNode(SyntaxKind.ExternalModuleReference);
5966            parseExpected(SyntaxKind.RequireKeyword);
5967            parseExpected(SyntaxKind.OpenParenToken);
5968            node.expression = parseModuleSpecifier();
5969            parseExpected(SyntaxKind.CloseParenToken);
5970            return finishNode(node);
5971        }
5972
5973        function parseModuleSpecifier(): Expression {
5974            if (token() === SyntaxKind.StringLiteral) {
5975                const result = parseLiteralNode();
5976                result.text = internIdentifier(result.text);
5977                return result;
5978            }
5979            else {
5980                // We allow arbitrary expressions here, even though the grammar only allows string
5981                // literals.  We check to ensure that it is only a string literal later in the grammar
5982                // check pass.
5983                return parseExpression();
5984            }
5985        }
5986
5987        function parseNamespaceImport(): NamespaceImport {
5988            // NameSpaceImport:
5989            //  * as ImportedBinding
5990            const namespaceImport = <NamespaceImport>createNode(SyntaxKind.NamespaceImport);
5991            parseExpected(SyntaxKind.AsteriskToken);
5992            parseExpected(SyntaxKind.AsKeyword);
5993            namespaceImport.name = parseIdentifier();
5994            return finishNode(namespaceImport);
5995        }
5996
5997        function parseNamedImportsOrExports(kind: SyntaxKind.NamedImports): NamedImports;
5998        function parseNamedImportsOrExports(kind: SyntaxKind.NamedExports): NamedExports;
5999        function parseNamedImportsOrExports(kind: SyntaxKind): NamedImportsOrExports {
6000            const node = <NamedImports | NamedExports>createNode(kind);
6001
6002            // NamedImports:
6003            //  { }
6004            //  { ImportsList }
6005            //  { ImportsList, }
6006
6007            // ImportsList:
6008            //  ImportSpecifier
6009            //  ImportsList, ImportSpecifier
6010            node.elements = <NodeArray<ImportSpecifier> | NodeArray<ExportSpecifier>>parseBracketedList(ParsingContext.ImportOrExportSpecifiers,
6011                kind === SyntaxKind.NamedImports ? parseImportSpecifier : parseExportSpecifier,
6012                SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken);
6013            return finishNode(node);
6014        }
6015
6016        function parseExportSpecifier() {
6017            return parseImportOrExportSpecifier(SyntaxKind.ExportSpecifier);
6018        }
6019
6020        function parseImportSpecifier() {
6021            return parseImportOrExportSpecifier(SyntaxKind.ImportSpecifier);
6022        }
6023
6024        function parseImportOrExportSpecifier(kind: SyntaxKind): ImportOrExportSpecifier {
6025            const node = <ImportSpecifier>createNode(kind);
6026            // ImportSpecifier:
6027            //   BindingIdentifier
6028            //   IdentifierName as BindingIdentifier
6029            // ExportSpecifier:
6030            //   IdentifierName
6031            //   IdentifierName as IdentifierName
6032            let checkIdentifierIsKeyword = isKeyword(token()) && !isIdentifier();
6033            let checkIdentifierStart = scanner.getTokenPos();
6034            let checkIdentifierEnd = scanner.getTextPos();
6035            const identifierName = parseIdentifierName();
6036            if (token() === SyntaxKind.AsKeyword) {
6037                node.propertyName = identifierName;
6038                parseExpected(SyntaxKind.AsKeyword);
6039                checkIdentifierIsKeyword = isKeyword(token()) && !isIdentifier();
6040                checkIdentifierStart = scanner.getTokenPos();
6041                checkIdentifierEnd = scanner.getTextPos();
6042                node.name = parseIdentifierName();
6043            }
6044            else {
6045                node.name = identifierName;
6046            }
6047            if (kind === SyntaxKind.ImportSpecifier && checkIdentifierIsKeyword) {
6048                // Report error identifier expected
6049                parseErrorAtPosition(checkIdentifierStart, checkIdentifierEnd - checkIdentifierStart, Diagnostics.Identifier_expected);
6050            }
6051            return finishNode(node);
6052        }
6053
6054        function parseExportDeclaration(node: ExportDeclaration): ExportDeclaration {
6055            node.kind = SyntaxKind.ExportDeclaration;
6056            if (parseOptional(SyntaxKind.AsteriskToken)) {
6057                parseExpected(SyntaxKind.FromKeyword);
6058                node.moduleSpecifier = parseModuleSpecifier();
6059            }
6060            else {
6061                node.exportClause = parseNamedImportsOrExports(SyntaxKind.NamedExports);
6062                // It is not uncommon to accidentally omit the 'from' keyword. Additionally, in editing scenarios,
6063                // the 'from' keyword can be parsed as a named export when the export clause is unterminated (i.e. `export { from "moduleName";`)
6064                // If we don't have a 'from' keyword, see if we have a string literal such that ASI won't take effect.
6065                if (token() === SyntaxKind.FromKeyword || (token() === SyntaxKind.StringLiteral && !scanner.hasPrecedingLineBreak())) {
6066                    parseExpected(SyntaxKind.FromKeyword);
6067                    node.moduleSpecifier = parseModuleSpecifier();
6068                }
6069            }
6070            parseSemicolon();
6071            return finishNode(node);
6072        }
6073
6074        function parseExportAssignment(node: ExportAssignment): ExportAssignment {
6075            node.kind = SyntaxKind.ExportAssignment;
6076            if (parseOptional(SyntaxKind.EqualsToken)) {
6077                node.isExportEquals = true;
6078            }
6079            else {
6080                parseExpected(SyntaxKind.DefaultKeyword);
6081            }
6082            node.expression = parseAssignmentExpressionOrHigher();
6083            parseSemicolon();
6084            return finishNode(node);
6085        }
6086
6087        function processReferenceComments(sourceFile: SourceFile): void {
6088            const triviaScanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ false, LanguageVariant.Standard, sourceText);
6089            const referencedFiles: FileReference[] = [];
6090            const typeReferenceDirectives: FileReference[] = [];
6091            const amdDependencies: { path: string; name: string }[] = [];
6092            let amdModuleName: string;
6093            let checkJsDirective: CheckJsDirective = undefined;
6094
6095            // Keep scanning all the leading trivia in the file until we get to something that
6096            // isn't trivia.  Any single line comment will be analyzed to see if it is a
6097            // reference comment.
6098            while (true) {
6099                const kind = triviaScanner.scan();
6100                if (kind !== SyntaxKind.SingleLineCommentTrivia) {
6101                    if (isTrivia(kind)) {
6102                        continue;
6103                    }
6104                    else {
6105                        break;
6106                    }
6107                }
6108
6109                const range = {
6110                    kind: <SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia>triviaScanner.getToken(),
6111                    pos: triviaScanner.getTokenPos(),
6112                    end: triviaScanner.getTextPos(),
6113                };
6114
6115                const comment = sourceText.substring(range.pos, range.end);
6116                const referencePathMatchResult = getFileReferenceFromReferencePath(comment, range);
6117                if (referencePathMatchResult) {
6118                    const fileReference = referencePathMatchResult.fileReference;
6119                    sourceFile.hasNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
6120                    const diagnosticMessage = referencePathMatchResult.diagnosticMessage;
6121                    if (fileReference) {
6122                        if (referencePathMatchResult.isTypeReferenceDirective) {
6123                            typeReferenceDirectives.push(fileReference);
6124                        }
6125                        else {
6126                            referencedFiles.push(fileReference);
6127                        }
6128                    }
6129                    if (diagnosticMessage) {
6130                        parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, diagnosticMessage));
6131                    }
6132                }
6133                else {
6134                    const amdModuleNameRegEx = /^\/\/\/\s*<amd-module\s+name\s*=\s*('|")(.+?)\1/gim;
6135                    const amdModuleNameMatchResult = amdModuleNameRegEx.exec(comment);
6136                    if (amdModuleNameMatchResult) {
6137                        if (amdModuleName) {
6138                            parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments));
6139                        }
6140                        amdModuleName = amdModuleNameMatchResult[2];
6141                    }
6142
6143                    const amdDependencyRegEx = /^\/\/\/\s*<amd-dependency\s/gim;
6144                    const pathRegex = /\spath\s*=\s*('|")(.+?)\1/gim;
6145                    const nameRegex = /\sname\s*=\s*('|")(.+?)\1/gim;
6146                    const amdDependencyMatchResult = amdDependencyRegEx.exec(comment);
6147                    if (amdDependencyMatchResult) {
6148                        const pathMatchResult = pathRegex.exec(comment);
6149                        const nameMatchResult = nameRegex.exec(comment);
6150                        if (pathMatchResult) {
6151                            const amdDependency = { path: pathMatchResult[2], name: nameMatchResult ? nameMatchResult[2] : undefined };
6152                            amdDependencies.push(amdDependency);
6153                        }
6154                    }
6155
6156                    const checkJsDirectiveRegEx = /^\/\/\/?\s*(@ts-check|@ts-nocheck)\s*$/gim;
6157                    const checkJsDirectiveMatchResult = checkJsDirectiveRegEx.exec(comment);
6158                    if (checkJsDirectiveMatchResult) {
6159                        checkJsDirective = {
6160                            enabled: equateStringsCaseInsensitive(checkJsDirectiveMatchResult[1], "@ts-check"),
6161                            end: range.end,
6162                            pos: range.pos
6163                        };
6164                    }
6165                }
6166            }
6167
6168            sourceFile.referencedFiles = referencedFiles;
6169            sourceFile.typeReferenceDirectives = typeReferenceDirectives;
6170            sourceFile.amdDependencies = amdDependencies;
6171            sourceFile.moduleName = amdModuleName;
6172            sourceFile.checkJsDirective = checkJsDirective;
6173        }
6174
6175        function setExternalModuleIndicator(sourceFile: SourceFile) {
6176            sourceFile.externalModuleIndicator = forEach(sourceFile.statements, node =>
6177                hasModifier(node, ModifierFlags.Export)
6178                    || node.kind === SyntaxKind.ImportEqualsDeclaration && (<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference
6179                    || node.kind === SyntaxKind.ImportDeclaration
6180                    || node.kind === SyntaxKind.ExportAssignment
6181                    || node.kind === SyntaxKind.ExportDeclaration
6182                    ? node
6183                    : undefined);
6184        }
6185
6186        const enum ParsingContext {
6187            SourceElements,            // Elements in source file
6188            BlockStatements,           // Statements in block
6189            SwitchClauses,             // Clauses in switch statement
6190            SwitchClauseStatements,    // Statements in switch clause
6191            TypeMembers,               // Members in interface or type literal
6192            ClassMembers,              // Members in class declaration
6193            EnumMembers,               // Members in enum declaration
6194            HeritageClauseElement,     // Elements in a heritage clause
6195            VariableDeclarations,      // Variable declarations in variable statement
6196            ObjectBindingElements,     // Binding elements in object binding list
6197            ArrayBindingElements,      // Binding elements in array binding list
6198            ArgumentExpressions,       // Expressions in argument list
6199            ObjectLiteralMembers,      // Members in object literal
6200            JsxAttributes,             // Attributes in jsx element
6201            JsxChildren,               // Things between opening and closing JSX tags
6202            ArrayLiteralMembers,       // Members in array literal
6203            Parameters,                // Parameters in parameter list
6204            RestProperties,            // Property names in a rest type list
6205            TypeParameters,            // Type parameters in type parameter list
6206            TypeArguments,             // Type arguments in type argument list
6207            TupleElementTypes,         // Element types in tuple element type list
6208            HeritageClauses,           // Heritage clauses for a class or interface declaration.
6209            ImportOrExportSpecifiers,  // Named import clause's import specifier list
6210            Count                      // Number of parsing contexts
6211        }
6212
6213        const enum Tristate {
6214            False,
6215            True,
6216            Unknown
6217        }
6218
6219        export namespace JSDocParser {
6220            export function parseJSDocTypeExpressionForTests(content: string, start: number, length: number): { jsDocTypeExpression: JSDocTypeExpression, diagnostics: Diagnostic[] } | undefined {
6221                initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS);
6222                sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS, /*isDeclarationFile*/ false);
6223                scanner.setText(content, start, length);
6224                currentToken = scanner.scan();
6225                const jsDocTypeExpression = parseJSDocTypeExpression();
6226                const diagnostics = parseDiagnostics;
6227                clearState();
6228
6229                return jsDocTypeExpression ? { jsDocTypeExpression, diagnostics } : undefined;
6230            }
6231
6232            // Parses out a JSDoc type expression.
6233            export function parseJSDocTypeExpression(mayOmitBraces?: boolean): JSDocTypeExpression {
6234                const result = <JSDocTypeExpression>createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos());
6235
6236                const hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(SyntaxKind.OpenBraceToken);
6237                result.type = doInsideOfContext(NodeFlags.JSDoc, parseType);
6238                if (!mayOmitBraces || hasBrace) {
6239                    parseExpected(SyntaxKind.CloseBraceToken);
6240                }
6241
6242                fixupParentReferences(result);
6243                return finishNode(result);
6244            }
6245
6246            export function parseIsolatedJSDocComment(content: string, start: number, length: number): { jsDoc: JSDoc, diagnostics: Diagnostic[] } | undefined {
6247                initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS);
6248                sourceFile = <SourceFile>{ languageVariant: LanguageVariant.Standard, text: content }; // tslint:disable-line no-object-literal-type-assertion
6249                const jsDoc = parseJSDocCommentWorker(start, length);
6250                const diagnostics = parseDiagnostics;
6251                clearState();
6252
6253                return jsDoc ? { jsDoc, diagnostics } : undefined;
6254            }
6255
6256            export function parseJSDocComment(parent: HasJSDoc, start: number, length: number): JSDoc {
6257                const saveToken = currentToken;
6258                const saveParseDiagnosticsLength = parseDiagnostics.length;
6259                const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
6260
6261                const comment = parseJSDocCommentWorker(start, length);
6262                if (comment) {
6263                    comment.parent = parent;
6264                }
6265
6266                if (contextFlags & NodeFlags.JavaScriptFile) {
6267                    if (!sourceFile.jsDocDiagnostics) {
6268                        sourceFile.jsDocDiagnostics = [];
6269                    }
6270                    sourceFile.jsDocDiagnostics.push(...parseDiagnostics);
6271                }
6272                currentToken = saveToken;
6273                parseDiagnostics.length = saveParseDiagnosticsLength;
6274                parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode;
6275
6276                return comment;
6277            }
6278
6279            const enum JSDocState {
6280                BeginningOfLine,
6281                SawAsterisk,
6282                SavingComments,
6283            }
6284
6285            const enum PropertyLikeParse {
6286                Property,
6287                Parameter,
6288            }
6289
6290            export function parseJSDocCommentWorker(start: number, length: number): JSDoc {
6291                const content = sourceText;
6292                start = start || 0;
6293                const end = length === undefined ? content.length : start + length;
6294                length = end - start;
6295
6296                Debug.assert(start >= 0);
6297                Debug.assert(start <= end);
6298                Debug.assert(end <= content.length);
6299
6300                let tags: JSDocTag[];
6301                let tagsPos: number;
6302                let tagsEnd: number;
6303                const comments: string[] = [];
6304                let result: JSDoc;
6305
6306                // Check for /** (JSDoc opening part)
6307                if (!isJsDocStart(content, start)) {
6308                    return result;
6309                }
6310
6311                // + 3 for leading /**, - 5 in total for /** */
6312                scanner.scanRange(start + 3, length - 5, () => {
6313                    // Initially we can parse out a tag.  We also have seen a starting asterisk.
6314                    // This is so that /** * @type */ doesn't parse.
6315                    let state = JSDocState.SawAsterisk;
6316                    let margin: number | undefined = undefined;
6317                    // + 4 for leading '/** '
6318                    let indent = start - Math.max(content.lastIndexOf("\n", start), 0) + 4;
6319                    function pushComment(text: string) {
6320                        if (!margin) {
6321                            margin = indent;
6322                        }
6323                        comments.push(text);
6324                        indent += text.length;
6325                    }
6326
6327                    let t = nextJSDocToken();
6328                    while (t === SyntaxKind.WhitespaceTrivia) {
6329                        t = nextJSDocToken();
6330                    }
6331                    if (t === SyntaxKind.NewLineTrivia) {
6332                        state = JSDocState.BeginningOfLine;
6333                        indent = 0;
6334                        t = nextJSDocToken();
6335                    }
6336                    loop: while (true) {
6337                        switch (t) {
6338                            case SyntaxKind.AtToken:
6339                                if (state === JSDocState.BeginningOfLine || state === JSDocState.SawAsterisk) {
6340                                    removeTrailingNewlines(comments);
6341                                    parseTag(indent);
6342                                    // NOTE: According to usejsdoc.org, a tag goes to end of line, except the last tag.
6343                                    // Real-world comments may break this rule, so "BeginningOfLine" will not be a real line beginning
6344                                    // for malformed examples like `/** @param {string} x @returns {number} the length */`
6345                                    state = JSDocState.BeginningOfLine;
6346                                    margin = undefined;
6347                                    indent++;
6348                                }
6349                                else {
6350                                    pushComment(scanner.getTokenText());
6351                                }
6352                                break;
6353                            case SyntaxKind.NewLineTrivia:
6354                                comments.push(scanner.getTokenText());
6355                                state = JSDocState.BeginningOfLine;
6356                                indent = 0;
6357                                break;
6358                            case SyntaxKind.AsteriskToken:
6359                                const asterisk = scanner.getTokenText();
6360                                if (state === JSDocState.SawAsterisk || state === JSDocState.SavingComments) {
6361                                    // If we've already seen an asterisk, then we can no longer parse a tag on this line
6362                                    state = JSDocState.SavingComments;
6363                                    pushComment(asterisk);
6364                                }
6365                                else {
6366                                    // Ignore the first asterisk on a line
6367                                    state = JSDocState.SawAsterisk;
6368                                    indent += asterisk.length;
6369                                }
6370                                break;
6371                            case SyntaxKind.Identifier:
6372                                // Anything else is doc comment text. We just save it. Because it
6373                                // wasn't a tag, we can no longer parse a tag on this line until we hit the next
6374                                // line break.
6375                                pushComment(scanner.getTokenText());
6376                                state = JSDocState.SavingComments;
6377                                break;
6378                            case SyntaxKind.WhitespaceTrivia:
6379                                // only collect whitespace if we're already saving comments or have just crossed the comment indent margin
6380                                const whitespace = scanner.getTokenText();
6381                                if (state === JSDocState.SavingComments) {
6382                                    comments.push(whitespace);
6383                                }
6384                                else if (margin !== undefined && indent + whitespace.length > margin) {
6385                                    comments.push(whitespace.slice(margin - indent - 1));
6386                                }
6387                                indent += whitespace.length;
6388                                break;
6389                            case SyntaxKind.EndOfFileToken:
6390                                break loop;
6391                            default:
6392                                // anything other than whitespace or asterisk at the beginning of the line starts the comment text
6393                                state = JSDocState.SavingComments;
6394                                pushComment(scanner.getTokenText());
6395                                break;
6396                        }
6397                        t = nextJSDocToken();
6398                    }
6399                    removeLeadingNewlines(comments);
6400                    removeTrailingNewlines(comments);
6401                    result = createJSDocComment();
6402
6403                });
6404
6405                return result;
6406
6407                function removeLeadingNewlines(comments: string[]) {
6408                    while (comments.length && (comments[0] === "\n" || comments[0] === "\r")) {
6409                        comments.shift();
6410                    }
6411                }
6412
6413                function removeTrailingNewlines(comments: string[]) {
6414                    while (comments.length && (comments[comments.length - 1] === "\n" || comments[comments.length - 1] === "\r")) {
6415                        comments.pop();
6416                    }
6417                }
6418
6419                function isJsDocStart(content: string, start: number) {
6420                    return content.charCodeAt(start) === CharacterCodes.slash &&
6421                        content.charCodeAt(start + 1) === CharacterCodes.asterisk &&
6422                        content.charCodeAt(start + 2) === CharacterCodes.asterisk &&
6423                        content.charCodeAt(start + 3) !== CharacterCodes.asterisk;
6424                }
6425
6426                function createJSDocComment(): JSDoc {
6427                    const result = <JSDoc>createNode(SyntaxKind.JSDocComment, start);
6428                    result.tags = tags && createNodeArray(tags, tagsPos, tagsEnd);
6429                    result.comment = comments.length ? comments.join("") : undefined;
6430                    return finishNode(result, end);
6431                }
6432
6433                function skipWhitespace(): void {
6434                    while (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) {
6435                        nextJSDocToken();
6436                    }
6437                }
6438
6439                function parseTag(indent: number) {
6440                    Debug.assert(token() === SyntaxKind.AtToken);
6441                    const atToken = <AtToken>createNode(SyntaxKind.AtToken, scanner.getTokenPos());
6442                    atToken.end = scanner.getTextPos();
6443                    nextJSDocToken();
6444
6445                    const tagName = parseJSDocIdentifierName();
6446                    skipWhitespace();
6447                    if (!tagName) {
6448                        return;
6449                    }
6450
6451                    let tag: JSDocTag;
6452                    if (tagName) {
6453                        switch (tagName.escapedText) {
6454                            case "augments":
6455                            case "extends":
6456                                tag = parseAugmentsTag(atToken, tagName);
6457                                break;
6458                            case "class":
6459                            case "constructor":
6460                                tag = parseClassTag(atToken, tagName);
6461                                break;
6462                            case "arg":
6463                            case "argument":
6464                            case "param":
6465                                tag = parseParameterOrPropertyTag(atToken, tagName, PropertyLikeParse.Parameter);
6466                                break;
6467                            case "return":
6468                            case "returns":
6469                                tag = parseReturnTag(atToken, tagName);
6470                                break;
6471                            case "template":
6472                                tag = parseTemplateTag(atToken, tagName);
6473                                break;
6474                            case "type":
6475                                tag = parseTypeTag(atToken, tagName);
6476                                break;
6477                            case "typedef":
6478                                tag = parseTypedefTag(atToken, tagName);
6479                                break;
6480                            default:
6481                                tag = parseUnknownTag(atToken, tagName);
6482                                break;
6483                        }
6484                    }
6485                    else {
6486                        tag = parseUnknownTag(atToken, tagName);
6487                    }
6488
6489                    if (!tag) {
6490                        // a badly malformed tag should not be added to the list of tags
6491                        return;
6492                    }
6493                    tag.comment = parseTagComments(indent + tag.end - tag.pos);
6494                    addTag(tag);
6495                }
6496
6497                function parseTagComments(indent: number): string | undefined {
6498                    const comments: string[] = [];
6499                    let state = JSDocState.BeginningOfLine;
6500                    let margin: number | undefined;
6501                    function pushComment(text: string) {
6502                        if (!margin) {
6503                            margin = indent;
6504                        }
6505                        comments.push(text);
6506                        indent += text.length;
6507                    }
6508                    let tok = token() as JsDocSyntaxKind;
6509                    loop: while (true) {
6510                        switch (tok) {
6511                            case SyntaxKind.NewLineTrivia:
6512                                if (state >= JSDocState.SawAsterisk) {
6513                                    state = JSDocState.BeginningOfLine;
6514                                    comments.push(scanner.getTokenText());
6515                                }
6516                                indent = 0;
6517                                break;
6518                            case SyntaxKind.AtToken:
6519                                scanner.setTextPos(scanner.getTextPos() - 1);
6520                                // falls through
6521                            case SyntaxKind.EndOfFileToken:
6522                                // Done
6523                                break loop;
6524                            case SyntaxKind.WhitespaceTrivia:
6525                                if (state === JSDocState.SavingComments) {
6526                                    pushComment(scanner.getTokenText());
6527                                }
6528                                else {
6529                                    const whitespace = scanner.getTokenText();
6530                                    // if the whitespace crosses the margin, take only the whitespace that passes the margin
6531                                    if (margin !== undefined && indent + whitespace.length > margin) {
6532                                        comments.push(whitespace.slice(margin - indent - 1));
6533                                    }
6534                                    indent += whitespace.length;
6535                                }
6536                                break;
6537                            case SyntaxKind.AsteriskToken:
6538                                if (state === JSDocState.BeginningOfLine) {
6539                                    // leading asterisks start recording on the *next* (non-whitespace) token
6540                                    state = JSDocState.SawAsterisk;
6541                                    indent += 1;
6542                                    break;
6543                                }
6544                                // record the * as a comment
6545                                // falls through
6546                            default:
6547                                state = JSDocState.SavingComments; // leading identifiers start recording as well
6548                                pushComment(scanner.getTokenText());
6549                                break;
6550                        }
6551                        tok = nextJSDocToken();
6552                    }
6553
6554                    removeLeadingNewlines(comments);
6555                    removeTrailingNewlines(comments);
6556                    return comments.length === 0 ? undefined : comments.join("");
6557                }
6558
6559                function parseUnknownTag(atToken: AtToken, tagName: Identifier) {
6560                    const result = <JSDocTag>createNode(SyntaxKind.JSDocTag, atToken.pos);
6561                    result.atToken = atToken;
6562                    result.tagName = tagName;
6563                    return finishNode(result);
6564                }
6565
6566                function addTag(tag: JSDocTag): void {
6567                    if (!tags) {
6568                        tags = [tag];
6569                        tagsPos = tag.pos;
6570                    }
6571                    else {
6572                        tags.push(tag);
6573                    }
6574                    tagsEnd = tag.end;
6575                }
6576
6577                function tryParseTypeExpression(): JSDocTypeExpression | undefined {
6578                    skipWhitespace();
6579                    return token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined;
6580                }
6581
6582                function parseBracketNameInPropertyAndParamTag(): { name: EntityName, isBracketed: boolean } {
6583                    // Looking for something like '[foo]', 'foo', '[foo.bar]' or 'foo.bar'
6584                    const isBracketed = parseOptional(SyntaxKind.OpenBracketToken);
6585                    const name = parseJSDocEntityName();
6586                    if (isBracketed) {
6587                        skipWhitespace();
6588
6589                        // May have an optional default, e.g. '[foo = 42]'
6590                        if (parseOptionalToken(SyntaxKind.EqualsToken)) {
6591                            parseExpression();
6592                        }
6593
6594                        parseExpected(SyntaxKind.CloseBracketToken);
6595                    }
6596
6597                    return { name, isBracketed };
6598                }
6599
6600                function isObjectOrObjectArrayTypeReference(node: TypeNode): boolean {
6601                    switch (node.kind) {
6602                        case SyntaxKind.ObjectKeyword:
6603                            return true;
6604                        case SyntaxKind.ArrayType:
6605                            return isObjectOrObjectArrayTypeReference((node as ArrayTypeNode).elementType);
6606                        default:
6607                            return isTypeReferenceNode(node) && ts.isIdentifier(node.typeName) && node.typeName.escapedText === "Object";
6608                    }
6609                }
6610
6611                function parseParameterOrPropertyTag(atToken: AtToken, tagName: Identifier, target: PropertyLikeParse): JSDocParameterTag | JSDocPropertyTag {
6612                    let typeExpression = tryParseTypeExpression();
6613                    let isNameFirst = !typeExpression;
6614                    skipWhitespace();
6615
6616                    const { name, isBracketed } = parseBracketNameInPropertyAndParamTag();
6617                    skipWhitespace();
6618
6619                    if (isNameFirst) {
6620                        typeExpression = tryParseTypeExpression();
6621                    }
6622
6623                    const result = target === PropertyLikeParse.Parameter ?
6624                        <JSDocParameterTag>createNode(SyntaxKind.JSDocParameterTag, atToken.pos) :
6625                        <JSDocPropertyTag>createNode(SyntaxKind.JSDocPropertyTag, atToken.pos);
6626                    const nestedTypeLiteral = parseNestedTypeLiteral(typeExpression, name);
6627                    if (nestedTypeLiteral) {
6628                        typeExpression = nestedTypeLiteral;
6629                        isNameFirst = true;
6630                    }
6631                    result.atToken = atToken;
6632                    result.tagName = tagName;
6633                    result.typeExpression = typeExpression;
6634                    result.name = name;
6635                    result.isNameFirst = isNameFirst;
6636                    result.isBracketed = isBracketed;
6637                    return finishNode(result);
6638                }
6639
6640                function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression, name: EntityName) {
6641                    if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) {
6642                        const typeLiteralExpression = <JSDocTypeExpression>createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos());
6643                        let child: JSDocParameterTag | false;
6644                        let jsdocTypeLiteral: JSDocTypeLiteral;
6645                        const start = scanner.getStartPos();
6646                        let children: JSDocParameterTag[];
6647                        while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.Parameter, name))) {
6648                            children = append(children, child);
6649                        }
6650                        if (children) {
6651                            jsdocTypeLiteral = <JSDocTypeLiteral>createNode(SyntaxKind.JSDocTypeLiteral, start);
6652                            jsdocTypeLiteral.jsDocPropertyTags = children;
6653                            if (typeExpression.type.kind === SyntaxKind.ArrayType) {
6654                                jsdocTypeLiteral.isArrayType = true;
6655                            }
6656                            typeLiteralExpression.type = finishNode(jsdocTypeLiteral);
6657                            return finishNode(typeLiteralExpression);
6658                        }
6659                    }
6660                }
6661
6662                function parseReturnTag(atToken: AtToken, tagName: Identifier): JSDocReturnTag {
6663                    if (forEach(tags, t => t.kind === SyntaxKind.JSDocReturnTag)) {
6664                        parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, Diagnostics._0_tag_already_specified, tagName.escapedText);
6665                    }
6666
6667                    const result = <JSDocReturnTag>createNode(SyntaxKind.JSDocReturnTag, atToken.pos);
6668                    result.atToken = atToken;
6669                    result.tagName = tagName;
6670                    result.typeExpression = tryParseTypeExpression();
6671                    return finishNode(result);
6672                }
6673
6674                function parseTypeTag(atToken: AtToken, tagName: Identifier): JSDocTypeTag {
6675                    if (forEach(tags, t => t.kind === SyntaxKind.JSDocTypeTag)) {
6676                        parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, Diagnostics._0_tag_already_specified, tagName.escapedText);
6677                    }
6678
6679                    const result = <JSDocTypeTag>createNode(SyntaxKind.JSDocTypeTag, atToken.pos);
6680                    result.atToken = atToken;
6681                    result.tagName = tagName;
6682                    result.typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true);
6683                    return finishNode(result);
6684                }
6685
6686                function parseAugmentsTag(atToken: AtToken, tagName: Identifier): JSDocAugmentsTag {
6687                    const result = <JSDocAugmentsTag>createNode(SyntaxKind.JSDocAugmentsTag, atToken.pos);
6688                    result.atToken = atToken;
6689                    result.tagName = tagName;
6690                    result.class = parseExpressionWithTypeArgumentsForAugments();
6691                    return finishNode(result);
6692                }
6693
6694                function parseExpressionWithTypeArgumentsForAugments(): ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression } {
6695                    const usedBrace = parseOptional(SyntaxKind.OpenBraceToken);
6696                    const node = createNode(SyntaxKind.ExpressionWithTypeArguments) as ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression };
6697                    node.expression = parsePropertyAccessEntityNameExpression();
6698                    node.typeArguments = tryParseTypeArguments();
6699                    const res = finishNode(node);
6700                    if (usedBrace) {
6701                        parseExpected(SyntaxKind.CloseBraceToken);
6702                    }
6703                    return res;
6704                }
6705
6706                function parsePropertyAccessEntityNameExpression() {
6707                    let node: Identifier | PropertyAccessEntityNameExpression = parseJSDocIdentifierName(/*createIfMissing*/ true);
6708                    while (parseOptional(SyntaxKind.DotToken)) {
6709                        const prop: PropertyAccessEntityNameExpression = createNode(SyntaxKind.PropertyAccessExpression, node.pos) as PropertyAccessEntityNameExpression;
6710                        prop.expression = node;
6711                        prop.name = parseJSDocIdentifierName();
6712                        node = finishNode(prop);
6713                    }
6714                    return node;
6715                }
6716
6717                function parseClassTag(atToken: AtToken, tagName: Identifier): JSDocClassTag {
6718                    const tag = <JSDocClassTag>createNode(SyntaxKind.JSDocClassTag, atToken.pos);
6719                    tag.atToken = atToken;
6720                    tag.tagName = tagName;
6721                    return finishNode(tag);
6722                }
6723
6724                function parseTypedefTag(atToken: AtToken, tagName: Identifier): JSDocTypedefTag {
6725                    const typeExpression = tryParseTypeExpression();
6726                    skipWhitespace();
6727
6728                    const typedefTag = <JSDocTypedefTag>createNode(SyntaxKind.JSDocTypedefTag, atToken.pos);
6729                    typedefTag.atToken = atToken;
6730                    typedefTag.tagName = tagName;
6731                    typedefTag.fullName = parseJSDocTypeNameWithNamespace(/*flags*/ 0);
6732                    if (typedefTag.fullName) {
6733                        let rightNode = typedefTag.fullName;
6734                        while (true) {
6735                            if (rightNode.kind === SyntaxKind.Identifier || !rightNode.body) {
6736                                // if node is identifier - use it as name
6737                                // otherwise use name of the rightmost part that we were able to parse
6738                                typedefTag.name = rightNode.kind === SyntaxKind.Identifier ? rightNode : rightNode.name;
6739                                break;
6740                            }
6741                            rightNode = rightNode.body;
6742                        }
6743                    }
6744                    skipWhitespace();
6745
6746                    typedefTag.typeExpression = typeExpression;
6747                    if (!typeExpression || isObjectOrObjectArrayTypeReference(typeExpression.type)) {
6748                        let child: JSDocTypeTag | JSDocPropertyTag | false;
6749                        let jsdocTypeLiteral: JSDocTypeLiteral;
6750                        let childTypeTag: JSDocTypeTag;
6751                        const start = scanner.getStartPos();
6752                        while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.Property))) {
6753                            if (!jsdocTypeLiteral) {
6754                                jsdocTypeLiteral = <JSDocTypeLiteral>createNode(SyntaxKind.JSDocTypeLiteral, start);
6755                            }
6756                            if (child.kind === SyntaxKind.JSDocTypeTag) {
6757                                if (childTypeTag) {
6758                                    break;
6759                                }
6760                                else {
6761                                    childTypeTag = child;
6762                                }
6763                            }
6764                            else {
6765                                jsdocTypeLiteral.jsDocPropertyTags = append(jsdocTypeLiteral.jsDocPropertyTags as MutableNodeArray<JSDocPropertyTag>, child);
6766                            }
6767                        }
6768                        if (jsdocTypeLiteral) {
6769                            if (typeExpression && typeExpression.type.kind === SyntaxKind.ArrayType) {
6770                                jsdocTypeLiteral.isArrayType = true;
6771                            }
6772                            typedefTag.typeExpression = childTypeTag && childTypeTag.typeExpression && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) ?
6773                                childTypeTag.typeExpression :
6774                                finishNode(jsdocTypeLiteral);
6775                        }
6776                    }
6777
6778                    return finishNode(typedefTag);
6779
6780                    function parseJSDocTypeNameWithNamespace(flags: NodeFlags) {
6781                        const pos = scanner.getTokenPos();
6782                        const typeNameOrNamespaceName = parseJSDocIdentifierName();
6783
6784                        if (typeNameOrNamespaceName && parseOptional(SyntaxKind.DotToken)) {
6785                            const jsDocNamespaceNode = <JSDocNamespaceDeclaration>createNode(SyntaxKind.ModuleDeclaration, pos);
6786                            jsDocNamespaceNode.flags |= flags;
6787                            jsDocNamespaceNode.name = typeNameOrNamespaceName;
6788                            jsDocNamespaceNode.body = parseJSDocTypeNameWithNamespace(NodeFlags.NestedNamespace);
6789                            return finishNode(jsDocNamespaceNode);
6790                        }
6791
6792                        if (typeNameOrNamespaceName && flags & NodeFlags.NestedNamespace) {
6793                            typeNameOrNamespaceName.isInJSDocNamespace = true;
6794                        }
6795                        return typeNameOrNamespaceName;
6796                    }
6797                }
6798
6799                function escapedTextsEqual(a: EntityName, b: EntityName): boolean {
6800                    while (!ts.isIdentifier(a) || !ts.isIdentifier(b)) {
6801                        if (!ts.isIdentifier(a) && !ts.isIdentifier(b) && a.right.escapedText === b.right.escapedText) {
6802                            a = a.left;
6803                            b = b.left;
6804                        }
6805                        else {
6806                            return false;
6807                        }
6808                    }
6809                    return a.escapedText === b.escapedText;
6810                }
6811
6812                function parseChildParameterOrPropertyTag(target: PropertyLikeParse.Property): JSDocTypeTag | JSDocPropertyTag | false;
6813                function parseChildParameterOrPropertyTag(target: PropertyLikeParse.Parameter, name: EntityName): JSDocParameterTag | false;
6814                function parseChildParameterOrPropertyTag(target: PropertyLikeParse, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false {
6815                    let canParseTag = true;
6816                    let seenAsterisk = false;
6817                    while (true) {
6818                        switch (nextJSDocToken()) {
6819                            case SyntaxKind.AtToken:
6820                                if (canParseTag) {
6821                                    const child = tryParseChildTag(target);
6822                                    if (child && child.kind === SyntaxKind.JSDocParameterTag &&
6823                                        (ts.isIdentifier(child.name) || !escapedTextsEqual(name, child.name.left))) {
6824                                        return false;
6825                                    }
6826                                    return child;
6827                                }
6828                                seenAsterisk = false;
6829                                break;
6830                            case SyntaxKind.NewLineTrivia:
6831                                canParseTag = true;
6832                                seenAsterisk = false;
6833                                break;
6834                            case SyntaxKind.AsteriskToken:
6835                                if (seenAsterisk) {
6836                                    canParseTag = false;
6837                                }
6838                                seenAsterisk = true;
6839                                break;
6840                            case SyntaxKind.Identifier:
6841                                canParseTag = false;
6842                                break;
6843                            case SyntaxKind.EndOfFileToken:
6844                                return false;
6845                        }
6846                    }
6847                }
6848
6849                function tryParseChildTag(target: PropertyLikeParse): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false {
6850                    Debug.assert(token() === SyntaxKind.AtToken);
6851                    const atToken = <AtToken>createNode(SyntaxKind.AtToken);
6852                    atToken.end = scanner.getTextPos();
6853                    nextJSDocToken();
6854
6855                    const tagName = parseJSDocIdentifierName();
6856                    skipWhitespace();
6857                    if (!tagName) {
6858                        return false;
6859                    }
6860                    let t: PropertyLikeParse;
6861                    switch (tagName.escapedText) {
6862                        case "type":
6863                            return target === PropertyLikeParse.Property && parseTypeTag(atToken, tagName);
6864                        case "prop":
6865                        case "property":
6866                            t = PropertyLikeParse.Property;
6867                            break;
6868                        case "arg":
6869                        case "argument":
6870                        case "param":
6871                            t = PropertyLikeParse.Parameter;
6872                            break;
6873                        default:
6874                            return false;
6875                    }
6876                    if (target !== t) {
6877                        return false;
6878                    }
6879                    const tag = parseParameterOrPropertyTag(atToken, tagName, target);
6880                    tag.comment = parseTagComments(tag.end - tag.pos);
6881                    return tag;
6882                }
6883
6884                function parseTemplateTag(atToken: AtToken, tagName: Identifier): JSDocTemplateTag | undefined {
6885                    if (some(tags, isJSDocTemplateTag)) {
6886                        parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, Diagnostics._0_tag_already_specified, tagName.escapedText);
6887                    }
6888
6889                    // Type parameter list looks like '@template T,U,V'
6890                    const typeParameters = [];
6891                    const typeParametersPos = getNodePos();
6892
6893                    while (true) {
6894                        const typeParameter = <TypeParameterDeclaration>createNode(SyntaxKind.TypeParameter);
6895                        const name = parseJSDocIdentifierNameWithOptionalBraces();
6896                        skipWhitespace();
6897                        if (!name) {
6898                            parseErrorAtPosition(scanner.getStartPos(), 0, Diagnostics.Identifier_expected);
6899                            return undefined;
6900                        }
6901
6902                        typeParameter.name = name;
6903                        finishNode(typeParameter);
6904
6905                        typeParameters.push(typeParameter);
6906
6907                        if (token() === SyntaxKind.CommaToken) {
6908                            nextJSDocToken();
6909                            skipWhitespace();
6910                        }
6911                        else {
6912                            break;
6913                        }
6914                    }
6915
6916                    const result = <JSDocTemplateTag>createNode(SyntaxKind.JSDocTemplateTag, atToken.pos);
6917                    result.atToken = atToken;
6918                    result.tagName = tagName;
6919                    result.typeParameters = createNodeArray(typeParameters, typeParametersPos);
6920                    finishNode(result);
6921                    return result;
6922                }
6923
6924                function parseJSDocIdentifierNameWithOptionalBraces(): Identifier | undefined {
6925                    const parsedBrace = parseOptional(SyntaxKind.OpenBraceToken);
6926                    const res = parseJSDocIdentifierName();
6927                    if (parsedBrace) {
6928                        parseExpected(SyntaxKind.CloseBraceToken);
6929                    }
6930                    return res;
6931                }
6932
6933                function nextJSDocToken(): JsDocSyntaxKind {
6934                    return currentToken = scanner.scanJSDocToken();
6935                }
6936
6937                function parseJSDocEntityName(): EntityName {
6938                    let entity: EntityName = parseJSDocIdentifierName(/*createIfMissing*/ true);
6939                    if (parseOptional(SyntaxKind.OpenBracketToken)) {
6940                        parseExpected(SyntaxKind.CloseBracketToken);
6941                        // Note that y[] is accepted as an entity name, but the postfix brackets are not saved for checking.
6942                        // Technically usejsdoc.org requires them for specifying a property of a type equivalent to Array<{ x: ...}>
6943                        // but it's not worth it to enforce that restriction.
6944                    }
6945                    while (parseOptional(SyntaxKind.DotToken)) {
6946                        const name = parseJSDocIdentifierName(/*createIfMissing*/ true);
6947                        if (parseOptional(SyntaxKind.OpenBracketToken)) {
6948                            parseExpected(SyntaxKind.CloseBracketToken);
6949                        }
6950                        entity = createQualifiedName(entity, name);
6951                    }
6952                    return entity;
6953                }
6954
6955                function parseJSDocIdentifierName(): Identifier | undefined;
6956                function parseJSDocIdentifierName(createIfMissing: true): Identifier;
6957                function parseJSDocIdentifierName(createIfMissing = false): Identifier | undefined {
6958                    if (!tokenIsIdentifierOrKeyword(token())) {
6959                        if (createIfMissing) {
6960                            return createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected);
6961                        }
6962                        else {
6963                            parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
6964                            return undefined;
6965                        }
6966                    }
6967
6968                    const pos = scanner.getTokenPos();
6969                    const end = scanner.getTextPos();
6970                    const result = <Identifier>createNode(SyntaxKind.Identifier, pos);
6971                    result.escapedText = escapeLeadingUnderscores(content.substring(pos, end));
6972                    finishNode(result, end);
6973
6974                    nextJSDocToken();
6975                    return result;
6976                }
6977            }
6978        }
6979    }
6980
6981    namespace IncrementalParser {
6982        export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean): SourceFile {
6983            aggressiveChecks = aggressiveChecks || Debug.shouldAssert(AssertionLevel.Aggressive);
6984
6985            checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks);
6986            if (textChangeRangeIsUnchanged(textChangeRange)) {
6987                // if the text didn't change, then we can just return our current source file as-is.
6988                return sourceFile;
6989            }
6990
6991            if (sourceFile.statements.length === 0) {
6992                // If we don't have any statements in the current source file, then there's no real
6993                // way to incrementally parse.  So just do a full parse instead.
6994                return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, sourceFile.scriptKind);
6995            }
6996
6997            // Make sure we're not trying to incrementally update a source file more than once.  Once
6998            // we do an update the original source file is considered unusable from that point onwards.
6999            //
7000            // This is because we do incremental parsing in-place.  i.e. we take nodes from the old
7001            // tree and give them new positions and parents.  From that point on, trusting the old
7002            // tree at all is not possible as far too much of it may violate invariants.
7003            const incrementalSourceFile = <IncrementalNode><Node>sourceFile;
7004            Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed);
7005            incrementalSourceFile.hasBeenIncrementallyParsed = true;
7006
7007            const oldText = sourceFile.text;
7008            const syntaxCursor = createSyntaxCursor(sourceFile);
7009
7010            // Make the actual change larger so that we know to reparse anything whose lookahead
7011            // might have intersected the change.
7012            const changeRange = extendToAffectedRange(sourceFile, textChangeRange);
7013            checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks);
7014
7015            // Ensure that extending the affected range only moved the start of the change range
7016            // earlier in the file.
7017            Debug.assert(changeRange.span.start <= textChangeRange.span.start);
7018            Debug.assert(textSpanEnd(changeRange.span) === textSpanEnd(textChangeRange.span));
7019            Debug.assert(textSpanEnd(textChangeRangeNewSpan(changeRange)) === textSpanEnd(textChangeRangeNewSpan(textChangeRange)));
7020
7021            // The is the amount the nodes after the edit range need to be adjusted.  It can be
7022            // positive (if the edit added characters), negative (if the edit deleted characters)
7023            // or zero (if this was a pure overwrite with nothing added/removed).
7024            const delta = textChangeRangeNewSpan(changeRange).length - changeRange.span.length;
7025
7026            // If we added or removed characters during the edit, then we need to go and adjust all
7027            // the nodes after the edit.  Those nodes may move forward (if we inserted chars) or they
7028            // may move backward (if we deleted chars).
7029            //
7030            // Doing this helps us out in two ways.  First, it means that any nodes/tokens we want
7031            // to reuse are already at the appropriate position in the new text.  That way when we
7032            // reuse them, we don't have to figure out if they need to be adjusted.  Second, it makes
7033            // it very easy to determine if we can reuse a node.  If the node's position is at where
7034            // we are in the text, then we can reuse it.  Otherwise we can't.  If the node's position
7035            // is ahead of us, then we'll need to rescan tokens.  If the node's position is behind
7036            // us, then we'll need to skip it or crumble it as appropriate
7037            //
7038            // We will also adjust the positions of nodes that intersect the change range as well.
7039            // By doing this, we ensure that all the positions in the old tree are consistent, not
7040            // just the positions of nodes entirely before/after the change range.  By being
7041            // consistent, we can then easily map from positions to nodes in the old tree easily.
7042            //
7043            // Also, mark any syntax elements that intersect the changed span.  We know, up front,
7044            // that we cannot reuse these elements.
7045            updateTokenPositionsAndMarkElements(incrementalSourceFile,
7046                changeRange.span.start, textSpanEnd(changeRange.span), textSpanEnd(textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks);
7047
7048            // Now that we've set up our internal incremental state just proceed and parse the
7049            // source file in the normal fashion.  When possible the parser will retrieve and
7050            // reuse nodes from the old tree.
7051            //
7052            // Note: passing in 'true' for setNodeParents is very important.  When incrementally
7053            // parsing, we will be reusing nodes from the old tree, and placing it into new
7054            // parents.  If we don't set the parents now, we'll end up with an observably
7055            // inconsistent tree.  Setting the parents on the new tree should be very fast.  We
7056            // will immediately bail out of walking any subtrees when we can see that their parents
7057            // are already correct.
7058            const result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.scriptKind);
7059
7060            return result;
7061        }
7062
7063        function moveElementEntirelyPastChangeRange(element: IncrementalElement, isArray: boolean, delta: number, oldText: string, newText: string, aggressiveChecks: boolean) {
7064            if (isArray) {
7065                visitArray(<IncrementalNodeArray>element);
7066            }
7067            else {
7068                visitNode(<IncrementalNode>element);
7069            }
7070            return;
7071
7072            function visitNode(node: IncrementalNode) {
7073                let text = "";
7074                if (aggressiveChecks && shouldCheckNode(node)) {
7075                    text = oldText.substring(node.pos, node.end);
7076                }
7077
7078                // Ditch any existing LS children we may have created.  This way we can avoid
7079                // moving them forward.
7080                if (node._children) {
7081                    node._children = undefined;
7082                }
7083
7084                node.pos += delta;
7085                node.end += delta;
7086
7087                if (aggressiveChecks && shouldCheckNode(node)) {
7088                    Debug.assert(text === newText.substring(node.pos, node.end));
7089                }
7090
7091                forEachChild(node, visitNode, visitArray);
7092                if (hasJSDocNodes(node)) {
7093                    for (const jsDocComment of node.jsDoc) {
7094                        forEachChild(jsDocComment, visitNode, visitArray);
7095                    }
7096                }
7097                checkNodePositions(node, aggressiveChecks);
7098            }
7099
7100            function visitArray(array: IncrementalNodeArray) {
7101                array._children = undefined;
7102                array.pos += delta;
7103                array.end += delta;
7104
7105                for (const node of array) {
7106                    visitNode(node);
7107                }
7108            }
7109        }
7110
7111        function shouldCheckNode(node: Node) {
7112            switch (node.kind) {
7113                case SyntaxKind.StringLiteral:
7114                case SyntaxKind.NumericLiteral:
7115                case SyntaxKind.Identifier:
7116                    return true;
7117            }
7118
7119            return false;
7120        }
7121
7122        function adjustIntersectingElement(element: IncrementalElement, changeStart: number, changeRangeOldEnd: number, changeRangeNewEnd: number, delta: number) {
7123            Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range");
7124            Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range");
7125            Debug.assert(element.pos <= element.end);
7126
7127            // We have an element that intersects the change range in some way.  It may have its
7128            // start, or its end (or both) in the changed range.  We want to adjust any part
7129            // that intersects such that the final tree is in a consistent state.  i.e. all
7130            // children have spans within the span of their parent, and all siblings are ordered
7131            // properly.
7132
7133            // We may need to update both the 'pos' and the 'end' of the element.
7134
7135            // If the 'pos' is before the start of the change, then we don't need to touch it.
7136            // If it isn't, then the 'pos' must be inside the change.  How we update it will
7137            // depend if delta is positive or negative. If delta is positive then we have
7138            // something like:
7139            //
7140            //  -------------------AAA-----------------
7141            //  -------------------BBBCCCCCCC-----------------
7142            //
7143            // In this case, we consider any node that started in the change range to still be
7144            // starting at the same position.
7145            //
7146            // however, if the delta is negative, then we instead have something like this:
7147            //
7148            //  -------------------XXXYYYYYYY-----------------
7149            //  -------------------ZZZ-----------------
7150            //
7151            // In this case, any element that started in the 'X' range will keep its position.
7152            // However any element that started after that will have their pos adjusted to be
7153            // at the end of the new range.  i.e. any node that started in the 'Y' range will
7154            // be adjusted to have their start at the end of the 'Z' range.
7155            //
7156            // The element will keep its position if possible.  Or Move backward to the new-end
7157            // if it's in the 'Y' range.
7158            element.pos = Math.min(element.pos, changeRangeNewEnd);
7159
7160            // If the 'end' is after the change range, then we always adjust it by the delta
7161            // amount.  However, if the end is in the change range, then how we adjust it
7162            // will depend on if delta is positive or negative.  If delta is positive then we
7163            // have something like:
7164            //
7165            //  -------------------AAA-----------------
7166            //  -------------------BBBCCCCCCC-----------------
7167            //
7168            // In this case, we consider any node that ended inside the change range to keep its
7169            // end position.
7170            //
7171            // however, if the delta is negative, then we instead have something like this:
7172            //
7173            //  -------------------XXXYYYYYYY-----------------
7174            //  -------------------ZZZ-----------------
7175            //
7176            // In this case, any element that ended in the 'X' range will keep its position.
7177            // However any element that ended after that will have their pos adjusted to be
7178            // at the end of the new range.  i.e. any node that ended in the 'Y' range will
7179            // be adjusted to have their end at the end of the 'Z' range.
7180            if (element.end >= changeRangeOldEnd) {
7181                // Element ends after the change range.  Always adjust the end pos.
7182                element.end += delta;
7183            }
7184            else {
7185                // Element ends in the change range.  The element will keep its position if
7186                // possible. Or Move backward to the new-end if it's in the 'Y' range.
7187                element.end = Math.min(element.end, changeRangeNewEnd);
7188            }
7189
7190            Debug.assert(element.pos <= element.end);
7191            if (element.parent) {
7192                Debug.assert(element.pos >= element.parent.pos);
7193                Debug.assert(element.end <= element.parent.end);
7194            }
7195        }
7196
7197        function checkNodePositions(node: Node, aggressiveChecks: boolean) {
7198            if (aggressiveChecks) {
7199                let pos = node.pos;
7200                forEachChild(node, child => {
7201                    Debug.assert(child.pos >= pos);
7202                    pos = child.end;
7203                });
7204                Debug.assert(pos <= node.end);
7205            }
7206        }
7207
7208        function updateTokenPositionsAndMarkElements(
7209            sourceFile: IncrementalNode,
7210            changeStart: number,
7211            changeRangeOldEnd: number,
7212            changeRangeNewEnd: number,
7213            delta: number,
7214            oldText: string,
7215            newText: string,
7216            aggressiveChecks: boolean): void {
7217
7218            visitNode(sourceFile);
7219            return;
7220
7221            function visitNode(child: IncrementalNode) {
7222                Debug.assert(child.pos <= child.end);
7223                if (child.pos > changeRangeOldEnd) {
7224                    // Node is entirely past the change range.  We need to move both its pos and
7225                    // end, forward or backward appropriately.
7226                    moveElementEntirelyPastChangeRange(child, /*isArray*/ false, delta, oldText, newText, aggressiveChecks);
7227                    return;
7228                }
7229
7230                // Check if the element intersects the change range.  If it does, then it is not
7231                // reusable.  Also, we'll need to recurse to see what constituent portions we may
7232                // be able to use.
7233                const fullEnd = child.end;
7234                if (fullEnd >= changeStart) {
7235                    child.intersectsChange = true;
7236                    child._children = undefined;
7237
7238                    // Adjust the pos or end (or both) of the intersecting element accordingly.
7239                    adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
7240                    forEachChild(child, visitNode, visitArray);
7241
7242                    checkNodePositions(child, aggressiveChecks);
7243                    return;
7244                }
7245
7246                // Otherwise, the node is entirely before the change range.  No need to do anything with it.
7247                Debug.assert(fullEnd < changeStart);
7248            }
7249
7250            function visitArray(array: IncrementalNodeArray) {
7251                Debug.assert(array.pos <= array.end);
7252                if (array.pos > changeRangeOldEnd) {
7253                    // Array is entirely after the change range.  We need to move it, and move any of
7254                    // its children.
7255                    moveElementEntirelyPastChangeRange(array, /*isArray*/ true, delta, oldText, newText, aggressiveChecks);
7256                    return;
7257                }
7258
7259                // Check if the element intersects the change range.  If it does, then it is not
7260                // reusable.  Also, we'll need to recurse to see what constituent portions we may
7261                // be able to use.
7262                const fullEnd = array.end;
7263                if (fullEnd >= changeStart) {
7264                    array.intersectsChange = true;
7265                    array._children = undefined;
7266
7267                    // Adjust the pos or end (or both) of the intersecting array accordingly.
7268                    adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
7269                    for (const node of array) {
7270                        visitNode(node);
7271                    }
7272                    return;
7273                }
7274
7275                // Otherwise, the array is entirely before the change range.  No need to do anything with it.
7276                Debug.assert(fullEnd < changeStart);
7277            }
7278        }
7279
7280        function extendToAffectedRange(sourceFile: SourceFile, changeRange: TextChangeRange): TextChangeRange {
7281            // Consider the following code:
7282            //      void foo() { /; }
7283            //
7284            // If the text changes with an insertion of / just before the semicolon then we end up with:
7285            //      void foo() { //; }
7286            //
7287            // If we were to just use the changeRange a is, then we would not rescan the { token
7288            // (as it does not intersect the actual original change range).  Because an edit may
7289            // change the token touching it, we actually need to look back *at least* one token so
7290            // that the prior token sees that change.
7291            const maxLookahead = 1;
7292
7293            let start = changeRange.span.start;
7294
7295            // the first iteration aligns us with the change start. subsequent iteration move us to
7296            // the left by maxLookahead tokens.  We only need to do this as long as we're not at the
7297            // start of the tree.
7298            for (let i = 0; start > 0 && i <= maxLookahead; i++) {
7299                const nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start);
7300                Debug.assert(nearestNode.pos <= start);
7301                const position = nearestNode.pos;
7302
7303                start = Math.max(0, position - 1);
7304            }
7305
7306            const finalSpan = createTextSpanFromBounds(start, textSpanEnd(changeRange.span));
7307            const finalLength = changeRange.newLength + (changeRange.span.start - start);
7308
7309            return createTextChangeRange(finalSpan, finalLength);
7310        }
7311
7312        function findNearestNodeStartingBeforeOrAtPosition(sourceFile: SourceFile, position: number): Node {
7313            let bestResult: Node = sourceFile;
7314            let lastNodeEntirelyBeforePosition: Node;
7315
7316            forEachChild(sourceFile, visit);
7317
7318            if (lastNodeEntirelyBeforePosition) {
7319                const lastChildOfLastEntireNodeBeforePosition = getLastChild(lastNodeEntirelyBeforePosition);
7320                if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) {
7321                    bestResult = lastChildOfLastEntireNodeBeforePosition;
7322                }
7323            }
7324
7325            return bestResult;
7326
7327            function getLastChild(node: Node): Node {
7328                while (true) {
7329                    const lastChild = getLastChildWorker(node);
7330                    if (lastChild) {
7331                        node = lastChild;
7332                    }
7333                    else {
7334                        return node;
7335                    }
7336                }
7337            }
7338
7339            function getLastChildWorker(node: Node): Node | undefined {
7340                let last: Node = undefined;
7341                forEachChild(node, child => {
7342                    if (nodeIsPresent(child)) {
7343                        last = child;
7344                    }
7345                });
7346                return last;
7347            }
7348
7349            function visit(child: Node) {
7350                if (nodeIsMissing(child)) {
7351                    // Missing nodes are effectively invisible to us.  We never even consider them
7352                    // When trying to find the nearest node before us.
7353                    return;
7354                }
7355
7356                // If the child intersects this position, then this node is currently the nearest
7357                // node that starts before the position.
7358                if (child.pos <= position) {
7359                    if (child.pos >= bestResult.pos) {
7360                        // This node starts before the position, and is closer to the position than
7361                        // the previous best node we found.  It is now the new best node.
7362                        bestResult = child;
7363                    }
7364
7365                    // Now, the node may overlap the position, or it may end entirely before the
7366                    // position.  If it overlaps with the position, then either it, or one of its
7367                    // children must be the nearest node before the position.  So we can just
7368                    // recurse into this child to see if we can find something better.
7369                    if (position < child.end) {
7370                        // The nearest node is either this child, or one of the children inside
7371                        // of it.  We've already marked this child as the best so far.  Recurse
7372                        // in case one of the children is better.
7373                        forEachChild(child, visit);
7374
7375                        // Once we look at the children of this node, then there's no need to
7376                        // continue any further.
7377                        return true;
7378                    }
7379                    else {
7380                        Debug.assert(child.end <= position);
7381                        // The child ends entirely before this position.  Say you have the following
7382                        // (where $ is the position)
7383                        //
7384                        //      <complex expr 1> ? <complex expr 2> $ : <...> <...>
7385                        //
7386                        // We would want to find the nearest preceding node in "complex expr 2".
7387                        // To support that, we keep track of this node, and once we're done searching
7388                        // for a best node, we recurse down this node to see if we can find a good
7389                        // result in it.
7390                        //
7391                        // This approach allows us to quickly skip over nodes that are entirely
7392                        // before the position, while still allowing us to find any nodes in the
7393                        // last one that might be what we want.
7394                        lastNodeEntirelyBeforePosition = child;
7395                    }
7396                }
7397                else {
7398                    Debug.assert(child.pos > position);
7399                    // We're now at a node that is entirely past the position we're searching for.
7400                    // This node (and all following nodes) could never contribute to the result,
7401                    // so just skip them by returning 'true' here.
7402                    return true;
7403                }
7404            }
7405        }
7406
7407        function checkChangeRange(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean) {
7408            const oldText = sourceFile.text;
7409            if (textChangeRange) {
7410                Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length);
7411
7412                if (aggressiveChecks || Debug.shouldAssert(AssertionLevel.VeryAggressive)) {
7413                    const oldTextPrefix = oldText.substr(0, textChangeRange.span.start);
7414                    const newTextPrefix = newText.substr(0, textChangeRange.span.start);
7415                    Debug.assert(oldTextPrefix === newTextPrefix);
7416
7417                    const oldTextSuffix = oldText.substring(textSpanEnd(textChangeRange.span), oldText.length);
7418                    const newTextSuffix = newText.substring(textSpanEnd(textChangeRangeNewSpan(textChangeRange)), newText.length);
7419                    Debug.assert(oldTextSuffix === newTextSuffix);
7420                }
7421            }
7422        }
7423
7424        interface IncrementalElement extends TextRange {
7425            parent?: Node;
7426            intersectsChange: boolean;
7427            length?: number;
7428            _children: Node[];
7429        }
7430
7431        export interface IncrementalNode extends Node, IncrementalElement {
7432            hasBeenIncrementallyParsed: boolean;
7433        }
7434
7435        interface IncrementalNodeArray extends NodeArray<IncrementalNode>, IncrementalElement {
7436            length: number;
7437        }
7438
7439        // Allows finding nodes in the source file at a certain position in an efficient manner.
7440        // The implementation takes advantage of the calling pattern it knows the parser will
7441        // make in order to optimize finding nodes as quickly as possible.
7442        export interface SyntaxCursor {
7443            currentNode(position: number): IncrementalNode;
7444        }
7445
7446        function createSyntaxCursor(sourceFile: SourceFile): SyntaxCursor {
7447            let currentArray: NodeArray<Node> = sourceFile.statements;
7448            let currentArrayIndex = 0;
7449
7450            Debug.assert(currentArrayIndex < currentArray.length);
7451            let current = currentArray[currentArrayIndex];
7452            let lastQueriedPosition = InvalidPosition.Value;
7453
7454            return {
7455                currentNode(position: number) {
7456                    // Only compute the current node if the position is different than the last time
7457                    // we were asked.  The parser commonly asks for the node at the same position
7458                    // twice.  Once to know if can read an appropriate list element at a certain point,
7459                    // and then to actually read and consume the node.
7460                    if (position !== lastQueriedPosition) {
7461                        // Much of the time the parser will need the very next node in the array that
7462                        // we just returned a node from.So just simply check for that case and move
7463                        // forward in the array instead of searching for the node again.
7464                        if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) {
7465                            currentArrayIndex++;
7466                            current = currentArray[currentArrayIndex];
7467                        }
7468
7469                        // If we don't have a node, or the node we have isn't in the right position,
7470                        // then try to find a viable node at the position requested.
7471                        if (!current || current.pos !== position) {
7472                            findHighestListElementThatStartsAtPosition(position);
7473                        }
7474                    }
7475
7476                    // Cache this query so that we don't do any extra work if the parser calls back
7477                    // into us.  Note: this is very common as the parser will make pairs of calls like
7478                    // 'isListElement -> parseListElement'.  If we were unable to find a node when
7479                    // called with 'isListElement', we don't want to redo the work when parseListElement
7480                    // is called immediately after.
7481                    lastQueriedPosition = position;
7482
7483                    // Either we don'd have a node, or we have a node at the position being asked for.
7484                    Debug.assert(!current || current.pos === position);
7485                    return <IncrementalNode>current;
7486                }
7487            };
7488
7489            // Finds the highest element in the tree we can find that starts at the provided position.
7490            // The element must be a direct child of some node list in the tree.  This way after we
7491            // return it, we can easily return its next sibling in the list.
7492            function findHighestListElementThatStartsAtPosition(position: number) {
7493                // Clear out any cached state about the last node we found.
7494                currentArray = undefined;
7495                currentArrayIndex = InvalidPosition.Value;
7496                current = undefined;
7497
7498                // Recurse into the source file to find the highest node at this position.
7499                forEachChild(sourceFile, visitNode, visitArray);
7500                return;
7501
7502                function visitNode(node: Node) {
7503                    if (position >= node.pos && position < node.end) {
7504                        // Position was within this node.  Keep searching deeper to find the node.
7505                        forEachChild(node, visitNode, visitArray);
7506
7507                        // don't proceed any further in the search.
7508                        return true;
7509                    }
7510
7511                    // position wasn't in this node, have to keep searching.
7512                    return false;
7513                }
7514
7515                function visitArray(array: NodeArray<Node>) {
7516                    if (position >= array.pos && position < array.end) {
7517                        // position was in this array.  Search through this array to see if we find a
7518                        // viable element.
7519                        for (let i = 0; i < array.length; i++) {
7520                            const child = array[i];
7521                            if (child) {
7522                                if (child.pos === position) {
7523                                    // Found the right node.  We're done.
7524                                    currentArray = array;
7525                                    currentArrayIndex = i;
7526                                    current = child;
7527                                    return true;
7528                                }
7529                                else {
7530                                    if (child.pos < position && position < child.end) {
7531                                        // Position in somewhere within this child.  Search in it and
7532                                        // stop searching in this array.
7533                                        forEachChild(child, visitNode, visitArray);
7534                                        return true;
7535                                    }
7536                                }
7537                            }
7538                        }
7539                    }
7540
7541                    // position wasn't in this array, have to keep searching.
7542                    return false;
7543                }
7544            }
7545        }
7546
7547        const enum InvalidPosition {
7548            Value = -1
7549        }
7550    }
7551
7552    function isDeclarationFileName(fileName: string): boolean {
7553        return fileExtensionIs(fileName, Extension.Dts);
7554    }
7555}
7556