Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(851)

Side by Side Diff: mojo/public/dart/third_party/analyzer/lib/src/generated/parser.dart

Issue 1346773002: Stop running pub get at gclient sync time and fix build bugs (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library engine.parser;
6
7 import 'dart:collection';
8 import "dart:math" as math;
9
10 import 'ast.dart';
11 import 'engine.dart' show AnalysisEngine, AnalysisOptionsImpl;
12 import 'error.dart';
13 import 'java_core.dart';
14 import 'java_engine.dart';
15 import 'scanner.dart';
16 import 'source.dart';
17 import 'utilities_collection.dart' show TokenMap;
18 import 'utilities_dart.dart';
19
20 Map<String, MethodTrampoline> methodTable_Parser = <String, MethodTrampoline>{
21 'parseCompilationUnit_1': new MethodTrampoline(
22 1, (Parser target, arg0) => target.parseCompilationUnit(arg0)),
23 'parseDirectives_1': new MethodTrampoline(
24 1, (Parser target, arg0) => target.parseDirectives(arg0)),
25 'parseExpression_1': new MethodTrampoline(
26 1, (Parser target, arg0) => target.parseExpression(arg0)),
27 'parseStatement_1': new MethodTrampoline(
28 1, (Parser target, arg0) => target.parseStatement(arg0)),
29 'parseStatements_1': new MethodTrampoline(
30 1, (Parser target, arg0) => target.parseStatements(arg0)),
31 'parseAnnotation_0':
32 new MethodTrampoline(0, (Parser target) => target.parseAnnotation()),
33 'parseArgument_0':
34 new MethodTrampoline(0, (Parser target) => target.parseArgument()),
35 'parseArgumentList_0':
36 new MethodTrampoline(0, (Parser target) => target.parseArgumentList()),
37 'parseBitwiseOrExpression_0': new MethodTrampoline(
38 0, (Parser target) => target.parseBitwiseOrExpression()),
39 'parseBlock_0':
40 new MethodTrampoline(0, (Parser target) => target.parseBlock()),
41 'parseClassMember_1': new MethodTrampoline(
42 1, (Parser target, arg0) => target.parseClassMember(arg0)),
43 'parseCompilationUnit_0': new MethodTrampoline(
44 0, (Parser target) => target.parseCompilationUnit2()),
45 'parseConditionalExpression_0': new MethodTrampoline(
46 0, (Parser target) => target.parseConditionalExpression()),
47 'parseConstructorName_0':
48 new MethodTrampoline(0, (Parser target) => target.parseConstructorName()),
49 'parseExpression_0':
50 new MethodTrampoline(0, (Parser target) => target.parseExpression2()),
51 'parseExpressionWithoutCascade_0': new MethodTrampoline(
52 0, (Parser target) => target.parseExpressionWithoutCascade()),
53 'parseExtendsClause_0':
54 new MethodTrampoline(0, (Parser target) => target.parseExtendsClause()),
55 'parseFormalParameterList_0': new MethodTrampoline(
56 0, (Parser target) => target.parseFormalParameterList()),
57 'parseFunctionExpression_0': new MethodTrampoline(
58 0, (Parser target) => target.parseFunctionExpression()),
59 'parseImplementsClause_0': new MethodTrampoline(
60 0, (Parser target) => target.parseImplementsClause()),
61 'parseLabel_0':
62 new MethodTrampoline(0, (Parser target) => target.parseLabel()),
63 'parseLibraryIdentifier_0': new MethodTrampoline(
64 0, (Parser target) => target.parseLibraryIdentifier()),
65 'parseLogicalOrExpression_0': new MethodTrampoline(
66 0, (Parser target) => target.parseLogicalOrExpression()),
67 'parseMapLiteralEntry_0':
68 new MethodTrampoline(0, (Parser target) => target.parseMapLiteralEntry()),
69 'parseNormalFormalParameter_0': new MethodTrampoline(
70 0, (Parser target) => target.parseNormalFormalParameter()),
71 'parsePrefixedIdentifier_0': new MethodTrampoline(
72 0, (Parser target) => target.parsePrefixedIdentifier()),
73 'parseReturnType_0':
74 new MethodTrampoline(0, (Parser target) => target.parseReturnType()),
75 'parseSimpleIdentifier_0': new MethodTrampoline(
76 0, (Parser target) => target.parseSimpleIdentifier()),
77 'parseStatement_0':
78 new MethodTrampoline(0, (Parser target) => target.parseStatement2()),
79 'parseStringLiteral_0':
80 new MethodTrampoline(0, (Parser target) => target.parseStringLiteral()),
81 'parseTypeArgumentList_0': new MethodTrampoline(
82 0, (Parser target) => target.parseTypeArgumentList()),
83 'parseTypeName_0':
84 new MethodTrampoline(0, (Parser target) => target.parseTypeName()),
85 'parseTypeParameter_0':
86 new MethodTrampoline(0, (Parser target) => target.parseTypeParameter()),
87 'parseTypeParameterList_0': new MethodTrampoline(
88 0, (Parser target) => target.parseTypeParameterList()),
89 'parseWithClause_0':
90 new MethodTrampoline(0, (Parser target) => target.parseWithClause()),
91 'advance_0': new MethodTrampoline(0, (Parser target) => target._advance()),
92 'appendScalarValue_5': new MethodTrampoline(5, (Parser target, arg0, arg1,
93 arg2, arg3,
94 arg4) => target._appendScalarValue(arg0, arg1, arg2, arg3, arg4)),
95 'computeStringValue_3': new MethodTrampoline(3, (Parser target, arg0, arg1,
96 arg2) => target._computeStringValue(arg0, arg1, arg2)),
97 'convertToFunctionDeclaration_1': new MethodTrampoline(
98 1, (Parser target, arg0) => target._convertToFunctionDeclaration(arg0)),
99 'couldBeStartOfCompilationUnitMember_0': new MethodTrampoline(
100 0, (Parser target) => target._couldBeStartOfCompilationUnitMember()),
101 'createSyntheticIdentifier_0': new MethodTrampoline(
102 0, (Parser target) => target._createSyntheticIdentifier()),
103 'createSyntheticKeyword_1': new MethodTrampoline(
104 1, (Parser target, arg0) => target._createSyntheticKeyword(arg0)),
105 'createSyntheticStringLiteral_0': new MethodTrampoline(
106 0, (Parser target) => target._createSyntheticStringLiteral()),
107 'createSyntheticToken_1': new MethodTrampoline(
108 1, (Parser target, arg0) => target._createSyntheticToken(arg0)),
109 'ensureAssignable_1': new MethodTrampoline(
110 1, (Parser target, arg0) => target._ensureAssignable(arg0)),
111 'expect_1':
112 new MethodTrampoline(1, (Parser target, arg0) => target._expect(arg0)),
113 'expectGt_0': new MethodTrampoline(0, (Parser target) => target._expectGt()),
114 'expectKeyword_1': new MethodTrampoline(
115 1, (Parser target, arg0) => target._expectKeyword(arg0)),
116 'expectSemicolon_0':
117 new MethodTrampoline(0, (Parser target) => target._expectSemicolon()),
118 'findRange_2': new MethodTrampoline(
119 2, (Parser target, arg0, arg1) => target._findRange(arg0, arg1)),
120 'getCodeBlockRanges_1': new MethodTrampoline(
121 1, (Parser target, arg0) => target._getCodeBlockRanges(arg0)),
122 'getEndToken_1': new MethodTrampoline(
123 1, (Parser target, arg0) => target._getEndToken(arg0)),
124 'injectToken_1': new MethodTrampoline(
125 1, (Parser target, arg0) => target._injectToken(arg0)),
126 'isFunctionDeclaration_0': new MethodTrampoline(
127 0, (Parser target) => target._isFunctionDeclaration()),
128 'isFunctionExpression_1': new MethodTrampoline(
129 1, (Parser target, arg0) => target._isFunctionExpression(arg0)),
130 'isHexDigit_1': new MethodTrampoline(
131 1, (Parser target, arg0) => target._isHexDigit(arg0)),
132 'isInitializedVariableDeclaration_0': new MethodTrampoline(
133 0, (Parser target) => target._isInitializedVariableDeclaration()),
134 'isLinkText_2': new MethodTrampoline(
135 2, (Parser target, arg0, arg1) => target._isLinkText(arg0, arg1)),
136 'isOperator_1': new MethodTrampoline(
137 1, (Parser target, arg0) => target._isOperator(arg0)),
138 'isSwitchMember_0':
139 new MethodTrampoline(0, (Parser target) => target._isSwitchMember()),
140 'isTypedIdentifier_1': new MethodTrampoline(
141 1, (Parser target, arg0) => target._isTypedIdentifier(arg0)),
142 'lockErrorListener_0':
143 new MethodTrampoline(0, (Parser target) => target._lockErrorListener()),
144 'matches_1':
145 new MethodTrampoline(1, (Parser target, arg0) => target._matches(arg0)),
146 'matchesGt_0':
147 new MethodTrampoline(0, (Parser target) => target._matchesGt()),
148 'matchesIdentifier_0':
149 new MethodTrampoline(0, (Parser target) => target._matchesIdentifier()),
150 'matchesKeyword_1': new MethodTrampoline(
151 1, (Parser target, arg0) => target._matchesKeyword(arg0)),
152 'matchesString_1': new MethodTrampoline(
153 1, (Parser target, arg0) => target._matchesString(arg0)),
154 'optional_1':
155 new MethodTrampoline(1, (Parser target, arg0) => target._optional(arg0)),
156 'parseAdditiveExpression_0': new MethodTrampoline(
157 0, (Parser target) => target._parseAdditiveExpression()),
158 'parseAssertStatement_0': new MethodTrampoline(
159 0, (Parser target) => target._parseAssertStatement()),
160 'parseAssignableExpression_1': new MethodTrampoline(
161 1, (Parser target, arg0) => target._parseAssignableExpression(arg0)),
162 'parseAssignableSelector_2': new MethodTrampoline(2, (Parser target, arg0,
163 arg1) => target._parseAssignableSelector(arg0, arg1)),
164 'parseAwaitExpression_0': new MethodTrampoline(
165 0, (Parser target) => target._parseAwaitExpression()),
166 'parseBitwiseAndExpression_0': new MethodTrampoline(
167 0, (Parser target) => target._parseBitwiseAndExpression()),
168 'parseBitwiseXorExpression_0': new MethodTrampoline(
169 0, (Parser target) => target._parseBitwiseXorExpression()),
170 'parseBreakStatement_0':
171 new MethodTrampoline(0, (Parser target) => target._parseBreakStatement()),
172 'parseCascadeSection_0':
173 new MethodTrampoline(0, (Parser target) => target._parseCascadeSection()),
174 'parseClassDeclaration_2': new MethodTrampoline(2,
175 (Parser target, arg0, arg1) => target._parseClassDeclaration(arg0, arg1)),
176 'parseClassMembers_2': new MethodTrampoline(
177 2, (Parser target, arg0, arg1) => target._parseClassMembers(arg0, arg1)),
178 'parseClassTypeAlias_3': new MethodTrampoline(3, (Parser target, arg0, arg1,
179 arg2) => target._parseClassTypeAlias(arg0, arg1, arg2)),
180 'parseCombinator_0':
181 new MethodTrampoline(0, (Parser target) => target.parseCombinator()),
182 'parseCombinators_0':
183 new MethodTrampoline(0, (Parser target) => target._parseCombinators()),
184 'parseCommentAndMetadata_0': new MethodTrampoline(
185 0, (Parser target) => target._parseCommentAndMetadata()),
186 'parseCommentReference_2': new MethodTrampoline(2,
187 (Parser target, arg0, arg1) => target._parseCommentReference(arg0, arg1)),
188 'parseCommentReferences_1': new MethodTrampoline(
189 1, (Parser target, arg0) => target._parseCommentReferences(arg0)),
190 'parseCompilationUnitMember_1': new MethodTrampoline(
191 1, (Parser target, arg0) => target._parseCompilationUnitMember(arg0)),
192 'parseConstExpression_0': new MethodTrampoline(
193 0, (Parser target) => target._parseConstExpression()),
194 'parseConstructor_8': new MethodTrampoline(8, (Parser target, arg0, arg1,
195 arg2, arg3, arg4, arg5, arg6, arg7) =>
196 target._parseConstructor(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)),
197 'parseConstructorFieldInitializer_0': new MethodTrampoline(
198 0, (Parser target) => target._parseConstructorFieldInitializer()),
199 'parseContinueStatement_0': new MethodTrampoline(
200 0, (Parser target) => target._parseContinueStatement()),
201 'parseDirective_1': new MethodTrampoline(
202 1, (Parser target, arg0) => target._parseDirective(arg0)),
203 'parseDirectives_0':
204 new MethodTrampoline(0, (Parser target) => target._parseDirectives()),
205 'parseDocumentationComment_0': new MethodTrampoline(
206 0, (Parser target) => target._parseDocumentationComment()),
207 'parseDoStatement_0':
208 new MethodTrampoline(0, (Parser target) => target._parseDoStatement()),
209 'parseEmptyStatement_0':
210 new MethodTrampoline(0, (Parser target) => target._parseEmptyStatement()),
211 'parseEnumConstantDeclaration_0': new MethodTrampoline(
212 0, (Parser target) => target._parseEnumConstantDeclaration()),
213 'parseEnumDeclaration_1': new MethodTrampoline(
214 1, (Parser target, arg0) => target._parseEnumDeclaration(arg0)),
215 'parseEqualityExpression_0': new MethodTrampoline(
216 0, (Parser target) => target._parseEqualityExpression()),
217 'parseExportDirective_1': new MethodTrampoline(
218 1, (Parser target, arg0) => target._parseExportDirective(arg0)),
219 'parseExpressionList_0':
220 new MethodTrampoline(0, (Parser target) => target._parseExpressionList()),
221 'parseFinalConstVarOrType_1': new MethodTrampoline(
222 1, (Parser target, arg0) => target._parseFinalConstVarOrType(arg0)),
223 'parseFormalParameter_1': new MethodTrampoline(
224 1, (Parser target, arg0) => target._parseFormalParameter(arg0)),
225 'parseForStatement_0':
226 new MethodTrampoline(0, (Parser target) => target._parseForStatement()),
227 'parseFunctionBody_3': new MethodTrampoline(3, (Parser target, arg0, arg1,
228 arg2) => target._parseFunctionBody(arg0, arg1, arg2)),
229 'parseFunctionDeclaration_3': new MethodTrampoline(3, (Parser target, arg0,
230 arg1, arg2) => target._parseFunctionDeclaration(arg0, arg1, arg2)),
231 'parseFunctionDeclarationStatement_0': new MethodTrampoline(
232 0, (Parser target) => target._parseFunctionDeclarationStatement()),
233 'parseFunctionDeclarationStatementAfterReturnType_2': new MethodTrampoline(2,
234 (Parser target, arg0, arg1) =>
235 target._parseFunctionDeclarationStatementAfterReturnType(arg0, arg1)),
236 'parseFunctionTypeAlias_2': new MethodTrampoline(2, (Parser target, arg0,
237 arg1) => target._parseFunctionTypeAlias(arg0, arg1)),
238 'parseGetter_4': new MethodTrampoline(4, (Parser target, arg0, arg1, arg2,
239 arg3) => target._parseGetter(arg0, arg1, arg2, arg3)),
240 'parseIdentifierList_0':
241 new MethodTrampoline(0, (Parser target) => target._parseIdentifierList()),
242 'parseIfStatement_0':
243 new MethodTrampoline(0, (Parser target) => target._parseIfStatement()),
244 'parseImportDirective_1': new MethodTrampoline(
245 1, (Parser target, arg0) => target._parseImportDirective(arg0)),
246 'parseInitializedIdentifierList_4': new MethodTrampoline(4,
247 (Parser target, arg0, arg1, arg2, arg3) =>
248 target._parseInitializedIdentifierList(arg0, arg1, arg2, arg3)),
249 'parseInstanceCreationExpression_1': new MethodTrampoline(1,
250 (Parser target, arg0) => target._parseInstanceCreationExpression(arg0)),
251 'parseLibraryDirective_1': new MethodTrampoline(
252 1, (Parser target, arg0) => target._parseLibraryDirective(arg0)),
253 'parseLibraryName_2': new MethodTrampoline(
254 2, (Parser target, arg0, arg1) => target._parseLibraryName(arg0, arg1)),
255 'parseListLiteral_2': new MethodTrampoline(
256 2, (Parser target, arg0, arg1) => target._parseListLiteral(arg0, arg1)),
257 'parseListOrMapLiteral_1': new MethodTrampoline(
258 1, (Parser target, arg0) => target._parseListOrMapLiteral(arg0)),
259 'parseLogicalAndExpression_0': new MethodTrampoline(
260 0, (Parser target) => target._parseLogicalAndExpression()),
261 'parseMapLiteral_2': new MethodTrampoline(
262 2, (Parser target, arg0, arg1) => target._parseMapLiteral(arg0, arg1)),
263 'parseMethodDeclarationAfterParameters_7': new MethodTrampoline(7,
264 (Parser target, arg0, arg1, arg2, arg3, arg4, arg5, arg6) => target
265 ._parseMethodDeclarationAfterParameters(
266 arg0, arg1, arg2, arg3, arg4, arg5, arg6)),
267 'parseMethodDeclarationAfterReturnType_4': new MethodTrampoline(4,
268 (Parser target, arg0, arg1, arg2, arg3) => target
269 ._parseMethodDeclarationAfterReturnType(arg0, arg1, arg2, arg3)),
270 'parseModifiers_0':
271 new MethodTrampoline(0, (Parser target) => target._parseModifiers()),
272 'parseMultiplicativeExpression_0': new MethodTrampoline(
273 0, (Parser target) => target._parseMultiplicativeExpression()),
274 'parseNativeClause_0':
275 new MethodTrampoline(0, (Parser target) => target._parseNativeClause()),
276 'parseNewExpression_0':
277 new MethodTrampoline(0, (Parser target) => target._parseNewExpression()),
278 'parseNonLabeledStatement_0': new MethodTrampoline(
279 0, (Parser target) => target._parseNonLabeledStatement()),
280 'parseOperator_3': new MethodTrampoline(3, (Parser target, arg0, arg1,
281 arg2) => target._parseOperator(arg0, arg1, arg2)),
282 'parseOptionalReturnType_0': new MethodTrampoline(
283 0, (Parser target) => target._parseOptionalReturnType()),
284 'parsePartDirective_1': new MethodTrampoline(
285 1, (Parser target, arg0) => target._parsePartDirective(arg0)),
286 'parsePostfixExpression_0': new MethodTrampoline(
287 0, (Parser target) => target._parsePostfixExpression()),
288 'parsePrimaryExpression_0': new MethodTrampoline(
289 0, (Parser target) => target._parsePrimaryExpression()),
290 'parseRedirectingConstructorInvocation_0': new MethodTrampoline(
291 0, (Parser target) => target._parseRedirectingConstructorInvocation()),
292 'parseRelationalExpression_0': new MethodTrampoline(
293 0, (Parser target) => target._parseRelationalExpression()),
294 'parseRethrowExpression_0': new MethodTrampoline(
295 0, (Parser target) => target._parseRethrowExpression()),
296 'parseReturnStatement_0': new MethodTrampoline(
297 0, (Parser target) => target._parseReturnStatement()),
298 'parseSetter_4': new MethodTrampoline(4, (Parser target, arg0, arg1, arg2,
299 arg3) => target._parseSetter(arg0, arg1, arg2, arg3)),
300 'parseShiftExpression_0': new MethodTrampoline(
301 0, (Parser target) => target._parseShiftExpression()),
302 'parseStatementList_0':
303 new MethodTrampoline(0, (Parser target) => target._parseStatementList()),
304 'parseStringInterpolation_1': new MethodTrampoline(
305 1, (Parser target, arg0) => target._parseStringInterpolation(arg0)),
306 'parseSuperConstructorInvocation_0': new MethodTrampoline(
307 0, (Parser target) => target._parseSuperConstructorInvocation()),
308 'parseSwitchStatement_0': new MethodTrampoline(
309 0, (Parser target) => target._parseSwitchStatement()),
310 'parseSymbolLiteral_0':
311 new MethodTrampoline(0, (Parser target) => target._parseSymbolLiteral()),
312 'parseThrowExpression_0': new MethodTrampoline(
313 0, (Parser target) => target._parseThrowExpression()),
314 'parseThrowExpressionWithoutCascade_0': new MethodTrampoline(
315 0, (Parser target) => target._parseThrowExpressionWithoutCascade()),
316 'parseTryStatement_0':
317 new MethodTrampoline(0, (Parser target) => target._parseTryStatement()),
318 'parseTypeAlias_1': new MethodTrampoline(
319 1, (Parser target, arg0) => target._parseTypeAlias(arg0)),
320 'parseUnaryExpression_0': new MethodTrampoline(
321 0, (Parser target) => target._parseUnaryExpression()),
322 'parseVariableDeclaration_0': new MethodTrampoline(
323 0, (Parser target) => target._parseVariableDeclaration()),
324 'parseVariableDeclarationListAfterMetadata_1': new MethodTrampoline(1,
325 (Parser target, arg0) =>
326 target._parseVariableDeclarationListAfterMetadata(arg0)),
327 'parseVariableDeclarationListAfterType_3': new MethodTrampoline(3,
328 (Parser target, arg0, arg1, arg2) =>
329 target._parseVariableDeclarationListAfterType(arg0, arg1, arg2)),
330 'parseVariableDeclarationStatementAfterMetadata_1': new MethodTrampoline(1,
331 (Parser target, arg0) =>
332 target._parseVariableDeclarationStatementAfterMetadata(arg0)),
333 'parseVariableDeclarationStatementAfterType_3': new MethodTrampoline(3,
334 (Parser target, arg0, arg1, arg2) =>
335 target._parseVariableDeclarationStatementAfterType(arg0, arg1, arg2)),
336 'parseWhileStatement_0':
337 new MethodTrampoline(0, (Parser target) => target._parseWhileStatement()),
338 'parseYieldStatement_0':
339 new MethodTrampoline(0, (Parser target) => target._parseYieldStatement()),
340 'peek_0': new MethodTrampoline(0, (Parser target) => target._peek()),
341 'peekAt_1':
342 new MethodTrampoline(1, (Parser target, arg0) => target._peekAt(arg0)),
343 'reportError_1': new MethodTrampoline(
344 1, (Parser target, arg0) => target._reportError(arg0)),
345 'reportErrorForCurrentToken_2': new MethodTrampoline(2, (Parser target, arg0,
346 arg1) => target._reportErrorForCurrentToken(arg0, arg1)),
347 'reportErrorForNode_3': new MethodTrampoline(3, (Parser target, arg0, arg1,
348 arg2) => target._reportErrorForNode(arg0, arg1, arg2)),
349 'reportErrorForToken_3': new MethodTrampoline(3, (Parser target, arg0, arg1,
350 arg2) => target._reportErrorForToken(arg0, arg1, arg2)),
351 'skipBlock_0':
352 new MethodTrampoline(0, (Parser target) => target._skipBlock()),
353 'skipFinalConstVarOrType_1': new MethodTrampoline(
354 1, (Parser target, arg0) => target._skipFinalConstVarOrType(arg0)),
355 'skipFormalParameterList_1': new MethodTrampoline(
356 1, (Parser target, arg0) => target._skipFormalParameterList(arg0)),
357 'skipPastMatchingToken_1': new MethodTrampoline(
358 1, (Parser target, arg0) => target._skipPastMatchingToken(arg0)),
359 'skipPrefixedIdentifier_1': new MethodTrampoline(
360 1, (Parser target, arg0) => target._skipPrefixedIdentifier(arg0)),
361 'skipReturnType_1': new MethodTrampoline(
362 1, (Parser target, arg0) => target._skipReturnType(arg0)),
363 'skipSimpleIdentifier_1': new MethodTrampoline(
364 1, (Parser target, arg0) => target._skipSimpleIdentifier(arg0)),
365 'skipStringInterpolation_1': new MethodTrampoline(
366 1, (Parser target, arg0) => target._skipStringInterpolation(arg0)),
367 'skipStringLiteral_1': new MethodTrampoline(
368 1, (Parser target, arg0) => target._skipStringLiteral(arg0)),
369 'skipTypeArgumentList_1': new MethodTrampoline(
370 1, (Parser target, arg0) => target._skipTypeArgumentList(arg0)),
371 'skipTypeName_1': new MethodTrampoline(
372 1, (Parser target, arg0) => target._skipTypeName(arg0)),
373 'skipTypeParameterList_1': new MethodTrampoline(
374 1, (Parser target, arg0) => target._skipTypeParameterList(arg0)),
375 'tokenMatches_2': new MethodTrampoline(
376 2, (Parser target, arg0, arg1) => target._tokenMatches(arg0, arg1)),
377 'tokenMatchesIdentifier_1': new MethodTrampoline(
378 1, (Parser target, arg0) => target._tokenMatchesIdentifier(arg0)),
379 'tokenMatchesKeyword_2': new MethodTrampoline(2,
380 (Parser target, arg0, arg1) => target._tokenMatchesKeyword(arg0, arg1)),
381 'tokenMatchesString_2': new MethodTrampoline(
382 2, (Parser target, arg0, arg1) => target._tokenMatchesString(arg0, arg1)),
383 'translateCharacter_3': new MethodTrampoline(3, (Parser target, arg0, arg1,
384 arg2) => target._translateCharacter(arg0, arg1, arg2)),
385 'unlockErrorListener_0':
386 new MethodTrampoline(0, (Parser target) => target._unlockErrorListener()),
387 'validateFormalParameterList_1': new MethodTrampoline(
388 1, (Parser target, arg0) => target._validateFormalParameterList(arg0)),
389 'validateModifiersForClass_1': new MethodTrampoline(
390 1, (Parser target, arg0) => target._validateModifiersForClass(arg0)),
391 'validateModifiersForConstructor_1': new MethodTrampoline(1,
392 (Parser target, arg0) => target._validateModifiersForConstructor(arg0)),
393 'validateModifiersForEnum_1': new MethodTrampoline(
394 1, (Parser target, arg0) => target._validateModifiersForEnum(arg0)),
395 'validateModifiersForField_1': new MethodTrampoline(
396 1, (Parser target, arg0) => target._validateModifiersForField(arg0)),
397 'validateModifiersForFunctionDeclarationStatement_1': new MethodTrampoline(1,
398 (Parser target, arg0) =>
399 target._validateModifiersForFunctionDeclarationStatement(arg0)),
400 'validateModifiersForGetterOrSetterOrMethod_1': new MethodTrampoline(1,
401 (Parser target, arg0) =>
402 target._validateModifiersForGetterOrSetterOrMethod(arg0)),
403 'validateModifiersForOperator_1': new MethodTrampoline(
404 1, (Parser target, arg0) => target._validateModifiersForOperator(arg0)),
405 'validateModifiersForTopLevelDeclaration_1': new MethodTrampoline(1,
406 (Parser target, arg0) =>
407 target._validateModifiersForTopLevelDeclaration(arg0)),
408 'validateModifiersForTopLevelFunction_1': new MethodTrampoline(1,
409 (Parser target, arg0) =>
410 target._validateModifiersForTopLevelFunction(arg0)),
411 'validateModifiersForTopLevelVariable_1': new MethodTrampoline(1,
412 (Parser target, arg0) =>
413 target._validateModifiersForTopLevelVariable(arg0)),
414 'validateModifiersForTypedef_1': new MethodTrampoline(
415 1, (Parser target, arg0) => target._validateModifiersForTypedef(arg0)),
416 };
417
418 Object invokeParserMethodImpl(
419 Parser parser, String methodName, List<Object> objects, Token tokenStream) {
420 parser.currentToken = tokenStream;
421 MethodTrampoline method =
422 methodTable_Parser['${methodName}_${objects.length}'];
423 if (method == null) {
424 throw new IllegalArgumentException('There is no method named $methodName');
425 }
426 return method.invoke(parser, objects);
427 }
428
429 /**
430 * A simple data-holder for a method that needs to return multiple values.
431 */
432 class CommentAndMetadata {
433 /**
434 * The documentation comment that was parsed, or `null` if none was given.
435 */
436 final Comment comment;
437
438 /**
439 * The metadata that was parsed.
440 */
441 final List<Annotation> metadata;
442
443 /**
444 * Initialize a newly created holder with the given [comment] and [metadata].
445 */
446 CommentAndMetadata(this.comment, this.metadata);
447 }
448
449 /**
450 * A simple data-holder for a method that needs to return multiple values.
451 */
452 class FinalConstVarOrType {
453 /**
454 * The 'final', 'const' or 'var' keyword, or `null` if none was given.
455 */
456 final Token keyword;
457
458 /**
459 * The type, of `null` if no type was specified.
460 */
461 final TypeName type;
462
463 /**
464 * Initialize a newly created holder with the given [keyword] and [type].
465 */
466 FinalConstVarOrType(this.keyword, this.type);
467 }
468
469 /**
470 * A dispatcher that will invoke the right parse method when re-parsing a
471 * specified child of the visited node. All of the methods in this class assume
472 * that the parser is positioned to parse the replacement for the node. All of
473 * the methods will throw an [IncrementalParseException] if the node could not
474 * be parsed for some reason.
475 */
476 class IncrementalParseDispatcher implements AstVisitor<AstNode> {
477 /**
478 * The parser used to parse the replacement for the node.
479 */
480 final Parser _parser;
481
482 /**
483 * The node that is to be replaced.
484 */
485 final AstNode _oldNode;
486
487 /**
488 * Initialize a newly created dispatcher to parse a single node that will
489 * use the [_parser] to replace the [_oldNode].
490 */
491 IncrementalParseDispatcher(this._parser, this._oldNode);
492
493 @override
494 AstNode visitAdjacentStrings(AdjacentStrings node) {
495 if (node.strings.contains(_oldNode)) {
496 return _parser.parseStringLiteral();
497 }
498 return _notAChild(node);
499 }
500
501 @override
502 AstNode visitAnnotation(Annotation node) {
503 if (identical(_oldNode, node.name)) {
504 throw new InsufficientContextException();
505 } else if (identical(_oldNode, node.constructorName)) {
506 throw new InsufficientContextException();
507 } else if (identical(_oldNode, node.arguments)) {
508 return _parser.parseArgumentList();
509 }
510 return _notAChild(node);
511 }
512
513 @override
514 AstNode visitArgumentList(ArgumentList node) {
515 if (node.arguments.contains(_oldNode)) {
516 return _parser.parseArgument();
517 }
518 return _notAChild(node);
519 }
520
521 @override
522 AstNode visitAsExpression(AsExpression node) {
523 if (identical(_oldNode, node.expression)) {
524 return _parser.parseBitwiseOrExpression();
525 } else if (identical(_oldNode, node.type)) {
526 return _parser.parseTypeName();
527 }
528 return _notAChild(node);
529 }
530
531 @override
532 AstNode visitAssertStatement(AssertStatement node) {
533 if (identical(_oldNode, node.condition)) {
534 return _parser.parseExpression2();
535 }
536 return _notAChild(node);
537 }
538
539 @override
540 AstNode visitAssignmentExpression(AssignmentExpression node) {
541 if (identical(_oldNode, node.leftHandSide)) {
542 // TODO(brianwilkerson) If the assignment is part of a cascade section,
543 // then we don't have a single parse method that will work.
544 // Otherwise, we can parse a conditional expression, but need to ensure
545 // that the resulting expression is assignable.
546 // return parser.parseConditionalExpression();
547 throw new InsufficientContextException();
548 } else if (identical(_oldNode, node.rightHandSide)) {
549 if (_isCascadeAllowedInAssignment(node)) {
550 return _parser.parseExpression2();
551 }
552 return _parser.parseExpressionWithoutCascade();
553 }
554 return _notAChild(node);
555 }
556
557 @override
558 AstNode visitAwaitExpression(AwaitExpression node) {
559 if (identical(_oldNode, node.expression)) {
560 // TODO(brianwilkerson) Depending on precedence,
561 // this might not be sufficient.
562 return _parser.parseExpression2();
563 }
564 return _notAChild(node);
565 }
566
567 @override
568 AstNode visitBinaryExpression(BinaryExpression node) {
569 if (identical(_oldNode, node.leftOperand)) {
570 throw new InsufficientContextException();
571 } else if (identical(_oldNode, node.rightOperand)) {
572 throw new InsufficientContextException();
573 }
574 return _notAChild(node);
575 }
576
577 @override
578 AstNode visitBlock(Block node) {
579 if (node.statements.contains(_oldNode)) {
580 return _parser.parseStatement2();
581 }
582 return _notAChild(node);
583 }
584
585 @override
586 AstNode visitBlockFunctionBody(BlockFunctionBody node) {
587 if (identical(_oldNode, node.block)) {
588 return _parser.parseBlock();
589 }
590 return _notAChild(node);
591 }
592
593 @override
594 AstNode visitBooleanLiteral(BooleanLiteral node) => _notAChild(node);
595
596 @override
597 AstNode visitBreakStatement(BreakStatement node) {
598 if (identical(_oldNode, node.label)) {
599 return _parser.parseSimpleIdentifier();
600 }
601 return _notAChild(node);
602 }
603
604 @override
605 AstNode visitCascadeExpression(CascadeExpression node) {
606 if (identical(_oldNode, node.target)) {
607 return _parser.parseConditionalExpression();
608 } else if (node.cascadeSections.contains(_oldNode)) {
609 throw new InsufficientContextException();
610 }
611 return _notAChild(node);
612 }
613
614 @override
615 AstNode visitCatchClause(CatchClause node) {
616 if (identical(_oldNode, node.exceptionType)) {
617 return _parser.parseTypeName();
618 } else if (identical(_oldNode, node.exceptionParameter)) {
619 return _parser.parseSimpleIdentifier();
620 } else if (identical(_oldNode, node.stackTraceParameter)) {
621 return _parser.parseSimpleIdentifier();
622 } else if (identical(_oldNode, node.body)) {
623 return _parser.parseBlock();
624 }
625 return _notAChild(node);
626 }
627
628 @override
629 AstNode visitClassDeclaration(ClassDeclaration node) {
630 if (identical(_oldNode, node.documentationComment)) {
631 throw new InsufficientContextException();
632 } else if (node.metadata.contains(_oldNode)) {
633 return _parser.parseAnnotation();
634 } else if (identical(_oldNode, node.name)) {
635 // Changing the class name changes whether a member is interpreted as a
636 // constructor or not, so we'll just have to re-parse the entire class.
637 throw new InsufficientContextException();
638 } else if (identical(_oldNode, node.typeParameters)) {
639 return _parser.parseTypeParameterList();
640 } else if (identical(_oldNode, node.extendsClause)) {
641 return _parser.parseExtendsClause();
642 } else if (identical(_oldNode, node.withClause)) {
643 return _parser.parseWithClause();
644 } else if (identical(_oldNode, node.implementsClause)) {
645 return _parser.parseImplementsClause();
646 } else if (node.members.contains(_oldNode)) {
647 ClassMember member = _parser.parseClassMember(node.name.name);
648 if (member == null) {
649 throw new InsufficientContextException();
650 }
651 return member;
652 }
653 return _notAChild(node);
654 }
655
656 @override
657 AstNode visitClassTypeAlias(ClassTypeAlias node) {
658 if (identical(_oldNode, node.documentationComment)) {
659 throw new InsufficientContextException();
660 } else if (node.metadata.contains(_oldNode)) {
661 return _parser.parseAnnotation();
662 } else if (identical(_oldNode, node.name)) {
663 return _parser.parseSimpleIdentifier();
664 } else if (identical(_oldNode, node.typeParameters)) {
665 return _parser.parseTypeParameterList();
666 } else if (identical(_oldNode, node.superclass)) {
667 return _parser.parseTypeName();
668 } else if (identical(_oldNode, node.withClause)) {
669 return _parser.parseWithClause();
670 } else if (identical(_oldNode, node.implementsClause)) {
671 return _parser.parseImplementsClause();
672 }
673 return _notAChild(node);
674 }
675
676 @override
677 AstNode visitComment(Comment node) {
678 throw new InsufficientContextException();
679 }
680
681 @override
682 AstNode visitCommentReference(CommentReference node) {
683 if (identical(_oldNode, node.identifier)) {
684 return _parser.parsePrefixedIdentifier();
685 }
686 return _notAChild(node);
687 }
688
689 @override
690 AstNode visitCompilationUnit(CompilationUnit node) {
691 throw new InsufficientContextException();
692 }
693
694 @override
695 AstNode visitConditionalExpression(ConditionalExpression node) {
696 if (identical(_oldNode, node.condition)) {
697 return _parser.parseIfNullExpression();
698 } else if (identical(_oldNode, node.thenExpression)) {
699 return _parser.parseExpressionWithoutCascade();
700 } else if (identical(_oldNode, node.elseExpression)) {
701 return _parser.parseExpressionWithoutCascade();
702 }
703 return _notAChild(node);
704 }
705
706 @override
707 AstNode visitConstructorDeclaration(ConstructorDeclaration node) {
708 if (identical(_oldNode, node.documentationComment)) {
709 throw new InsufficientContextException();
710 } else if (node.metadata.contains(_oldNode)) {
711 return _parser.parseAnnotation();
712 } else if (identical(_oldNode, node.returnType)) {
713 throw new InsufficientContextException();
714 } else if (identical(_oldNode, node.name)) {
715 throw new InsufficientContextException();
716 } else if (identical(_oldNode, node.parameters)) {
717 return _parser.parseFormalParameterList();
718 } else if (identical(_oldNode, node.redirectedConstructor)) {
719 throw new InsufficientContextException();
720 } else if (node.initializers.contains(_oldNode)) {
721 throw new InsufficientContextException();
722 } else if (identical(_oldNode, node.body)) {
723 throw new InsufficientContextException();
724 }
725 return _notAChild(node);
726 }
727
728 @override
729 AstNode visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
730 if (identical(_oldNode, node.fieldName)) {
731 return _parser.parseSimpleIdentifier();
732 } else if (identical(_oldNode, node.expression)) {
733 throw new InsufficientContextException();
734 }
735 return _notAChild(node);
736 }
737
738 @override
739 AstNode visitConstructorName(ConstructorName node) {
740 if (identical(_oldNode, node.type)) {
741 return _parser.parseTypeName();
742 } else if (identical(_oldNode, node.name)) {
743 return _parser.parseSimpleIdentifier();
744 }
745 return _notAChild(node);
746 }
747
748 @override
749 AstNode visitContinueStatement(ContinueStatement node) {
750 if (identical(_oldNode, node.label)) {
751 return _parser.parseSimpleIdentifier();
752 }
753 return _notAChild(node);
754 }
755
756 @override
757 AstNode visitDeclaredIdentifier(DeclaredIdentifier node) {
758 if (identical(_oldNode, node.documentationComment)) {
759 throw new InsufficientContextException();
760 } else if (node.metadata.contains(_oldNode)) {
761 return _parser.parseAnnotation();
762 } else if (identical(_oldNode, node.type)) {
763 throw new InsufficientContextException();
764 } else if (identical(_oldNode, node.identifier)) {
765 return _parser.parseSimpleIdentifier();
766 }
767 return _notAChild(node);
768 }
769
770 @override
771 AstNode visitDefaultFormalParameter(DefaultFormalParameter node) {
772 if (identical(_oldNode, node.parameter)) {
773 return _parser.parseNormalFormalParameter();
774 } else if (identical(_oldNode, node.defaultValue)) {
775 return _parser.parseExpression2();
776 }
777 return _notAChild(node);
778 }
779
780 @override
781 AstNode visitDoStatement(DoStatement node) {
782 if (identical(_oldNode, node.body)) {
783 return _parser.parseStatement2();
784 } else if (identical(_oldNode, node.condition)) {
785 return _parser.parseExpression2();
786 }
787 return _notAChild(node);
788 }
789
790 @override
791 AstNode visitDoubleLiteral(DoubleLiteral node) => _notAChild(node);
792
793 @override
794 AstNode visitEmptyFunctionBody(EmptyFunctionBody node) => _notAChild(node);
795
796 @override
797 AstNode visitEmptyStatement(EmptyStatement node) => _notAChild(node);
798
799 @override
800 AstNode visitEnumConstantDeclaration(EnumConstantDeclaration node) {
801 if (identical(_oldNode, node.documentationComment)) {
802 throw new InsufficientContextException();
803 } else if (node.metadata.contains(_oldNode)) {
804 return _parser.parseAnnotation();
805 } else if (identical(_oldNode, node.name)) {
806 return _parser.parseSimpleIdentifier();
807 }
808 return _notAChild(node);
809 }
810
811 @override
812 AstNode visitEnumDeclaration(EnumDeclaration node) {
813 if (identical(_oldNode, node.documentationComment)) {
814 throw new InsufficientContextException();
815 } else if (node.metadata.contains(_oldNode)) {
816 return _parser.parseAnnotation();
817 } else if (identical(_oldNode, node.name)) {
818 return _parser.parseSimpleIdentifier();
819 } else if (node.constants.contains(_oldNode)) {
820 throw new InsufficientContextException();
821 }
822 return _notAChild(node);
823 }
824
825 @override
826 AstNode visitExportDirective(ExportDirective node) {
827 if (identical(_oldNode, node.documentationComment)) {
828 throw new InsufficientContextException();
829 } else if (node.metadata.contains(_oldNode)) {
830 return _parser.parseAnnotation();
831 } else if (identical(_oldNode, node.uri)) {
832 return _parser.parseStringLiteral();
833 } else if (node.combinators.contains(_oldNode)) {
834 throw new IncrementalParseException();
835 //return parser.parseCombinator();
836 }
837 return _notAChild(node);
838 }
839
840 @override
841 AstNode visitExpressionFunctionBody(ExpressionFunctionBody node) {
842 if (identical(_oldNode, node.expression)) {
843 return _parser.parseExpression2();
844 }
845 return _notAChild(node);
846 }
847
848 @override
849 AstNode visitExpressionStatement(ExpressionStatement node) {
850 if (identical(_oldNode, node.expression)) {
851 return _parser.parseExpression2();
852 }
853 return _notAChild(node);
854 }
855
856 @override
857 AstNode visitExtendsClause(ExtendsClause node) {
858 if (identical(_oldNode, node.superclass)) {
859 return _parser.parseTypeName();
860 }
861 return _notAChild(node);
862 }
863
864 @override
865 AstNode visitFieldDeclaration(FieldDeclaration node) {
866 if (identical(_oldNode, node.documentationComment)) {
867 throw new InsufficientContextException();
868 } else if (node.metadata.contains(_oldNode)) {
869 return _parser.parseAnnotation();
870 } else if (identical(_oldNode, node.fields)) {
871 throw new InsufficientContextException();
872 }
873 return _notAChild(node);
874 }
875
876 @override
877 AstNode visitFieldFormalParameter(FieldFormalParameter node) {
878 if (identical(_oldNode, node.documentationComment)) {
879 throw new InsufficientContextException();
880 } else if (node.metadata.contains(_oldNode)) {
881 return _parser.parseAnnotation();
882 } else if (identical(_oldNode, node.type)) {
883 return _parser.parseTypeName();
884 } else if (identical(_oldNode, node.identifier)) {
885 return _parser.parseSimpleIdentifier();
886 } else if (identical(_oldNode, node.parameters)) {
887 return _parser.parseFormalParameterList();
888 }
889 return _notAChild(node);
890 }
891
892 @override
893 AstNode visitForEachStatement(ForEachStatement node) {
894 if (identical(_oldNode, node.loopVariable)) {
895 throw new InsufficientContextException();
896 //return parser.parseDeclaredIdentifier();
897 } else if (identical(_oldNode, node.identifier)) {
898 return _parser.parseSimpleIdentifier();
899 } else if (identical(_oldNode, node.body)) {
900 return _parser.parseStatement2();
901 }
902 return _notAChild(node);
903 }
904
905 @override
906 AstNode visitFormalParameterList(FormalParameterList node) {
907 // We don't know which kind of parameter to parse.
908 throw new InsufficientContextException();
909 }
910
911 @override
912 AstNode visitForStatement(ForStatement node) {
913 if (identical(_oldNode, node.variables)) {
914 throw new InsufficientContextException();
915 } else if (identical(_oldNode, node.initialization)) {
916 throw new InsufficientContextException();
917 } else if (identical(_oldNode, node.condition)) {
918 return _parser.parseExpression2();
919 } else if (node.updaters.contains(_oldNode)) {
920 return _parser.parseExpression2();
921 } else if (identical(_oldNode, node.body)) {
922 return _parser.parseStatement2();
923 }
924 return _notAChild(node);
925 }
926
927 @override
928 AstNode visitFunctionDeclaration(FunctionDeclaration node) {
929 if (identical(_oldNode, node.documentationComment)) {
930 throw new InsufficientContextException();
931 } else if (node.metadata.contains(_oldNode)) {
932 return _parser.parseAnnotation();
933 } else if (identical(_oldNode, node.returnType)) {
934 return _parser.parseReturnType();
935 } else if (identical(_oldNode, node.name)) {
936 return _parser.parseSimpleIdentifier();
937 } else if (identical(_oldNode, node.functionExpression)) {
938 throw new InsufficientContextException();
939 }
940 return _notAChild(node);
941 }
942
943 @override
944 AstNode visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
945 if (identical(_oldNode, node.functionDeclaration)) {
946 throw new InsufficientContextException();
947 }
948 return _notAChild(node);
949 }
950
951 @override
952 AstNode visitFunctionExpression(FunctionExpression node) {
953 if (identical(_oldNode, node.parameters)) {
954 return _parser.parseFormalParameterList();
955 } else if (identical(_oldNode, node.body)) {
956 throw new InsufficientContextException();
957 }
958 return _notAChild(node);
959 }
960
961 @override
962 AstNode visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
963 if (identical(_oldNode, node.function)) {
964 throw new InsufficientContextException();
965 } else if (identical(_oldNode, node.argumentList)) {
966 return _parser.parseArgumentList();
967 }
968 return _notAChild(node);
969 }
970
971 @override
972 AstNode visitFunctionTypeAlias(FunctionTypeAlias node) {
973 if (identical(_oldNode, node.documentationComment)) {
974 throw new InsufficientContextException();
975 } else if (node.metadata.contains(_oldNode)) {
976 return _parser.parseAnnotation();
977 } else if (identical(_oldNode, node.returnType)) {
978 return _parser.parseReturnType();
979 } else if (identical(_oldNode, node.name)) {
980 return _parser.parseSimpleIdentifier();
981 } else if (identical(_oldNode, node.typeParameters)) {
982 return _parser.parseTypeParameterList();
983 } else if (identical(_oldNode, node.parameters)) {
984 return _parser.parseFormalParameterList();
985 }
986 return _notAChild(node);
987 }
988
989 @override
990 AstNode visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
991 if (identical(_oldNode, node.documentationComment)) {
992 throw new InsufficientContextException();
993 } else if (node.metadata.contains(_oldNode)) {
994 return _parser.parseAnnotation();
995 } else if (identical(_oldNode, node.returnType)) {
996 return _parser.parseReturnType();
997 } else if (identical(_oldNode, node.identifier)) {
998 return _parser.parseSimpleIdentifier();
999 } else if (identical(_oldNode, node.parameters)) {
1000 return _parser.parseFormalParameterList();
1001 }
1002 return _notAChild(node);
1003 }
1004
1005 @override
1006 AstNode visitHideCombinator(HideCombinator node) {
1007 if (node.hiddenNames.contains(_oldNode)) {
1008 return _parser.parseSimpleIdentifier();
1009 }
1010 return _notAChild(node);
1011 }
1012
1013 @override
1014 AstNode visitIfStatement(IfStatement node) {
1015 if (identical(_oldNode, node.condition)) {
1016 return _parser.parseExpression2();
1017 } else if (identical(_oldNode, node.thenStatement)) {
1018 return _parser.parseStatement2();
1019 } else if (identical(_oldNode, node.elseStatement)) {
1020 return _parser.parseStatement2();
1021 }
1022 return _notAChild(node);
1023 }
1024
1025 @override
1026 AstNode visitImplementsClause(ImplementsClause node) {
1027 if (node.interfaces.contains(node)) {
1028 return _parser.parseTypeName();
1029 }
1030 return _notAChild(node);
1031 }
1032
1033 @override
1034 AstNode visitImportDirective(ImportDirective node) {
1035 if (identical(_oldNode, node.documentationComment)) {
1036 throw new InsufficientContextException();
1037 } else if (node.metadata.contains(_oldNode)) {
1038 return _parser.parseAnnotation();
1039 } else if (identical(_oldNode, node.uri)) {
1040 return _parser.parseStringLiteral();
1041 } else if (identical(_oldNode, node.prefix)) {
1042 return _parser.parseSimpleIdentifier();
1043 } else if (node.combinators.contains(_oldNode)) {
1044 return _parser.parseCombinator();
1045 }
1046 return _notAChild(node);
1047 }
1048
1049 @override
1050 AstNode visitIndexExpression(IndexExpression node) {
1051 if (identical(_oldNode, node.target)) {
1052 throw new InsufficientContextException();
1053 } else if (identical(_oldNode, node.index)) {
1054 return _parser.parseExpression2();
1055 }
1056 return _notAChild(node);
1057 }
1058
1059 @override
1060 AstNode visitInstanceCreationExpression(InstanceCreationExpression node) {
1061 if (identical(_oldNode, node.constructorName)) {
1062 return _parser.parseConstructorName();
1063 } else if (identical(_oldNode, node.argumentList)) {
1064 return _parser.parseArgumentList();
1065 }
1066 return _notAChild(node);
1067 }
1068
1069 @override
1070 AstNode visitIntegerLiteral(IntegerLiteral node) => _notAChild(node);
1071
1072 @override
1073 AstNode visitInterpolationExpression(InterpolationExpression node) {
1074 if (identical(_oldNode, node.expression)) {
1075 if (node.leftBracket == null) {
1076 throw new InsufficientContextException();
1077 //return parser.parseThisOrSimpleIdentifier();
1078 }
1079 return _parser.parseExpression2();
1080 }
1081 return _notAChild(node);
1082 }
1083
1084 @override
1085 AstNode visitInterpolationString(InterpolationString node) {
1086 throw new InsufficientContextException();
1087 }
1088
1089 @override
1090 AstNode visitIsExpression(IsExpression node) {
1091 if (identical(_oldNode, node.expression)) {
1092 return _parser.parseBitwiseOrExpression();
1093 } else if (identical(_oldNode, node.type)) {
1094 return _parser.parseTypeName();
1095 }
1096 return _notAChild(node);
1097 }
1098
1099 @override
1100 AstNode visitLabel(Label node) {
1101 if (identical(_oldNode, node.label)) {
1102 return _parser.parseSimpleIdentifier();
1103 }
1104 return _notAChild(node);
1105 }
1106
1107 @override
1108 AstNode visitLabeledStatement(LabeledStatement node) {
1109 if (node.labels.contains(_oldNode)) {
1110 return _parser.parseLabel();
1111 } else if (identical(_oldNode, node.statement)) {
1112 return _parser.parseStatement2();
1113 }
1114 return _notAChild(node);
1115 }
1116
1117 @override
1118 AstNode visitLibraryDirective(LibraryDirective node) {
1119 if (identical(_oldNode, node.documentationComment)) {
1120 throw new InsufficientContextException();
1121 } else if (node.metadata.contains(_oldNode)) {
1122 return _parser.parseAnnotation();
1123 } else if (identical(_oldNode, node.name)) {
1124 return _parser.parseLibraryIdentifier();
1125 }
1126 return _notAChild(node);
1127 }
1128
1129 @override
1130 AstNode visitLibraryIdentifier(LibraryIdentifier node) {
1131 if (node.components.contains(_oldNode)) {
1132 return _parser.parseSimpleIdentifier();
1133 }
1134 return _notAChild(node);
1135 }
1136
1137 @override
1138 AstNode visitListLiteral(ListLiteral node) {
1139 if (identical(_oldNode, node.typeArguments)) {
1140 return _parser.parseTypeArgumentList();
1141 } else if (node.elements.contains(_oldNode)) {
1142 return _parser.parseExpression2();
1143 }
1144 return _notAChild(node);
1145 }
1146
1147 @override
1148 AstNode visitMapLiteral(MapLiteral node) {
1149 if (identical(_oldNode, node.typeArguments)) {
1150 return _parser.parseTypeArgumentList();
1151 } else if (node.entries.contains(_oldNode)) {
1152 return _parser.parseMapLiteralEntry();
1153 }
1154 return _notAChild(node);
1155 }
1156
1157 @override
1158 AstNode visitMapLiteralEntry(MapLiteralEntry node) {
1159 if (identical(_oldNode, node.key)) {
1160 return _parser.parseExpression2();
1161 } else if (identical(_oldNode, node.value)) {
1162 return _parser.parseExpression2();
1163 }
1164 return _notAChild(node);
1165 }
1166
1167 @override
1168 AstNode visitMethodDeclaration(MethodDeclaration node) {
1169 if (identical(_oldNode, node.documentationComment)) {
1170 throw new InsufficientContextException();
1171 } else if (node.metadata.contains(_oldNode)) {
1172 return _parser.parseAnnotation();
1173 } else if (identical(_oldNode, node.returnType)) {
1174 throw new InsufficientContextException();
1175 //return parser.parseTypeName();
1176 //return parser.parseReturnType();
1177 } else if (identical(_oldNode, node.name)) {
1178 if (node.operatorKeyword != null) {
1179 throw new InsufficientContextException();
1180 }
1181 return _parser.parseSimpleIdentifier();
1182 } else if (identical(_oldNode, node.body)) {
1183 //return parser.parseFunctionBody();
1184 throw new InsufficientContextException();
1185 } else if (identical(_oldNode, node.parameters)) {
1186 // TODO(paulberry): if we want errors to be correct, we'll need to also
1187 // call _validateFormalParameterList, and sometimes
1188 // _validateModifiersForGetterOrSetterOrMethod.
1189 return _parser.parseFormalParameterList();
1190 }
1191 return _notAChild(node);
1192 }
1193
1194 @override
1195 AstNode visitMethodInvocation(MethodInvocation node) {
1196 if (identical(_oldNode, node.target)) {
1197 throw new IncrementalParseException();
1198 } else if (identical(_oldNode, node.methodName)) {
1199 return _parser.parseSimpleIdentifier();
1200 } else if (identical(_oldNode, node.argumentList)) {
1201 return _parser.parseArgumentList();
1202 }
1203 return _notAChild(node);
1204 }
1205
1206 @override
1207 AstNode visitNamedExpression(NamedExpression node) {
1208 if (identical(_oldNode, node.name)) {
1209 return _parser.parseLabel();
1210 } else if (identical(_oldNode, node.expression)) {
1211 return _parser.parseExpression2();
1212 }
1213 return _notAChild(node);
1214 }
1215
1216 @override
1217 AstNode visitNativeClause(NativeClause node) {
1218 if (identical(_oldNode, node.name)) {
1219 return _parser.parseStringLiteral();
1220 }
1221 return _notAChild(node);
1222 }
1223
1224 @override
1225 AstNode visitNativeFunctionBody(NativeFunctionBody node) {
1226 if (identical(_oldNode, node.stringLiteral)) {
1227 return _parser.parseStringLiteral();
1228 }
1229 return _notAChild(node);
1230 }
1231
1232 @override
1233 AstNode visitNullLiteral(NullLiteral node) => _notAChild(node);
1234
1235 @override
1236 AstNode visitParenthesizedExpression(ParenthesizedExpression node) {
1237 if (identical(_oldNode, node.expression)) {
1238 return _parser.parseExpression2();
1239 }
1240 return _notAChild(node);
1241 }
1242
1243 @override
1244 AstNode visitPartDirective(PartDirective node) {
1245 if (identical(_oldNode, node.documentationComment)) {
1246 throw new InsufficientContextException();
1247 } else if (node.metadata.contains(_oldNode)) {
1248 return _parser.parseAnnotation();
1249 } else if (identical(_oldNode, node.uri)) {
1250 return _parser.parseStringLiteral();
1251 }
1252 return _notAChild(node);
1253 }
1254
1255 @override
1256 AstNode visitPartOfDirective(PartOfDirective node) {
1257 if (identical(_oldNode, node.documentationComment)) {
1258 throw new InsufficientContextException();
1259 } else if (node.metadata.contains(_oldNode)) {
1260 return _parser.parseAnnotation();
1261 } else if (identical(_oldNode, node.libraryName)) {
1262 return _parser.parseLibraryIdentifier();
1263 }
1264 return _notAChild(node);
1265 }
1266
1267 @override
1268 AstNode visitPostfixExpression(PostfixExpression node) {
1269 if (identical(_oldNode, node.operand)) {
1270 throw new InsufficientContextException();
1271 }
1272 return _notAChild(node);
1273 }
1274
1275 @override
1276 AstNode visitPrefixedIdentifier(PrefixedIdentifier node) {
1277 if (identical(_oldNode, node.prefix)) {
1278 return _parser.parseSimpleIdentifier();
1279 } else if (identical(_oldNode, node.identifier)) {
1280 return _parser.parseSimpleIdentifier();
1281 }
1282 return _notAChild(node);
1283 }
1284
1285 @override
1286 AstNode visitPrefixExpression(PrefixExpression node) {
1287 if (identical(_oldNode, node.operand)) {
1288 throw new InsufficientContextException();
1289 }
1290 return _notAChild(node);
1291 }
1292
1293 @override
1294 AstNode visitPropertyAccess(PropertyAccess node) {
1295 if (identical(_oldNode, node.target)) {
1296 throw new InsufficientContextException();
1297 } else if (identical(_oldNode, node.propertyName)) {
1298 return _parser.parseSimpleIdentifier();
1299 }
1300 return _notAChild(node);
1301 }
1302
1303 @override
1304 AstNode visitRedirectingConstructorInvocation(
1305 RedirectingConstructorInvocation node) {
1306 if (identical(_oldNode, node.constructorName)) {
1307 return _parser.parseSimpleIdentifier();
1308 } else if (identical(_oldNode, node.argumentList)) {
1309 return _parser.parseArgumentList();
1310 }
1311 return _notAChild(node);
1312 }
1313
1314 @override
1315 AstNode visitRethrowExpression(RethrowExpression node) => _notAChild(node);
1316
1317 @override
1318 AstNode visitReturnStatement(ReturnStatement node) {
1319 if (identical(_oldNode, node.expression)) {
1320 return _parser.parseExpression2();
1321 }
1322 return _notAChild(node);
1323 }
1324
1325 @override
1326 AstNode visitScriptTag(ScriptTag node) => _notAChild(node);
1327
1328 @override
1329 AstNode visitShowCombinator(ShowCombinator node) {
1330 if (node.shownNames.contains(_oldNode)) {
1331 return _parser.parseSimpleIdentifier();
1332 }
1333 return _notAChild(node);
1334 }
1335
1336 @override
1337 AstNode visitSimpleFormalParameter(SimpleFormalParameter node) {
1338 if (identical(_oldNode, node.documentationComment)) {
1339 throw new InsufficientContextException();
1340 } else if (node.metadata.contains(_oldNode)) {
1341 return _parser.parseAnnotation();
1342 } else if (identical(_oldNode, node.type)) {
1343 throw new InsufficientContextException();
1344 } else if (identical(_oldNode, node.identifier)) {
1345 throw new InsufficientContextException();
1346 }
1347 return _notAChild(node);
1348 }
1349
1350 @override
1351 AstNode visitSimpleIdentifier(SimpleIdentifier node) => _notAChild(node);
1352
1353 @override
1354 AstNode visitSimpleStringLiteral(SimpleStringLiteral node) =>
1355 _notAChild(node);
1356
1357 @override
1358 AstNode visitStringInterpolation(StringInterpolation node) {
1359 if (node.elements.contains(_oldNode)) {
1360 throw new InsufficientContextException();
1361 }
1362 return _notAChild(node);
1363 }
1364
1365 @override
1366 AstNode visitSuperConstructorInvocation(SuperConstructorInvocation node) {
1367 if (identical(_oldNode, node.constructorName)) {
1368 return _parser.parseSimpleIdentifier();
1369 } else if (identical(_oldNode, node.argumentList)) {
1370 return _parser.parseArgumentList();
1371 }
1372 return _notAChild(node);
1373 }
1374
1375 @override
1376 AstNode visitSuperExpression(SuperExpression node) => _notAChild(node);
1377
1378 @override
1379 AstNode visitSwitchCase(SwitchCase node) {
1380 if (node.labels.contains(_oldNode)) {
1381 return _parser.parseLabel();
1382 } else if (identical(_oldNode, node.expression)) {
1383 return _parser.parseExpression2();
1384 } else if (node.statements.contains(_oldNode)) {
1385 return _parser.parseStatement2();
1386 }
1387 return _notAChild(node);
1388 }
1389
1390 @override
1391 AstNode visitSwitchDefault(SwitchDefault node) {
1392 if (node.labels.contains(_oldNode)) {
1393 return _parser.parseLabel();
1394 } else if (node.statements.contains(_oldNode)) {
1395 return _parser.parseStatement2();
1396 }
1397 return _notAChild(node);
1398 }
1399
1400 @override
1401 AstNode visitSwitchStatement(SwitchStatement node) {
1402 if (identical(_oldNode, node.expression)) {
1403 return _parser.parseExpression2();
1404 } else if (node.members.contains(_oldNode)) {
1405 throw new InsufficientContextException();
1406 }
1407 return _notAChild(node);
1408 }
1409
1410 @override
1411 AstNode visitSymbolLiteral(SymbolLiteral node) => _notAChild(node);
1412
1413 @override
1414 AstNode visitThisExpression(ThisExpression node) => _notAChild(node);
1415
1416 @override
1417 AstNode visitThrowExpression(ThrowExpression node) {
1418 if (identical(_oldNode, node.expression)) {
1419 if (_isCascadeAllowedInThrow(node)) {
1420 return _parser.parseExpression2();
1421 }
1422 return _parser.parseExpressionWithoutCascade();
1423 }
1424 return _notAChild(node);
1425 }
1426
1427 @override
1428 AstNode visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
1429 if (identical(_oldNode, node.documentationComment)) {
1430 throw new InsufficientContextException();
1431 } else if (node.metadata.contains(_oldNode)) {
1432 return _parser.parseAnnotation();
1433 } else if (identical(_oldNode, node.variables)) {
1434 throw new InsufficientContextException();
1435 }
1436 return _notAChild(node);
1437 }
1438
1439 @override
1440 AstNode visitTryStatement(TryStatement node) {
1441 if (identical(_oldNode, node.body)) {
1442 return _parser.parseBlock();
1443 } else if (node.catchClauses.contains(_oldNode)) {
1444 throw new InsufficientContextException();
1445 } else if (identical(_oldNode, node.finallyBlock)) {
1446 throw new InsufficientContextException();
1447 }
1448 return _notAChild(node);
1449 }
1450
1451 @override
1452 AstNode visitTypeArgumentList(TypeArgumentList node) {
1453 if (node.arguments.contains(_oldNode)) {
1454 return _parser.parseTypeName();
1455 }
1456 return _notAChild(node);
1457 }
1458
1459 @override
1460 AstNode visitTypeName(TypeName node) {
1461 if (identical(_oldNode, node.name)) {
1462 return _parser.parsePrefixedIdentifier();
1463 } else if (identical(_oldNode, node.typeArguments)) {
1464 return _parser.parseTypeArgumentList();
1465 }
1466 return _notAChild(node);
1467 }
1468
1469 @override
1470 AstNode visitTypeParameter(TypeParameter node) {
1471 if (identical(_oldNode, node.documentationComment)) {
1472 throw new InsufficientContextException();
1473 } else if (node.metadata.contains(_oldNode)) {
1474 return _parser.parseAnnotation();
1475 } else if (identical(_oldNode, node.name)) {
1476 return _parser.parseSimpleIdentifier();
1477 } else if (identical(_oldNode, node.bound)) {
1478 return _parser.parseTypeName();
1479 }
1480 return _notAChild(node);
1481 }
1482
1483 @override
1484 AstNode visitTypeParameterList(TypeParameterList node) {
1485 if (node.typeParameters.contains(node)) {
1486 return _parser.parseTypeParameter();
1487 }
1488 return _notAChild(node);
1489 }
1490
1491 @override
1492 AstNode visitVariableDeclaration(VariableDeclaration node) {
1493 if (identical(_oldNode, node.documentationComment)) {
1494 throw new InsufficientContextException();
1495 } else if (node.metadata.contains(_oldNode)) {
1496 return _parser.parseAnnotation();
1497 } else if (identical(_oldNode, node.name)) {
1498 throw new InsufficientContextException();
1499 } else if (identical(_oldNode, node.initializer)) {
1500 throw new InsufficientContextException();
1501 }
1502 return _notAChild(node);
1503 }
1504
1505 @override
1506 AstNode visitVariableDeclarationList(VariableDeclarationList node) {
1507 if (identical(_oldNode, node.documentationComment)) {
1508 throw new InsufficientContextException();
1509 } else if (node.metadata.contains(_oldNode)) {
1510 return _parser.parseAnnotation();
1511 } else if (identical(_oldNode, node.type)) {
1512 // There is not enough context to know whether we should reparse the type
1513 // using parseReturnType() (which allows 'void') or parseTypeName()
1514 // (which doesn't). Note that even though the language disallows
1515 // variables of type 'void', the parser sometimes accepts them in the
1516 // course of error recovery (e.g. "class C { void v; }"
1517 throw new InsufficientContextException();
1518 } else if (node.variables.contains(_oldNode)) {
1519 throw new InsufficientContextException();
1520 }
1521 return _notAChild(node);
1522 }
1523
1524 @override
1525 AstNode visitVariableDeclarationStatement(VariableDeclarationStatement node) {
1526 if (identical(_oldNode, node.variables)) {
1527 throw new InsufficientContextException();
1528 }
1529 return _notAChild(node);
1530 }
1531
1532 @override
1533 AstNode visitWhileStatement(WhileStatement node) {
1534 if (identical(_oldNode, node.condition)) {
1535 return _parser.parseExpression2();
1536 } else if (identical(_oldNode, node.body)) {
1537 return _parser.parseStatement2();
1538 }
1539 return _notAChild(node);
1540 }
1541
1542 @override
1543 AstNode visitWithClause(WithClause node) {
1544 if (node.mixinTypes.contains(node)) {
1545 return _parser.parseTypeName();
1546 }
1547 return _notAChild(node);
1548 }
1549
1550 @override
1551 AstNode visitYieldStatement(YieldStatement node) {
1552 if (identical(_oldNode, node.expression)) {
1553 return _parser.parseExpression2();
1554 }
1555 return _notAChild(node);
1556 }
1557
1558 /**
1559 * Return `true` if the given assignment [expression] can have a cascade
1560 * expression on the right-hand side.
1561 */
1562 bool _isCascadeAllowedInAssignment(AssignmentExpression expression) {
1563 // TODO(brianwilkerson) Implement this method.
1564 throw new InsufficientContextException();
1565 }
1566
1567 /**
1568 * Return `true` if the given throw [expression] can have a cascade
1569 * expression.
1570 */
1571 bool _isCascadeAllowedInThrow(ThrowExpression expression) {
1572 // TODO(brianwilkerson) Implement this method.
1573 throw new InsufficientContextException();
1574 }
1575
1576 /**
1577 * Throw an exception indicating that the visited [node] was not the parent of
1578 * the node to be replaced.
1579 */
1580 AstNode _notAChild(AstNode node) {
1581 throw new IncrementalParseException.con1(
1582 "Internal error: the visited node (a ${node.runtimeType}) was not the pa rent of the node to be replaced (a ${_oldNode.runtimeType})");
1583 }
1584 }
1585
1586 /**
1587 * An exception that occurred while attempting to parse a replacement for a
1588 * specified node in an existing AST structure.
1589 */
1590 class IncrementalParseException extends RuntimeException {
1591 /**
1592 * Initialize a newly created exception to have no message and to be its own
1593 * cause.
1594 */
1595 IncrementalParseException() : super();
1596
1597 /**
1598 * Initialize a newly created exception to have the given [message] and to be
1599 * its own cause.
1600 */
1601 IncrementalParseException.con1(String message) : super(message: message);
1602
1603 /**
1604 * Initialize a newly created exception to have no message and to have the
1605 * given [cause].
1606 */
1607 IncrementalParseException.con2(Exception cause) : super(cause: cause);
1608 }
1609
1610 /**
1611 * An object used to re-parse a single AST structure within a larger AST
1612 * structure.
1613 */
1614 class IncrementalParser {
1615 /**
1616 * The source being parsed.
1617 */
1618 final Source _source;
1619
1620 /**
1621 * A map from old tokens to new tokens used during the cloning process.
1622 */
1623 final TokenMap _tokenMap;
1624
1625 /**
1626 * The error listener that will be informed of any errors that are found
1627 * during the parse.
1628 */
1629 final AnalysisErrorListener _errorListener;
1630
1631 /**
1632 * The node in the AST structure that contains the revised content.
1633 */
1634 AstNode _updatedNode;
1635
1636 /**
1637 * Initialize a newly created incremental parser to parse a portion of the
1638 * content of the given [_source]. The [_tokenMap] is a map from old tokens to
1639 * new tokens that is used during the cloning process. The [_errorListener]
1640 * will be informed of any errors that are found during the parse.
1641 */
1642 IncrementalParser(this._source, this._tokenMap, this._errorListener);
1643
1644 /**
1645 * Return the node in the AST structure that contains the revised content.
1646 */
1647 AstNode get updatedNode => _updatedNode;
1648
1649 /**
1650 * Given a range of tokens that were re-scanned, re-parse the minimum number
1651 * of tokens to produce a consistent AST structure. The range is represented
1652 * by the first and last tokens in the range.
1653 *
1654 * More specifically, the [leftToken] is the token in the new token stream
1655 * immediately to the left of the range of tokens that were inserted and the
1656 * [rightToken] is the token in the new token stream immediately to the right
1657 * of the range of tokens that were inserted. The [originalStart] and
1658 * [originalEnd] are the offsets in the original source of the first and last
1659 * characters that were modified.
1660 *
1661 * The tokens are assumed to be contained in the same token stream.
1662 */
1663 AstNode reparse(AstNode originalStructure, Token leftToken, Token rightToken,
1664 int originalStart, int originalEnd) {
1665 AstNode oldNode = null;
1666 AstNode newNode = null;
1667 //
1668 // Find the first token that needs to be re-parsed.
1669 //
1670 Token firstToken = leftToken.next;
1671 if (identical(firstToken, rightToken)) {
1672 // If there are no new tokens, then we need to include at least one copied
1673 // node in the range.
1674 firstToken = leftToken;
1675 }
1676 //
1677 // Find the smallest AST node that encompasses the range of re-scanned
1678 // tokens.
1679 //
1680 if (originalEnd < originalStart) {
1681 oldNode = new NodeLocator(originalStart).searchWithin(originalStructure);
1682 } else {
1683 oldNode = new NodeLocator(originalStart, originalEnd)
1684 .searchWithin(originalStructure);
1685 }
1686 //
1687 // Find the token at which parsing is to begin.
1688 //
1689 int originalOffset = oldNode.offset;
1690 Token parseToken = _findTokenAt(firstToken, originalOffset);
1691 if (parseToken == null) {
1692 return null;
1693 }
1694 //
1695 // Parse the appropriate AST structure starting at the appropriate place.
1696 //
1697 Parser parser = new Parser(_source, _errorListener);
1698 parser.currentToken = parseToken;
1699 while (newNode == null) {
1700 AstNode parent = oldNode.parent;
1701 if (parent == null) {
1702 parseToken = _findFirstToken(parseToken);
1703 parser.currentToken = parseToken;
1704 return parser.parseCompilationUnit2();
1705 }
1706 bool advanceToParent = false;
1707 try {
1708 IncrementalParseDispatcher dispatcher =
1709 new IncrementalParseDispatcher(parser, oldNode);
1710 IncrementalParseStateBuilder contextBuilder =
1711 new IncrementalParseStateBuilder(parser);
1712 contextBuilder.buildState(oldNode);
1713 newNode = parent.accept(dispatcher);
1714 //
1715 // Validate that the new node can replace the old node.
1716 //
1717 Token mappedToken = _tokenMap.get(oldNode.endToken.next);
1718 if (mappedToken == null ||
1719 newNode == null ||
1720 mappedToken.offset != newNode.endToken.next.offset ||
1721 newNode.offset != oldNode.offset) {
1722 advanceToParent = true;
1723 }
1724 } on InsufficientContextException {
1725 advanceToParent = true;
1726 } catch (exception) {
1727 return null;
1728 }
1729 if (advanceToParent) {
1730 newNode = null;
1731 oldNode = parent;
1732 originalOffset = oldNode.offset;
1733 parseToken = _findTokenAt(parseToken, originalOffset);
1734 parser.currentToken = parseToken;
1735 }
1736 }
1737 _updatedNode = newNode;
1738 //
1739 // Replace the old node with the new node in a copy of the original AST
1740 // structure.
1741 //
1742 if (identical(oldNode, originalStructure)) {
1743 // We ended up re-parsing the whole structure, so there's no need for a
1744 // copy.
1745 ResolutionCopier.copyResolutionData(oldNode, newNode);
1746 return newNode;
1747 }
1748 ResolutionCopier.copyResolutionData(oldNode, newNode);
1749 IncrementalAstCloner cloner =
1750 new IncrementalAstCloner(oldNode, newNode, _tokenMap);
1751 return originalStructure.accept(cloner) as AstNode;
1752 }
1753
1754 /**
1755 * Return the first (non-EOF) token in the token stream containing the
1756 * [firstToken].
1757 */
1758 Token _findFirstToken(Token firstToken) {
1759 while (firstToken.type != TokenType.EOF) {
1760 firstToken = firstToken.previous;
1761 }
1762 return firstToken.next;
1763 }
1764
1765 /**
1766 * Find the token at or before the [firstToken] with the given [offset], or
1767 * `null` if there is no such token.
1768 */
1769 Token _findTokenAt(Token firstToken, int offset) {
1770 while (firstToken.offset > offset && firstToken.type != TokenType.EOF) {
1771 firstToken = firstToken.previous;
1772 }
1773 return firstToken;
1774 }
1775 }
1776
1777 /**
1778 * A visitor capable of inferring the correct parser state for incremental
1779 * parsing. This visitor visits each parent/child relationship in the chain of
1780 * ancestors of the node to be replaced (starting with the root of the parse
1781 * tree), updating the parser to the correct state for parsing the child of the
1782 * given parent. Once it has visited all of these relationships, the parser
1783 * will be in the correct state for reparsing the node to be replaced.
1784 */
1785 class IncrementalParseStateBuilder extends SimpleAstVisitor {
1786 // TODO(paulberry): add support for other pieces of parser state (_inAsync,
1787 // _inGenerator, _inLoop, and _inSwitch). Note that _inLoop and _inSwitch
1788 // only affect error message generation.
1789
1790 /**
1791 * The parser whose state should be built.
1792 */
1793 final Parser _parser;
1794
1795 /**
1796 * The child node in the parent/child relationship currently being visited.
1797 * (The corresponding parent is the node passed to the visit...() function.)
1798 */
1799 AstNode _childNode;
1800
1801 /**
1802 * Create an IncrementalParseStateBuilder which will build the correct state
1803 * for [_parser].
1804 */
1805 IncrementalParseStateBuilder(this._parser);
1806
1807 /**
1808 * Build the correct parser state for parsing a replacement for [node].
1809 */
1810 void buildState(AstNode node) {
1811 List<AstNode> ancestors = <AstNode>[];
1812 while (node != null) {
1813 ancestors.add(node);
1814 node = node.parent;
1815 }
1816 _parser._inInitializer = false;
1817 for (int i = ancestors.length - 2; i >= 0; i--) {
1818 _childNode = ancestors[i];
1819 ancestors[i + 1].accept(this);
1820 }
1821 }
1822
1823 @override
1824 void visitArgumentList(ArgumentList node) {
1825 _parser._inInitializer = false;
1826 }
1827
1828 @override
1829 void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
1830 if (identical(_childNode, node.expression)) {
1831 _parser._inInitializer = true;
1832 }
1833 }
1834
1835 @override
1836 void visitIndexExpression(IndexExpression node) {
1837 if (identical(_childNode, node.index)) {
1838 _parser._inInitializer = false;
1839 }
1840 }
1841
1842 @override
1843 void visitInterpolationExpression(InterpolationExpression node) {
1844 if (identical(_childNode, node.expression)) {
1845 _parser._inInitializer = false;
1846 }
1847 }
1848
1849 @override
1850 void visitListLiteral(ListLiteral node) {
1851 if (node.elements.contains(_childNode)) {
1852 _parser._inInitializer = false;
1853 }
1854 }
1855
1856 @override
1857 void visitMapLiteral(MapLiteral node) {
1858 if (node.entries.contains(_childNode)) {
1859 _parser._inInitializer = false;
1860 }
1861 }
1862
1863 @override
1864 void visitParenthesizedExpression(ParenthesizedExpression node) {
1865 if (identical(_childNode, node.expression)) {
1866 _parser._inInitializer = false;
1867 }
1868 }
1869 }
1870
1871 /**
1872 * An exception indicating that an AST node cannot be re-parsed because there is
1873 * not enough context to know how to re-parse the node. Clients can attempt to
1874 * re-parse the parent of the node.
1875 */
1876 class InsufficientContextException extends IncrementalParseException {
1877 /**
1878 * Initialize a newly created exception to have no message and to be its own
1879 * cause.
1880 */
1881 InsufficientContextException() : super();
1882
1883 /**
1884 * Initialize a newly created exception to have the given [message] and to be
1885 * its own cause.
1886 */
1887 InsufficientContextException.con1(String message) : super.con1(message);
1888
1889 /**
1890 * Initialize a newly created exception to have no message and to have the
1891 * given [cause].
1892 */
1893 InsufficientContextException.con2(Exception cause) : super.con2(cause);
1894 }
1895
1896 /**
1897 * Wrapper around [Function] which should be called with "target" and
1898 * "arguments".
1899 */
1900 class MethodTrampoline {
1901 int parameterCount;
1902 Function trampoline;
1903 MethodTrampoline(this.parameterCount, this.trampoline);
1904 Object invoke(target, List arguments) {
1905 if (arguments.length != parameterCount) {
1906 throw new IllegalArgumentException(
1907 "${arguments.length} != $parameterCount");
1908 }
1909 switch (parameterCount) {
1910 case 0:
1911 return trampoline(target);
1912 case 1:
1913 return trampoline(target, arguments[0]);
1914 case 2:
1915 return trampoline(target, arguments[0], arguments[1]);
1916 case 3:
1917 return trampoline(target, arguments[0], arguments[1], arguments[2]);
1918 case 4:
1919 return trampoline(
1920 target, arguments[0], arguments[1], arguments[2], arguments[3]);
1921 default:
1922 throw new IllegalArgumentException("Not implemented for > 4 arguments");
1923 }
1924 }
1925 }
1926
1927 /**
1928 * A simple data-holder for a method that needs to return multiple values.
1929 */
1930 class Modifiers {
1931 /**
1932 * The token representing the keyword 'abstract', or `null` if the keyword was
1933 * not found.
1934 */
1935 Token abstractKeyword;
1936
1937 /**
1938 * The token representing the keyword 'const', or `null` if the keyword was
1939 * not found.
1940 */
1941 Token constKeyword;
1942
1943 /**
1944 * The token representing the keyword 'external', or `null` if the keyword was
1945 * not found.
1946 */
1947 Token externalKeyword;
1948
1949 /**
1950 * The token representing the keyword 'factory', or `null` if the keyword was
1951 * not found.
1952 */
1953 Token factoryKeyword;
1954
1955 /**
1956 * The token representing the keyword 'final', or `null` if the keyword was
1957 * not found.
1958 */
1959 Token finalKeyword;
1960
1961 /**
1962 * The token representing the keyword 'static', or `null` if the keyword was
1963 * not found.
1964 */
1965 Token staticKeyword;
1966
1967 /**
1968 * The token representing the keyword 'var', or `null` if the keyword was not
1969 * found.
1970 */
1971 Token varKeyword;
1972
1973 @override
1974 String toString() {
1975 StringBuffer buffer = new StringBuffer();
1976 bool needsSpace = _appendKeyword(buffer, false, abstractKeyword);
1977 needsSpace = _appendKeyword(buffer, needsSpace, constKeyword);
1978 needsSpace = _appendKeyword(buffer, needsSpace, externalKeyword);
1979 needsSpace = _appendKeyword(buffer, needsSpace, factoryKeyword);
1980 needsSpace = _appendKeyword(buffer, needsSpace, finalKeyword);
1981 needsSpace = _appendKeyword(buffer, needsSpace, staticKeyword);
1982 _appendKeyword(buffer, needsSpace, varKeyword);
1983 return buffer.toString();
1984 }
1985
1986 /**
1987 * If the given [keyword] is not `null`, append it to the given [builder],
1988 * prefixing it with a space if [needsSpace] is `true`. Return `true` if
1989 * subsequent keywords need to be prefixed with a space.
1990 */
1991 bool _appendKeyword(StringBuffer buffer, bool needsSpace, Token keyword) {
1992 if (keyword != null) {
1993 if (needsSpace) {
1994 buffer.writeCharCode(0x20);
1995 }
1996 buffer.write(keyword.lexeme);
1997 return true;
1998 }
1999 return needsSpace;
2000 }
2001 }
2002
2003 /**
2004 * A parser used to parse tokens into an AST structure.
2005 */
2006 class Parser {
2007 static String ASYNC = "async";
2008
2009 static String _AWAIT = "await";
2010
2011 static String _HIDE = "hide";
2012
2013 static String _OF = "of";
2014
2015 static String _ON = "on";
2016
2017 static String _NATIVE = "native";
2018
2019 static String _SHOW = "show";
2020
2021 static String SYNC = "sync";
2022
2023 static String _YIELD = "yield";
2024
2025 /**
2026 * The source being parsed.
2027 */
2028 final Source _source;
2029
2030 /**
2031 * The error listener that will be informed of any errors that are found
2032 * during the parse.
2033 */
2034 final AnalysisErrorListener _errorListener;
2035
2036 /**
2037 * An [errorListener] lock, if more than `0`, then errors are not reported.
2038 */
2039 int _errorListenerLock = 0;
2040
2041 /**
2042 * A flag indicating whether parser is to parse function bodies.
2043 */
2044 bool _parseFunctionBodies = true;
2045
2046 /**
2047 * The next token to be parsed.
2048 */
2049 Token _currentToken;
2050
2051 /**
2052 * A flag indicating whether the parser is currently in a function body marked
2053 * as being 'async'.
2054 */
2055 bool _inAsync = false;
2056
2057 /**
2058 * A flag indicating whether the parser is currently in a function body marked
2059 * as being 'async'.
2060 */
2061 bool _inGenerator = false;
2062
2063 /**
2064 * A flag indicating whether the parser is currently in the body of a loop.
2065 */
2066 bool _inLoop = false;
2067
2068 /**
2069 * A flag indicating whether the parser is currently in a switch statement.
2070 */
2071 bool _inSwitch = false;
2072
2073 /**
2074 * A flag indicating whether the parser is currently in a constructor field
2075 * initializer, with no intervening parens, braces, or brackets.
2076 */
2077 bool _inInitializer = false;
2078
2079 /**
2080 * A flag indicating whether the parser is to parse generic method syntax.
2081 */
2082 bool parseGenericMethods = false;
2083
2084 /**
2085 * Initialize a newly created parser to parse the content of the given
2086 * [_source] and to report any errors that are found to the given
2087 * [_errorListener].
2088 */
2089 Parser(this._source, this._errorListener);
2090
2091 void set currentToken(Token currentToken) {
2092 this._currentToken = currentToken;
2093 }
2094
2095 /**
2096 * Return `true` if the current token is the first token of a return type that
2097 * is followed by an identifier, possibly followed by a list of type
2098 * parameters, followed by a left-parenthesis. This is used by
2099 * [_parseTypeAlias] to determine whether or not to parse a return type.
2100 */
2101 bool get hasReturnTypeInTypeAlias {
2102 Token next = _skipReturnType(_currentToken);
2103 if (next == null) {
2104 return false;
2105 }
2106 return _tokenMatchesIdentifier(next);
2107 }
2108
2109 /**
2110 * Set whether the parser is to parse the async support.
2111 */
2112 @deprecated
2113 void set parseAsync(bool parseAsync) {
2114 // Async support cannot be disabled
2115 }
2116
2117 /**
2118 * Set whether the parser is to parse deferred libraries.
2119 */
2120 @deprecated
2121 void set parseDeferredLibraries(bool parseDeferredLibraries) {
2122 // Deferred libraries support cannot be disabled
2123 }
2124
2125 /**
2126 * Set whether the parser is to parse enum declarations.
2127 */
2128 @deprecated
2129 void set parseEnum(bool parseEnum) {
2130 // Enum support cannot be disabled
2131 }
2132
2133 /**
2134 * Set whether parser is to parse function bodies.
2135 */
2136 void set parseFunctionBodies(bool parseFunctionBodies) {
2137 this._parseFunctionBodies = parseFunctionBodies;
2138 }
2139
2140 /**
2141 * Advance to the next token in the token stream, making it the new current
2142 * token and return the token that was current before this method was invoked.
2143 */
2144 Token getAndAdvance() {
2145 Token token = _currentToken;
2146 _advance();
2147 return token;
2148 }
2149
2150 /**
2151 * Parse an annotation. Return the annotation that was parsed.
2152 *
2153 * annotation ::=
2154 * '@' qualified ('.' identifier)? arguments?
2155 *
2156 */
2157 Annotation parseAnnotation() {
2158 Token atSign = _expect(TokenType.AT);
2159 Identifier name = parsePrefixedIdentifier();
2160 Token period = null;
2161 SimpleIdentifier constructorName = null;
2162 if (_matches(TokenType.PERIOD)) {
2163 period = getAndAdvance();
2164 constructorName = parseSimpleIdentifier();
2165 }
2166 ArgumentList arguments = null;
2167 if (_matches(TokenType.OPEN_PAREN)) {
2168 arguments = parseArgumentList();
2169 }
2170 return new Annotation(atSign, name, period, constructorName, arguments);
2171 }
2172
2173 /**
2174 * Parse an argument. Return the argument that was parsed.
2175 *
2176 * argument ::=
2177 * namedArgument
2178 * | expression
2179 *
2180 * namedArgument ::=
2181 * label expression
2182 */
2183 Expression parseArgument() {
2184 //
2185 // Both namedArgument and expression can start with an identifier, but only
2186 // namedArgument can have an identifier followed by a colon.
2187 //
2188 if (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) {
2189 return new NamedExpression(parseLabel(), parseExpression2());
2190 } else {
2191 return parseExpression2();
2192 }
2193 }
2194
2195 /**
2196 * Parse a list of arguments. Return the argument list that was parsed.
2197 *
2198 * arguments ::=
2199 * '(' argumentList? ')'
2200 *
2201 * argumentList ::=
2202 * namedArgument (',' namedArgument)*
2203 * | expressionList (',' namedArgument)*
2204 */
2205 ArgumentList parseArgumentList() {
2206 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
2207 List<Expression> arguments = new List<Expression>();
2208 if (_matches(TokenType.CLOSE_PAREN)) {
2209 return new ArgumentList(leftParenthesis, arguments, getAndAdvance());
2210 }
2211 //
2212 // Even though unnamed arguments must all appear before any named arguments,
2213 // we allow them to appear in any order so that we can recover faster.
2214 //
2215 bool wasInInitializer = _inInitializer;
2216 _inInitializer = false;
2217 try {
2218 Expression argument = parseArgument();
2219 arguments.add(argument);
2220 bool foundNamedArgument = argument is NamedExpression;
2221 bool generatedError = false;
2222 while (_optional(TokenType.COMMA)) {
2223 argument = parseArgument();
2224 arguments.add(argument);
2225 if (foundNamedArgument) {
2226 bool blankArgument =
2227 argument is SimpleIdentifier && argument.name.isEmpty;
2228 if (!generatedError &&
2229 !(argument is NamedExpression && !blankArgument)) {
2230 // Report the error, once, but allow the arguments to be in any
2231 // order in the AST.
2232 _reportErrorForCurrentToken(
2233 ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT);
2234 generatedError = true;
2235 }
2236 } else if (argument is NamedExpression) {
2237 foundNamedArgument = true;
2238 }
2239 }
2240 // TODO(brianwilkerson) Recovery: Look at the left parenthesis to see
2241 // whether there is a matching right parenthesis. If there is, then we're
2242 // more likely missing a comma and should go back to parsing arguments.
2243 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
2244 return new ArgumentList(leftParenthesis, arguments, rightParenthesis);
2245 } finally {
2246 _inInitializer = wasInInitializer;
2247 }
2248 }
2249
2250 /**
2251 * Parse a bitwise or expression. Return the bitwise or expression that was
2252 * parsed.
2253 *
2254 * bitwiseOrExpression ::=
2255 * bitwiseXorExpression ('|' bitwiseXorExpression)*
2256 * | 'super' ('|' bitwiseXorExpression)+
2257 */
2258 Expression parseBitwiseOrExpression() {
2259 Expression expression;
2260 if (_matchesKeyword(Keyword.SUPER) &&
2261 _tokenMatches(_peek(), TokenType.BAR)) {
2262 expression = new SuperExpression(getAndAdvance());
2263 } else {
2264 expression = _parseBitwiseXorExpression();
2265 }
2266 while (_matches(TokenType.BAR)) {
2267 Token operator = getAndAdvance();
2268 expression = new BinaryExpression(
2269 expression, operator, _parseBitwiseXorExpression());
2270 }
2271 return expression;
2272 }
2273
2274 /**
2275 * Parse a block. Return the block that was parsed.
2276 *
2277 * block ::=
2278 * '{' statements '}'
2279 */
2280 Block parseBlock() {
2281 Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
2282 List<Statement> statements = new List<Statement>();
2283 Token statementStart = _currentToken;
2284 while (
2285 !_matches(TokenType.EOF) && !_matches(TokenType.CLOSE_CURLY_BRACKET)) {
2286 Statement statement = parseStatement2();
2287 if (statement != null) {
2288 statements.add(statement);
2289 }
2290 if (identical(_currentToken, statementStart)) {
2291 // Ensure that we are making progress and report an error if we're not.
2292 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
2293 [_currentToken.lexeme]);
2294 _advance();
2295 }
2296 statementStart = _currentToken;
2297 }
2298 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
2299 return new Block(leftBracket, statements, rightBracket);
2300 }
2301
2302 /**
2303 * Parse a class member. The [className] is the name of the class containing
2304 * the member being parsed. Return the class member that was parsed, or `null`
2305 * if what was found was not a valid class member.
2306 *
2307 * classMemberDefinition ::=
2308 * declaration ';'
2309 * | methodSignature functionBody
2310 */
2311 ClassMember parseClassMember(String className) {
2312 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
2313 Modifiers modifiers = _parseModifiers();
2314 if (_matchesKeyword(Keyword.VOID)) {
2315 TypeName returnType = parseReturnType();
2316 if (_matchesKeyword(Keyword.GET) && _tokenMatchesIdentifier(_peek())) {
2317 _validateModifiersForGetterOrSetterOrMethod(modifiers);
2318 return _parseGetter(commentAndMetadata, modifiers.externalKeyword,
2319 modifiers.staticKeyword, returnType);
2320 } else if (_matchesKeyword(Keyword.SET) &&
2321 _tokenMatchesIdentifier(_peek())) {
2322 _validateModifiersForGetterOrSetterOrMethod(modifiers);
2323 return _parseSetter(commentAndMetadata, modifiers.externalKeyword,
2324 modifiers.staticKeyword, returnType);
2325 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) {
2326 _validateModifiersForOperator(modifiers);
2327 return _parseOperator(
2328 commentAndMetadata, modifiers.externalKeyword, returnType);
2329 } else if (_matchesIdentifier() &&
2330 _peek().matchesAny([
2331 TokenType.OPEN_PAREN,
2332 TokenType.OPEN_CURLY_BRACKET,
2333 TokenType.FUNCTION,
2334 TokenType.LT
2335 ])) {
2336 _validateModifiersForGetterOrSetterOrMethod(modifiers);
2337 return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
2338 modifiers.externalKeyword, modifiers.staticKeyword, returnType);
2339 } else {
2340 //
2341 // We have found an error of some kind. Try to recover.
2342 //
2343 if (_matchesIdentifier()) {
2344 if (_peek().matchesAny(
2345 [TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
2346 //
2347 // We appear to have a variable declaration with a type of "void".
2348 //
2349 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
2350 return _parseInitializedIdentifierList(commentAndMetadata,
2351 modifiers.staticKeyword, _validateModifiersForField(modifiers),
2352 returnType);
2353 }
2354 }
2355 if (_isOperator(_currentToken)) {
2356 //
2357 // We appear to have found an operator declaration without the
2358 // 'operator' keyword.
2359 //
2360 _validateModifiersForOperator(modifiers);
2361 return _parseOperator(
2362 commentAndMetadata, modifiers.externalKeyword, returnType);
2363 }
2364 _reportErrorForToken(
2365 ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
2366 return null;
2367 }
2368 } else if (_matchesKeyword(Keyword.GET) &&
2369 _tokenMatchesIdentifier(_peek())) {
2370 _validateModifiersForGetterOrSetterOrMethod(modifiers);
2371 return _parseGetter(commentAndMetadata, modifiers.externalKeyword,
2372 modifiers.staticKeyword, null);
2373 } else if (_matchesKeyword(Keyword.SET) &&
2374 _tokenMatchesIdentifier(_peek())) {
2375 _validateModifiersForGetterOrSetterOrMethod(modifiers);
2376 return _parseSetter(commentAndMetadata, modifiers.externalKeyword,
2377 modifiers.staticKeyword, null);
2378 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) {
2379 _validateModifiersForOperator(modifiers);
2380 return _parseOperator(
2381 commentAndMetadata, modifiers.externalKeyword, null);
2382 } else if (!_matchesIdentifier()) {
2383 //
2384 // Recover from an error.
2385 //
2386 if (_matchesKeyword(Keyword.CLASS)) {
2387 _reportErrorForCurrentToken(ParserErrorCode.CLASS_IN_CLASS);
2388 // TODO(brianwilkerson) We don't currently have any way to capture the
2389 // class that was parsed.
2390 _parseClassDeclaration(commentAndMetadata, null);
2391 return null;
2392 } else if (_matchesKeyword(Keyword.ABSTRACT) &&
2393 _tokenMatchesKeyword(_peek(), Keyword.CLASS)) {
2394 _reportErrorForToken(ParserErrorCode.CLASS_IN_CLASS, _peek());
2395 // TODO(brianwilkerson) We don't currently have any way to capture the
2396 // class that was parsed.
2397 _parseClassDeclaration(commentAndMetadata, getAndAdvance());
2398 return null;
2399 } else if (_matchesKeyword(Keyword.ENUM)) {
2400 _reportErrorForToken(ParserErrorCode.ENUM_IN_CLASS, _peek());
2401 // TODO(brianwilkerson) We don't currently have any way to capture the
2402 // enum that was parsed.
2403 _parseEnumDeclaration(commentAndMetadata);
2404 return null;
2405 } else if (_isOperator(_currentToken)) {
2406 //
2407 // We appear to have found an operator declaration without the
2408 // 'operator' keyword.
2409 //
2410 _validateModifiersForOperator(modifiers);
2411 return _parseOperator(
2412 commentAndMetadata, modifiers.externalKeyword, null);
2413 }
2414 Token keyword = modifiers.varKeyword;
2415 if (keyword == null) {
2416 keyword = modifiers.finalKeyword;
2417 }
2418 if (keyword == null) {
2419 keyword = modifiers.constKeyword;
2420 }
2421 if (keyword != null) {
2422 //
2423 // We appear to have found an incomplete field declaration.
2424 //
2425 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
2426 List<VariableDeclaration> variables = new List<VariableDeclaration>();
2427 variables.add(
2428 new VariableDeclaration(_createSyntheticIdentifier(), null, null));
2429 return new FieldDeclaration(commentAndMetadata.comment,
2430 commentAndMetadata.metadata, null,
2431 new VariableDeclarationList(null, null, keyword, null, variables),
2432 _expectSemicolon());
2433 }
2434 _reportErrorForToken(
2435 ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken);
2436 if (commentAndMetadata.comment != null ||
2437 !commentAndMetadata.metadata.isEmpty) {
2438 //
2439 // We appear to have found an incomplete declaration at the end of the
2440 // class. At this point it consists of a metadata, which we don't want
2441 // to loose, so we'll treat it as a method declaration with a missing
2442 // name, parameters and empty body.
2443 //
2444 return new MethodDeclaration(commentAndMetadata.comment,
2445 commentAndMetadata.metadata, null, null, null, null, null,
2446 _createSyntheticIdentifier(), null, new FormalParameterList(
2447 null, new List<FormalParameter>(), null, null, null),
2448 new EmptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON)));
2449 }
2450 return null;
2451 } else if (_tokenMatches(_peek(), TokenType.PERIOD) &&
2452 _tokenMatchesIdentifier(_peekAt(2)) &&
2453 _tokenMatches(_peekAt(3), TokenType.OPEN_PAREN)) {
2454 return _parseConstructor(commentAndMetadata, modifiers.externalKeyword,
2455 _validateModifiersForConstructor(modifiers), modifiers.factoryKeyword,
2456 parseSimpleIdentifier(), getAndAdvance(), parseSimpleIdentifier(),
2457 parseFormalParameterList());
2458 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
2459 SimpleIdentifier methodName = parseSimpleIdentifier();
2460 FormalParameterList parameters = parseFormalParameterList();
2461 if (_matches(TokenType.COLON) ||
2462 modifiers.factoryKeyword != null ||
2463 methodName.name == className) {
2464 return _parseConstructor(commentAndMetadata, modifiers.externalKeyword,
2465 _validateModifiersForConstructor(modifiers),
2466 modifiers.factoryKeyword, methodName, null, null, parameters);
2467 }
2468 _validateModifiersForGetterOrSetterOrMethod(modifiers);
2469 _validateFormalParameterList(parameters);
2470 return _parseMethodDeclarationAfterParameters(commentAndMetadata,
2471 modifiers.externalKeyword, modifiers.staticKeyword, null, methodName,
2472 null, parameters);
2473 } else if (_peek()
2474 .matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
2475 if (modifiers.constKeyword == null &&
2476 modifiers.finalKeyword == null &&
2477 modifiers.varKeyword == null) {
2478 _reportErrorForCurrentToken(
2479 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
2480 }
2481 return _parseInitializedIdentifierList(commentAndMetadata,
2482 modifiers.staticKeyword, _validateModifiersForField(modifiers), null);
2483 } else if (_matchesKeyword(Keyword.TYPEDEF)) {
2484 _reportErrorForCurrentToken(ParserErrorCode.TYPEDEF_IN_CLASS);
2485 // TODO(brianwilkerson) We don't currently have any way to capture the
2486 // function type alias that was parsed.
2487 _parseFunctionTypeAlias(commentAndMetadata, getAndAdvance());
2488 return null;
2489 } else if (parseGenericMethods) {
2490 Token token = _skipTypeParameterList(_peek());
2491 if (token != null && _tokenMatches(token, TokenType.OPEN_PAREN)) {
2492 return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
2493 modifiers.externalKeyword, modifiers.staticKeyword, null);
2494 }
2495 }
2496 TypeName type = parseTypeName();
2497 if (_matchesKeyword(Keyword.GET) && _tokenMatchesIdentifier(_peek())) {
2498 _validateModifiersForGetterOrSetterOrMethod(modifiers);
2499 return _parseGetter(commentAndMetadata, modifiers.externalKeyword,
2500 modifiers.staticKeyword, type);
2501 } else if (_matchesKeyword(Keyword.SET) &&
2502 _tokenMatchesIdentifier(_peek())) {
2503 _validateModifiersForGetterOrSetterOrMethod(modifiers);
2504 return _parseSetter(commentAndMetadata, modifiers.externalKeyword,
2505 modifiers.staticKeyword, type);
2506 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) {
2507 _validateModifiersForOperator(modifiers);
2508 return _parseOperator(
2509 commentAndMetadata, modifiers.externalKeyword, type);
2510 } else if (!_matchesIdentifier()) {
2511 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
2512 //
2513 // We appear to have found an incomplete declaration at the end of the
2514 // class. At this point it consists of a type name, so we'll treat it as
2515 // a field declaration with a missing field name and semicolon.
2516 //
2517 return _parseInitializedIdentifierList(commentAndMetadata,
2518 modifiers.staticKeyword, _validateModifiersForField(modifiers),
2519 type);
2520 }
2521 if (_isOperator(_currentToken)) {
2522 //
2523 // We appear to have found an operator declaration without the
2524 // 'operator' keyword.
2525 //
2526 _validateModifiersForOperator(modifiers);
2527 return _parseOperator(
2528 commentAndMetadata, modifiers.externalKeyword, type);
2529 }
2530 //
2531 // We appear to have found an incomplete declaration before another
2532 // declaration. At this point it consists of a type name, so we'll treat
2533 // it as a field declaration with a missing field name and semicolon.
2534 //
2535 _reportErrorForToken(
2536 ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken);
2537 try {
2538 _lockErrorListener();
2539 return _parseInitializedIdentifierList(commentAndMetadata,
2540 modifiers.staticKeyword, _validateModifiersForField(modifiers),
2541 type);
2542 } finally {
2543 _unlockErrorListener();
2544 }
2545 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
2546 SimpleIdentifier methodName = parseSimpleIdentifier();
2547 FormalParameterList parameters = parseFormalParameterList();
2548 if (methodName.name == className) {
2549 _reportErrorForNode(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type);
2550 return _parseConstructor(commentAndMetadata, modifiers.externalKeyword,
2551 _validateModifiersForConstructor(modifiers),
2552 modifiers.factoryKeyword, methodName, null, null, parameters);
2553 }
2554 _validateModifiersForGetterOrSetterOrMethod(modifiers);
2555 _validateFormalParameterList(parameters);
2556 return _parseMethodDeclarationAfterParameters(commentAndMetadata,
2557 modifiers.externalKeyword, modifiers.staticKeyword, type, methodName,
2558 null, parameters);
2559 } else if (parseGenericMethods && _tokenMatches(_peek(), TokenType.LT)) {
2560 return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
2561 modifiers.externalKeyword, modifiers.staticKeyword, type);
2562 } else if (_tokenMatches(_peek(), TokenType.OPEN_CURLY_BRACKET)) {
2563 // We have found "TypeName identifier {", and are guessing that this is a
2564 // getter without the keyword 'get'.
2565 _validateModifiersForGetterOrSetterOrMethod(modifiers);
2566 _reportErrorForCurrentToken(ParserErrorCode.MISSING_GET);
2567 _currentToken = _injectToken(
2568 new Parser_SyntheticKeywordToken(Keyword.GET, _currentToken.offset));
2569 return _parseGetter(commentAndMetadata, modifiers.externalKeyword,
2570 modifiers.staticKeyword, type);
2571 }
2572 return _parseInitializedIdentifierList(commentAndMetadata,
2573 modifiers.staticKeyword, _validateModifiersForField(modifiers), type);
2574 }
2575
2576 /**
2577 * Parse a single combinator. Return the combinator that was parsed, or `null`
2578 * if no combinator is found.
2579 *
2580 * combinator ::=
2581 * 'show' identifier (',' identifier)*
2582 * | 'hide' identifier (',' identifier)*
2583 */
2584 Combinator parseCombinator() {
2585 if (_matchesString(_SHOW) || _matchesString(_HIDE)) {
2586 Token keyword = getAndAdvance();
2587 List<SimpleIdentifier> names = _parseIdentifierList();
2588 if (keyword.lexeme == _SHOW) {
2589 return new ShowCombinator(keyword, names);
2590 } else {
2591 return new HideCombinator(keyword, names);
2592 }
2593 }
2594 return null;
2595 }
2596
2597 /**
2598 * Parse a compilation unit, starting with the given [token]. Return the
2599 * compilation unit that was parsed.
2600 */
2601 CompilationUnit parseCompilationUnit(Token token) {
2602 _currentToken = token;
2603 return parseCompilationUnit2();
2604 }
2605
2606 /**
2607 * Parse a compilation unit. Return the compilation unit that was parsed.
2608 *
2609 * Specified:
2610 *
2611 * compilationUnit ::=
2612 * scriptTag? directive* topLevelDeclaration*
2613 *
2614 * Actual:
2615 *
2616 * compilationUnit ::=
2617 * scriptTag? topLevelElement*
2618 *
2619 * topLevelElement ::=
2620 * directive
2621 * | topLevelDeclaration
2622 */
2623 CompilationUnit parseCompilationUnit2() {
2624 Token firstToken = _currentToken;
2625 ScriptTag scriptTag = null;
2626 if (_matches(TokenType.SCRIPT_TAG)) {
2627 scriptTag = new ScriptTag(getAndAdvance());
2628 }
2629 //
2630 // Even though all directives must appear before declarations and must occur
2631 // in a given order, we allow directives and declarations to occur in any
2632 // order so that we can recover better.
2633 //
2634 bool libraryDirectiveFound = false;
2635 bool partOfDirectiveFound = false;
2636 bool partDirectiveFound = false;
2637 bool directiveFoundAfterDeclaration = false;
2638 List<Directive> directives = new List<Directive>();
2639 List<CompilationUnitMember> declarations =
2640 new List<CompilationUnitMember>();
2641 Token memberStart = _currentToken;
2642 while (!_matches(TokenType.EOF)) {
2643 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
2644 if ((_matchesKeyword(Keyword.IMPORT) ||
2645 _matchesKeyword(Keyword.EXPORT) ||
2646 _matchesKeyword(Keyword.LIBRARY) ||
2647 _matchesKeyword(Keyword.PART)) &&
2648 !_tokenMatches(_peek(), TokenType.PERIOD) &&
2649 !_tokenMatches(_peek(), TokenType.LT) &&
2650 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
2651 Directive directive = _parseDirective(commentAndMetadata);
2652 if (declarations.length > 0 && !directiveFoundAfterDeclaration) {
2653 _reportErrorForToken(ParserErrorCode.DIRECTIVE_AFTER_DECLARATION,
2654 directive.beginToken);
2655 directiveFoundAfterDeclaration = true;
2656 }
2657 if (directive is LibraryDirective) {
2658 if (libraryDirectiveFound) {
2659 _reportErrorForCurrentToken(
2660 ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES);
2661 } else {
2662 if (directives.length > 0) {
2663 _reportErrorForToken(ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST,
2664 directive.libraryKeyword);
2665 }
2666 libraryDirectiveFound = true;
2667 }
2668 } else if (directive is PartDirective) {
2669 partDirectiveFound = true;
2670 } else if (partDirectiveFound) {
2671 if (directive is ExportDirective) {
2672 _reportErrorForToken(
2673 ParserErrorCode.EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE,
2674 directive.keyword);
2675 } else if (directive is ImportDirective) {
2676 _reportErrorForToken(
2677 ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE,
2678 directive.keyword);
2679 }
2680 }
2681 if (directive is PartOfDirective) {
2682 if (partOfDirectiveFound) {
2683 _reportErrorForCurrentToken(
2684 ParserErrorCode.MULTIPLE_PART_OF_DIRECTIVES);
2685 } else {
2686 int directiveCount = directives.length;
2687 for (int i = 0; i < directiveCount; i++) {
2688 _reportErrorForToken(
2689 ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART,
2690 directives[i].keyword);
2691 }
2692 partOfDirectiveFound = true;
2693 }
2694 } else {
2695 if (partOfDirectiveFound) {
2696 _reportErrorForToken(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART,
2697 directive.keyword);
2698 }
2699 }
2700 directives.add(directive);
2701 } else if (_matches(TokenType.SEMICOLON)) {
2702 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
2703 [_currentToken.lexeme]);
2704 _advance();
2705 } else {
2706 CompilationUnitMember member =
2707 _parseCompilationUnitMember(commentAndMetadata);
2708 if (member != null) {
2709 declarations.add(member);
2710 }
2711 }
2712 if (identical(_currentToken, memberStart)) {
2713 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
2714 [_currentToken.lexeme]);
2715 _advance();
2716 while (!_matches(TokenType.EOF) &&
2717 !_couldBeStartOfCompilationUnitMember()) {
2718 _advance();
2719 }
2720 }
2721 memberStart = _currentToken;
2722 }
2723 return new CompilationUnit(
2724 firstToken, scriptTag, directives, declarations, _currentToken);
2725 }
2726
2727 /**
2728 * Parse a conditional expression. Return the conditional expression that was
2729 * parsed.
2730 *
2731 * conditionalExpression ::=
2732 * ifNullExpression ('?' expressionWithoutCascade ':' expressionWithou tCascade)?
2733 */
2734 Expression parseConditionalExpression() {
2735 Expression condition = parseIfNullExpression();
2736 if (!_matches(TokenType.QUESTION)) {
2737 return condition;
2738 }
2739 Token question = getAndAdvance();
2740 Expression thenExpression = parseExpressionWithoutCascade();
2741 Token colon = _expect(TokenType.COLON);
2742 Expression elseExpression = parseExpressionWithoutCascade();
2743 return new ConditionalExpression(
2744 condition, question, thenExpression, colon, elseExpression);
2745 }
2746
2747 /**
2748 * Parse the name of a constructor. Return the constructor name that was
2749 * parsed.
2750 *
2751 * constructorName:
2752 * type ('.' identifier)?
2753 */
2754 ConstructorName parseConstructorName() {
2755 TypeName type = parseTypeName();
2756 Token period = null;
2757 SimpleIdentifier name = null;
2758 if (_matches(TokenType.PERIOD)) {
2759 period = getAndAdvance();
2760 name = parseSimpleIdentifier();
2761 }
2762 return new ConstructorName(type, period, name);
2763 }
2764
2765 /**
2766 * Parse the script tag and directives in a compilation unit, starting with
2767 * the given [token], until the first non-directive is encountered. The
2768 * remainder of the compilation unit will not be parsed. Specifically, if
2769 * there are directives later in the file, they will not be parsed. Return the
2770 * compilation unit that was parsed.
2771 */
2772 CompilationUnit parseDirectives(Token token) {
2773 _currentToken = token;
2774 return _parseDirectives();
2775 }
2776
2777 /**
2778 * Parse an expression, starting with the given [token]. Return the expression
2779 * that was parsed, or `null` if the tokens do not represent a recognizable
2780 * expression.
2781 */
2782 Expression parseExpression(Token token) {
2783 _currentToken = token;
2784 return parseExpression2();
2785 }
2786
2787 /**
2788 * Parse an expression that might contain a cascade. Return the expression
2789 * that was parsed.
2790 *
2791 * expression ::=
2792 * assignableExpression assignmentOperator expression
2793 * | conditionalExpression cascadeSection*
2794 * | throwExpression
2795 */
2796 Expression parseExpression2() {
2797 if (_matchesKeyword(Keyword.THROW)) {
2798 return _parseThrowExpression();
2799 } else if (_matchesKeyword(Keyword.RETHROW)) {
2800 // TODO(brianwilkerson) Rethrow is a statement again.
2801 return _parseRethrowExpression();
2802 }
2803 //
2804 // assignableExpression is a subset of conditionalExpression, so we can
2805 // parse a conditional expression and then determine whether it is followed
2806 // by an assignmentOperator, checking for conformance to the restricted
2807 // grammar after making that determination.
2808 //
2809 Expression expression = parseConditionalExpression();
2810 TokenType tokenType = _currentToken.type;
2811 if (tokenType == TokenType.PERIOD_PERIOD) {
2812 List<Expression> cascadeSections = new List<Expression>();
2813 while (tokenType == TokenType.PERIOD_PERIOD) {
2814 Expression section = _parseCascadeSection();
2815 if (section != null) {
2816 cascadeSections.add(section);
2817 }
2818 tokenType = _currentToken.type;
2819 }
2820 return new CascadeExpression(expression, cascadeSections);
2821 } else if (tokenType.isAssignmentOperator) {
2822 Token operator = getAndAdvance();
2823 _ensureAssignable(expression);
2824 return new AssignmentExpression(expression, operator, parseExpression2());
2825 }
2826 return expression;
2827 }
2828
2829 /**
2830 * Parse an expression that does not contain any cascades. Return the
2831 * expression that was parsed.
2832 *
2833 * expressionWithoutCascade ::=
2834 * assignableExpression assignmentOperator expressionWithoutCascade
2835 * | conditionalExpression
2836 * | throwExpressionWithoutCascade
2837 */
2838 Expression parseExpressionWithoutCascade() {
2839 if (_matchesKeyword(Keyword.THROW)) {
2840 return _parseThrowExpressionWithoutCascade();
2841 } else if (_matchesKeyword(Keyword.RETHROW)) {
2842 return _parseRethrowExpression();
2843 }
2844 //
2845 // assignableExpression is a subset of conditionalExpression, so we can
2846 // parse a conditional expression and then determine whether it is followed
2847 // by an assignmentOperator, checking for conformance to the restricted
2848 // grammar after making that determination.
2849 //
2850 Expression expression = parseConditionalExpression();
2851 if (_currentToken.type.isAssignmentOperator) {
2852 Token operator = getAndAdvance();
2853 _ensureAssignable(expression);
2854 expression = new AssignmentExpression(
2855 expression, operator, parseExpressionWithoutCascade());
2856 }
2857 return expression;
2858 }
2859
2860 /**
2861 * Parse a class extends clause. Return the class extends clause that was
2862 * parsed.
2863 *
2864 * classExtendsClause ::=
2865 * 'extends' type
2866 */
2867 ExtendsClause parseExtendsClause() {
2868 Token keyword = _expectKeyword(Keyword.EXTENDS);
2869 TypeName superclass = parseTypeName();
2870 return new ExtendsClause(keyword, superclass);
2871 }
2872
2873 /**
2874 * Parse a list of formal parameters. Return the formal parameters that were
2875 * parsed.
2876 *
2877 * formalParameterList ::=
2878 * '(' ')'
2879 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
2880 * | '(' optionalFormalParameters ')'
2881 *
2882 * normalFormalParameters ::=
2883 * normalFormalParameter (',' normalFormalParameter)*
2884 *
2885 * optionalFormalParameters ::=
2886 * optionalPositionalFormalParameters
2887 * | namedFormalParameters
2888 *
2889 * optionalPositionalFormalParameters ::=
2890 * '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
2891 *
2892 * namedFormalParameters ::=
2893 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
2894 */
2895 FormalParameterList parseFormalParameterList() {
2896 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
2897 if (_matches(TokenType.CLOSE_PAREN)) {
2898 return new FormalParameterList(
2899 leftParenthesis, null, null, null, getAndAdvance());
2900 }
2901 //
2902 // Even though it is invalid to have default parameters outside of brackets,
2903 // required parameters inside of brackets, or multiple groups of default and
2904 // named parameters, we allow all of these cases so that we can recover
2905 // better.
2906 //
2907 List<FormalParameter> parameters = new List<FormalParameter>();
2908 List<FormalParameter> normalParameters = new List<FormalParameter>();
2909 List<FormalParameter> positionalParameters = new List<FormalParameter>();
2910 List<FormalParameter> namedParameters = new List<FormalParameter>();
2911 List<FormalParameter> currentParameters = normalParameters;
2912 Token leftSquareBracket = null;
2913 Token rightSquareBracket = null;
2914 Token leftCurlyBracket = null;
2915 Token rightCurlyBracket = null;
2916 ParameterKind kind = ParameterKind.REQUIRED;
2917 bool firstParameter = true;
2918 bool reportedMuliplePositionalGroups = false;
2919 bool reportedMulipleNamedGroups = false;
2920 bool reportedMixedGroups = false;
2921 bool wasOptionalParameter = false;
2922 Token initialToken = null;
2923 do {
2924 if (firstParameter) {
2925 firstParameter = false;
2926 } else if (!_optional(TokenType.COMMA)) {
2927 // TODO(brianwilkerson) The token is wrong, we need to recover from this
2928 // case.
2929 if (_getEndToken(leftParenthesis) != null) {
2930 _reportErrorForCurrentToken(
2931 ParserErrorCode.EXPECTED_TOKEN, [TokenType.COMMA.lexeme]);
2932 } else {
2933 _reportErrorForToken(ParserErrorCode.MISSING_CLOSING_PARENTHESIS,
2934 _currentToken.previous);
2935 break;
2936 }
2937 }
2938 initialToken = _currentToken;
2939 //
2940 // Handle the beginning of parameter groups.
2941 //
2942 if (_matches(TokenType.OPEN_SQUARE_BRACKET)) {
2943 wasOptionalParameter = true;
2944 if (leftSquareBracket != null && !reportedMuliplePositionalGroups) {
2945 _reportErrorForCurrentToken(
2946 ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS);
2947 reportedMuliplePositionalGroups = true;
2948 }
2949 if (leftCurlyBracket != null && !reportedMixedGroups) {
2950 _reportErrorForCurrentToken(ParserErrorCode.MIXED_PARAMETER_GROUPS);
2951 reportedMixedGroups = true;
2952 }
2953 leftSquareBracket = getAndAdvance();
2954 currentParameters = positionalParameters;
2955 kind = ParameterKind.POSITIONAL;
2956 } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
2957 wasOptionalParameter = true;
2958 if (leftCurlyBracket != null && !reportedMulipleNamedGroups) {
2959 _reportErrorForCurrentToken(
2960 ParserErrorCode.MULTIPLE_NAMED_PARAMETER_GROUPS);
2961 reportedMulipleNamedGroups = true;
2962 }
2963 if (leftSquareBracket != null && !reportedMixedGroups) {
2964 _reportErrorForCurrentToken(ParserErrorCode.MIXED_PARAMETER_GROUPS);
2965 reportedMixedGroups = true;
2966 }
2967 leftCurlyBracket = getAndAdvance();
2968 currentParameters = namedParameters;
2969 kind = ParameterKind.NAMED;
2970 }
2971 //
2972 // Parse and record the parameter.
2973 //
2974 FormalParameter parameter = _parseFormalParameter(kind);
2975 parameters.add(parameter);
2976 currentParameters.add(parameter);
2977 if (kind == ParameterKind.REQUIRED && wasOptionalParameter) {
2978 _reportErrorForNode(
2979 ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, parameter);
2980 }
2981 //
2982 // Handle the end of parameter groups.
2983 //
2984 // TODO(brianwilkerson) Improve the detection and reporting of missing and
2985 // mismatched delimiters.
2986 if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) {
2987 rightSquareBracket = getAndAdvance();
2988 currentParameters = normalParameters;
2989 if (leftSquareBracket == null) {
2990 if (leftCurlyBracket != null) {
2991 _reportErrorForCurrentToken(
2992 ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, ["}"]);
2993 rightCurlyBracket = rightSquareBracket;
2994 rightSquareBracket = null;
2995 } else {
2996 _reportErrorForCurrentToken(
2997 ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP,
2998 ["["]);
2999 }
3000 }
3001 kind = ParameterKind.REQUIRED;
3002 } else if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
3003 rightCurlyBracket = getAndAdvance();
3004 currentParameters = normalParameters;
3005 if (leftCurlyBracket == null) {
3006 if (leftSquareBracket != null) {
3007 _reportErrorForCurrentToken(
3008 ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, ["]"]);
3009 rightSquareBracket = rightCurlyBracket;
3010 rightCurlyBracket = null;
3011 } else {
3012 _reportErrorForCurrentToken(
3013 ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP,
3014 ["{"]);
3015 }
3016 }
3017 kind = ParameterKind.REQUIRED;
3018 }
3019 } while (!_matches(TokenType.CLOSE_PAREN) &&
3020 !identical(initialToken, _currentToken));
3021 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
3022 //
3023 // Check that the groups were closed correctly.
3024 //
3025 if (leftSquareBracket != null && rightSquareBracket == null) {
3026 _reportErrorForCurrentToken(
3027 ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["]"]);
3028 }
3029 if (leftCurlyBracket != null && rightCurlyBracket == null) {
3030 _reportErrorForCurrentToken(
3031 ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["}"]);
3032 }
3033 //
3034 // Build the parameter list.
3035 //
3036 if (leftSquareBracket == null) {
3037 leftSquareBracket = leftCurlyBracket;
3038 }
3039 if (rightSquareBracket == null) {
3040 rightSquareBracket = rightCurlyBracket;
3041 }
3042 return new FormalParameterList(leftParenthesis, parameters,
3043 leftSquareBracket, rightSquareBracket, rightParenthesis);
3044 }
3045
3046 /**
3047 * Parse a function expression. Return the function expression that was
3048 * parsed.
3049 *
3050 * functionExpression ::=
3051 * typeParameters? formalParameterList functionExpressionBody
3052 */
3053 FunctionExpression parseFunctionExpression() {
3054 TypeParameterList typeParameters = null;
3055 if (parseGenericMethods && _matches(TokenType.LT)) {
3056 typeParameters = parseTypeParameterList();
3057 }
3058 FormalParameterList parameters = parseFormalParameterList();
3059 _validateFormalParameterList(parameters);
3060 FunctionBody body =
3061 _parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, true);
3062 return new FunctionExpression(typeParameters, parameters, body);
3063 }
3064
3065 /**
3066 * Parse an if-null expression. Return the if-null expression that was
3067 * parsed.
3068 *
3069 * ifNullExpression ::= logicalOrExpression ('??' logicalOrExpression)*
3070 */
3071 Expression parseIfNullExpression() {
3072 Expression expression = parseLogicalOrExpression();
3073 while (_matches(TokenType.QUESTION_QUESTION)) {
3074 Token operator = getAndAdvance();
3075 expression = new BinaryExpression(
3076 expression, operator, parseLogicalOrExpression());
3077 }
3078 return expression;
3079 }
3080
3081 /**
3082 * Parse an implements clause. Return the implements clause that was parsed.
3083 *
3084 * implementsClause ::=
3085 * 'implements' type (',' type)*
3086 */
3087 ImplementsClause parseImplementsClause() {
3088 Token keyword = _expectKeyword(Keyword.IMPLEMENTS);
3089 List<TypeName> interfaces = new List<TypeName>();
3090 interfaces.add(parseTypeName());
3091 while (_optional(TokenType.COMMA)) {
3092 interfaces.add(parseTypeName());
3093 }
3094 return new ImplementsClause(keyword, interfaces);
3095 }
3096
3097 /**
3098 * Parse a label. Return the label that was parsed.
3099 *
3100 * label ::=
3101 * identifier ':'
3102 */
3103 Label parseLabel() {
3104 SimpleIdentifier label = parseSimpleIdentifier();
3105 Token colon = _expect(TokenType.COLON);
3106 return new Label(label, colon);
3107 }
3108
3109 /**
3110 * Parse a library identifier. Return the library identifier that was parsed.
3111 *
3112 * libraryIdentifier ::=
3113 * identifier ('.' identifier)*
3114 */
3115 LibraryIdentifier parseLibraryIdentifier() {
3116 List<SimpleIdentifier> components = new List<SimpleIdentifier>();
3117 components.add(parseSimpleIdentifier());
3118 while (_matches(TokenType.PERIOD)) {
3119 _advance();
3120 components.add(parseSimpleIdentifier());
3121 }
3122 return new LibraryIdentifier(components);
3123 }
3124
3125 /**
3126 * Parse a logical or expression. Return the logical or expression that was
3127 * parsed.
3128 *
3129 * logicalOrExpression ::=
3130 * logicalAndExpression ('||' logicalAndExpression)*
3131 */
3132 Expression parseLogicalOrExpression() {
3133 Expression expression = _parseLogicalAndExpression();
3134 while (_matches(TokenType.BAR_BAR)) {
3135 Token operator = getAndAdvance();
3136 expression = new BinaryExpression(
3137 expression, operator, _parseLogicalAndExpression());
3138 }
3139 return expression;
3140 }
3141
3142 /**
3143 * Parse a map literal entry. Return the map literal entry that was parsed.
3144 *
3145 * mapLiteralEntry ::=
3146 * expression ':' expression
3147 */
3148 MapLiteralEntry parseMapLiteralEntry() {
3149 Expression key = parseExpression2();
3150 Token separator = _expect(TokenType.COLON);
3151 Expression value = parseExpression2();
3152 return new MapLiteralEntry(key, separator, value);
3153 }
3154
3155 /**
3156 * Parse a normal formal parameter. Return the normal formal parameter that
3157 * was parsed.
3158 *
3159 * normalFormalParameter ::=
3160 * functionSignature
3161 * | fieldFormalParameter
3162 * | simpleFormalParameter
3163 *
3164 * functionSignature:
3165 * metadata returnType? identifier typeParameters? formalParameterList
3166 *
3167 * fieldFormalParameter ::=
3168 * metadata finalConstVarOrType? 'this' '.' identifier
3169 *
3170 * simpleFormalParameter ::=
3171 * declaredIdentifier
3172 * | metadata identifier
3173 */
3174 NormalFormalParameter parseNormalFormalParameter() {
3175 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
3176 FinalConstVarOrType holder = _parseFinalConstVarOrType(true);
3177 Token thisKeyword = null;
3178 Token period = null;
3179 if (_matchesKeyword(Keyword.THIS)) {
3180 thisKeyword = getAndAdvance();
3181 period = _expect(TokenType.PERIOD);
3182 }
3183 SimpleIdentifier identifier = parseSimpleIdentifier();
3184 TypeParameterList typeParameters = null;
3185 if (parseGenericMethods && _matches(TokenType.LT)) {
3186 typeParameters = parseTypeParameterList();
3187 }
3188 if (_matches(TokenType.OPEN_PAREN)) {
3189 FormalParameterList parameters = parseFormalParameterList();
3190 if (thisKeyword == null) {
3191 if (holder.keyword != null) {
3192 _reportErrorForToken(
3193 ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword);
3194 }
3195 return new FunctionTypedFormalParameter(commentAndMetadata.comment,
3196 commentAndMetadata.metadata, holder.type, identifier,
3197 typeParameters, parameters);
3198 } else {
3199 return new FieldFormalParameter(commentAndMetadata.comment,
3200 commentAndMetadata.metadata, holder.keyword, holder.type,
3201 thisKeyword, period, identifier, typeParameters, parameters);
3202 }
3203 } else if (typeParameters != null) {
3204 // TODO(brianwilkerson) Report an error. It looks like a function-typed
3205 // parameter with no parameter list.
3206 //_reportErrorForToken(ParserErrorCode.MISSING_PARAMETERS, typeParameters. endToken);
3207 }
3208 TypeName type = holder.type;
3209 if (type != null) {
3210 if (_tokenMatchesKeyword(type.name.beginToken, Keyword.VOID)) {
3211 _reportErrorForToken(
3212 ParserErrorCode.VOID_PARAMETER, type.name.beginToken);
3213 } else if (holder.keyword != null &&
3214 _tokenMatchesKeyword(holder.keyword, Keyword.VAR)) {
3215 _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, holder.keyword);
3216 }
3217 }
3218 if (thisKeyword != null) {
3219 // TODO(brianwilkerson) If there are type parameters but no parameters,
3220 // should we create a synthetic empty parameter list here so we can
3221 // capture the type parameters?
3222 return new FieldFormalParameter(commentAndMetadata.comment,
3223 commentAndMetadata.metadata, holder.keyword, holder.type, thisKeyword,
3224 period, identifier, null, null);
3225 }
3226 return new SimpleFormalParameter(commentAndMetadata.comment,
3227 commentAndMetadata.metadata, holder.keyword, holder.type, identifier);
3228 }
3229
3230 /**
3231 * Parse a prefixed identifier. Return the prefixed identifier that was
3232 * parsed.
3233 *
3234 * prefixedIdentifier ::=
3235 * identifier ('.' identifier)?
3236 */
3237 Identifier parsePrefixedIdentifier() {
3238 SimpleIdentifier qualifier = parseSimpleIdentifier();
3239 if (!_matches(TokenType.PERIOD)) {
3240 return qualifier;
3241 }
3242 Token period = getAndAdvance();
3243 SimpleIdentifier qualified = parseSimpleIdentifier();
3244 return new PrefixedIdentifier(qualifier, period, qualified);
3245 }
3246
3247 /**
3248 * Parse a return type. Return the return type that was parsed.
3249 *
3250 * returnType ::=
3251 * 'void'
3252 * | type
3253 */
3254 TypeName parseReturnType() {
3255 if (_matchesKeyword(Keyword.VOID)) {
3256 return new TypeName(new SimpleIdentifier(getAndAdvance()), null);
3257 } else {
3258 return parseTypeName();
3259 }
3260 }
3261
3262 /**
3263 * Parse a simple identifier. Return the simple identifier that was parsed.
3264 *
3265 * identifier ::=
3266 * IDENTIFIER
3267 */
3268 SimpleIdentifier parseSimpleIdentifier() {
3269 if (_matchesIdentifier()) {
3270 String lexeme = _currentToken.lexeme;
3271 if ((_inAsync || _inGenerator) &&
3272 (lexeme == 'async' || lexeme == 'await' || lexeme == 'yield')) {
3273 _reportErrorForCurrentToken(
3274 ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER);
3275 }
3276 return new SimpleIdentifier(getAndAdvance());
3277 }
3278 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
3279 return _createSyntheticIdentifier();
3280 }
3281
3282 /**
3283 * Parse a statement, starting with the given [token]. Return the statement
3284 * that was parsed, or `null` if the tokens do not represent a recognizable
3285 * statement.
3286 */
3287 Statement parseStatement(Token token) {
3288 _currentToken = token;
3289 return parseStatement2();
3290 }
3291
3292 /**
3293 * Parse a statement. Return the statement that was parsed.
3294 *
3295 * statement ::=
3296 * label* nonLabeledStatement
3297 */
3298 Statement parseStatement2() {
3299 List<Label> labels = new List<Label>();
3300 while (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) {
3301 labels.add(parseLabel());
3302 }
3303 Statement statement = _parseNonLabeledStatement();
3304 if (labels.isEmpty) {
3305 return statement;
3306 }
3307 return new LabeledStatement(labels, statement);
3308 }
3309
3310 /**
3311 * Parse a sequence of statements, starting with the given [token]. Return the
3312 * statements that were parsed, or `null` if the tokens do not represent a
3313 * recognizable sequence of statements.
3314 */
3315 List<Statement> parseStatements(Token token) {
3316 _currentToken = token;
3317 return _parseStatementList();
3318 }
3319
3320 /**
3321 * Parse a string literal. Return the string literal that was parsed.
3322 *
3323 * stringLiteral ::=
3324 * MULTI_LINE_STRING+
3325 * | SINGLE_LINE_STRING+
3326 */
3327 StringLiteral parseStringLiteral() {
3328 List<StringLiteral> strings = new List<StringLiteral>();
3329 while (_matches(TokenType.STRING)) {
3330 Token string = getAndAdvance();
3331 if (_matches(TokenType.STRING_INTERPOLATION_EXPRESSION) ||
3332 _matches(TokenType.STRING_INTERPOLATION_IDENTIFIER)) {
3333 strings.add(_parseStringInterpolation(string));
3334 } else {
3335 strings.add(new SimpleStringLiteral(
3336 string, _computeStringValue(string.lexeme, true, true)));
3337 }
3338 }
3339 if (strings.length < 1) {
3340 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_STRING_LITERAL);
3341 return _createSyntheticStringLiteral();
3342 } else if (strings.length == 1) {
3343 return strings[0];
3344 } else {
3345 return new AdjacentStrings(strings);
3346 }
3347 }
3348
3349 /**
3350 * Parse a list of type arguments. Return the type argument list that was
3351 * parsed.
3352 *
3353 * typeArguments ::=
3354 * '<' typeList '>'
3355 *
3356 * typeList ::=
3357 * type (',' type)*
3358 */
3359 TypeArgumentList parseTypeArgumentList() {
3360 Token leftBracket = _expect(TokenType.LT);
3361 List<TypeName> arguments = new List<TypeName>();
3362 arguments.add(parseTypeName());
3363 while (_optional(TokenType.COMMA)) {
3364 arguments.add(parseTypeName());
3365 }
3366 Token rightBracket = _expectGt();
3367 return new TypeArgumentList(leftBracket, arguments, rightBracket);
3368 }
3369
3370 /**
3371 * Parse a type name. Return the type name that was parsed.
3372 *
3373 * type ::=
3374 * qualified typeArguments?
3375 */
3376 TypeName parseTypeName() {
3377 Identifier typeName;
3378 if (_matchesKeyword(Keyword.VAR)) {
3379 _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME);
3380 typeName = new SimpleIdentifier(getAndAdvance());
3381 } else if (_matchesIdentifier()) {
3382 typeName = parsePrefixedIdentifier();
3383 } else {
3384 typeName = _createSyntheticIdentifier();
3385 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME);
3386 }
3387 TypeArgumentList typeArguments = null;
3388 if (_matches(TokenType.LT)) {
3389 typeArguments = parseTypeArgumentList();
3390 }
3391 return new TypeName(typeName, typeArguments);
3392 }
3393
3394 /**
3395 * Parse a type parameter. Return the type parameter that was parsed.
3396 *
3397 * typeParameter ::=
3398 * metadata name ('extends' bound)?
3399 */
3400 TypeParameter parseTypeParameter() {
3401 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
3402 SimpleIdentifier name = parseSimpleIdentifier();
3403 if (_matchesKeyword(Keyword.EXTENDS)) {
3404 Token keyword = getAndAdvance();
3405 TypeName bound = parseTypeName();
3406 return new TypeParameter(commentAndMetadata.comment,
3407 commentAndMetadata.metadata, name, keyword, bound);
3408 }
3409 return new TypeParameter(commentAndMetadata.comment,
3410 commentAndMetadata.metadata, name, null, null);
3411 }
3412
3413 /**
3414 * Parse a list of type parameters. Return the list of type parameters that
3415 * were parsed.
3416 *
3417 * typeParameterList ::=
3418 * '<' typeParameter (',' typeParameter)* '>'
3419 */
3420 TypeParameterList parseTypeParameterList() {
3421 Token leftBracket = _expect(TokenType.LT);
3422 List<TypeParameter> typeParameters = new List<TypeParameter>();
3423 typeParameters.add(parseTypeParameter());
3424 while (_optional(TokenType.COMMA)) {
3425 typeParameters.add(parseTypeParameter());
3426 }
3427 Token rightBracket = _expectGt();
3428 return new TypeParameterList(leftBracket, typeParameters, rightBracket);
3429 }
3430
3431 /**
3432 * Parse a with clause. Return the with clause that was parsed.
3433 *
3434 * withClause ::=
3435 * 'with' typeName (',' typeName)*
3436 */
3437 WithClause parseWithClause() {
3438 Token with2 = _expectKeyword(Keyword.WITH);
3439 List<TypeName> types = new List<TypeName>();
3440 types.add(parseTypeName());
3441 while (_optional(TokenType.COMMA)) {
3442 types.add(parseTypeName());
3443 }
3444 return new WithClause(with2, types);
3445 }
3446
3447 /**
3448 * Advance to the next token in the token stream.
3449 */
3450 void _advance() {
3451 _currentToken = _currentToken.next;
3452 }
3453
3454 /**
3455 * Append the character equivalent of the given [scalarValue] to the given
3456 * [builder]. Use the [startIndex] and [endIndex] to report an error, and
3457 * don't append anything to the builder, if the scalar value is invalid. The
3458 * [escapeSequence] is the escape sequence that was parsed to produce the
3459 * scalar value (used for error reporting).
3460 */
3461 void _appendScalarValue(StringBuffer buffer, String escapeSequence,
3462 int scalarValue, int startIndex, int endIndex) {
3463 if (scalarValue < 0 ||
3464 scalarValue > Character.MAX_CODE_POINT ||
3465 (scalarValue >= 0xD800 && scalarValue <= 0xDFFF)) {
3466 _reportErrorForCurrentToken(
3467 ParserErrorCode.INVALID_CODE_POINT, [escapeSequence]);
3468 return;
3469 }
3470 if (scalarValue < Character.MAX_VALUE) {
3471 buffer.writeCharCode(scalarValue);
3472 } else {
3473 buffer.write(Character.toChars(scalarValue));
3474 }
3475 }
3476
3477 /**
3478 * Return the content of a string with the given literal representation. The
3479 * [lexeme] is the literal representation of the string. The flag [isFirst] is
3480 * `true` if this is the first token in a string literal. The flag [isLast] is
3481 * `true` if this is the last token in a string literal.
3482 */
3483 String _computeStringValue(String lexeme, bool isFirst, bool isLast) {
3484 StringLexemeHelper helper = new StringLexemeHelper(lexeme, isFirst, isLast);
3485 int start = helper.start;
3486 int end = helper.end;
3487 bool stringEndsAfterStart = end >= start;
3488 assert(stringEndsAfterStart);
3489 if (!stringEndsAfterStart) {
3490 AnalysisEngine.instance.logger.logError(
3491 "Internal error: computeStringValue($lexeme, $isFirst, $isLast)");
3492 return "";
3493 }
3494 if (helper.isRaw) {
3495 return lexeme.substring(start, end);
3496 }
3497 StringBuffer buffer = new StringBuffer();
3498 int index = start;
3499 while (index < end) {
3500 index = _translateCharacter(buffer, lexeme, index);
3501 }
3502 return buffer.toString();
3503 }
3504
3505 /**
3506 * Convert the given [method] declaration into the nearest valid top-level
3507 * function declaration (that is, the function declaration that most closely
3508 * captures the components of the given method declaration).
3509 */
3510 FunctionDeclaration _convertToFunctionDeclaration(MethodDeclaration method) =>
3511 new FunctionDeclaration(method.documentationComment, method.metadata,
3512 method.externalKeyword, method.returnType, method.propertyKeyword,
3513 method.name, new FunctionExpression(
3514 method.typeParameters, method.parameters, method.body));
3515
3516 /**
3517 * Return `true` if the current token could be the start of a compilation unit
3518 * member. This method is used for recovery purposes to decide when to stop
3519 * skipping tokens after finding an error while parsing a compilation unit
3520 * member.
3521 */
3522 bool _couldBeStartOfCompilationUnitMember() {
3523 if ((_matchesKeyword(Keyword.IMPORT) ||
3524 _matchesKeyword(Keyword.EXPORT) ||
3525 _matchesKeyword(Keyword.LIBRARY) ||
3526 _matchesKeyword(Keyword.PART)) &&
3527 !_tokenMatches(_peek(), TokenType.PERIOD) &&
3528 !_tokenMatches(_peek(), TokenType.LT)) {
3529 // This looks like the start of a directive
3530 return true;
3531 } else if (_matchesKeyword(Keyword.CLASS)) {
3532 // This looks like the start of a class definition
3533 return true;
3534 } else if (_matchesKeyword(Keyword.TYPEDEF) &&
3535 !_tokenMatches(_peek(), TokenType.PERIOD) &&
3536 !_tokenMatches(_peek(), TokenType.LT)) {
3537 // This looks like the start of a typedef
3538 return true;
3539 } else if (_matchesKeyword(Keyword.VOID) ||
3540 ((_matchesKeyword(Keyword.GET) || _matchesKeyword(Keyword.SET)) &&
3541 _tokenMatchesIdentifier(_peek())) ||
3542 (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek()))) {
3543 // This looks like the start of a function
3544 return true;
3545 } else if (_matchesIdentifier()) {
3546 if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
3547 // This looks like the start of a function
3548 return true;
3549 }
3550 Token token = _skipReturnType(_currentToken);
3551 if (token == null) {
3552 return false;
3553 }
3554 if (_matchesKeyword(Keyword.GET) ||
3555 _matchesKeyword(Keyword.SET) ||
3556 (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) ||
3557 _matchesIdentifier()) {
3558 return true;
3559 }
3560 }
3561 return false;
3562 }
3563
3564 /**
3565 * Return a synthetic identifier.
3566 */
3567 SimpleIdentifier _createSyntheticIdentifier() {
3568 Token syntheticToken;
3569 if (_currentToken.type == TokenType.KEYWORD) {
3570 // Consider current keyword token as an identifier.
3571 // It is not always true, e.g. "^is T" where "^" is place the place for
3572 // synthetic identifier. By creating SyntheticStringToken we can
3573 // distinguish a real identifier from synthetic. In the code completion
3574 // behavior will depend on a cursor position - before or on "is".
3575 syntheticToken = _injectToken(new SyntheticStringToken(
3576 TokenType.IDENTIFIER, _currentToken.lexeme, _currentToken.offset));
3577 } else {
3578 syntheticToken = _createSyntheticToken(TokenType.IDENTIFIER);
3579 }
3580 return new SimpleIdentifier(syntheticToken);
3581 }
3582
3583 /**
3584 * Return a synthetic token representing the given [keyword].
3585 */
3586 Token _createSyntheticKeyword(Keyword keyword) => _injectToken(
3587 new Parser_SyntheticKeywordToken(keyword, _currentToken.offset));
3588
3589 /**
3590 * Return a synthetic string literal.
3591 */
3592 SimpleStringLiteral _createSyntheticStringLiteral() =>
3593 new SimpleStringLiteral(_createSyntheticToken(TokenType.STRING), "");
3594
3595 /**
3596 * Return a synthetic token with the given [type].
3597 */
3598 Token _createSyntheticToken(TokenType type) =>
3599 _injectToken(new StringToken(type, "", _currentToken.offset));
3600
3601 /**
3602 * Create and return a new token with the given [type]. The token will replace
3603 * the first portion of the given [token], so it will have the same offset and
3604 * will have any comments that might have preceeded the token.
3605 */
3606 Token _createToken(Token token, TokenType type, {bool isBegin: false}) {
3607 CommentToken comments = token.precedingComments;
3608 if (comments == null) {
3609 if (isBegin) {
3610 return new BeginToken(type, token.offset);
3611 }
3612 return new Token(type, token.offset);
3613 } else if (isBegin) {
3614 return new BeginTokenWithComment(type, token.offset, comments);
3615 }
3616 return new TokenWithComment(type, token.offset, comments);
3617 }
3618
3619 /**
3620 * Check that the given [expression] is assignable and report an error if it
3621 * isn't.
3622 *
3623 * assignableExpression ::=
3624 * primary (arguments* assignableSelector)+
3625 * | 'super' unconditionalAssignableSelector
3626 * | identifier
3627 *
3628 * unconditionalAssignableSelector ::=
3629 * '[' expression ']'
3630 * | '.' identifier
3631 *
3632 * assignableSelector ::=
3633 * unconditionalAssignableSelector
3634 * | '?.' identifier
3635 */
3636 void _ensureAssignable(Expression expression) {
3637 if (expression != null && !expression.isAssignable) {
3638 _reportErrorForCurrentToken(
3639 ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE);
3640 }
3641 }
3642
3643 /**
3644 * If the current token has the expected type, return it after advancing to
3645 * the next token. Otherwise report an error and return the current token
3646 * without advancing.
3647 *
3648 * Note that the method [_expectGt] should be used if the argument to this
3649 * method would be [TokenType.GT].
3650 *
3651 * The [type] is the type of token that is expected.
3652 */
3653 Token _expect(TokenType type) {
3654 if (_matches(type)) {
3655 return getAndAdvance();
3656 }
3657 // Remove uses of this method in favor of matches?
3658 // Pass in the error code to use to report the error?
3659 if (type == TokenType.SEMICOLON) {
3660 if (_tokenMatches(_currentToken.next, TokenType.SEMICOLON)) {
3661 _reportErrorForCurrentToken(
3662 ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
3663 _advance();
3664 return getAndAdvance();
3665 }
3666 _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN,
3667 _currentToken.previous, [type.lexeme]);
3668 } else {
3669 _reportErrorForCurrentToken(
3670 ParserErrorCode.EXPECTED_TOKEN, [type.lexeme]);
3671 }
3672 return _currentToken;
3673 }
3674
3675 /**
3676 * If the current token has the type [TokenType.GT], return it after advancing
3677 * to the next token. Otherwise report an error and return the current token
3678 * without advancing.
3679 */
3680 Token _expectGt() {
3681 if (_matchesGt()) {
3682 return getAndAdvance();
3683 }
3684 _reportErrorForCurrentToken(
3685 ParserErrorCode.EXPECTED_TOKEN, [TokenType.GT.lexeme]);
3686 return _currentToken;
3687 }
3688
3689 /**
3690 * If the current token is a keyword matching the given [keyword], return it
3691 * after advancing to the next token. Otherwise report an error and return the
3692 * current token without advancing.
3693 */
3694 Token _expectKeyword(Keyword keyword) {
3695 if (_matchesKeyword(keyword)) {
3696 return getAndAdvance();
3697 }
3698 // Remove uses of this method in favor of matches?
3699 // Pass in the error code to use to report the error?
3700 _reportErrorForCurrentToken(
3701 ParserErrorCode.EXPECTED_TOKEN, [keyword.syntax]);
3702 return _currentToken;
3703 }
3704
3705 /**
3706 * If the current token is a semicolon, return it after advancing to the next
3707 * token. Otherwise report an error and create a synthetic semicolon.
3708 */
3709 Token _expectSemicolon() {
3710 // TODO(scheglov) consider pushing this behavior into [_expect]
3711 if (_matches(TokenType.SEMICOLON)) {
3712 return getAndAdvance();
3713 } else {
3714 _reportErrorForToken(
3715 ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, [";"]);
3716 return _createSyntheticToken(TokenType.SEMICOLON);
3717 }
3718 }
3719
3720 /**
3721 * Search the given list of [ranges] for a range that contains the given
3722 * [index]. Return the range that was found, or `null` if none of the ranges
3723 * contain the index.
3724 */
3725 List<int> _findRange(List<List<int>> ranges, int index) {
3726 int rangeCount = ranges.length;
3727 for (int i = 0; i < rangeCount; i++) {
3728 List<int> range = ranges[i];
3729 if (range[0] <= index && index <= range[1]) {
3730 return range;
3731 } else if (index < range[0]) {
3732 return null;
3733 }
3734 }
3735 return null;
3736 }
3737
3738 /**
3739 * Return a list of the ranges of characters in the given [comment] that
3740 * should be treated as code blocks.
3741 */
3742 List<List<int>> _getCodeBlockRanges(String comment) {
3743 List<List<int>> ranges = new List<List<int>>();
3744 int length = comment.length;
3745 if (length < 3) {
3746 return ranges;
3747 }
3748 int index = 0;
3749 int firstChar = comment.codeUnitAt(0);
3750 if (firstChar == 0x2F) {
3751 int secondChar = comment.codeUnitAt(1);
3752 int thirdChar = comment.codeUnitAt(2);
3753 if ((secondChar == 0x2A && thirdChar == 0x2A) ||
3754 (secondChar == 0x2F && thirdChar == 0x2F)) {
3755 index = 3;
3756 }
3757 }
3758 while (index < length) {
3759 int currentChar = comment.codeUnitAt(index);
3760 if (currentChar == 0xD || currentChar == 0xA) {
3761 index = index + 1;
3762 while (index < length &&
3763 Character.isWhitespace(comment.codeUnitAt(index))) {
3764 index = index + 1;
3765 }
3766 if (StringUtilities.startsWith6(
3767 comment, index, 0x2A, 0x20, 0x20, 0x20, 0x20, 0x20)) {
3768 int end = index + 6;
3769 while (end < length &&
3770 comment.codeUnitAt(end) != 0xD &&
3771 comment.codeUnitAt(end) != 0xA) {
3772 end = end + 1;
3773 }
3774 ranges.add(<int>[index, end]);
3775 index = end;
3776 }
3777 } else if (index + 1 < length &&
3778 currentChar == 0x5B &&
3779 comment.codeUnitAt(index + 1) == 0x3A) {
3780 int end = StringUtilities.indexOf2(comment, index + 2, 0x3A, 0x5D);
3781 if (end < 0) {
3782 end = length;
3783 }
3784 ranges.add(<int>[index, end]);
3785 index = end + 1;
3786 } else {
3787 index = index + 1;
3788 }
3789 }
3790 return ranges;
3791 }
3792
3793 /**
3794 * Return the end token associated with the given [beginToken], or `null` if
3795 * either the given token is not a begin token or it does not have an end
3796 * token associated with it.
3797 */
3798 Token _getEndToken(Token beginToken) {
3799 if (beginToken is BeginToken) {
3800 return beginToken.endToken;
3801 }
3802 return null;
3803 }
3804
3805 /**
3806 * Inject the given [token] into the token stream immediately before the
3807 * current token.
3808 */
3809 Token _injectToken(Token token) {
3810 Token previous = _currentToken.previous;
3811 token.setNext(_currentToken);
3812 previous.setNext(token);
3813 return token;
3814 }
3815
3816 /**
3817 * Return `true` if the current token appears to be the beginning of a
3818 * function declaration.
3819 */
3820 bool _isFunctionDeclaration() {
3821 if (_matchesKeyword(Keyword.VOID)) {
3822 return true;
3823 }
3824 Token afterReturnType = _skipTypeName(_currentToken);
3825 if (afterReturnType == null) {
3826 // There was no return type, but it is optional, so go back to where we
3827 // started.
3828 afterReturnType = _currentToken;
3829 }
3830 Token afterIdentifier = _skipSimpleIdentifier(afterReturnType);
3831 if (afterIdentifier == null) {
3832 // It's possible that we parsed the function name as if it were a type
3833 // name, so see whether it makes sense if we assume that there is no type.
3834 afterIdentifier = _skipSimpleIdentifier(_currentToken);
3835 }
3836 if (afterIdentifier == null) {
3837 return false;
3838 }
3839 if (_isFunctionExpression(afterIdentifier)) {
3840 return true;
3841 }
3842 // It's possible that we have found a getter. While this isn't valid at this
3843 // point we test for it in order to recover better.
3844 if (_matchesKeyword(Keyword.GET)) {
3845 Token afterName = _skipSimpleIdentifier(_currentToken.next);
3846 if (afterName == null) {
3847 return false;
3848 }
3849 return _tokenMatches(afterName, TokenType.FUNCTION) ||
3850 _tokenMatches(afterName, TokenType.OPEN_CURLY_BRACKET);
3851 } else if (_tokenMatchesKeyword(afterReturnType, Keyword.GET)) {
3852 Token afterName = _skipSimpleIdentifier(afterReturnType.next);
3853 if (afterName == null) {
3854 return false;
3855 }
3856 return _tokenMatches(afterName, TokenType.FUNCTION) ||
3857 _tokenMatches(afterName, TokenType.OPEN_CURLY_BRACKET);
3858 }
3859 return false;
3860 }
3861
3862 /**
3863 * Return `true` if the given [token] appears to be the beginning of a
3864 * function expression.
3865 */
3866 bool _isFunctionExpression(Token token) {
3867 // Function expressions aren't allowed in initializer lists.
3868 if (_inInitializer) {
3869 return false;
3870 }
3871 Token afterTypeParameters = _skipTypeParameterList(token);
3872 if (afterTypeParameters == null) {
3873 afterTypeParameters = token;
3874 }
3875 Token afterParameters = _skipFormalParameterList(afterTypeParameters);
3876 if (afterParameters == null) {
3877 return false;
3878 }
3879 if (afterParameters
3880 .matchesAny([TokenType.OPEN_CURLY_BRACKET, TokenType.FUNCTION])) {
3881 return true;
3882 }
3883 String lexeme = afterParameters.lexeme;
3884 return lexeme == ASYNC || lexeme == SYNC;
3885 }
3886
3887 /**
3888 * Return `true` if the given [character] is a valid hexadecimal digit.
3889 */
3890 bool _isHexDigit(int character) => (0x30 <= character && character <= 0x39) ||
3891 (0x41 <= character && character <= 0x46) ||
3892 (0x61 <= character && character <= 0x66);
3893
3894 /**
3895 * Return `true` if the current token is the first token in an initialized
3896 * variable declaration rather than an expression. This method assumes that we
3897 * have already skipped past any metadata that might be associated with the
3898 * declaration.
3899 *
3900 * initializedVariableDeclaration ::=
3901 * declaredIdentifier ('=' expression)? (',' initializedIdentifier)*
3902 *
3903 * declaredIdentifier ::=
3904 * metadata finalConstVarOrType identifier
3905 *
3906 * finalConstVarOrType ::=
3907 * 'final' type?
3908 * | 'const' type?
3909 * | 'var'
3910 * | type
3911 *
3912 * type ::=
3913 * qualified typeArguments?
3914 *
3915 * initializedIdentifier ::=
3916 * identifier ('=' expression)?
3917 */
3918 bool _isInitializedVariableDeclaration() {
3919 if (_matchesKeyword(Keyword.FINAL) || _matchesKeyword(Keyword.VAR)) {
3920 // An expression cannot start with a keyword other than 'const',
3921 // 'rethrow', or 'throw'.
3922 return true;
3923 }
3924 if (_matchesKeyword(Keyword.CONST)) {
3925 // Look to see whether we might be at the start of a list or map literal,
3926 // otherwise this should be the start of a variable declaration.
3927 return !_peek().matchesAny([
3928 TokenType.LT,
3929 TokenType.OPEN_CURLY_BRACKET,
3930 TokenType.OPEN_SQUARE_BRACKET,
3931 TokenType.INDEX
3932 ]);
3933 }
3934 // We know that we have an identifier, and need to see whether it might be
3935 // a type name.
3936 Token token = _skipTypeName(_currentToken);
3937 if (token == null) {
3938 // There was no type name, so this can't be a declaration.
3939 return false;
3940 }
3941 token = _skipSimpleIdentifier(token);
3942 if (token == null) {
3943 return false;
3944 }
3945 TokenType type = token.type;
3946 return type == TokenType.EQ ||
3947 type == TokenType.COMMA ||
3948 type == TokenType.SEMICOLON ||
3949 _tokenMatchesKeyword(token, Keyword.IN);
3950 }
3951
3952 bool _isLikelyParameterList() {
3953 if (_matches(TokenType.OPEN_PAREN)) {
3954 return true;
3955 }
3956 if (!parseGenericMethods) {
3957 return false;
3958 }
3959 Token token = _skipTypeArgumentList(_currentToken);
3960 return token != null && _tokenMatches(token, TokenType.OPEN_PAREN);
3961 }
3962
3963 /**
3964 * Given that we have just found bracketed text within the given [comment],
3965 * look to see whether that text is (a) followed by a parenthesized link
3966 * address, (b) followed by a colon, or (c) followed by optional whitespace
3967 * and another square bracket. The [rightIndex] is the index of the right
3968 * bracket. Return `true` if the bracketed text is followed by a link address.
3969 *
3970 * This method uses the syntax described by the
3971 * <a href="http://daringfireball.net/projects/markdown/syntax">markdown</a>
3972 * project.
3973 */
3974 bool _isLinkText(String comment, int rightIndex) {
3975 int length = comment.length;
3976 int index = rightIndex + 1;
3977 if (index >= length) {
3978 return false;
3979 }
3980 int nextChar = comment.codeUnitAt(index);
3981 if (nextChar == 0x28 || nextChar == 0x3A) {
3982 return true;
3983 }
3984 while (Character.isWhitespace(nextChar)) {
3985 index = index + 1;
3986 if (index >= length) {
3987 return false;
3988 }
3989 nextChar = comment.codeUnitAt(index);
3990 }
3991 return nextChar == 0x5B;
3992 }
3993
3994 /**
3995 * Return `true` if the given [startToken] appears to be the beginning of an
3996 * operator declaration.
3997 */
3998 bool _isOperator(Token startToken) {
3999 // Accept any operator here, even if it is not user definable.
4000 if (!startToken.isOperator) {
4001 return false;
4002 }
4003 // Token "=" means that it is actually field initializer.
4004 if (startToken.type == TokenType.EQ) {
4005 return false;
4006 }
4007 // Consume all operator tokens.
4008 Token token = startToken.next;
4009 while (token.isOperator) {
4010 token = token.next;
4011 }
4012 // Formal parameter list is expect now.
4013 return _tokenMatches(token, TokenType.OPEN_PAREN);
4014 }
4015
4016 /**
4017 * Return `true` if the current token appears to be the beginning of a switch
4018 * member.
4019 */
4020 bool _isSwitchMember() {
4021 Token token = _currentToken;
4022 while (_tokenMatches(token, TokenType.IDENTIFIER) &&
4023 _tokenMatches(token.next, TokenType.COLON)) {
4024 token = token.next.next;
4025 }
4026 if (token.type == TokenType.KEYWORD) {
4027 Keyword keyword = (token as KeywordToken).keyword;
4028 return keyword == Keyword.CASE || keyword == Keyword.DEFAULT;
4029 }
4030 return false;
4031 }
4032
4033 /**
4034 * Return `true` if the [startToken] appears to be the first token of a type
4035 * name that is followed by a variable or field formal parameter.
4036 */
4037 bool _isTypedIdentifier(Token startToken) {
4038 Token token = _skipReturnType(startToken);
4039 if (token == null) {
4040 return false;
4041 } else if (_tokenMatchesIdentifier(token)) {
4042 return true;
4043 } else if (_tokenMatchesKeyword(token, Keyword.THIS) &&
4044 _tokenMatches(token.next, TokenType.PERIOD) &&
4045 _tokenMatchesIdentifier(token.next.next)) {
4046 return true;
4047 } else if (_tokenMatchesKeyword(startToken, Keyword.VOID)) {
4048 // The keyword 'void' isn't a valid identifier, so it should be assumed to
4049 // be a type name.
4050 return true;
4051 } else if (startToken.next != token &&
4052 !_tokenMatches(token, TokenType.OPEN_PAREN)) {
4053 // The type is more than a simple identifier, so it should be assumed to
4054 // be a type name.
4055 return true;
4056 }
4057 return false;
4058 }
4059
4060 /**
4061 * Increments the error reporting lock level. If level is more than `0`, then
4062 * [reportError] wont report any error.
4063 */
4064 void _lockErrorListener() {
4065 _errorListenerLock++;
4066 }
4067
4068 /**
4069 * Return `true` if the current token has the given [type]. Note that the
4070 * method [_matchesGt] should be used if the argument to this method would be
4071 * [TokenType.GT].
4072 */
4073 bool _matches(TokenType type) => _currentToken.type == type;
4074
4075 /**
4076 * Return `true` if the current token has a type of [TokenType.GT]. Note that
4077 * this method, unlike other variants, will modify the token stream if
4078 * possible to match desired type. In particular, if the next token is either
4079 * a '>>' or '>>>', the token stream will be re-written and `true` will be
4080 * returned.
4081 */
4082 bool _matchesGt() {
4083 TokenType currentType = _currentToken.type;
4084 if (currentType == TokenType.GT) {
4085 return true;
4086 } else if (currentType == TokenType.GT_GT) {
4087 Token first = _createToken(_currentToken, TokenType.GT);
4088 Token second = new Token(TokenType.GT, _currentToken.offset + 1);
4089 second.setNext(_currentToken.next);
4090 first.setNext(second);
4091 _currentToken.previous.setNext(first);
4092 _currentToken = first;
4093 return true;
4094 } else if (currentType == TokenType.GT_EQ) {
4095 Token first = _createToken(_currentToken, TokenType.GT);
4096 Token second = new Token(TokenType.EQ, _currentToken.offset + 1);
4097 second.setNext(_currentToken.next);
4098 first.setNext(second);
4099 _currentToken.previous.setNext(first);
4100 _currentToken = first;
4101 return true;
4102 } else if (currentType == TokenType.GT_GT_EQ) {
4103 int offset = _currentToken.offset;
4104 Token first = _createToken(_currentToken, TokenType.GT);
4105 Token second = new Token(TokenType.GT, offset + 1);
4106 Token third = new Token(TokenType.EQ, offset + 2);
4107 third.setNext(_currentToken.next);
4108 second.setNext(third);
4109 first.setNext(second);
4110 _currentToken.previous.setNext(first);
4111 _currentToken = first;
4112 return true;
4113 }
4114 return false;
4115 }
4116
4117 /**
4118 * Return `true` if the current token is a valid identifier. Valid identifiers
4119 * include built-in identifiers (pseudo-keywords).
4120 */
4121 bool _matchesIdentifier() => _tokenMatchesIdentifier(_currentToken);
4122
4123 /**
4124 * Return `true` if the current token matches the given [keyword].
4125 */
4126 bool _matchesKeyword(Keyword keyword) =>
4127 _tokenMatchesKeyword(_currentToken, keyword);
4128
4129 /**
4130 * Return `true` if the current token matches the given [identifier].
4131 */
4132 bool _matchesString(String identifier) =>
4133 _currentToken.type == TokenType.IDENTIFIER &&
4134 _currentToken.lexeme == identifier;
4135
4136 /**
4137 * If the current token has the given [type], then advance to the next token
4138 * and return `true`. Otherwise, return `false` without advancing. This method
4139 * should not be invoked with an argument value of [TokenType.GT].
4140 */
4141 bool _optional(TokenType type) {
4142 if (_matches(type)) {
4143 _advance();
4144 return true;
4145 }
4146 return false;
4147 }
4148
4149 /**
4150 * Parse an additive expression. Return the additive expression that was
4151 * parsed.
4152 *
4153 * additiveExpression ::=
4154 * multiplicativeExpression (additiveOperator multiplicativeExpression )*
4155 * | 'super' (additiveOperator multiplicativeExpression)+
4156 */
4157 Expression _parseAdditiveExpression() {
4158 Expression expression;
4159 if (_matchesKeyword(Keyword.SUPER) &&
4160 _currentToken.next.type.isAdditiveOperator) {
4161 expression = new SuperExpression(getAndAdvance());
4162 } else {
4163 expression = _parseMultiplicativeExpression();
4164 }
4165 while (_currentToken.type.isAdditiveOperator) {
4166 Token operator = getAndAdvance();
4167 expression = new BinaryExpression(
4168 expression, operator, _parseMultiplicativeExpression());
4169 }
4170 return expression;
4171 }
4172
4173 /**
4174 * Parse an assert statement. Return the assert statement.
4175 *
4176 * assertStatement ::=
4177 * 'assert' '(' conditionalExpression ')' ';'
4178 */
4179 AssertStatement _parseAssertStatement() {
4180 Token keyword = _expectKeyword(Keyword.ASSERT);
4181 Token leftParen = _expect(TokenType.OPEN_PAREN);
4182 Expression expression = parseExpression2();
4183 if (expression is AssignmentExpression) {
4184 _reportErrorForNode(
4185 ParserErrorCode.ASSERT_DOES_NOT_TAKE_ASSIGNMENT, expression);
4186 } else if (expression is CascadeExpression) {
4187 _reportErrorForNode(
4188 ParserErrorCode.ASSERT_DOES_NOT_TAKE_CASCADE, expression);
4189 } else if (expression is ThrowExpression) {
4190 _reportErrorForNode(
4191 ParserErrorCode.ASSERT_DOES_NOT_TAKE_THROW, expression);
4192 } else if (expression is RethrowExpression) {
4193 _reportErrorForNode(
4194 ParserErrorCode.ASSERT_DOES_NOT_TAKE_RETHROW, expression);
4195 }
4196 Token rightParen = _expect(TokenType.CLOSE_PAREN);
4197 Token semicolon = _expect(TokenType.SEMICOLON);
4198 return new AssertStatement(
4199 keyword, leftParen, expression, rightParen, semicolon);
4200 }
4201
4202 /**
4203 * Parse an assignable expression. The [primaryAllowed] is `true` if the
4204 * expression is allowed to be a primary without any assignable selector.
4205 * Return the assignable expression that was parsed.
4206 *
4207 * assignableExpression ::=
4208 * primary (arguments* assignableSelector)+
4209 * | 'super' unconditionalAssignableSelector
4210 * | identifier
4211 */
4212 Expression _parseAssignableExpression(bool primaryAllowed) {
4213 if (_matchesKeyword(Keyword.SUPER)) {
4214 return _parseAssignableSelector(
4215 new SuperExpression(getAndAdvance()), false, allowConditional: false);
4216 }
4217 //
4218 // A primary expression can start with an identifier. We resolve the
4219 // ambiguity by determining whether the primary consists of anything other
4220 // than an identifier and/or is followed by an assignableSelector.
4221 //
4222 Expression expression = _parsePrimaryExpression();
4223 bool isOptional = primaryAllowed || expression is SimpleIdentifier;
4224 while (true) {
4225 while (_isLikelyParameterList()) {
4226 TypeArgumentList typeArguments = null;
4227 if (_matches(TokenType.LT)) {
4228 typeArguments = parseTypeArgumentList();
4229 }
4230 ArgumentList argumentList = parseArgumentList();
4231 if (expression is SimpleIdentifier) {
4232 expression = new MethodInvocation(null, null,
4233 expression as SimpleIdentifier, typeArguments, argumentList);
4234 } else if (expression is PrefixedIdentifier) {
4235 PrefixedIdentifier identifier = expression as PrefixedIdentifier;
4236 expression = new MethodInvocation(identifier.prefix,
4237 identifier.period, identifier.identifier, typeArguments,
4238 argumentList);
4239 } else if (expression is PropertyAccess) {
4240 PropertyAccess access = expression as PropertyAccess;
4241 expression = new MethodInvocation(access.target, access.operator,
4242 access.propertyName, typeArguments, argumentList);
4243 } else {
4244 expression = new FunctionExpressionInvocation(
4245 expression, typeArguments, argumentList);
4246 }
4247 if (!primaryAllowed) {
4248 isOptional = false;
4249 }
4250 }
4251 Expression selectorExpression = _parseAssignableSelector(
4252 expression, isOptional || (expression is PrefixedIdentifier));
4253 if (identical(selectorExpression, expression)) {
4254 if (!isOptional && (expression is PrefixedIdentifier)) {
4255 PrefixedIdentifier identifier = expression as PrefixedIdentifier;
4256 expression = new PropertyAccess(
4257 identifier.prefix, identifier.period, identifier.identifier);
4258 }
4259 return expression;
4260 }
4261 expression = selectorExpression;
4262 isOptional = true;
4263 }
4264 }
4265
4266 /**
4267 * Parse an assignable selector. The [prefix] is the expression preceding the
4268 * selector. The [optional] is `true` if the selector is optional. Return the
4269 * assignable selector that was parsed, or the original prefix if there was no
4270 * assignable selector. If [allowConditional] is false, then the '?.'
4271 * operator will still be parsed, but a parse error will be generated.
4272 *
4273 * unconditionalAssignableSelector ::=
4274 * '[' expression ']'
4275 * | '.' identifier
4276 *
4277 * assignableSelector ::=
4278 * unconditionalAssignableSelector
4279 * | '?.' identifier
4280 */
4281 Expression _parseAssignableSelector(Expression prefix, bool optional,
4282 {bool allowConditional: true}) {
4283 if (_matches(TokenType.OPEN_SQUARE_BRACKET)) {
4284 Token leftBracket = getAndAdvance();
4285 bool wasInInitializer = _inInitializer;
4286 _inInitializer = false;
4287 try {
4288 Expression index = parseExpression2();
4289 Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
4290 return new IndexExpression.forTarget(
4291 prefix, leftBracket, index, rightBracket);
4292 } finally {
4293 _inInitializer = wasInInitializer;
4294 }
4295 } else if (_matches(TokenType.PERIOD) ||
4296 _matches(TokenType.QUESTION_PERIOD)) {
4297 if (_matches(TokenType.QUESTION_PERIOD) && !allowConditional) {
4298 _reportErrorForCurrentToken(
4299 ParserErrorCode.INVALID_OPERATOR_FOR_SUPER, [_currentToken.lexeme]);
4300 }
4301 Token operator = getAndAdvance();
4302 return new PropertyAccess(prefix, operator, parseSimpleIdentifier());
4303 } else {
4304 if (!optional) {
4305 // Report the missing selector.
4306 _reportErrorForCurrentToken(
4307 ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR);
4308 }
4309 return prefix;
4310 }
4311 }
4312
4313 /**
4314 * Parse a await expression. Return the await expression that was parsed.
4315 *
4316 * awaitExpression ::=
4317 * 'await' unaryExpression
4318 */
4319 AwaitExpression _parseAwaitExpression() {
4320 Token awaitToken = getAndAdvance();
4321 Expression expression = _parseUnaryExpression();
4322 return new AwaitExpression(awaitToken, expression);
4323 }
4324
4325 /**
4326 * Parse a bitwise and expression. Return the bitwise and expression that was
4327 * parsed.
4328 *
4329 * bitwiseAndExpression ::=
4330 * shiftExpression ('&' shiftExpression)*
4331 * | 'super' ('&' shiftExpression)+
4332 */
4333 Expression _parseBitwiseAndExpression() {
4334 Expression expression;
4335 if (_matchesKeyword(Keyword.SUPER) &&
4336 _tokenMatches(_peek(), TokenType.AMPERSAND)) {
4337 expression = new SuperExpression(getAndAdvance());
4338 } else {
4339 expression = _parseShiftExpression();
4340 }
4341 while (_matches(TokenType.AMPERSAND)) {
4342 Token operator = getAndAdvance();
4343 expression =
4344 new BinaryExpression(expression, operator, _parseShiftExpression());
4345 }
4346 return expression;
4347 }
4348
4349 /**
4350 * Parse a bitwise exclusive-or expression. Return the bitwise exclusive-or
4351 * expression that was parsed.
4352 *
4353 * bitwiseXorExpression ::=
4354 * bitwiseAndExpression ('^' bitwiseAndExpression)*
4355 * | 'super' ('^' bitwiseAndExpression)+
4356 */
4357 Expression _parseBitwiseXorExpression() {
4358 Expression expression;
4359 if (_matchesKeyword(Keyword.SUPER) &&
4360 _tokenMatches(_peek(), TokenType.CARET)) {
4361 expression = new SuperExpression(getAndAdvance());
4362 } else {
4363 expression = _parseBitwiseAndExpression();
4364 }
4365 while (_matches(TokenType.CARET)) {
4366 Token operator = getAndAdvance();
4367 expression = new BinaryExpression(
4368 expression, operator, _parseBitwiseAndExpression());
4369 }
4370 return expression;
4371 }
4372
4373 /**
4374 * Parse a break statement. Return the break statement that was parsed.
4375 *
4376 * breakStatement ::=
4377 * 'break' identifier? ';'
4378 */
4379 Statement _parseBreakStatement() {
4380 Token breakKeyword = _expectKeyword(Keyword.BREAK);
4381 SimpleIdentifier label = null;
4382 if (_matchesIdentifier()) {
4383 label = parseSimpleIdentifier();
4384 }
4385 if (!_inLoop && !_inSwitch && label == null) {
4386 _reportErrorForToken(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP, breakKeyword);
4387 }
4388 Token semicolon = _expect(TokenType.SEMICOLON);
4389 return new BreakStatement(breakKeyword, label, semicolon);
4390 }
4391
4392 /**
4393 * Parse a cascade section. Return the expression representing the cascaded
4394 * method invocation.
4395 *
4396 * cascadeSection ::=
4397 * '..' (cascadeSelector typeArguments? arguments*)
4398 * (assignableSelector typeArguments? arguments*)* cascadeAssignment?
4399 *
4400 * cascadeSelector ::=
4401 * '[' expression ']'
4402 * | identifier
4403 *
4404 * cascadeAssignment ::=
4405 * assignmentOperator expressionWithoutCascade
4406 */
4407 Expression _parseCascadeSection() {
4408 Token period = _expect(TokenType.PERIOD_PERIOD);
4409 Expression expression = null;
4410 SimpleIdentifier functionName = null;
4411 if (_matchesIdentifier()) {
4412 functionName = parseSimpleIdentifier();
4413 } else if (_currentToken.type == TokenType.OPEN_SQUARE_BRACKET) {
4414 Token leftBracket = getAndAdvance();
4415 bool wasInInitializer = _inInitializer;
4416 _inInitializer = false;
4417 try {
4418 Expression index = parseExpression2();
4419 Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
4420 expression = new IndexExpression.forCascade(
4421 period, leftBracket, index, rightBracket);
4422 period = null;
4423 } finally {
4424 _inInitializer = wasInInitializer;
4425 }
4426 } else {
4427 _reportErrorForToken(ParserErrorCode.MISSING_IDENTIFIER, _currentToken,
4428 [_currentToken.lexeme]);
4429 functionName = _createSyntheticIdentifier();
4430 }
4431 assert((expression == null && functionName != null) ||
4432 (expression != null && functionName == null));
4433 if (_isLikelyParameterList()) {
4434 while (_isLikelyParameterList()) {
4435 TypeArgumentList typeArguments = null;
4436 if (_matches(TokenType.LT)) {
4437 typeArguments = parseTypeArgumentList();
4438 }
4439 if (functionName != null) {
4440 expression = new MethodInvocation(expression, period, functionName,
4441 typeArguments, parseArgumentList());
4442 period = null;
4443 functionName = null;
4444 } else if (expression == null) {
4445 // It should not be possible to get here.
4446 expression = new MethodInvocation(expression, period,
4447 _createSyntheticIdentifier(), typeArguments, parseArgumentList());
4448 } else {
4449 expression = new FunctionExpressionInvocation(
4450 expression, typeArguments, parseArgumentList());
4451 }
4452 }
4453 } else if (functionName != null) {
4454 expression = new PropertyAccess(expression, period, functionName);
4455 period = null;
4456 }
4457 assert(expression != null);
4458 bool progress = true;
4459 while (progress) {
4460 progress = false;
4461 Expression selector = _parseAssignableSelector(expression, true);
4462 if (!identical(selector, expression)) {
4463 expression = selector;
4464 progress = true;
4465 while (_isLikelyParameterList()) {
4466 TypeArgumentList typeArguments = null;
4467 if (_matches(TokenType.LT)) {
4468 typeArguments = parseTypeArgumentList();
4469 }
4470 if (expression is PropertyAccess) {
4471 PropertyAccess propertyAccess = expression as PropertyAccess;
4472 expression = new MethodInvocation(propertyAccess.target,
4473 propertyAccess.operator, propertyAccess.propertyName,
4474 typeArguments, parseArgumentList());
4475 } else {
4476 expression = new FunctionExpressionInvocation(
4477 expression, typeArguments, parseArgumentList());
4478 }
4479 }
4480 }
4481 }
4482 if (_currentToken.type.isAssignmentOperator) {
4483 Token operator = getAndAdvance();
4484 _ensureAssignable(expression);
4485 expression = new AssignmentExpression(
4486 expression, operator, parseExpressionWithoutCascade());
4487 }
4488 return expression;
4489 }
4490
4491 /**
4492 * Parse a class declaration. The [commentAndMetadata] is the metadata to be
4493 * associated with the member. The [abstractKeyword] is the token for the
4494 * keyword 'abstract', or `null` if the keyword was not given. Return the
4495 * class declaration that was parsed.
4496 *
4497 * classDeclaration ::=
4498 * metadata 'abstract'? 'class' name typeParameterList? (extendsClause withClause?)? implementsClause? '{' classMembers '}' |
4499 * metadata 'abstract'? 'class' mixinApplicationClass
4500 */
4501 CompilationUnitMember _parseClassDeclaration(
4502 CommentAndMetadata commentAndMetadata, Token abstractKeyword) {
4503 Token keyword = _expectKeyword(Keyword.CLASS);
4504 if (_matchesIdentifier()) {
4505 Token next = _peek();
4506 if (_tokenMatches(next, TokenType.LT)) {
4507 next = _skipTypeParameterList(next);
4508 if (next != null && _tokenMatches(next, TokenType.EQ)) {
4509 return _parseClassTypeAlias(
4510 commentAndMetadata, abstractKeyword, keyword);
4511 }
4512 } else if (_tokenMatches(next, TokenType.EQ)) {
4513 return _parseClassTypeAlias(
4514 commentAndMetadata, abstractKeyword, keyword);
4515 }
4516 }
4517 SimpleIdentifier name = parseSimpleIdentifier();
4518 String className = name.name;
4519 TypeParameterList typeParameters = null;
4520 if (_matches(TokenType.LT)) {
4521 typeParameters = parseTypeParameterList();
4522 }
4523 //
4524 // Parse the clauses. The parser accepts clauses in any order, but will
4525 // generate errors if they are not in the order required by the
4526 // specification.
4527 //
4528 ExtendsClause extendsClause = null;
4529 WithClause withClause = null;
4530 ImplementsClause implementsClause = null;
4531 bool foundClause = true;
4532 while (foundClause) {
4533 if (_matchesKeyword(Keyword.EXTENDS)) {
4534 if (extendsClause == null) {
4535 extendsClause = parseExtendsClause();
4536 if (withClause != null) {
4537 _reportErrorForToken(
4538 ParserErrorCode.WITH_BEFORE_EXTENDS, withClause.withKeyword);
4539 } else if (implementsClause != null) {
4540 _reportErrorForToken(ParserErrorCode.IMPLEMENTS_BEFORE_EXTENDS,
4541 implementsClause.implementsKeyword);
4542 }
4543 } else {
4544 _reportErrorForToken(ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES,
4545 extendsClause.extendsKeyword);
4546 parseExtendsClause();
4547 }
4548 } else if (_matchesKeyword(Keyword.WITH)) {
4549 if (withClause == null) {
4550 withClause = parseWithClause();
4551 if (implementsClause != null) {
4552 _reportErrorForToken(ParserErrorCode.IMPLEMENTS_BEFORE_WITH,
4553 implementsClause.implementsKeyword);
4554 }
4555 } else {
4556 _reportErrorForToken(
4557 ParserErrorCode.MULTIPLE_WITH_CLAUSES, withClause.withKeyword);
4558 parseWithClause();
4559 // TODO(brianwilkerson) Should we merge the list of applied mixins
4560 // into a single list?
4561 }
4562 } else if (_matchesKeyword(Keyword.IMPLEMENTS)) {
4563 if (implementsClause == null) {
4564 implementsClause = parseImplementsClause();
4565 } else {
4566 _reportErrorForToken(ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES,
4567 implementsClause.implementsKeyword);
4568 parseImplementsClause();
4569 // TODO(brianwilkerson) Should we merge the list of implemented
4570 // classes into a single list?
4571 }
4572 } else {
4573 foundClause = false;
4574 }
4575 }
4576 if (withClause != null && extendsClause == null) {
4577 _reportErrorForToken(
4578 ParserErrorCode.WITH_WITHOUT_EXTENDS, withClause.withKeyword);
4579 }
4580 //
4581 // Look for and skip over the extra-lingual 'native' specification.
4582 //
4583 NativeClause nativeClause = null;
4584 if (_matchesString(_NATIVE) && _tokenMatches(_peek(), TokenType.STRING)) {
4585 nativeClause = _parseNativeClause();
4586 }
4587 //
4588 // Parse the body of the class.
4589 //
4590 Token leftBracket = null;
4591 List<ClassMember> members = null;
4592 Token rightBracket = null;
4593 if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
4594 leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
4595 members = _parseClassMembers(className, _getEndToken(leftBracket));
4596 rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
4597 } else {
4598 leftBracket = _createSyntheticToken(TokenType.OPEN_CURLY_BRACKET);
4599 rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET);
4600 _reportErrorForCurrentToken(ParserErrorCode.MISSING_CLASS_BODY);
4601 }
4602 ClassDeclaration classDeclaration = new ClassDeclaration(
4603 commentAndMetadata.comment, commentAndMetadata.metadata,
4604 abstractKeyword, keyword, name, typeParameters, extendsClause,
4605 withClause, implementsClause, leftBracket, members, rightBracket);
4606 classDeclaration.nativeClause = nativeClause;
4607 return classDeclaration;
4608 }
4609
4610 /**
4611 * Parse a list of class members. The [className] is the name of the class
4612 * whose members are being parsed. The [closingBracket] is the closing bracket
4613 * for the class, or `null` if the closing bracket is missing. Return the list
4614 * of class members that were parsed.
4615 *
4616 * classMembers ::=
4617 * (metadata memberDefinition)*
4618 */
4619 List<ClassMember> _parseClassMembers(String className, Token closingBracket) {
4620 List<ClassMember> members = new List<ClassMember>();
4621 Token memberStart = _currentToken;
4622 while (!_matches(TokenType.EOF) &&
4623 !_matches(TokenType.CLOSE_CURLY_BRACKET) &&
4624 (closingBracket != null ||
4625 (!_matchesKeyword(Keyword.CLASS) &&
4626 !_matchesKeyword(Keyword.TYPEDEF)))) {
4627 if (_matches(TokenType.SEMICOLON)) {
4628 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
4629 [_currentToken.lexeme]);
4630 _advance();
4631 } else {
4632 ClassMember member = parseClassMember(className);
4633 if (member != null) {
4634 members.add(member);
4635 }
4636 }
4637 if (identical(_currentToken, memberStart)) {
4638 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
4639 [_currentToken.lexeme]);
4640 _advance();
4641 }
4642 memberStart = _currentToken;
4643 }
4644 return members;
4645 }
4646
4647 /**
4648 * Parse a class type alias. The [commentAndMetadata] is the metadata to be
4649 * associated with the member. The [abstractKeyword] is the token representing
4650 * the 'abstract' keyword. The [classKeyword] is the token representing the
4651 * 'class' keyword. Return the class type alias that was parsed.
4652 *
4653 * classTypeAlias ::=
4654 * identifier typeParameters? '=' 'abstract'? mixinApplication
4655 *
4656 * mixinApplication ::=
4657 * type withClause implementsClause? ';'
4658 */
4659 ClassTypeAlias _parseClassTypeAlias(CommentAndMetadata commentAndMetadata,
4660 Token abstractKeyword, Token classKeyword) {
4661 SimpleIdentifier className = parseSimpleIdentifier();
4662 TypeParameterList typeParameters = null;
4663 if (_matches(TokenType.LT)) {
4664 typeParameters = parseTypeParameterList();
4665 }
4666 Token equals = _expect(TokenType.EQ);
4667 TypeName superclass = parseTypeName();
4668 WithClause withClause = null;
4669 if (_matchesKeyword(Keyword.WITH)) {
4670 withClause = parseWithClause();
4671 } else {
4672 _reportErrorForCurrentToken(
4673 ParserErrorCode.EXPECTED_TOKEN, [Keyword.WITH.syntax]);
4674 }
4675 ImplementsClause implementsClause = null;
4676 if (_matchesKeyword(Keyword.IMPLEMENTS)) {
4677 implementsClause = parseImplementsClause();
4678 }
4679 Token semicolon;
4680 if (_matches(TokenType.SEMICOLON)) {
4681 semicolon = getAndAdvance();
4682 } else {
4683 if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
4684 _reportErrorForCurrentToken(
4685 ParserErrorCode.EXPECTED_TOKEN, [TokenType.SEMICOLON.lexeme]);
4686 Token leftBracket = getAndAdvance();
4687 _parseClassMembers(className.name, _getEndToken(leftBracket));
4688 _expect(TokenType.CLOSE_CURLY_BRACKET);
4689 } else {
4690 _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN,
4691 _currentToken.previous, [TokenType.SEMICOLON.lexeme]);
4692 }
4693 semicolon = _createSyntheticToken(TokenType.SEMICOLON);
4694 }
4695 return new ClassTypeAlias(commentAndMetadata.comment,
4696 commentAndMetadata.metadata, classKeyword, className, typeParameters,
4697 equals, abstractKeyword, superclass, withClause, implementsClause,
4698 semicolon);
4699 }
4700
4701 /**
4702 * Parse a list of combinators in a directive. Return the combinators that
4703 * were parsed.
4704 *
4705 * combinator ::=
4706 * 'show' identifier (',' identifier)*
4707 * | 'hide' identifier (',' identifier)*
4708 */
4709 List<Combinator> _parseCombinators() {
4710 List<Combinator> combinators = new List<Combinator>();
4711 while (true) {
4712 Combinator combinator = parseCombinator();
4713 if (combinator == null) {
4714 break;
4715 }
4716 combinators.add(combinator);
4717 }
4718 return combinators;
4719 }
4720
4721 /**
4722 * Parse the documentation comment and metadata preceding a declaration. This
4723 * method allows any number of documentation comments to occur before, after
4724 * or between the metadata, but only returns the last (right-most)
4725 * documentation comment that is found. Return the documentation comment and
4726 * metadata that were parsed.
4727 *
4728 * metadata ::=
4729 * annotation*
4730 */
4731 CommentAndMetadata _parseCommentAndMetadata() {
4732 Comment comment = _parseDocumentationComment();
4733 List<Annotation> metadata = new List<Annotation>();
4734 while (_matches(TokenType.AT)) {
4735 metadata.add(parseAnnotation());
4736 Comment optionalComment = _parseDocumentationComment();
4737 if (optionalComment != null) {
4738 comment = optionalComment;
4739 }
4740 }
4741 return new CommentAndMetadata(comment, metadata);
4742 }
4743
4744 /**
4745 * Parse a comment reference from the source between square brackets. The
4746 * [referenceSource] is the source occurring between the square brackets
4747 * within a documentation comment. The [sourceOffset] is the offset of the
4748 * first character of the reference source. Return the comment reference that
4749 * was parsed, or `null` if no reference could be found.
4750 *
4751 * commentReference ::=
4752 * 'new'? prefixedIdentifier
4753 */
4754 CommentReference _parseCommentReference(
4755 String referenceSource, int sourceOffset) {
4756 // TODO(brianwilkerson) The errors are not getting the right offset/length
4757 // and are being duplicated.
4758 if (referenceSource.length == 0) {
4759 Token syntheticToken =
4760 new SyntheticStringToken(TokenType.IDENTIFIER, "", sourceOffset);
4761 return new CommentReference(null, new SimpleIdentifier(syntheticToken));
4762 }
4763 try {
4764 BooleanErrorListener listener = new BooleanErrorListener();
4765 Scanner scanner = new Scanner(
4766 null, new SubSequenceReader(referenceSource, sourceOffset), listener);
4767 scanner.setSourceStart(1, 1);
4768 Token firstToken = scanner.tokenize();
4769 if (listener.errorReported) {
4770 return null;
4771 }
4772 Token newKeyword = null;
4773 if (_tokenMatchesKeyword(firstToken, Keyword.NEW)) {
4774 newKeyword = firstToken;
4775 firstToken = firstToken.next;
4776 }
4777 if (_tokenMatchesIdentifier(firstToken)) {
4778 Token secondToken = firstToken.next;
4779 Token thirdToken = secondToken.next;
4780 Token nextToken;
4781 Identifier identifier;
4782 if (_tokenMatches(secondToken, TokenType.PERIOD) &&
4783 _tokenMatchesIdentifier(thirdToken)) {
4784 identifier = new PrefixedIdentifier(new SimpleIdentifier(firstToken),
4785 secondToken, new SimpleIdentifier(thirdToken));
4786 nextToken = thirdToken.next;
4787 } else {
4788 identifier = new SimpleIdentifier(firstToken);
4789 nextToken = firstToken.next;
4790 }
4791 if (nextToken.type != TokenType.EOF) {
4792 return null;
4793 }
4794 return new CommentReference(newKeyword, identifier);
4795 } else if (_tokenMatchesKeyword(firstToken, Keyword.THIS) ||
4796 _tokenMatchesKeyword(firstToken, Keyword.NULL) ||
4797 _tokenMatchesKeyword(firstToken, Keyword.TRUE) ||
4798 _tokenMatchesKeyword(firstToken, Keyword.FALSE)) {
4799 // TODO(brianwilkerson) If we want to support this we will need to
4800 // extend the definition of CommentReference to take an expression
4801 // rather than an identifier. For now we just ignore it to reduce the
4802 // number of errors produced, but that's probably not a valid long term
4803 // approach.
4804 return null;
4805 }
4806 } catch (exception) {
4807 // Ignored because we assume that it wasn't a real comment reference.
4808 }
4809 return null;
4810 }
4811
4812 /**
4813 * Parse all of the comment references occurring in the given array of
4814 * documentation comments. The [tokens] are the comment tokens representing
4815 * the documentation comments to be parsed. Return the comment references that
4816 * were parsed.
4817 *
4818 * commentReference ::=
4819 * '[' 'new'? qualified ']' libraryReference?
4820 *
4821 * libraryReference ::=
4822 * '(' stringLiteral ')'
4823 */
4824 List<CommentReference> _parseCommentReferences(
4825 List<DocumentationCommentToken> tokens) {
4826 List<CommentReference> references = new List<CommentReference>();
4827 for (DocumentationCommentToken token in tokens) {
4828 String comment = token.lexeme;
4829 int length = comment.length;
4830 List<List<int>> codeBlockRanges = _getCodeBlockRanges(comment);
4831 int leftIndex = comment.indexOf('[');
4832 while (leftIndex >= 0 && leftIndex + 1 < length) {
4833 List<int> range = _findRange(codeBlockRanges, leftIndex);
4834 if (range == null) {
4835 int nameOffset = token.offset + leftIndex + 1;
4836 int rightIndex = JavaString.indexOf(comment, ']', leftIndex);
4837 if (rightIndex >= 0) {
4838 int firstChar = comment.codeUnitAt(leftIndex + 1);
4839 if (firstChar != 0x27 && firstChar != 0x22) {
4840 if (_isLinkText(comment, rightIndex)) {
4841 // TODO(brianwilkerson) Handle the case where there's a library
4842 // URI in the link text.
4843 } else {
4844 CommentReference reference = _parseCommentReference(
4845 comment.substring(leftIndex + 1, rightIndex), nameOffset);
4846 if (reference != null) {
4847 references.add(reference);
4848 token.references.add(reference.beginToken);
4849 }
4850 }
4851 }
4852 } else {
4853 // terminating ']' is not typed yet
4854 int charAfterLeft = comment.codeUnitAt(leftIndex + 1);
4855 if (Character.isLetterOrDigit(charAfterLeft)) {
4856 int nameEnd = StringUtilities.indexOfFirstNotLetterDigit(
4857 comment, leftIndex + 1);
4858 String name = comment.substring(leftIndex + 1, nameEnd);
4859 Token nameToken =
4860 new StringToken(TokenType.IDENTIFIER, name, nameOffset);
4861 references.add(
4862 new CommentReference(null, new SimpleIdentifier(nameToken)));
4863 } else {
4864 Token nameToken = new SyntheticStringToken(
4865 TokenType.IDENTIFIER, "", nameOffset);
4866 references.add(
4867 new CommentReference(null, new SimpleIdentifier(nameToken)));
4868 }
4869 // next character
4870 rightIndex = leftIndex + 1;
4871 }
4872 leftIndex = JavaString.indexOf(comment, '[', rightIndex);
4873 } else {
4874 leftIndex = JavaString.indexOf(comment, '[', range[1] + 1);
4875 }
4876 }
4877 }
4878 return references;
4879 }
4880
4881 /**
4882 * Parse a compilation unit member. The [commentAndMetadata] is the metadata
4883 * to be associated with the member. Return the compilation unit member that
4884 * was parsed, or `null` if what was parsed could not be represented as a
4885 * compilation unit member.
4886 *
4887 * compilationUnitMember ::=
4888 * classDefinition
4889 * | functionTypeAlias
4890 * | external functionSignature
4891 * | external getterSignature
4892 * | external setterSignature
4893 * | functionSignature functionBody
4894 * | returnType? getOrSet identifier formalParameterList functionBody
4895 * | (final | const) type? staticFinalDeclarationList ';'
4896 * | variableDeclaration ';'
4897 */
4898 CompilationUnitMember _parseCompilationUnitMember(
4899 CommentAndMetadata commentAndMetadata) {
4900 Modifiers modifiers = _parseModifiers();
4901 if (_matchesKeyword(Keyword.CLASS)) {
4902 return _parseClassDeclaration(
4903 commentAndMetadata, _validateModifiersForClass(modifiers));
4904 } else if (_matchesKeyword(Keyword.TYPEDEF) &&
4905 !_tokenMatches(_peek(), TokenType.PERIOD) &&
4906 !_tokenMatches(_peek(), TokenType.LT) &&
4907 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
4908 _validateModifiersForTypedef(modifiers);
4909 return _parseTypeAlias(commentAndMetadata);
4910 } else if (_matchesKeyword(Keyword.ENUM)) {
4911 _validateModifiersForEnum(modifiers);
4912 return _parseEnumDeclaration(commentAndMetadata);
4913 }
4914 if (_matchesKeyword(Keyword.VOID)) {
4915 TypeName returnType = parseReturnType();
4916 if ((_matchesKeyword(Keyword.GET) || _matchesKeyword(Keyword.SET)) &&
4917 _tokenMatchesIdentifier(_peek())) {
4918 _validateModifiersForTopLevelFunction(modifiers);
4919 return _parseFunctionDeclaration(
4920 commentAndMetadata, modifiers.externalKeyword, returnType);
4921 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) {
4922 _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken);
4923 return _convertToFunctionDeclaration(_parseOperator(
4924 commentAndMetadata, modifiers.externalKeyword, returnType));
4925 } else if (_matchesIdentifier() &&
4926 _peek().matchesAny([
4927 TokenType.OPEN_PAREN,
4928 TokenType.OPEN_CURLY_BRACKET,
4929 TokenType.FUNCTION
4930 ])) {
4931 _validateModifiersForTopLevelFunction(modifiers);
4932 return _parseFunctionDeclaration(
4933 commentAndMetadata, modifiers.externalKeyword, returnType);
4934 } else {
4935 //
4936 // We have found an error of some kind. Try to recover.
4937 //
4938 if (_matchesIdentifier()) {
4939 if (_peek().matchesAny(
4940 [TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
4941 //
4942 // We appear to have a variable declaration with a type of "void".
4943 //
4944 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
4945 return new TopLevelVariableDeclaration(commentAndMetadata.comment,
4946 commentAndMetadata.metadata,
4947 _parseVariableDeclarationListAfterType(null,
4948 _validateModifiersForTopLevelVariable(modifiers), null),
4949 _expect(TokenType.SEMICOLON));
4950 }
4951 }
4952 _reportErrorForToken(
4953 ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
4954 return null;
4955 }
4956 } else if ((_matchesKeyword(Keyword.GET) || _matchesKeyword(Keyword.SET)) &&
4957 _tokenMatchesIdentifier(_peek())) {
4958 _validateModifiersForTopLevelFunction(modifiers);
4959 return _parseFunctionDeclaration(
4960 commentAndMetadata, modifiers.externalKeyword, null);
4961 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) {
4962 _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken);
4963 return _convertToFunctionDeclaration(
4964 _parseOperator(commentAndMetadata, modifiers.externalKeyword, null));
4965 } else if (!_matchesIdentifier()) {
4966 Token keyword = modifiers.varKeyword;
4967 if (keyword == null) {
4968 keyword = modifiers.finalKeyword;
4969 }
4970 if (keyword == null) {
4971 keyword = modifiers.constKeyword;
4972 }
4973 if (keyword != null) {
4974 //
4975 // We appear to have found an incomplete top-level variable declaration.
4976 //
4977 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
4978 List<VariableDeclaration> variables = new List<VariableDeclaration>();
4979 variables.add(
4980 new VariableDeclaration(_createSyntheticIdentifier(), null, null));
4981 return new TopLevelVariableDeclaration(commentAndMetadata.comment,
4982 commentAndMetadata.metadata,
4983 new VariableDeclarationList(null, null, keyword, null, variables),
4984 _expectSemicolon());
4985 }
4986 _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
4987 return null;
4988 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
4989 _validateModifiersForTopLevelFunction(modifiers);
4990 return _parseFunctionDeclaration(
4991 commentAndMetadata, modifiers.externalKeyword, null);
4992 } else if (_peek()
4993 .matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
4994 if (modifiers.constKeyword == null &&
4995 modifiers.finalKeyword == null &&
4996 modifiers.varKeyword == null) {
4997 _reportErrorForCurrentToken(
4998 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
4999 }
5000 return new TopLevelVariableDeclaration(commentAndMetadata.comment,
5001 commentAndMetadata.metadata, _parseVariableDeclarationListAfterType(
5002 null, _validateModifiersForTopLevelVariable(modifiers), null),
5003 _expect(TokenType.SEMICOLON));
5004 }
5005 TypeName returnType = parseReturnType();
5006 if ((_matchesKeyword(Keyword.GET) || _matchesKeyword(Keyword.SET)) &&
5007 _tokenMatchesIdentifier(_peek())) {
5008 _validateModifiersForTopLevelFunction(modifiers);
5009 return _parseFunctionDeclaration(
5010 commentAndMetadata, modifiers.externalKeyword, returnType);
5011 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) {
5012 _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken);
5013 return _convertToFunctionDeclaration(_parseOperator(
5014 commentAndMetadata, modifiers.externalKeyword, returnType));
5015 } else if (_matches(TokenType.AT)) {
5016 return new TopLevelVariableDeclaration(commentAndMetadata.comment,
5017 commentAndMetadata.metadata, _parseVariableDeclarationListAfterType(
5018 null, _validateModifiersForTopLevelVariable(modifiers),
5019 returnType), _expect(TokenType.SEMICOLON));
5020 } else if (!_matchesIdentifier()) {
5021 // TODO(brianwilkerson) Generalize this error. We could also be parsing a
5022 // top-level variable at this point.
5023 _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
5024 Token semicolon;
5025 if (_matches(TokenType.SEMICOLON)) {
5026 semicolon = getAndAdvance();
5027 } else {
5028 semicolon = _createSyntheticToken(TokenType.SEMICOLON);
5029 }
5030 List<VariableDeclaration> variables = new List<VariableDeclaration>();
5031 variables.add(
5032 new VariableDeclaration(_createSyntheticIdentifier(), null, null));
5033 return new TopLevelVariableDeclaration(commentAndMetadata.comment,
5034 commentAndMetadata.metadata,
5035 new VariableDeclarationList(null, null, null, returnType, variables),
5036 semicolon);
5037 }
5038 if (_peek().matchesAny([
5039 TokenType.OPEN_PAREN,
5040 TokenType.FUNCTION,
5041 TokenType.OPEN_CURLY_BRACKET
5042 ])) {
5043 _validateModifiersForTopLevelFunction(modifiers);
5044 return _parseFunctionDeclaration(
5045 commentAndMetadata, modifiers.externalKeyword, returnType);
5046 }
5047 return new TopLevelVariableDeclaration(commentAndMetadata.comment,
5048 commentAndMetadata.metadata, _parseVariableDeclarationListAfterType(
5049 null, _validateModifiersForTopLevelVariable(modifiers), returnType),
5050 _expect(TokenType.SEMICOLON));
5051 }
5052
5053 /**
5054 * Parse a const expression. Return the const expression that was parsed.
5055 *
5056 * constExpression ::=
5057 * instanceCreationExpression
5058 * | listLiteral
5059 * | mapLiteral
5060 */
5061 Expression _parseConstExpression() {
5062 Token keyword = _expectKeyword(Keyword.CONST);
5063 if (_matches(TokenType.OPEN_SQUARE_BRACKET) || _matches(TokenType.INDEX)) {
5064 return _parseListLiteral(keyword, null);
5065 } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
5066 return _parseMapLiteral(keyword, null);
5067 } else if (_matches(TokenType.LT)) {
5068 return _parseListOrMapLiteral(keyword);
5069 }
5070 return _parseInstanceCreationExpression(keyword);
5071 }
5072
5073 ConstructorDeclaration _parseConstructor(
5074 CommentAndMetadata commentAndMetadata, Token externalKeyword,
5075 Token constKeyword, Token factoryKeyword, SimpleIdentifier returnType,
5076 Token period, SimpleIdentifier name, FormalParameterList parameters) {
5077 bool bodyAllowed = externalKeyword == null;
5078 Token separator = null;
5079 List<ConstructorInitializer> initializers = null;
5080 if (_matches(TokenType.COLON)) {
5081 separator = getAndAdvance();
5082 initializers = new List<ConstructorInitializer>();
5083 do {
5084 if (_matchesKeyword(Keyword.THIS)) {
5085 if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
5086 bodyAllowed = false;
5087 initializers.add(_parseRedirectingConstructorInvocation());
5088 } else if (_tokenMatches(_peek(), TokenType.PERIOD) &&
5089 _tokenMatches(_peekAt(3), TokenType.OPEN_PAREN)) {
5090 bodyAllowed = false;
5091 initializers.add(_parseRedirectingConstructorInvocation());
5092 } else {
5093 initializers.add(_parseConstructorFieldInitializer());
5094 }
5095 } else if (_matchesKeyword(Keyword.SUPER)) {
5096 initializers.add(_parseSuperConstructorInvocation());
5097 } else if (_matches(TokenType.OPEN_CURLY_BRACKET) ||
5098 _matches(TokenType.FUNCTION)) {
5099 _reportErrorForCurrentToken(ParserErrorCode.MISSING_INITIALIZER);
5100 } else {
5101 initializers.add(_parseConstructorFieldInitializer());
5102 }
5103 } while (_optional(TokenType.COMMA));
5104 if (factoryKeyword != null) {
5105 _reportErrorForToken(
5106 ParserErrorCode.FACTORY_WITH_INITIALIZERS, factoryKeyword);
5107 }
5108 }
5109 ConstructorName redirectedConstructor = null;
5110 FunctionBody body;
5111 if (_matches(TokenType.EQ)) {
5112 separator = getAndAdvance();
5113 redirectedConstructor = parseConstructorName();
5114 body = new EmptyFunctionBody(_expect(TokenType.SEMICOLON));
5115 if (factoryKeyword == null) {
5116 _reportErrorForNode(
5117 ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR,
5118 redirectedConstructor);
5119 }
5120 } else {
5121 body = _parseFunctionBody(
5122 true, ParserErrorCode.MISSING_FUNCTION_BODY, false);
5123 if (constKeyword != null &&
5124 factoryKeyword != null &&
5125 externalKeyword == null) {
5126 _reportErrorForToken(ParserErrorCode.CONST_FACTORY, factoryKeyword);
5127 } else if (body is EmptyFunctionBody) {
5128 if (factoryKeyword != null &&
5129 externalKeyword == null &&
5130 _parseFunctionBodies) {
5131 _reportErrorForToken(
5132 ParserErrorCode.FACTORY_WITHOUT_BODY, factoryKeyword);
5133 }
5134 } else {
5135 if (constKeyword != null) {
5136 _reportErrorForNode(
5137 ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, body);
5138 } else if (!bodyAllowed) {
5139 _reportErrorForNode(
5140 ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY, body);
5141 }
5142 }
5143 }
5144 return new ConstructorDeclaration(commentAndMetadata.comment,
5145 commentAndMetadata.metadata, externalKeyword, constKeyword,
5146 factoryKeyword, returnType, period, name, parameters, separator,
5147 initializers, redirectedConstructor, body);
5148 }
5149
5150 /**
5151 * Parse a field initializer within a constructor. Return the field
5152 * initializer that was parsed.
5153 *
5154 * fieldInitializer:
5155 * ('this' '.')? identifier '=' conditionalExpression cascadeSection*
5156 */
5157 ConstructorFieldInitializer _parseConstructorFieldInitializer() {
5158 Token keyword = null;
5159 Token period = null;
5160 if (_matchesKeyword(Keyword.THIS)) {
5161 keyword = getAndAdvance();
5162 period = _expect(TokenType.PERIOD);
5163 }
5164 SimpleIdentifier fieldName = parseSimpleIdentifier();
5165 Token equals = null;
5166 if (_matches(TokenType.EQ)) {
5167 equals = getAndAdvance();
5168 } else if (!_matchesKeyword(Keyword.THIS) &&
5169 !_matchesKeyword(Keyword.SUPER) &&
5170 !_matches(TokenType.OPEN_CURLY_BRACKET) &&
5171 !_matches(TokenType.FUNCTION)) {
5172 _reportErrorForCurrentToken(
5173 ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER);
5174 equals = _createSyntheticToken(TokenType.EQ);
5175 } else {
5176 _reportErrorForCurrentToken(
5177 ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER);
5178 return new ConstructorFieldInitializer(keyword, period, fieldName,
5179 _createSyntheticToken(TokenType.EQ), _createSyntheticIdentifier());
5180 }
5181 bool wasInInitializer = _inInitializer;
5182 _inInitializer = true;
5183 try {
5184 Expression expression = parseConditionalExpression();
5185 TokenType tokenType = _currentToken.type;
5186 if (tokenType == TokenType.PERIOD_PERIOD) {
5187 List<Expression> cascadeSections = new List<Expression>();
5188 while (tokenType == TokenType.PERIOD_PERIOD) {
5189 Expression section = _parseCascadeSection();
5190 if (section != null) {
5191 cascadeSections.add(section);
5192 }
5193 tokenType = _currentToken.type;
5194 }
5195 expression = new CascadeExpression(expression, cascadeSections);
5196 }
5197 return new ConstructorFieldInitializer(
5198 keyword, period, fieldName, equals, expression);
5199 } finally {
5200 _inInitializer = wasInInitializer;
5201 }
5202 }
5203
5204 /**
5205 * Parse a continue statement. Return the continue statement that was parsed.
5206 *
5207 * continueStatement ::=
5208 * 'continue' identifier? ';'
5209 */
5210 Statement _parseContinueStatement() {
5211 Token continueKeyword = _expectKeyword(Keyword.CONTINUE);
5212 if (!_inLoop && !_inSwitch) {
5213 _reportErrorForToken(
5214 ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, continueKeyword);
5215 }
5216 SimpleIdentifier label = null;
5217 if (_matchesIdentifier()) {
5218 label = parseSimpleIdentifier();
5219 }
5220 if (_inSwitch && !_inLoop && label == null) {
5221 _reportErrorForToken(
5222 ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE, continueKeyword);
5223 }
5224 Token semicolon = _expect(TokenType.SEMICOLON);
5225 return new ContinueStatement(continueKeyword, label, semicolon);
5226 }
5227
5228 /**
5229 * Parse a directive. The [commentAndMetadata] is the metadata to be
5230 * associated with the directive. Return the directive that was parsed.
5231 *
5232 * directive ::=
5233 * exportDirective
5234 * | libraryDirective
5235 * | importDirective
5236 * | partDirective
5237 */
5238 Directive _parseDirective(CommentAndMetadata commentAndMetadata) {
5239 if (_matchesKeyword(Keyword.IMPORT)) {
5240 return _parseImportDirective(commentAndMetadata);
5241 } else if (_matchesKeyword(Keyword.EXPORT)) {
5242 return _parseExportDirective(commentAndMetadata);
5243 } else if (_matchesKeyword(Keyword.LIBRARY)) {
5244 return _parseLibraryDirective(commentAndMetadata);
5245 } else if (_matchesKeyword(Keyword.PART)) {
5246 return _parsePartDirective(commentAndMetadata);
5247 } else {
5248 // Internal error: this method should not have been invoked if the current
5249 // token was something other than one of the above.
5250 throw new IllegalStateException(
5251 "parseDirective invoked in an invalid state; currentToken = $_currentT oken");
5252 }
5253 }
5254
5255 /**
5256 * Parse the script tag and directives in a compilation unit until the first
5257 * non-directive is encountered. Return the compilation unit that was parsed.
5258 *
5259 * compilationUnit ::=
5260 * scriptTag? directive*
5261 */
5262 CompilationUnit _parseDirectives() {
5263 Token firstToken = _currentToken;
5264 ScriptTag scriptTag = null;
5265 if (_matches(TokenType.SCRIPT_TAG)) {
5266 scriptTag = new ScriptTag(getAndAdvance());
5267 }
5268 List<Directive> directives = new List<Directive>();
5269 while (!_matches(TokenType.EOF)) {
5270 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
5271 if ((_matchesKeyword(Keyword.IMPORT) ||
5272 _matchesKeyword(Keyword.EXPORT) ||
5273 _matchesKeyword(Keyword.LIBRARY) ||
5274 _matchesKeyword(Keyword.PART)) &&
5275 !_tokenMatches(_peek(), TokenType.PERIOD) &&
5276 !_tokenMatches(_peek(), TokenType.LT) &&
5277 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
5278 directives.add(_parseDirective(commentAndMetadata));
5279 } else if (_matches(TokenType.SEMICOLON)) {
5280 _advance();
5281 } else {
5282 while (!_matches(TokenType.EOF)) {
5283 _advance();
5284 }
5285 return new CompilationUnit(firstToken, scriptTag, directives,
5286 new List<CompilationUnitMember>(), _currentToken);
5287 }
5288 }
5289 return new CompilationUnit(firstToken, scriptTag, directives,
5290 new List<CompilationUnitMember>(), _currentToken);
5291 }
5292
5293 /**
5294 * Parse a documentation comment. Return the documentation comment that was
5295 * parsed, or `null` if there was no comment.
5296 *
5297 * documentationComment ::=
5298 * multiLineComment?
5299 * | singleLineComment*
5300 */
5301 Comment _parseDocumentationComment() {
5302 List<DocumentationCommentToken> documentationTokens =
5303 <DocumentationCommentToken>[];
5304 CommentToken commentToken = _currentToken.precedingComments;
5305 while (commentToken != null) {
5306 if (commentToken is DocumentationCommentToken) {
5307 if (documentationTokens.isNotEmpty) {
5308 if (commentToken.type == TokenType.SINGLE_LINE_COMMENT) {
5309 if (documentationTokens[0].type != TokenType.SINGLE_LINE_COMMENT) {
5310 documentationTokens.clear();
5311 }
5312 } else {
5313 documentationTokens.clear();
5314 }
5315 }
5316 documentationTokens.add(commentToken);
5317 }
5318 commentToken = commentToken.next;
5319 }
5320 if (documentationTokens.isEmpty) {
5321 return null;
5322 }
5323 List<CommentReference> references =
5324 _parseCommentReferences(documentationTokens);
5325 return Comment.createDocumentationCommentWithReferences(
5326 documentationTokens, references);
5327 }
5328
5329 /**
5330 * Parse a do statement. Return the do statement that was parsed.
5331 *
5332 * doStatement ::=
5333 * 'do' statement 'while' '(' expression ')' ';'
5334 */
5335 Statement _parseDoStatement() {
5336 bool wasInLoop = _inLoop;
5337 _inLoop = true;
5338 try {
5339 Token doKeyword = _expectKeyword(Keyword.DO);
5340 Statement body = parseStatement2();
5341 Token whileKeyword = _expectKeyword(Keyword.WHILE);
5342 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
5343 Expression condition = parseExpression2();
5344 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
5345 Token semicolon = _expect(TokenType.SEMICOLON);
5346 return new DoStatement(doKeyword, body, whileKeyword, leftParenthesis,
5347 condition, rightParenthesis, semicolon);
5348 } finally {
5349 _inLoop = wasInLoop;
5350 }
5351 }
5352
5353 /**
5354 * Parse an empty statement. Return the empty statement that was parsed.
5355 *
5356 * emptyStatement ::=
5357 * ';'
5358 */
5359 Statement _parseEmptyStatement() => new EmptyStatement(getAndAdvance());
5360
5361 EnumConstantDeclaration _parseEnumConstantDeclaration() {
5362 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
5363 SimpleIdentifier name;
5364 if (_matchesIdentifier()) {
5365 name = parseSimpleIdentifier();
5366 } else {
5367 name = _createSyntheticIdentifier();
5368 }
5369 if (commentAndMetadata.metadata.isNotEmpty) {
5370 _reportErrorForNode(ParserErrorCode.ANNOTATION_ON_ENUM_CONSTANT,
5371 commentAndMetadata.metadata[0]);
5372 }
5373 return new EnumConstantDeclaration(
5374 commentAndMetadata.comment, commentAndMetadata.metadata, name);
5375 }
5376
5377 /**
5378 * Parse an enum declaration. The [commentAndMetadata] is the metadata to be
5379 * associated with the member. Return the enum declaration that was parsed.
5380 *
5381 * enumType ::=
5382 * metadata 'enum' id '{' id (',' id)* (',')? '}'
5383 */
5384 EnumDeclaration _parseEnumDeclaration(CommentAndMetadata commentAndMetadata) {
5385 Token keyword = _expectKeyword(Keyword.ENUM);
5386 SimpleIdentifier name = parseSimpleIdentifier();
5387 Token leftBracket = null;
5388 List<EnumConstantDeclaration> constants =
5389 new List<EnumConstantDeclaration>();
5390 Token rightBracket = null;
5391 if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
5392 leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
5393 if (_matchesIdentifier() || _matches(TokenType.AT)) {
5394 constants.add(_parseEnumConstantDeclaration());
5395 } else if (_matches(TokenType.COMMA) &&
5396 _tokenMatchesIdentifier(_peek())) {
5397 constants.add(_parseEnumConstantDeclaration());
5398 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
5399 } else {
5400 constants.add(_parseEnumConstantDeclaration());
5401 _reportErrorForCurrentToken(ParserErrorCode.EMPTY_ENUM_BODY);
5402 }
5403 while (_optional(TokenType.COMMA)) {
5404 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
5405 break;
5406 }
5407 constants.add(_parseEnumConstantDeclaration());
5408 }
5409 rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
5410 } else {
5411 leftBracket = _createSyntheticToken(TokenType.OPEN_CURLY_BRACKET);
5412 rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET);
5413 _reportErrorForCurrentToken(ParserErrorCode.MISSING_ENUM_BODY);
5414 }
5415 return new EnumDeclaration(commentAndMetadata.comment,
5416 commentAndMetadata.metadata, keyword, name, leftBracket, constants,
5417 rightBracket);
5418 }
5419
5420 /**
5421 * Parse an equality expression. Return the equality expression that was
5422 * parsed.
5423 *
5424 * equalityExpression ::=
5425 * relationalExpression (equalityOperator relationalExpression)?
5426 * | 'super' equalityOperator relationalExpression
5427 */
5428 Expression _parseEqualityExpression() {
5429 Expression expression;
5430 if (_matchesKeyword(Keyword.SUPER) &&
5431 _currentToken.next.type.isEqualityOperator) {
5432 expression = new SuperExpression(getAndAdvance());
5433 } else {
5434 expression = _parseRelationalExpression();
5435 }
5436 bool leftEqualityExpression = false;
5437 while (_currentToken.type.isEqualityOperator) {
5438 Token operator = getAndAdvance();
5439 if (leftEqualityExpression) {
5440 _reportErrorForNode(
5441 ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, expression);
5442 }
5443 expression = new BinaryExpression(
5444 expression, operator, _parseRelationalExpression());
5445 leftEqualityExpression = true;
5446 }
5447 return expression;
5448 }
5449
5450 /**
5451 * Parse an export directive. The [commentAndMetadata] is the metadata to be
5452 * associated with the directive. Return the export directive that was parsed.
5453 *
5454 * exportDirective ::=
5455 * metadata 'export' stringLiteral combinator*';'
5456 */
5457 ExportDirective _parseExportDirective(CommentAndMetadata commentAndMetadata) {
5458 Token exportKeyword = _expectKeyword(Keyword.EXPORT);
5459 StringLiteral libraryUri = _parseUri();
5460 List<Combinator> combinators = _parseCombinators();
5461 Token semicolon = _expectSemicolon();
5462 return new ExportDirective(commentAndMetadata.comment,
5463 commentAndMetadata.metadata, exportKeyword, libraryUri, combinators,
5464 semicolon);
5465 }
5466
5467 /**
5468 * Parse a list of expressions. Return the expression that was parsed.
5469 *
5470 * expressionList ::=
5471 * expression (',' expression)*
5472 */
5473 List<Expression> _parseExpressionList() {
5474 List<Expression> expressions = new List<Expression>();
5475 expressions.add(parseExpression2());
5476 while (_optional(TokenType.COMMA)) {
5477 expressions.add(parseExpression2());
5478 }
5479 return expressions;
5480 }
5481
5482 /**
5483 * Parse the 'final', 'const', 'var' or type preceding a variable declaration.
5484 * The [optional] is `true` if the keyword and type are optional. Return the
5485 * 'final', 'const', 'var' or type that was parsed.
5486 *
5487 * finalConstVarOrType ::=
5488 * 'final' type?
5489 * | 'const' type?
5490 * | 'var'
5491 * | type
5492 */
5493 FinalConstVarOrType _parseFinalConstVarOrType(bool optional) {
5494 Token keyword = null;
5495 TypeName type = null;
5496 if (_matchesKeyword(Keyword.FINAL) || _matchesKeyword(Keyword.CONST)) {
5497 keyword = getAndAdvance();
5498 if (_isTypedIdentifier(_currentToken)) {
5499 type = parseTypeName();
5500 }
5501 } else if (_matchesKeyword(Keyword.VAR)) {
5502 keyword = getAndAdvance();
5503 } else {
5504 if (_isTypedIdentifier(_currentToken)) {
5505 type = parseReturnType();
5506 } else if (!optional) {
5507 _reportErrorForCurrentToken(
5508 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
5509 }
5510 }
5511 return new FinalConstVarOrType(keyword, type);
5512 }
5513
5514 /**
5515 * Parse a formal parameter. At most one of `isOptional` and `isNamed` can be
5516 * `true`. The [kind] is the kind of parameter being expected based on the
5517 * presence or absence of group delimiters. Return the formal parameter that
5518 * was parsed.
5519 *
5520 * defaultFormalParameter ::=
5521 * normalFormalParameter ('=' expression)?
5522 *
5523 * defaultNamedParameter ::=
5524 * normalFormalParameter (':' expression)?
5525 */
5526 FormalParameter _parseFormalParameter(ParameterKind kind) {
5527 NormalFormalParameter parameter = parseNormalFormalParameter();
5528 if (_matches(TokenType.EQ)) {
5529 Token seperator = getAndAdvance();
5530 Expression defaultValue = parseExpression2();
5531 if (kind == ParameterKind.NAMED) {
5532 _reportErrorForToken(
5533 ParserErrorCode.WRONG_SEPARATOR_FOR_NAMED_PARAMETER, seperator);
5534 } else if (kind == ParameterKind.REQUIRED) {
5535 _reportErrorForNode(
5536 ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP, parameter);
5537 }
5538 return new DefaultFormalParameter(
5539 parameter, kind, seperator, defaultValue);
5540 } else if (_matches(TokenType.COLON)) {
5541 Token seperator = getAndAdvance();
5542 Expression defaultValue = parseExpression2();
5543 if (kind == ParameterKind.POSITIONAL) {
5544 _reportErrorForToken(
5545 ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER,
5546 seperator);
5547 } else if (kind == ParameterKind.REQUIRED) {
5548 _reportErrorForNode(
5549 ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, parameter);
5550 }
5551 return new DefaultFormalParameter(
5552 parameter, kind, seperator, defaultValue);
5553 } else if (kind != ParameterKind.REQUIRED) {
5554 return new DefaultFormalParameter(parameter, kind, null, null);
5555 }
5556 return parameter;
5557 }
5558
5559 /**
5560 * Parse a for statement. Return the for statement that was parsed.
5561 *
5562 * forStatement ::=
5563 * 'for' '(' forLoopParts ')' statement
5564 *
5565 * forLoopParts ::=
5566 * forInitializerStatement expression? ';' expressionList?
5567 * | declaredIdentifier 'in' expression
5568 * | identifier 'in' expression
5569 *
5570 * forInitializerStatement ::=
5571 * localVariableDeclaration ';'
5572 * | expression? ';'
5573 */
5574 Statement _parseForStatement() {
5575 bool wasInLoop = _inLoop;
5576 _inLoop = true;
5577 try {
5578 Token awaitKeyword = null;
5579 if (_matchesString(_AWAIT)) {
5580 awaitKeyword = getAndAdvance();
5581 }
5582 Token forKeyword = _expectKeyword(Keyword.FOR);
5583 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
5584 VariableDeclarationList variableList = null;
5585 Expression initialization = null;
5586 if (!_matches(TokenType.SEMICOLON)) {
5587 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
5588 if (_matchesIdentifier() &&
5589 (_tokenMatchesKeyword(_peek(), Keyword.IN) ||
5590 _tokenMatches(_peek(), TokenType.COLON))) {
5591 List<VariableDeclaration> variables = new List<VariableDeclaration>();
5592 SimpleIdentifier variableName = parseSimpleIdentifier();
5593 variables.add(new VariableDeclaration(variableName, null, null));
5594 variableList = new VariableDeclarationList(commentAndMetadata.comment,
5595 commentAndMetadata.metadata, null, null, variables);
5596 } else if (_isInitializedVariableDeclaration()) {
5597 variableList =
5598 _parseVariableDeclarationListAfterMetadata(commentAndMetadata);
5599 } else {
5600 initialization = parseExpression2();
5601 }
5602 if (_matchesKeyword(Keyword.IN) || _matches(TokenType.COLON)) {
5603 if (_matches(TokenType.COLON)) {
5604 _reportErrorForCurrentToken(ParserErrorCode.COLON_IN_PLACE_OF_IN);
5605 }
5606 DeclaredIdentifier loopVariable = null;
5607 SimpleIdentifier identifier = null;
5608 if (variableList == null) {
5609 // We found: <expression> 'in'
5610 _reportErrorForCurrentToken(
5611 ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH);
5612 } else {
5613 NodeList<VariableDeclaration> variables = variableList.variables;
5614 if (variables.length > 1) {
5615 _reportErrorForCurrentToken(
5616 ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH,
5617 [variables.length.toString()]);
5618 }
5619 VariableDeclaration variable = variables[0];
5620 if (variable.initializer != null) {
5621 _reportErrorForCurrentToken(
5622 ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH);
5623 }
5624 Token keyword = variableList.keyword;
5625 TypeName type = variableList.type;
5626 if (keyword != null || type != null) {
5627 loopVariable = new DeclaredIdentifier(commentAndMetadata.comment,
5628 commentAndMetadata.metadata, keyword, type, variable.name);
5629 } else {
5630 if (!commentAndMetadata.metadata.isEmpty) {
5631 // TODO(jwren) metadata isn't allowed before the identifier in
5632 // "identifier in expression", add warning if commentAndMetadata
5633 // has content
5634 }
5635 identifier = variable.name;
5636 }
5637 }
5638 Token inKeyword = getAndAdvance();
5639 Expression iterator = parseExpression2();
5640 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
5641 Statement body = parseStatement2();
5642 if (loopVariable == null) {
5643 return new ForEachStatement.withReference(awaitKeyword, forKeyword,
5644 leftParenthesis, identifier, inKeyword, iterator,
5645 rightParenthesis, body);
5646 }
5647 return new ForEachStatement.withDeclaration(awaitKeyword, forKeyword,
5648 leftParenthesis, loopVariable, inKeyword, iterator,
5649 rightParenthesis, body);
5650 }
5651 }
5652 if (awaitKeyword != null) {
5653 _reportErrorForToken(
5654 ParserErrorCode.INVALID_AWAIT_IN_FOR, awaitKeyword);
5655 }
5656 Token leftSeparator = _expect(TokenType.SEMICOLON);
5657 Expression condition = null;
5658 if (!_matches(TokenType.SEMICOLON)) {
5659 condition = parseExpression2();
5660 }
5661 Token rightSeparator = _expect(TokenType.SEMICOLON);
5662 List<Expression> updaters = null;
5663 if (!_matches(TokenType.CLOSE_PAREN)) {
5664 updaters = _parseExpressionList();
5665 }
5666 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
5667 Statement body = parseStatement2();
5668 return new ForStatement(forKeyword, leftParenthesis, variableList,
5669 initialization, leftSeparator, condition, rightSeparator, updaters,
5670 rightParenthesis, body);
5671 } finally {
5672 _inLoop = wasInLoop;
5673 }
5674 }
5675
5676 /**
5677 * Parse a function body. The [mayBeEmpty] is `true` if the function body is
5678 * allowed to be empty. The [emptyErrorCode] is the error code to report if
5679 * function body expected, but not found. The [inExpression] is `true` if the
5680 * function body is being parsed as part of an expression and therefore does
5681 * not have a terminating semicolon. Return the function body that was parsed.
5682 *
5683 * functionBody ::=
5684 * '=>' expression ';'
5685 * | block
5686 *
5687 * functionExpressionBody ::=
5688 * '=>' expression
5689 * | block
5690 */
5691 FunctionBody _parseFunctionBody(
5692 bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) {
5693 bool wasInAsync = _inAsync;
5694 bool wasInGenerator = _inGenerator;
5695 bool wasInLoop = _inLoop;
5696 bool wasInSwitch = _inSwitch;
5697 _inAsync = false;
5698 _inGenerator = false;
5699 _inLoop = false;
5700 _inSwitch = false;
5701 try {
5702 if (_matches(TokenType.SEMICOLON)) {
5703 if (!mayBeEmpty) {
5704 _reportErrorForCurrentToken(emptyErrorCode);
5705 }
5706 return new EmptyFunctionBody(getAndAdvance());
5707 } else if (_matchesString(_NATIVE)) {
5708 Token nativeToken = getAndAdvance();
5709 StringLiteral stringLiteral = null;
5710 if (_matches(TokenType.STRING)) {
5711 stringLiteral = parseStringLiteral();
5712 }
5713 return new NativeFunctionBody(
5714 nativeToken, stringLiteral, _expect(TokenType.SEMICOLON));
5715 }
5716 Token keyword = null;
5717 Token star = null;
5718 if (_matchesString(ASYNC)) {
5719 keyword = getAndAdvance();
5720 if (_matches(TokenType.STAR)) {
5721 star = getAndAdvance();
5722 _inGenerator = true;
5723 }
5724 _inAsync = true;
5725 } else if (_matchesString(SYNC)) {
5726 keyword = getAndAdvance();
5727 if (_matches(TokenType.STAR)) {
5728 star = getAndAdvance();
5729 _inGenerator = true;
5730 }
5731 }
5732 if (_matches(TokenType.FUNCTION)) {
5733 if (keyword != null) {
5734 if (!_tokenMatchesString(keyword, ASYNC)) {
5735 _reportErrorForToken(ParserErrorCode.INVALID_SYNC, keyword);
5736 keyword = null;
5737 } else if (star != null) {
5738 _reportErrorForToken(
5739 ParserErrorCode.INVALID_STAR_AFTER_ASYNC, star);
5740 }
5741 }
5742 Token functionDefinition = getAndAdvance();
5743 if (_matchesKeyword(Keyword.RETURN)) {
5744 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
5745 [_currentToken.lexeme]);
5746 _advance();
5747 }
5748 Expression expression = parseExpression2();
5749 Token semicolon = null;
5750 if (!inExpression) {
5751 semicolon = _expect(TokenType.SEMICOLON);
5752 }
5753 if (!_parseFunctionBodies) {
5754 return new EmptyFunctionBody(
5755 _createSyntheticToken(TokenType.SEMICOLON));
5756 }
5757 return new ExpressionFunctionBody(
5758 keyword, functionDefinition, expression, semicolon);
5759 } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
5760 if (keyword != null) {
5761 if (_tokenMatchesString(keyword, SYNC) && star == null) {
5762 _reportErrorForToken(
5763 ParserErrorCode.MISSING_STAR_AFTER_SYNC, keyword);
5764 }
5765 }
5766 if (!_parseFunctionBodies) {
5767 _skipBlock();
5768 return new EmptyFunctionBody(
5769 _createSyntheticToken(TokenType.SEMICOLON));
5770 }
5771 return new BlockFunctionBody(keyword, star, parseBlock());
5772 } else {
5773 // Invalid function body
5774 _reportErrorForCurrentToken(emptyErrorCode);
5775 return new EmptyFunctionBody(
5776 _createSyntheticToken(TokenType.SEMICOLON));
5777 }
5778 } finally {
5779 _inAsync = wasInAsync;
5780 _inGenerator = wasInGenerator;
5781 _inLoop = wasInLoop;
5782 _inSwitch = wasInSwitch;
5783 }
5784 }
5785
5786 /**
5787 * Parse a function declaration. The [commentAndMetadata] is the documentation
5788 * comment and metadata to be associated with the declaration. The
5789 * [externalKeyword] is the 'external' keyword, or `null` if the function is
5790 * not external. The [returnType] is the return type, or `null` if there is no
5791 * return type. The [isStatement] is `true` if the function declaration is
5792 * being parsed as a statement. Return the function declaration that was
5793 * parsed.
5794 *
5795 * functionDeclaration ::=
5796 * functionSignature functionBody
5797 * | returnType? getOrSet identifier formalParameterList functionBody
5798 */
5799 FunctionDeclaration _parseFunctionDeclaration(
5800 CommentAndMetadata commentAndMetadata, Token externalKeyword,
5801 TypeName returnType) {
5802 Token keyword = null;
5803 bool isGetter = false;
5804 if (_matchesKeyword(Keyword.GET) &&
5805 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
5806 keyword = getAndAdvance();
5807 isGetter = true;
5808 } else if (_matchesKeyword(Keyword.SET) &&
5809 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
5810 keyword = getAndAdvance();
5811 }
5812 SimpleIdentifier name = parseSimpleIdentifier();
5813 TypeParameterList typeParameters = null;
5814 if (parseGenericMethods && _matches(TokenType.LT)) {
5815 typeParameters = parseTypeParameterList();
5816 }
5817 FormalParameterList parameters = null;
5818 if (!isGetter) {
5819 if (_matches(TokenType.OPEN_PAREN)) {
5820 parameters = parseFormalParameterList();
5821 _validateFormalParameterList(parameters);
5822 } else {
5823 _reportErrorForCurrentToken(
5824 ParserErrorCode.MISSING_FUNCTION_PARAMETERS);
5825 parameters = new FormalParameterList(
5826 _createSyntheticToken(TokenType.OPEN_PAREN), null, null, null,
5827 _createSyntheticToken(TokenType.CLOSE_PAREN));
5828 }
5829 } else if (_matches(TokenType.OPEN_PAREN)) {
5830 _reportErrorForCurrentToken(ParserErrorCode.GETTER_WITH_PARAMETERS);
5831 parseFormalParameterList();
5832 }
5833 FunctionBody body;
5834 if (externalKeyword == null) {
5835 body = _parseFunctionBody(
5836 false, ParserErrorCode.MISSING_FUNCTION_BODY, false);
5837 } else {
5838 body = new EmptyFunctionBody(_expect(TokenType.SEMICOLON));
5839 }
5840 // if (!isStatement && matches(TokenType.SEMICOLON)) {
5841 // // TODO(brianwilkerson) Improve this error message.
5842 // reportError(ParserErrorCode.UNEXPECTED_TOKEN, currentToken.getLexeme ());
5843 // advance();
5844 // }
5845 return new FunctionDeclaration(commentAndMetadata.comment,
5846 commentAndMetadata.metadata, externalKeyword, returnType, keyword, name,
5847 new FunctionExpression(typeParameters, parameters, body));
5848 }
5849
5850 /**
5851 * Parse a function declaration statement. Return the function declaration
5852 * statement that was parsed.
5853 *
5854 * functionDeclarationStatement ::=
5855 * functionSignature functionBody
5856 */
5857 Statement _parseFunctionDeclarationStatement() {
5858 Modifiers modifiers = _parseModifiers();
5859 _validateModifiersForFunctionDeclarationStatement(modifiers);
5860 return _parseFunctionDeclarationStatementAfterReturnType(
5861 _parseCommentAndMetadata(), _parseOptionalReturnType());
5862 }
5863
5864 /**
5865 * Parse a function declaration statement. The [commentAndMetadata] is the
5866 * documentation comment and metadata to be associated with the declaration.
5867 * The [returnType] is the return type, or `null` if there is no return type.
5868 * Return the function declaration statement that was parsed.
5869 *
5870 * functionDeclarationStatement ::=
5871 * functionSignature functionBody
5872 */
5873 Statement _parseFunctionDeclarationStatementAfterReturnType(
5874 CommentAndMetadata commentAndMetadata, TypeName returnType) {
5875 FunctionDeclaration declaration =
5876 _parseFunctionDeclaration(commentAndMetadata, null, returnType);
5877 Token propertyKeyword = declaration.propertyKeyword;
5878 if (propertyKeyword != null) {
5879 if ((propertyKeyword as KeywordToken).keyword == Keyword.GET) {
5880 _reportErrorForToken(
5881 ParserErrorCode.GETTER_IN_FUNCTION, propertyKeyword);
5882 } else {
5883 _reportErrorForToken(
5884 ParserErrorCode.SETTER_IN_FUNCTION, propertyKeyword);
5885 }
5886 }
5887 return new FunctionDeclarationStatement(declaration);
5888 }
5889
5890 /**
5891 * Parse a function type alias. The [commentAndMetadata] is the metadata to be
5892 * associated with the member. The [keyword] is the token representing the
5893 * 'typedef' keyword. Return the function type alias that was parsed.
5894 *
5895 * functionTypeAlias ::=
5896 * functionPrefix typeParameterList? formalParameterList ';'
5897 *
5898 * functionPrefix ::=
5899 * returnType? name
5900 */
5901 FunctionTypeAlias _parseFunctionTypeAlias(
5902 CommentAndMetadata commentAndMetadata, Token keyword) {
5903 TypeName returnType = null;
5904 if (hasReturnTypeInTypeAlias) {
5905 returnType = parseReturnType();
5906 }
5907 SimpleIdentifier name = parseSimpleIdentifier();
5908 TypeParameterList typeParameters = null;
5909 if (_matches(TokenType.LT)) {
5910 typeParameters = parseTypeParameterList();
5911 }
5912 if (_matches(TokenType.SEMICOLON) || _matches(TokenType.EOF)) {
5913 _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS);
5914 FormalParameterList parameters = new FormalParameterList(
5915 _createSyntheticToken(TokenType.OPEN_PAREN), null, null, null,
5916 _createSyntheticToken(TokenType.CLOSE_PAREN));
5917 Token semicolon = _expect(TokenType.SEMICOLON);
5918 return new FunctionTypeAlias(commentAndMetadata.comment,
5919 commentAndMetadata.metadata, keyword, returnType, name,
5920 typeParameters, parameters, semicolon);
5921 } else if (!_matches(TokenType.OPEN_PAREN)) {
5922 _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS);
5923 // TODO(brianwilkerson) Recover from this error. At the very least we
5924 // should skip to the start of the next valid compilation unit member,
5925 // allowing for the possibility of finding the typedef parameters before
5926 // that point.
5927 return new FunctionTypeAlias(commentAndMetadata.comment,
5928 commentAndMetadata.metadata, keyword, returnType, name,
5929 typeParameters, new FormalParameterList(
5930 _createSyntheticToken(TokenType.OPEN_PAREN), null, null, null,
5931 _createSyntheticToken(TokenType.CLOSE_PAREN)),
5932 _createSyntheticToken(TokenType.SEMICOLON));
5933 }
5934 FormalParameterList parameters = parseFormalParameterList();
5935 _validateFormalParameterList(parameters);
5936 Token semicolon = _expect(TokenType.SEMICOLON);
5937 return new FunctionTypeAlias(commentAndMetadata.comment,
5938 commentAndMetadata.metadata, keyword, returnType, name, typeParameters,
5939 parameters, semicolon);
5940 }
5941
5942 /**
5943 * Parse a getter. The [commentAndMetadata] is the documentation comment and
5944 * metadata to be associated with the declaration. The externalKeyword] is the
5945 * 'external' token. The staticKeyword] is the static keyword, or `null` if
5946 * the getter is not static. The [returnType] the return type that has already
5947 * been parsed, or `null` if there was no return type. Return the getter that
5948 * was parsed.
5949 *
5950 * getter ::=
5951 * getterSignature functionBody?
5952 *
5953 * getterSignature ::=
5954 * 'external'? 'static'? returnType? 'get' identifier
5955 */
5956 MethodDeclaration _parseGetter(CommentAndMetadata commentAndMetadata,
5957 Token externalKeyword, Token staticKeyword, TypeName returnType) {
5958 Token propertyKeyword = _expectKeyword(Keyword.GET);
5959 SimpleIdentifier name = parseSimpleIdentifier();
5960 if (_matches(TokenType.OPEN_PAREN) &&
5961 _tokenMatches(_peek(), TokenType.CLOSE_PAREN)) {
5962 _reportErrorForCurrentToken(ParserErrorCode.GETTER_WITH_PARAMETERS);
5963 _advance();
5964 _advance();
5965 }
5966 FunctionBody body = _parseFunctionBody(
5967 externalKeyword != null || staticKeyword == null,
5968 ParserErrorCode.STATIC_GETTER_WITHOUT_BODY, false);
5969 if (externalKeyword != null && body is! EmptyFunctionBody) {
5970 _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_GETTER_WITH_BODY);
5971 }
5972 return new MethodDeclaration(commentAndMetadata.comment,
5973 commentAndMetadata.metadata, externalKeyword, staticKeyword, returnType,
5974 propertyKeyword, null, name, null, null, body);
5975 }
5976
5977 /**
5978 * Parse a list of identifiers. Return the list of identifiers that were
5979 * parsed.
5980 *
5981 * identifierList ::=
5982 * identifier (',' identifier)*
5983 */
5984 List<SimpleIdentifier> _parseIdentifierList() {
5985 List<SimpleIdentifier> identifiers = new List<SimpleIdentifier>();
5986 identifiers.add(parseSimpleIdentifier());
5987 while (_matches(TokenType.COMMA)) {
5988 _advance();
5989 identifiers.add(parseSimpleIdentifier());
5990 }
5991 return identifiers;
5992 }
5993
5994 /**
5995 * Parse an if statement. Return the if statement that was parsed.
5996 *
5997 * ifStatement ::=
5998 * 'if' '(' expression ')' statement ('else' statement)?
5999 */
6000 Statement _parseIfStatement() {
6001 Token ifKeyword = _expectKeyword(Keyword.IF);
6002 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
6003 Expression condition = parseExpression2();
6004 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
6005 Statement thenStatement = parseStatement2();
6006 Token elseKeyword = null;
6007 Statement elseStatement = null;
6008 if (_matchesKeyword(Keyword.ELSE)) {
6009 elseKeyword = getAndAdvance();
6010 elseStatement = parseStatement2();
6011 }
6012 return new IfStatement(ifKeyword, leftParenthesis, condition,
6013 rightParenthesis, thenStatement, elseKeyword, elseStatement);
6014 }
6015
6016 /**
6017 * Parse an import directive. The [commentAndMetadata] is the metadata to be
6018 * associated with the directive. Return the import directive that was parsed.
6019 *
6020 * importDirective ::=
6021 * metadata 'import' stringLiteral (deferred)? ('as' identifier)? comb inator*';'
6022 */
6023 ImportDirective _parseImportDirective(CommentAndMetadata commentAndMetadata) {
6024 Token importKeyword = _expectKeyword(Keyword.IMPORT);
6025 StringLiteral libraryUri = _parseUri();
6026 Token deferredToken = null;
6027 Token asToken = null;
6028 SimpleIdentifier prefix = null;
6029 if (_matchesKeyword(Keyword.DEFERRED)) {
6030 deferredToken = getAndAdvance();
6031 }
6032 if (_matchesKeyword(Keyword.AS)) {
6033 asToken = getAndAdvance();
6034 prefix = parseSimpleIdentifier();
6035 } else if (deferredToken != null) {
6036 _reportErrorForCurrentToken(
6037 ParserErrorCode.MISSING_PREFIX_IN_DEFERRED_IMPORT);
6038 } else if (!_matches(TokenType.SEMICOLON) &&
6039 !_matchesString(_SHOW) &&
6040 !_matchesString(_HIDE)) {
6041 Token nextToken = _peek();
6042 if (_tokenMatchesKeyword(nextToken, Keyword.AS) ||
6043 _tokenMatchesString(nextToken, _SHOW) ||
6044 _tokenMatchesString(nextToken, _HIDE)) {
6045 _reportErrorForCurrentToken(
6046 ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken]);
6047 _advance();
6048 if (_matchesKeyword(Keyword.AS)) {
6049 asToken = getAndAdvance();
6050 prefix = parseSimpleIdentifier();
6051 }
6052 }
6053 }
6054 List<Combinator> combinators = _parseCombinators();
6055 Token semicolon = _expectSemicolon();
6056 return new ImportDirective(commentAndMetadata.comment,
6057 commentAndMetadata.metadata, importKeyword, libraryUri, deferredToken,
6058 asToken, prefix, combinators, semicolon);
6059 }
6060
6061 /**
6062 * Parse a list of initialized identifiers. The [commentAndMetadata] is the
6063 * documentation comment and metadata to be associated with the declaration.
6064 * The [staticKeyword] is the static keyword, or `null` if the getter is not
6065 * static. The [keyword] is the token representing the 'final', 'const' or
6066 * 'var' keyword, or `null` if there is no keyword. The [type] is the type
6067 * that has already been parsed, or `null` if 'var' was provided. Return the
6068 * getter that was parsed.
6069 *
6070 * ?? ::=
6071 * 'static'? ('var' | type) initializedIdentifierList ';'
6072 * | 'final' type? initializedIdentifierList ';'
6073 *
6074 * initializedIdentifierList ::=
6075 * initializedIdentifier (',' initializedIdentifier)*
6076 *
6077 * initializedIdentifier ::=
6078 * identifier ('=' expression)?
6079 */
6080 FieldDeclaration _parseInitializedIdentifierList(
6081 CommentAndMetadata commentAndMetadata, Token staticKeyword, Token keyword,
6082 TypeName type) {
6083 VariableDeclarationList fieldList =
6084 _parseVariableDeclarationListAfterType(null, keyword, type);
6085 return new FieldDeclaration(commentAndMetadata.comment,
6086 commentAndMetadata.metadata, staticKeyword, fieldList,
6087 _expect(TokenType.SEMICOLON));
6088 }
6089
6090 /**
6091 * Parse an instance creation expression. The [keyword] is the 'new' or
6092 * 'const' keyword that introduces the expression. Return the instance
6093 * creation expression that was parsed.
6094 *
6095 * instanceCreationExpression ::=
6096 * ('new' | 'const') type ('.' identifier)? argumentList
6097 */
6098 InstanceCreationExpression _parseInstanceCreationExpression(Token keyword) {
6099 ConstructorName constructorName = parseConstructorName();
6100 ArgumentList argumentList = parseArgumentList();
6101 return new InstanceCreationExpression(
6102 keyword, constructorName, argumentList);
6103 }
6104
6105 /**
6106 * Parse a library directive. The [commentAndMetadata] is the metadata to be
6107 * associated with the directive. Return the library directive that was
6108 * parsed.
6109 *
6110 * libraryDirective ::=
6111 * metadata 'library' identifier ';'
6112 */
6113 LibraryDirective _parseLibraryDirective(
6114 CommentAndMetadata commentAndMetadata) {
6115 Token keyword = _expectKeyword(Keyword.LIBRARY);
6116 LibraryIdentifier libraryName = _parseLibraryName(
6117 ParserErrorCode.MISSING_NAME_IN_LIBRARY_DIRECTIVE, keyword);
6118 Token semicolon = _expect(TokenType.SEMICOLON);
6119 return new LibraryDirective(commentAndMetadata.comment,
6120 commentAndMetadata.metadata, keyword, libraryName, semicolon);
6121 }
6122
6123 /**
6124 * Parse a library name. The [missingNameError] is the error code to be used
6125 * if the library name is missing. The [missingNameToken] is the token
6126 * associated with the error produced if the library name is missing. Return
6127 * the library name that was parsed.
6128 *
6129 * libraryName ::=
6130 * libraryIdentifier
6131 */
6132 LibraryIdentifier _parseLibraryName(
6133 ParserErrorCode missingNameError, Token missingNameToken) {
6134 if (_matchesIdentifier()) {
6135 return parseLibraryIdentifier();
6136 } else if (_matches(TokenType.STRING)) {
6137 // TODO(brianwilkerson) Recovery: This should be extended to handle
6138 // arbitrary tokens until we can find a token that can start a compilation
6139 // unit member.
6140 StringLiteral string = parseStringLiteral();
6141 _reportErrorForNode(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, string);
6142 } else {
6143 _reportErrorForToken(missingNameError, missingNameToken);
6144 }
6145 List<SimpleIdentifier> components = new List<SimpleIdentifier>();
6146 components.add(_createSyntheticIdentifier());
6147 return new LibraryIdentifier(components);
6148 }
6149
6150 /**
6151 * Parse a list literal. The [modifier] is the 'const' modifier appearing
6152 * before the literal, or `null` if there is no modifier. The [typeArguments]
6153 * is the type arguments appearing before the literal, or `null` if there are
6154 * no type arguments. Return the list literal that was parsed.
6155 *
6156 * listLiteral ::=
6157 * 'const'? typeArguments? '[' (expressionList ','?)? ']'
6158 */
6159 ListLiteral _parseListLiteral(
6160 Token modifier, TypeArgumentList typeArguments) {
6161 // may be empty list literal
6162 if (_matches(TokenType.INDEX)) {
6163 BeginToken leftBracket = _createToken(
6164 _currentToken, TokenType.OPEN_SQUARE_BRACKET, isBegin: true);
6165 Token rightBracket =
6166 new Token(TokenType.CLOSE_SQUARE_BRACKET, _currentToken.offset + 1);
6167 leftBracket.endToken = rightBracket;
6168 rightBracket.setNext(_currentToken.next);
6169 leftBracket.setNext(rightBracket);
6170 _currentToken.previous.setNext(leftBracket);
6171 _currentToken = _currentToken.next;
6172 return new ListLiteral(
6173 modifier, typeArguments, leftBracket, null, rightBracket);
6174 }
6175 // open
6176 Token leftBracket = _expect(TokenType.OPEN_SQUARE_BRACKET);
6177 if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) {
6178 return new ListLiteral(
6179 modifier, typeArguments, leftBracket, null, getAndAdvance());
6180 }
6181 bool wasInInitializer = _inInitializer;
6182 _inInitializer = false;
6183 try {
6184 List<Expression> elements = new List<Expression>();
6185 elements.add(parseExpression2());
6186 while (_optional(TokenType.COMMA)) {
6187 if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) {
6188 return new ListLiteral(
6189 modifier, typeArguments, leftBracket, elements, getAndAdvance());
6190 }
6191 elements.add(parseExpression2());
6192 }
6193 Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
6194 return new ListLiteral(
6195 modifier, typeArguments, leftBracket, elements, rightBracket);
6196 } finally {
6197 _inInitializer = wasInInitializer;
6198 }
6199 }
6200
6201 /**
6202 * Parse a list or map literal. The [modifier] is the 'const' modifier
6203 * appearing before the literal, or `null` if there is no modifier. Return the
6204 * list or map literal that was parsed.
6205 *
6206 * listOrMapLiteral ::=
6207 * listLiteral
6208 * | mapLiteral
6209 */
6210 TypedLiteral _parseListOrMapLiteral(Token modifier) {
6211 TypeArgumentList typeArguments = null;
6212 if (_matches(TokenType.LT)) {
6213 typeArguments = parseTypeArgumentList();
6214 }
6215 if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
6216 return _parseMapLiteral(modifier, typeArguments);
6217 } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
6218 _matches(TokenType.INDEX)) {
6219 return _parseListLiteral(modifier, typeArguments);
6220 }
6221 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL);
6222 return new ListLiteral(modifier, typeArguments,
6223 _createSyntheticToken(TokenType.OPEN_SQUARE_BRACKET), null,
6224 _createSyntheticToken(TokenType.CLOSE_SQUARE_BRACKET));
6225 }
6226
6227 /**
6228 * Parse a logical and expression. Return the logical and expression that was
6229 * parsed.
6230 *
6231 * logicalAndExpression ::=
6232 * equalityExpression ('&&' equalityExpression)*
6233 */
6234 Expression _parseLogicalAndExpression() {
6235 Expression expression = _parseEqualityExpression();
6236 while (_matches(TokenType.AMPERSAND_AMPERSAND)) {
6237 Token operator = getAndAdvance();
6238 expression = new BinaryExpression(
6239 expression, operator, _parseEqualityExpression());
6240 }
6241 return expression;
6242 }
6243
6244 /**
6245 * Parse a map literal. The [modifier] is the 'const' modifier appearing
6246 * before the literal, or `null` if there is no modifier. The [typeArguments]
6247 * is the type arguments that were declared, or `null` if there are no type
6248 * arguments. Return the map literal that was parsed.
6249 *
6250 * mapLiteral ::=
6251 * 'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
6252 */
6253 MapLiteral _parseMapLiteral(Token modifier, TypeArgumentList typeArguments) {
6254 Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
6255 List<MapLiteralEntry> entries = new List<MapLiteralEntry>();
6256 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
6257 return new MapLiteral(
6258 modifier, typeArguments, leftBracket, entries, getAndAdvance());
6259 }
6260 bool wasInInitializer = _inInitializer;
6261 _inInitializer = false;
6262 try {
6263 entries.add(parseMapLiteralEntry());
6264 while (_optional(TokenType.COMMA)) {
6265 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
6266 return new MapLiteral(
6267 modifier, typeArguments, leftBracket, entries, getAndAdvance());
6268 }
6269 entries.add(parseMapLiteralEntry());
6270 }
6271 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
6272 return new MapLiteral(
6273 modifier, typeArguments, leftBracket, entries, rightBracket);
6274 } finally {
6275 _inInitializer = wasInInitializer;
6276 }
6277 }
6278
6279 /**
6280 * Parse a method declaration. The [commentAndMetadata] is the documentation
6281 * comment and metadata to be associated with the declaration. The
6282 * [externalKeyword] is the 'external' token. The [staticKeyword] is the
6283 * static keyword, or `null` if the getter is not static. The [returnType] is
6284 * the return type of the method. The [name] is the name of the method. The
6285 * [parameters] is the parameters to the method. Return the method declaration
6286 * that was parsed.
6287 *
6288 * functionDeclaration ::=
6289 * ('external' 'static'?)? functionSignature functionBody
6290 * | 'external'? functionSignature ';'
6291 */
6292 MethodDeclaration _parseMethodDeclarationAfterParameters(
6293 CommentAndMetadata commentAndMetadata, Token externalKeyword,
6294 Token staticKeyword, TypeName returnType, SimpleIdentifier name,
6295 TypeParameterList typeParameters, FormalParameterList parameters) {
6296 FunctionBody body = _parseFunctionBody(
6297 externalKeyword != null || staticKeyword == null,
6298 ParserErrorCode.MISSING_FUNCTION_BODY, false);
6299 if (externalKeyword != null) {
6300 if (body is! EmptyFunctionBody) {
6301 _reportErrorForNode(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, body);
6302 }
6303 } else if (staticKeyword != null) {
6304 if (body is EmptyFunctionBody && _parseFunctionBodies) {
6305 _reportErrorForNode(ParserErrorCode.ABSTRACT_STATIC_METHOD, body);
6306 }
6307 }
6308 return new MethodDeclaration(commentAndMetadata.comment,
6309 commentAndMetadata.metadata, externalKeyword, staticKeyword, returnType,
6310 null, null, name, typeParameters, parameters, body);
6311 }
6312
6313 /**
6314 * Parse a method declaration. The [commentAndMetadata] is the documentation
6315 * comment and metadata to be associated with the declaration. The
6316 * [externalKeyword] is the 'external' token. The [staticKeyword] is the
6317 * static keyword, or `null` if the getter is not static. The [returnType] is
6318 * the return type of the method. Return the method declaration that was
6319 * parsed.
6320 *
6321 * functionDeclaration ::=
6322 * 'external'? 'static'? functionSignature functionBody
6323 * | 'external'? functionSignature ';'
6324 */
6325 MethodDeclaration _parseMethodDeclarationAfterReturnType(
6326 CommentAndMetadata commentAndMetadata, Token externalKeyword,
6327 Token staticKeyword, TypeName returnType) {
6328 SimpleIdentifier methodName = parseSimpleIdentifier();
6329 TypeParameterList typeParameters = null;
6330 if (parseGenericMethods && _matches(TokenType.LT)) {
6331 typeParameters = parseTypeParameterList();
6332 }
6333 FormalParameterList parameters;
6334 if (!_matches(TokenType.OPEN_PAREN) &&
6335 (_matches(TokenType.OPEN_CURLY_BRACKET) ||
6336 _matches(TokenType.FUNCTION))) {
6337 _reportErrorForToken(
6338 ParserErrorCode.MISSING_METHOD_PARAMETERS, _currentToken.previous);
6339 parameters = new FormalParameterList(
6340 _createSyntheticToken(TokenType.OPEN_PAREN), null, null, null,
6341 _createSyntheticToken(TokenType.CLOSE_PAREN));
6342 } else {
6343 parameters = parseFormalParameterList();
6344 }
6345 _validateFormalParameterList(parameters);
6346 return _parseMethodDeclarationAfterParameters(commentAndMetadata,
6347 externalKeyword, staticKeyword, returnType, methodName, typeParameters,
6348 parameters);
6349 }
6350
6351 /**
6352 * Parse the modifiers preceding a declaration. This method allows the
6353 * modifiers to appear in any order but does generate errors for duplicated
6354 * modifiers. Checks for other problems, such as having the modifiers appear
6355 * in the wrong order or specifying both 'const' and 'final', are reported in
6356 * one of the methods whose name is prefixed with `validateModifiersFor`.
6357 * Return the modifiers that were parsed.
6358 *
6359 * modifiers ::=
6360 * ('abstract' | 'const' | 'external' | 'factory' | 'final' | 'static' | 'var')*
6361 */
6362 Modifiers _parseModifiers() {
6363 Modifiers modifiers = new Modifiers();
6364 bool progress = true;
6365 while (progress) {
6366 if (_tokenMatches(_peek(), TokenType.PERIOD) ||
6367 _tokenMatches(_peek(), TokenType.LT) ||
6368 _tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
6369 return modifiers;
6370 }
6371 if (_matchesKeyword(Keyword.ABSTRACT)) {
6372 if (modifiers.abstractKeyword != null) {
6373 _reportErrorForCurrentToken(
6374 ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
6375 _advance();
6376 } else {
6377 modifiers.abstractKeyword = getAndAdvance();
6378 }
6379 } else if (_matchesKeyword(Keyword.CONST)) {
6380 if (modifiers.constKeyword != null) {
6381 _reportErrorForCurrentToken(
6382 ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
6383 _advance();
6384 } else {
6385 modifiers.constKeyword = getAndAdvance();
6386 }
6387 } else if (_matchesKeyword(Keyword.EXTERNAL) &&
6388 !_tokenMatches(_peek(), TokenType.PERIOD) &&
6389 !_tokenMatches(_peek(), TokenType.LT)) {
6390 if (modifiers.externalKeyword != null) {
6391 _reportErrorForCurrentToken(
6392 ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
6393 _advance();
6394 } else {
6395 modifiers.externalKeyword = getAndAdvance();
6396 }
6397 } else if (_matchesKeyword(Keyword.FACTORY) &&
6398 !_tokenMatches(_peek(), TokenType.PERIOD) &&
6399 !_tokenMatches(_peek(), TokenType.LT)) {
6400 if (modifiers.factoryKeyword != null) {
6401 _reportErrorForCurrentToken(
6402 ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
6403 _advance();
6404 } else {
6405 modifiers.factoryKeyword = getAndAdvance();
6406 }
6407 } else if (_matchesKeyword(Keyword.FINAL)) {
6408 if (modifiers.finalKeyword != null) {
6409 _reportErrorForCurrentToken(
6410 ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
6411 _advance();
6412 } else {
6413 modifiers.finalKeyword = getAndAdvance();
6414 }
6415 } else if (_matchesKeyword(Keyword.STATIC) &&
6416 !_tokenMatches(_peek(), TokenType.PERIOD) &&
6417 !_tokenMatches(_peek(), TokenType.LT)) {
6418 if (modifiers.staticKeyword != null) {
6419 _reportErrorForCurrentToken(
6420 ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
6421 _advance();
6422 } else {
6423 modifiers.staticKeyword = getAndAdvance();
6424 }
6425 } else if (_matchesKeyword(Keyword.VAR)) {
6426 if (modifiers.varKeyword != null) {
6427 _reportErrorForCurrentToken(
6428 ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
6429 _advance();
6430 } else {
6431 modifiers.varKeyword = getAndAdvance();
6432 }
6433 } else {
6434 progress = false;
6435 }
6436 }
6437 return modifiers;
6438 }
6439
6440 /**
6441 * Parse a multiplicative expression. Return the multiplicative expression
6442 * that was parsed.
6443 *
6444 * multiplicativeExpression ::=
6445 * unaryExpression (multiplicativeOperator unaryExpression)*
6446 * | 'super' (multiplicativeOperator unaryExpression)+
6447 */
6448 Expression _parseMultiplicativeExpression() {
6449 Expression expression;
6450 if (_matchesKeyword(Keyword.SUPER) &&
6451 _currentToken.next.type.isMultiplicativeOperator) {
6452 expression = new SuperExpression(getAndAdvance());
6453 } else {
6454 expression = _parseUnaryExpression();
6455 }
6456 while (_currentToken.type.isMultiplicativeOperator) {
6457 Token operator = getAndAdvance();
6458 expression =
6459 new BinaryExpression(expression, operator, _parseUnaryExpression());
6460 }
6461 return expression;
6462 }
6463
6464 /**
6465 * Parse a class native clause. Return the native clause that was parsed.
6466 *
6467 * classNativeClause ::=
6468 * 'native' name
6469 */
6470 NativeClause _parseNativeClause() {
6471 Token keyword = getAndAdvance();
6472 StringLiteral name = parseStringLiteral();
6473 return new NativeClause(keyword, name);
6474 }
6475
6476 /**
6477 * Parse a new expression. Return the new expression that was parsed.
6478 *
6479 * newExpression ::=
6480 * instanceCreationExpression
6481 */
6482 InstanceCreationExpression _parseNewExpression() =>
6483 _parseInstanceCreationExpression(_expectKeyword(Keyword.NEW));
6484
6485 /**
6486 * Parse a non-labeled statement. Return the non-labeled statement that was
6487 * parsed.
6488 *
6489 * nonLabeledStatement ::=
6490 * block
6491 * | assertStatement
6492 * | breakStatement
6493 * | continueStatement
6494 * | doStatement
6495 * | forStatement
6496 * | ifStatement
6497 * | returnStatement
6498 * | switchStatement
6499 * | tryStatement
6500 * | whileStatement
6501 * | variableDeclarationList ';'
6502 * | expressionStatement
6503 * | functionSignature functionBody
6504 */
6505 Statement _parseNonLabeledStatement() {
6506 // TODO(brianwilkerson) Pass the comment and metadata on where appropriate.
6507 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
6508 if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
6509 if (_tokenMatches(_peek(), TokenType.STRING)) {
6510 Token afterString = _skipStringLiteral(_currentToken.next);
6511 if (afterString != null && afterString.type == TokenType.COLON) {
6512 return new ExpressionStatement(
6513 parseExpression2(), _expect(TokenType.SEMICOLON));
6514 }
6515 }
6516 return parseBlock();
6517 } else if (_matches(TokenType.KEYWORD) &&
6518 !(_currentToken as KeywordToken).keyword.isPseudoKeyword) {
6519 Keyword keyword = (_currentToken as KeywordToken).keyword;
6520 // TODO(jwren) compute some metrics to figure out a better order for this
6521 // if-then sequence to optimize performance
6522 if (keyword == Keyword.ASSERT) {
6523 return _parseAssertStatement();
6524 } else if (keyword == Keyword.BREAK) {
6525 return _parseBreakStatement();
6526 } else if (keyword == Keyword.CONTINUE) {
6527 return _parseContinueStatement();
6528 } else if (keyword == Keyword.DO) {
6529 return _parseDoStatement();
6530 } else if (keyword == Keyword.FOR) {
6531 return _parseForStatement();
6532 } else if (keyword == Keyword.IF) {
6533 return _parseIfStatement();
6534 } else if (keyword == Keyword.RETHROW) {
6535 return new ExpressionStatement(
6536 _parseRethrowExpression(), _expect(TokenType.SEMICOLON));
6537 } else if (keyword == Keyword.RETURN) {
6538 return _parseReturnStatement();
6539 } else if (keyword == Keyword.SWITCH) {
6540 return _parseSwitchStatement();
6541 } else if (keyword == Keyword.THROW) {
6542 return new ExpressionStatement(
6543 _parseThrowExpression(), _expect(TokenType.SEMICOLON));
6544 } else if (keyword == Keyword.TRY) {
6545 return _parseTryStatement();
6546 } else if (keyword == Keyword.WHILE) {
6547 return _parseWhileStatement();
6548 } else if (keyword == Keyword.VAR || keyword == Keyword.FINAL) {
6549 return _parseVariableDeclarationStatementAfterMetadata(
6550 commentAndMetadata);
6551 } else if (keyword == Keyword.VOID) {
6552 TypeName returnType = parseReturnType();
6553 if (_matchesIdentifier() &&
6554 _peek().matchesAny([
6555 TokenType.OPEN_PAREN,
6556 TokenType.OPEN_CURLY_BRACKET,
6557 TokenType.FUNCTION
6558 ])) {
6559 return _parseFunctionDeclarationStatementAfterReturnType(
6560 commentAndMetadata, returnType);
6561 } else {
6562 //
6563 // We have found an error of some kind. Try to recover.
6564 //
6565 if (_matchesIdentifier()) {
6566 if (_peek().matchesAny(
6567 [TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
6568 //
6569 // We appear to have a variable declaration with a type of "void".
6570 //
6571 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
6572 return _parseVariableDeclarationStatementAfterMetadata(
6573 commentAndMetadata);
6574 }
6575 } else if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
6576 //
6577 // We appear to have found an incomplete statement at the end of a
6578 // block. Parse it as a variable declaration.
6579 //
6580 return _parseVariableDeclarationStatementAfterType(
6581 commentAndMetadata, null, returnType);
6582 }
6583 _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
6584 // TODO(brianwilkerson) Recover from this error.
6585 return new EmptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
6586 }
6587 } else if (keyword == Keyword.CONST) {
6588 if (_peek().matchesAny([
6589 TokenType.LT,
6590 TokenType.OPEN_CURLY_BRACKET,
6591 TokenType.OPEN_SQUARE_BRACKET,
6592 TokenType.INDEX
6593 ])) {
6594 return new ExpressionStatement(
6595 parseExpression2(), _expect(TokenType.SEMICOLON));
6596 } else if (_tokenMatches(_peek(), TokenType.IDENTIFIER)) {
6597 Token afterType = _skipTypeName(_peek());
6598 if (afterType != null) {
6599 if (_tokenMatches(afterType, TokenType.OPEN_PAREN) ||
6600 (_tokenMatches(afterType, TokenType.PERIOD) &&
6601 _tokenMatches(afterType.next, TokenType.IDENTIFIER) &&
6602 _tokenMatches(afterType.next.next, TokenType.OPEN_PAREN))) {
6603 return new ExpressionStatement(
6604 parseExpression2(), _expect(TokenType.SEMICOLON));
6605 }
6606 }
6607 }
6608 return _parseVariableDeclarationStatementAfterMetadata(
6609 commentAndMetadata);
6610 } else if (keyword == Keyword.NEW ||
6611 keyword == Keyword.TRUE ||
6612 keyword == Keyword.FALSE ||
6613 keyword == Keyword.NULL ||
6614 keyword == Keyword.SUPER ||
6615 keyword == Keyword.THIS) {
6616 return new ExpressionStatement(
6617 parseExpression2(), _expect(TokenType.SEMICOLON));
6618 } else {
6619 //
6620 // We have found an error of some kind. Try to recover.
6621 //
6622 _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
6623 return new EmptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
6624 }
6625 } else if (_inGenerator && _matchesString(_YIELD)) {
6626 return _parseYieldStatement();
6627 } else if (_inAsync && _matchesString(_AWAIT)) {
6628 if (_tokenMatchesKeyword(_peek(), Keyword.FOR)) {
6629 return _parseForStatement();
6630 }
6631 return new ExpressionStatement(
6632 parseExpression2(), _expect(TokenType.SEMICOLON));
6633 } else if (_matchesString(_AWAIT) &&
6634 _tokenMatchesKeyword(_peek(), Keyword.FOR)) {
6635 Token awaitToken = _currentToken;
6636 Statement statement = _parseForStatement();
6637 if (statement is! ForStatement) {
6638 _reportErrorForToken(
6639 CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT, awaitToken);
6640 }
6641 return statement;
6642 } else if (_matches(TokenType.SEMICOLON)) {
6643 return _parseEmptyStatement();
6644 } else if (_isInitializedVariableDeclaration()) {
6645 return _parseVariableDeclarationStatementAfterMetadata(
6646 commentAndMetadata);
6647 } else if (_isFunctionDeclaration()) {
6648 return _parseFunctionDeclarationStatement();
6649 } else if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
6650 _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
6651 return new EmptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
6652 } else {
6653 return new ExpressionStatement(parseExpression2(), _expectSemicolon());
6654 }
6655 }
6656
6657 /**
6658 * Parse an operator declaration. The [commentAndMetadata] is the
6659 * documentation comment and metadata to be associated with the declaration.
6660 * The [externalKeyword] is the 'external' token. The [returnType] is the
6661 * return type that has already been parsed, or `null` if there was no return
6662 * type. Return the operator declaration that was parsed.
6663 *
6664 * operatorDeclaration ::=
6665 * operatorSignature (';' | functionBody)
6666 *
6667 * operatorSignature ::=
6668 * 'external'? returnType? 'operator' operator formalParameterList
6669 */
6670 MethodDeclaration _parseOperator(CommentAndMetadata commentAndMetadata,
6671 Token externalKeyword, TypeName returnType) {
6672 Token operatorKeyword;
6673 if (_matchesKeyword(Keyword.OPERATOR)) {
6674 operatorKeyword = getAndAdvance();
6675 } else {
6676 _reportErrorForToken(
6677 ParserErrorCode.MISSING_KEYWORD_OPERATOR, _currentToken);
6678 operatorKeyword = _createSyntheticKeyword(Keyword.OPERATOR);
6679 }
6680 if (!_currentToken.isUserDefinableOperator) {
6681 _reportErrorForCurrentToken(
6682 ParserErrorCode.NON_USER_DEFINABLE_OPERATOR, [_currentToken.lexeme]);
6683 }
6684 SimpleIdentifier name = new SimpleIdentifier(getAndAdvance());
6685 if (_matches(TokenType.EQ)) {
6686 Token previous = _currentToken.previous;
6687 if ((_tokenMatches(previous, TokenType.EQ_EQ) ||
6688 _tokenMatches(previous, TokenType.BANG_EQ)) &&
6689 _currentToken.offset == previous.offset + 2) {
6690 _reportErrorForCurrentToken(ParserErrorCode.INVALID_OPERATOR,
6691 ["${previous.lexeme}${_currentToken.lexeme}"]);
6692 _advance();
6693 }
6694 }
6695 FormalParameterList parameters = parseFormalParameterList();
6696 _validateFormalParameterList(parameters);
6697 FunctionBody body =
6698 _parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTION_BODY, false);
6699 if (externalKeyword != null && body is! EmptyFunctionBody) {
6700 _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY);
6701 }
6702 return new MethodDeclaration(commentAndMetadata.comment,
6703 commentAndMetadata.metadata, externalKeyword, null, returnType, null,
6704 operatorKeyword, name, null, parameters, body);
6705 }
6706
6707 /**
6708 * Parse a return type if one is given, otherwise return `null` without
6709 * advancing. Return the return type that was parsed.
6710 */
6711 TypeName _parseOptionalReturnType() {
6712 if (_matchesKeyword(Keyword.VOID)) {
6713 return parseReturnType();
6714 } else if (_matchesIdentifier() &&
6715 !_matchesKeyword(Keyword.GET) &&
6716 !_matchesKeyword(Keyword.SET) &&
6717 !_matchesKeyword(Keyword.OPERATOR) &&
6718 (_tokenMatchesIdentifier(_peek()) ||
6719 _tokenMatches(_peek(), TokenType.LT))) {
6720 return parseReturnType();
6721 } else if (_matchesIdentifier() &&
6722 _tokenMatches(_peek(), TokenType.PERIOD) &&
6723 _tokenMatchesIdentifier(_peekAt(2)) &&
6724 (_tokenMatchesIdentifier(_peekAt(3)) ||
6725 _tokenMatches(_peekAt(3), TokenType.LT))) {
6726 return parseReturnType();
6727 }
6728 return null;
6729 }
6730
6731 /**
6732 * Parse a part or part-of directive. The [commentAndMetadata] is the metadata
6733 * to be associated with the directive. Return the part or part-of directive
6734 * that was parsed.
6735 *
6736 * partDirective ::=
6737 * metadata 'part' stringLiteral ';'
6738 *
6739 * partOfDirective ::=
6740 * metadata 'part' 'of' identifier ';'
6741 */
6742 Directive _parsePartDirective(CommentAndMetadata commentAndMetadata) {
6743 Token partKeyword = _expectKeyword(Keyword.PART);
6744 if (_matchesString(_OF)) {
6745 Token ofKeyword = getAndAdvance();
6746 LibraryIdentifier libraryName = _parseLibraryName(
6747 ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE, ofKeyword);
6748 Token semicolon = _expect(TokenType.SEMICOLON);
6749 return new PartOfDirective(commentAndMetadata.comment,
6750 commentAndMetadata.metadata, partKeyword, ofKeyword, libraryName,
6751 semicolon);
6752 }
6753 StringLiteral partUri = _parseUri();
6754 Token semicolon = _expect(TokenType.SEMICOLON);
6755 return new PartDirective(commentAndMetadata.comment,
6756 commentAndMetadata.metadata, partKeyword, partUri, semicolon);
6757 }
6758
6759 /**
6760 * Parse a postfix expression. Return the postfix expression that was parsed.
6761 *
6762 * postfixExpression ::=
6763 * assignableExpression postfixOperator
6764 * | primary selector*
6765 *
6766 * selector ::=
6767 * assignableSelector
6768 * | argumentList
6769 */
6770 Expression _parsePostfixExpression() {
6771 Expression operand = _parseAssignableExpression(true);
6772 if (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
6773 _matches(TokenType.PERIOD) ||
6774 _matches(TokenType.QUESTION_PERIOD) ||
6775 _matches(TokenType.OPEN_PAREN) ||
6776 (parseGenericMethods && _matches(TokenType.LT))) {
6777 do {
6778 if (_isLikelyParameterList()) {
6779 TypeArgumentList typeArguments = null;
6780 if (_matches(TokenType.LT)) {
6781 typeArguments = parseTypeArgumentList();
6782 }
6783 ArgumentList argumentList = parseArgumentList();
6784 if (operand is PropertyAccess) {
6785 PropertyAccess access = operand as PropertyAccess;
6786 operand = new MethodInvocation(access.target, access.operator,
6787 access.propertyName, typeArguments, argumentList);
6788 } else {
6789 operand = new FunctionExpressionInvocation(
6790 operand, typeArguments, argumentList);
6791 }
6792 } else {
6793 operand = _parseAssignableSelector(operand, true);
6794 }
6795 } while (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
6796 _matches(TokenType.PERIOD) ||
6797 _matches(TokenType.QUESTION_PERIOD) ||
6798 _matches(TokenType.OPEN_PAREN));
6799 return operand;
6800 }
6801 if (!_currentToken.type.isIncrementOperator) {
6802 return operand;
6803 }
6804 _ensureAssignable(operand);
6805 Token operator = getAndAdvance();
6806 return new PostfixExpression(operand, operator);
6807 }
6808
6809 /**
6810 * Parse a primary expression. Return the primary expression that was parsed.
6811 *
6812 * primary ::=
6813 * thisExpression
6814 * | 'super' unconditionalAssignableSelector
6815 * | functionExpression
6816 * | literal
6817 * | identifier
6818 * | newExpression
6819 * | constObjectExpression
6820 * | '(' expression ')'
6821 * | argumentDefinitionTest
6822 *
6823 * literal ::=
6824 * nullLiteral
6825 * | booleanLiteral
6826 * | numericLiteral
6827 * | stringLiteral
6828 * | symbolLiteral
6829 * | mapLiteral
6830 * | listLiteral
6831 */
6832 Expression _parsePrimaryExpression() {
6833 if (_matchesKeyword(Keyword.THIS)) {
6834 return new ThisExpression(getAndAdvance());
6835 } else if (_matchesKeyword(Keyword.SUPER)) {
6836 // TODO(paulberry): verify with Gilad that "super" must be followed by
6837 // unconditionalAssignableSelector in this case.
6838 return _parseAssignableSelector(
6839 new SuperExpression(getAndAdvance()), false, allowConditional: false);
6840 } else if (_matchesKeyword(Keyword.NULL)) {
6841 return new NullLiteral(getAndAdvance());
6842 } else if (_matchesKeyword(Keyword.FALSE)) {
6843 return new BooleanLiteral(getAndAdvance(), false);
6844 } else if (_matchesKeyword(Keyword.TRUE)) {
6845 return new BooleanLiteral(getAndAdvance(), true);
6846 } else if (_matches(TokenType.DOUBLE)) {
6847 Token token = getAndAdvance();
6848 double value = 0.0;
6849 try {
6850 value = double.parse(token.lexeme);
6851 } on FormatException {
6852 // The invalid format should have been reported by the scanner.
6853 }
6854 return new DoubleLiteral(token, value);
6855 } else if (_matches(TokenType.HEXADECIMAL)) {
6856 Token token = getAndAdvance();
6857 int value = null;
6858 try {
6859 value = int.parse(token.lexeme.substring(2), radix: 16);
6860 } on FormatException {
6861 // The invalid format should have been reported by the scanner.
6862 }
6863 return new IntegerLiteral(token, value);
6864 } else if (_matches(TokenType.INT)) {
6865 Token token = getAndAdvance();
6866 int value = null;
6867 try {
6868 value = int.parse(token.lexeme);
6869 } on FormatException {
6870 // The invalid format should have been reported by the scanner.
6871 }
6872 return new IntegerLiteral(token, value);
6873 } else if (_matches(TokenType.STRING)) {
6874 return parseStringLiteral();
6875 } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
6876 return _parseMapLiteral(null, null);
6877 } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
6878 _matches(TokenType.INDEX)) {
6879 return _parseListLiteral(null, null);
6880 } else if (_matchesIdentifier()) {
6881 // TODO(brianwilkerson) The code below was an attempt to recover from an
6882 // error case, but it needs to be applied as a recovery only after we
6883 // know that parsing it as an identifier doesn't work. Leaving the code as
6884 // a reminder of how to recover.
6885 // if (isFunctionExpression(peek())) {
6886 // //
6887 // // Function expressions were allowed to have names at one point, but this is now illegal.
6888 // //
6889 // reportError(ParserErrorCode.NAMED_FUNCTION_EXPRESSION, getAndAdv ance());
6890 // return parseFunctionExpression();
6891 // }
6892 return parsePrefixedIdentifier();
6893 } else if (_matchesKeyword(Keyword.NEW)) {
6894 return _parseNewExpression();
6895 } else if (_matchesKeyword(Keyword.CONST)) {
6896 return _parseConstExpression();
6897 } else if (_matches(TokenType.OPEN_PAREN)) {
6898 if (_isFunctionExpression(_currentToken)) {
6899 return parseFunctionExpression();
6900 }
6901 Token leftParenthesis = getAndAdvance();
6902 bool wasInInitializer = _inInitializer;
6903 _inInitializer = false;
6904 try {
6905 Expression expression = parseExpression2();
6906 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
6907 return new ParenthesizedExpression(
6908 leftParenthesis, expression, rightParenthesis);
6909 } finally {
6910 _inInitializer = wasInInitializer;
6911 }
6912 } else if (_matches(TokenType.LT)) {
6913 return _parseListOrMapLiteral(null);
6914 } else if (_matches(TokenType.QUESTION) &&
6915 _tokenMatches(_peek(), TokenType.IDENTIFIER)) {
6916 _reportErrorForCurrentToken(
6917 ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
6918 _advance();
6919 return _parsePrimaryExpression();
6920 } else if (_matchesKeyword(Keyword.VOID)) {
6921 //
6922 // Recover from having a return type of "void" where a return type is not
6923 // expected.
6924 //
6925 // TODO(brianwilkerson) Improve this error message.
6926 _reportErrorForCurrentToken(
6927 ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
6928 _advance();
6929 return _parsePrimaryExpression();
6930 } else if (_matches(TokenType.HASH)) {
6931 return _parseSymbolLiteral();
6932 } else {
6933 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
6934 return _createSyntheticIdentifier();
6935 }
6936 }
6937
6938 /**
6939 * Parse a redirecting constructor invocation. Return the redirecting
6940 * constructor invocation that was parsed.
6941 *
6942 * redirectingConstructorInvocation ::=
6943 * 'this' ('.' identifier)? arguments
6944 */
6945 RedirectingConstructorInvocation _parseRedirectingConstructorInvocation() {
6946 Token keyword = _expectKeyword(Keyword.THIS);
6947 Token period = null;
6948 SimpleIdentifier constructorName = null;
6949 if (_matches(TokenType.PERIOD)) {
6950 period = getAndAdvance();
6951 constructorName = parseSimpleIdentifier();
6952 }
6953 ArgumentList argumentList = parseArgumentList();
6954 return new RedirectingConstructorInvocation(
6955 keyword, period, constructorName, argumentList);
6956 }
6957
6958 /**
6959 * Parse a relational expression. Return the relational expression that was
6960 * parsed.
6961 *
6962 * relationalExpression ::=
6963 * bitwiseOrExpression ('is' '!'? type | 'as' type | relationalOperato r bitwiseOrExpression)?
6964 * | 'super' relationalOperator bitwiseOrExpression
6965 */
6966 Expression _parseRelationalExpression() {
6967 if (_matchesKeyword(Keyword.SUPER) &&
6968 _currentToken.next.type.isRelationalOperator) {
6969 Expression expression = new SuperExpression(getAndAdvance());
6970 Token operator = getAndAdvance();
6971 expression = new BinaryExpression(
6972 expression, operator, parseBitwiseOrExpression());
6973 return expression;
6974 }
6975 Expression expression = parseBitwiseOrExpression();
6976 if (_matchesKeyword(Keyword.AS)) {
6977 Token asOperator = getAndAdvance();
6978 expression = new AsExpression(expression, asOperator, parseTypeName());
6979 } else if (_matchesKeyword(Keyword.IS)) {
6980 Token isOperator = getAndAdvance();
6981 Token notOperator = null;
6982 if (_matches(TokenType.BANG)) {
6983 notOperator = getAndAdvance();
6984 }
6985 expression = new IsExpression(
6986 expression, isOperator, notOperator, parseTypeName());
6987 } else if (_currentToken.type.isRelationalOperator) {
6988 Token operator = getAndAdvance();
6989 expression = new BinaryExpression(
6990 expression, operator, parseBitwiseOrExpression());
6991 }
6992 return expression;
6993 }
6994
6995 /**
6996 * Parse a rethrow expression. Return the rethrow expression that was parsed.
6997 *
6998 * rethrowExpression ::=
6999 * 'rethrow'
7000 */
7001 Expression _parseRethrowExpression() =>
7002 new RethrowExpression(_expectKeyword(Keyword.RETHROW));
7003
7004 /**
7005 * Parse a return statement. Return the return statement that was parsed.
7006 *
7007 * returnStatement ::=
7008 * 'return' expression? ';'
7009 */
7010 Statement _parseReturnStatement() {
7011 Token returnKeyword = _expectKeyword(Keyword.RETURN);
7012 if (_matches(TokenType.SEMICOLON)) {
7013 return new ReturnStatement(returnKeyword, null, getAndAdvance());
7014 }
7015 Expression expression = parseExpression2();
7016 Token semicolon = _expect(TokenType.SEMICOLON);
7017 return new ReturnStatement(returnKeyword, expression, semicolon);
7018 }
7019
7020 /**
7021 * Parse a setter. The [commentAndMetadata] is the documentation comment and
7022 * metadata to be associated with the declaration. The [externalKeyword] is
7023 * the 'external' token. The [staticKeyword] is the static keyword, or `null`
7024 * if the setter is not static. The [returnType] is the return type that has
7025 * already been parsed, or `null` if there was no return type. Return the
7026 * setter that was parsed.
7027 *
7028 * setter ::=
7029 * setterSignature functionBody?
7030 *
7031 * setterSignature ::=
7032 * 'external'? 'static'? returnType? 'set' identifier formalParameterL ist
7033 */
7034 MethodDeclaration _parseSetter(CommentAndMetadata commentAndMetadata,
7035 Token externalKeyword, Token staticKeyword, TypeName returnType) {
7036 Token propertyKeyword = _expectKeyword(Keyword.SET);
7037 SimpleIdentifier name = parseSimpleIdentifier();
7038 FormalParameterList parameters = parseFormalParameterList();
7039 _validateFormalParameterList(parameters);
7040 FunctionBody body = _parseFunctionBody(
7041 externalKeyword != null || staticKeyword == null,
7042 ParserErrorCode.STATIC_SETTER_WITHOUT_BODY, false);
7043 if (externalKeyword != null && body is! EmptyFunctionBody) {
7044 _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_SETTER_WITH_BODY);
7045 }
7046 return new MethodDeclaration(commentAndMetadata.comment,
7047 commentAndMetadata.metadata, externalKeyword, staticKeyword, returnType,
7048 propertyKeyword, null, name, null, parameters, body);
7049 }
7050
7051 /**
7052 * Parse a shift expression. Return the shift expression that was parsed.
7053 *
7054 * shiftExpression ::=
7055 * additiveExpression (shiftOperator additiveExpression)*
7056 * | 'super' (shiftOperator additiveExpression)+
7057 */
7058 Expression _parseShiftExpression() {
7059 Expression expression;
7060 if (_matchesKeyword(Keyword.SUPER) &&
7061 _currentToken.next.type.isShiftOperator) {
7062 expression = new SuperExpression(getAndAdvance());
7063 } else {
7064 expression = _parseAdditiveExpression();
7065 }
7066 while (_currentToken.type.isShiftOperator) {
7067 Token operator = getAndAdvance();
7068 expression = new BinaryExpression(
7069 expression, operator, _parseAdditiveExpression());
7070 }
7071 return expression;
7072 }
7073
7074 /**
7075 * Parse a list of statements within a switch statement. Return the statements
7076 * that were parsed.
7077 *
7078 * statements ::=
7079 * statement*
7080 */
7081 List<Statement> _parseStatementList() {
7082 List<Statement> statements = new List<Statement>();
7083 Token statementStart = _currentToken;
7084 while (!_matches(TokenType.EOF) &&
7085 !_matches(TokenType.CLOSE_CURLY_BRACKET) &&
7086 !_isSwitchMember()) {
7087 statements.add(parseStatement2());
7088 if (identical(_currentToken, statementStart)) {
7089 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
7090 [_currentToken.lexeme]);
7091 _advance();
7092 }
7093 statementStart = _currentToken;
7094 }
7095 return statements;
7096 }
7097
7098 /**
7099 * Parse a string literal that contains interpolations. Return the string
7100 * literal that was parsed.
7101 */
7102 StringInterpolation _parseStringInterpolation(Token string) {
7103 List<InterpolationElement> elements = new List<InterpolationElement>();
7104 bool hasMore = _matches(TokenType.STRING_INTERPOLATION_EXPRESSION) ||
7105 _matches(TokenType.STRING_INTERPOLATION_IDENTIFIER);
7106 elements.add(new InterpolationString(
7107 string, _computeStringValue(string.lexeme, true, !hasMore)));
7108 while (hasMore) {
7109 if (_matches(TokenType.STRING_INTERPOLATION_EXPRESSION)) {
7110 Token openToken = getAndAdvance();
7111 bool wasInInitializer = _inInitializer;
7112 _inInitializer = false;
7113 try {
7114 Expression expression = parseExpression2();
7115 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
7116 elements.add(
7117 new InterpolationExpression(openToken, expression, rightBracket));
7118 } finally {
7119 _inInitializer = wasInInitializer;
7120 }
7121 } else {
7122 Token openToken = getAndAdvance();
7123 Expression expression = null;
7124 if (_matchesKeyword(Keyword.THIS)) {
7125 expression = new ThisExpression(getAndAdvance());
7126 } else {
7127 expression = parseSimpleIdentifier();
7128 }
7129 elements.add(new InterpolationExpression(openToken, expression, null));
7130 }
7131 if (_matches(TokenType.STRING)) {
7132 string = getAndAdvance();
7133 hasMore = _matches(TokenType.STRING_INTERPOLATION_EXPRESSION) ||
7134 _matches(TokenType.STRING_INTERPOLATION_IDENTIFIER);
7135 elements.add(new InterpolationString(
7136 string, _computeStringValue(string.lexeme, false, !hasMore)));
7137 } else {
7138 hasMore = false;
7139 }
7140 }
7141 return new StringInterpolation(elements);
7142 }
7143
7144 /**
7145 * Parse a super constructor invocation. Return the super constructor
7146 * invocation that was parsed.
7147 *
7148 * superConstructorInvocation ::=
7149 * 'super' ('.' identifier)? arguments
7150 */
7151 SuperConstructorInvocation _parseSuperConstructorInvocation() {
7152 Token keyword = _expectKeyword(Keyword.SUPER);
7153 Token period = null;
7154 SimpleIdentifier constructorName = null;
7155 if (_matches(TokenType.PERIOD)) {
7156 period = getAndAdvance();
7157 constructorName = parseSimpleIdentifier();
7158 }
7159 ArgumentList argumentList = parseArgumentList();
7160 return new SuperConstructorInvocation(
7161 keyword, period, constructorName, argumentList);
7162 }
7163
7164 /**
7165 * Parse a switch statement. Return the switch statement that was parsed.
7166 *
7167 * switchStatement ::=
7168 * 'switch' '(' expression ')' '{' switchCase* defaultCase? '}'
7169 *
7170 * switchCase ::=
7171 * label* ('case' expression ':') statements
7172 *
7173 * defaultCase ::=
7174 * label* 'default' ':' statements
7175 */
7176 SwitchStatement _parseSwitchStatement() {
7177 bool wasInSwitch = _inSwitch;
7178 _inSwitch = true;
7179 try {
7180 HashSet<String> definedLabels = new HashSet<String>();
7181 Token keyword = _expectKeyword(Keyword.SWITCH);
7182 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
7183 Expression expression = parseExpression2();
7184 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
7185 Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
7186 Token defaultKeyword = null;
7187 List<SwitchMember> members = new List<SwitchMember>();
7188 while (!_matches(TokenType.EOF) &&
7189 !_matches(TokenType.CLOSE_CURLY_BRACKET)) {
7190 List<Label> labels = new List<Label>();
7191 while (
7192 _matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) {
7193 SimpleIdentifier identifier = parseSimpleIdentifier();
7194 String label = identifier.token.lexeme;
7195 if (definedLabels.contains(label)) {
7196 _reportErrorForToken(
7197 ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT,
7198 identifier.token, [label]);
7199 } else {
7200 definedLabels.add(label);
7201 }
7202 Token colon = _expect(TokenType.COLON);
7203 labels.add(new Label(identifier, colon));
7204 }
7205 if (_matchesKeyword(Keyword.CASE)) {
7206 Token caseKeyword = getAndAdvance();
7207 Expression caseExpression = parseExpression2();
7208 Token colon = _expect(TokenType.COLON);
7209 members.add(new SwitchCase(labels, caseKeyword, caseExpression, colon,
7210 _parseStatementList()));
7211 if (defaultKeyword != null) {
7212 _reportErrorForToken(
7213 ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE,
7214 caseKeyword);
7215 }
7216 } else if (_matchesKeyword(Keyword.DEFAULT)) {
7217 if (defaultKeyword != null) {
7218 _reportErrorForToken(
7219 ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES, _peek());
7220 }
7221 defaultKeyword = getAndAdvance();
7222 Token colon = _expect(TokenType.COLON);
7223 members.add(new SwitchDefault(
7224 labels, defaultKeyword, colon, _parseStatementList()));
7225 } else {
7226 // We need to advance, otherwise we could end up in an infinite loop,
7227 // but this could be a lot smarter about recovering from the error.
7228 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT);
7229 while (!_matches(TokenType.EOF) &&
7230 !_matches(TokenType.CLOSE_CURLY_BRACKET) &&
7231 !_matchesKeyword(Keyword.CASE) &&
7232 !_matchesKeyword(Keyword.DEFAULT)) {
7233 _advance();
7234 }
7235 }
7236 }
7237 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
7238 return new SwitchStatement(keyword, leftParenthesis, expression,
7239 rightParenthesis, leftBracket, members, rightBracket);
7240 } finally {
7241 _inSwitch = wasInSwitch;
7242 }
7243 }
7244
7245 /**
7246 * Parse a symbol literal. Return the symbol literal that was parsed.
7247 *
7248 * symbolLiteral ::=
7249 * '#' identifier ('.' identifier)*
7250 */
7251 SymbolLiteral _parseSymbolLiteral() {
7252 Token poundSign = getAndAdvance();
7253 List<Token> components = new List<Token>();
7254 if (_matchesIdentifier()) {
7255 components.add(getAndAdvance());
7256 while (_matches(TokenType.PERIOD)) {
7257 _advance();
7258 if (_matchesIdentifier()) {
7259 components.add(getAndAdvance());
7260 } else {
7261 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
7262 components.add(_createSyntheticToken(TokenType.IDENTIFIER));
7263 break;
7264 }
7265 }
7266 } else if (_currentToken.isOperator) {
7267 components.add(getAndAdvance());
7268 } else if (_tokenMatchesKeyword(_currentToken, Keyword.VOID)) {
7269 components.add(getAndAdvance());
7270 } else {
7271 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
7272 components.add(_createSyntheticToken(TokenType.IDENTIFIER));
7273 }
7274 return new SymbolLiteral(poundSign, components);
7275 }
7276
7277 /**
7278 * Parse a throw expression. Return the throw expression that was parsed.
7279 *
7280 * throwExpression ::=
7281 * 'throw' expression
7282 */
7283 Expression _parseThrowExpression() {
7284 Token keyword = _expectKeyword(Keyword.THROW);
7285 if (_matches(TokenType.SEMICOLON) || _matches(TokenType.CLOSE_PAREN)) {
7286 _reportErrorForToken(
7287 ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken);
7288 return new ThrowExpression(keyword, _createSyntheticIdentifier());
7289 }
7290 Expression expression = parseExpression2();
7291 return new ThrowExpression(keyword, expression);
7292 }
7293
7294 /**
7295 * Parse a throw expression. Return the throw expression that was parsed.
7296 *
7297 * throwExpressionWithoutCascade ::=
7298 * 'throw' expressionWithoutCascade
7299 */
7300 Expression _parseThrowExpressionWithoutCascade() {
7301 Token keyword = _expectKeyword(Keyword.THROW);
7302 if (_matches(TokenType.SEMICOLON) || _matches(TokenType.CLOSE_PAREN)) {
7303 _reportErrorForToken(
7304 ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken);
7305 return new ThrowExpression(keyword, _createSyntheticIdentifier());
7306 }
7307 Expression expression = parseExpressionWithoutCascade();
7308 return new ThrowExpression(keyword, expression);
7309 }
7310
7311 /**
7312 * Parse a try statement. Return the try statement that was parsed.
7313 *
7314 * tryStatement ::=
7315 * 'try' block (onPart+ finallyPart? | finallyPart)
7316 *
7317 * onPart ::=
7318 * catchPart block
7319 * | 'on' type catchPart? block
7320 *
7321 * catchPart ::=
7322 * 'catch' '(' identifier (',' identifier)? ')'
7323 *
7324 * finallyPart ::=
7325 * 'finally' block
7326 */
7327 Statement _parseTryStatement() {
7328 Token tryKeyword = _expectKeyword(Keyword.TRY);
7329 Block body = parseBlock();
7330 List<CatchClause> catchClauses = new List<CatchClause>();
7331 Block finallyClause = null;
7332 while (_matchesString(_ON) || _matchesKeyword(Keyword.CATCH)) {
7333 Token onKeyword = null;
7334 TypeName exceptionType = null;
7335 if (_matchesString(_ON)) {
7336 onKeyword = getAndAdvance();
7337 exceptionType = parseTypeName();
7338 }
7339 Token catchKeyword = null;
7340 Token leftParenthesis = null;
7341 SimpleIdentifier exceptionParameter = null;
7342 Token comma = null;
7343 SimpleIdentifier stackTraceParameter = null;
7344 Token rightParenthesis = null;
7345 if (_matchesKeyword(Keyword.CATCH)) {
7346 catchKeyword = getAndAdvance();
7347 leftParenthesis = _expect(TokenType.OPEN_PAREN);
7348 exceptionParameter = parseSimpleIdentifier();
7349 if (_matches(TokenType.COMMA)) {
7350 comma = getAndAdvance();
7351 stackTraceParameter = parseSimpleIdentifier();
7352 }
7353 rightParenthesis = _expect(TokenType.CLOSE_PAREN);
7354 }
7355 Block catchBody = parseBlock();
7356 catchClauses.add(new CatchClause(onKeyword, exceptionType, catchKeyword,
7357 leftParenthesis, exceptionParameter, comma, stackTraceParameter,
7358 rightParenthesis, catchBody));
7359 }
7360 Token finallyKeyword = null;
7361 if (_matchesKeyword(Keyword.FINALLY)) {
7362 finallyKeyword = getAndAdvance();
7363 finallyClause = parseBlock();
7364 } else {
7365 if (catchClauses.isEmpty) {
7366 _reportErrorForCurrentToken(ParserErrorCode.MISSING_CATCH_OR_FINALLY);
7367 }
7368 }
7369 return new TryStatement(
7370 tryKeyword, body, catchClauses, finallyKeyword, finallyClause);
7371 }
7372
7373 /**
7374 * Parse a type alias. The [commentAndMetadata] is the metadata to be
7375 * associated with the member. Return the type alias that was parsed.
7376 *
7377 * typeAlias ::=
7378 * 'typedef' typeAliasBody
7379 *
7380 * typeAliasBody ::=
7381 * classTypeAlias
7382 * | functionTypeAlias
7383 *
7384 * classTypeAlias ::=
7385 * identifier typeParameters? '=' 'abstract'? mixinApplication
7386 *
7387 * mixinApplication ::=
7388 * qualified withClause implementsClause? ';'
7389 *
7390 * functionTypeAlias ::=
7391 * functionPrefix typeParameterList? formalParameterList ';'
7392 *
7393 * functionPrefix ::=
7394 * returnType? name
7395 */
7396 TypeAlias _parseTypeAlias(CommentAndMetadata commentAndMetadata) {
7397 Token keyword = _expectKeyword(Keyword.TYPEDEF);
7398 if (_matchesIdentifier()) {
7399 Token next = _peek();
7400 if (_tokenMatches(next, TokenType.LT)) {
7401 next = _skipTypeParameterList(next);
7402 if (next != null && _tokenMatches(next, TokenType.EQ)) {
7403 TypeAlias typeAlias =
7404 _parseClassTypeAlias(commentAndMetadata, null, keyword);
7405 _reportErrorForToken(
7406 ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword);
7407 return typeAlias;
7408 }
7409 } else if (_tokenMatches(next, TokenType.EQ)) {
7410 TypeAlias typeAlias =
7411 _parseClassTypeAlias(commentAndMetadata, null, keyword);
7412 _reportErrorForToken(
7413 ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword);
7414 return typeAlias;
7415 }
7416 }
7417 return _parseFunctionTypeAlias(commentAndMetadata, keyword);
7418 }
7419
7420 /**
7421 * Parse a unary expression. Return the unary expression that was parsed.
7422 *
7423 * unaryExpression ::=
7424 * prefixOperator unaryExpression
7425 * | awaitExpression
7426 * | postfixExpression
7427 * | unaryOperator 'super'
7428 * | '-' 'super'
7429 * | incrementOperator assignableExpression
7430 */
7431 Expression _parseUnaryExpression() {
7432 if (_matches(TokenType.MINUS) ||
7433 _matches(TokenType.BANG) ||
7434 _matches(TokenType.TILDE)) {
7435 Token operator = getAndAdvance();
7436 if (_matchesKeyword(Keyword.SUPER)) {
7437 if (_tokenMatches(_peek(), TokenType.OPEN_SQUARE_BRACKET) ||
7438 _tokenMatches(_peek(), TokenType.PERIOD)) {
7439 // "prefixOperator unaryExpression"
7440 // --> "prefixOperator postfixExpression"
7441 // --> "prefixOperator primary selector*"
7442 // --> "prefixOperator 'super' assignableSelector selector*"
7443 return new PrefixExpression(operator, _parseUnaryExpression());
7444 }
7445 return new PrefixExpression(
7446 operator, new SuperExpression(getAndAdvance()));
7447 }
7448 return new PrefixExpression(operator, _parseUnaryExpression());
7449 } else if (_currentToken.type.isIncrementOperator) {
7450 Token operator = getAndAdvance();
7451 if (_matchesKeyword(Keyword.SUPER)) {
7452 if (_tokenMatches(_peek(), TokenType.OPEN_SQUARE_BRACKET) ||
7453 _tokenMatches(_peek(), TokenType.PERIOD)) {
7454 // --> "prefixOperator 'super' assignableSelector selector*"
7455 return new PrefixExpression(operator, _parseUnaryExpression());
7456 }
7457 //
7458 // Even though it is not valid to use an incrementing operator
7459 // ('++' or '--') before 'super', we can (and therefore must) interpret
7460 // "--super" as semantically equivalent to "-(-super)". Unfortunately,
7461 // we cannot do the same for "++super" because "+super" is also not
7462 // valid.
7463 //
7464 if (operator.type == TokenType.MINUS_MINUS) {
7465 Token firstOperator = _createToken(operator, TokenType.MINUS);
7466 Token secondOperator =
7467 new Token(TokenType.MINUS, operator.offset + 1);
7468 secondOperator.setNext(_currentToken);
7469 firstOperator.setNext(secondOperator);
7470 operator.previous.setNext(firstOperator);
7471 return new PrefixExpression(firstOperator, new PrefixExpression(
7472 secondOperator, new SuperExpression(getAndAdvance())));
7473 } else {
7474 // Invalid operator before 'super'
7475 _reportErrorForCurrentToken(
7476 ParserErrorCode.INVALID_OPERATOR_FOR_SUPER, [operator.lexeme]);
7477 return new PrefixExpression(
7478 operator, new SuperExpression(getAndAdvance()));
7479 }
7480 }
7481 return new PrefixExpression(operator, _parseAssignableExpression(false));
7482 } else if (_matches(TokenType.PLUS)) {
7483 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
7484 return _createSyntheticIdentifier();
7485 } else if (_inAsync && _matchesString(_AWAIT)) {
7486 return _parseAwaitExpression();
7487 }
7488 return _parsePostfixExpression();
7489 }
7490
7491 /**
7492 * Parse a string literal representing a URI. Return the string literal that
7493 * was parsed.
7494 */
7495 StringLiteral _parseUri() {
7496 bool iskeywordAfterUri(Token token) => token.lexeme == Keyword.AS.syntax ||
7497 token.lexeme == _HIDE ||
7498 token.lexeme == _SHOW;
7499 if (!_matches(TokenType.STRING) &&
7500 !_matches(TokenType.SEMICOLON) &&
7501 !iskeywordAfterUri(_currentToken)) {
7502 // Attempt to recover in the case where the URI was not enclosed in
7503 // quotes.
7504 Token token = _currentToken;
7505 while ((_tokenMatchesIdentifier(token) && !iskeywordAfterUri(token)) ||
7506 _tokenMatches(token, TokenType.COLON) ||
7507 _tokenMatches(token, TokenType.SLASH) ||
7508 _tokenMatches(token, TokenType.PERIOD) ||
7509 _tokenMatches(token, TokenType.PERIOD_PERIOD) ||
7510 _tokenMatches(token, TokenType.PERIOD_PERIOD_PERIOD) ||
7511 _tokenMatches(token, TokenType.INT) ||
7512 _tokenMatches(token, TokenType.DOUBLE)) {
7513 token = token.next;
7514 }
7515 if (_tokenMatches(token, TokenType.SEMICOLON) ||
7516 iskeywordAfterUri(token)) {
7517 Token endToken = token.previous;
7518 token = _currentToken;
7519 int endOffset = token.end;
7520 StringBuffer buffer = new StringBuffer();
7521 buffer.write(token.lexeme);
7522 while (token != endToken) {
7523 token = token.next;
7524 if (token.offset != endOffset || token.precedingComments != null) {
7525 return parseStringLiteral();
7526 }
7527 buffer.write(token.lexeme);
7528 endOffset = token.end;
7529 }
7530 String value = buffer.toString();
7531 Token newToken =
7532 new StringToken(TokenType.STRING, "'$value'", _currentToken.offset);
7533 _reportErrorForToken(
7534 ParserErrorCode.NON_STRING_LITERAL_AS_URI, newToken);
7535 _currentToken = endToken.next;
7536 return new SimpleStringLiteral(newToken, value);
7537 }
7538 }
7539 return parseStringLiteral();
7540 }
7541
7542 /**
7543 * Parse a variable declaration. Return the variable declaration that was
7544 * parsed.
7545 *
7546 * variableDeclaration ::=
7547 * identifier ('=' expression)?
7548 */
7549 VariableDeclaration _parseVariableDeclaration() {
7550 // TODO(paulberry): prior to the fix for bug 23204, we permitted
7551 // annotations before variable declarations (e.g. "String @deprecated s;").
7552 // Although such constructions are prohibited by the spec, we may want to
7553 // consider handling them anyway to allow for better parser recovery in the
7554 // event that the user erroneously tries to use them. However, as a
7555 // counterargument, this would likely degrade parser recovery in the event
7556 // of a construct like "class C { int @deprecated foo() {} }" (i.e. the
7557 // user is in the middle of inserting "int bar;" prior to
7558 // "@deprecated foo() {}").
7559 SimpleIdentifier name = parseSimpleIdentifier();
7560 Token equals = null;
7561 Expression initializer = null;
7562 if (_matches(TokenType.EQ)) {
7563 equals = getAndAdvance();
7564 initializer = parseExpression2();
7565 }
7566 return new VariableDeclaration(name, equals, initializer);
7567 }
7568
7569 /**
7570 * Parse a variable declaration list. The [commentAndMetadata] is the metadata
7571 * to be associated with the variable declaration list. Return the variable
7572 * declaration list that was parsed.
7573 *
7574 * variableDeclarationList ::=
7575 * finalConstVarOrType variableDeclaration (',' variableDeclaration)*
7576 */
7577 VariableDeclarationList _parseVariableDeclarationListAfterMetadata(
7578 CommentAndMetadata commentAndMetadata) {
7579 FinalConstVarOrType holder = _parseFinalConstVarOrType(false);
7580 return _parseVariableDeclarationListAfterType(
7581 commentAndMetadata, holder.keyword, holder.type);
7582 }
7583
7584 /**
7585 * Parse a variable declaration list. The [commentAndMetadata] is the metadata
7586 * to be associated with the variable declaration list, or `null` if there is
7587 * no attempt at parsing the comment and metadata. The [keyword] is the token
7588 * representing the 'final', 'const' or 'var' keyword, or `null` if there is
7589 * no keyword. The [type] is the type of the variables in the list. Return the
7590 * variable declaration list that was parsed.
7591 *
7592 * variableDeclarationList ::=
7593 * finalConstVarOrType variableDeclaration (',' variableDeclaration)*
7594 */
7595 VariableDeclarationList _parseVariableDeclarationListAfterType(
7596 CommentAndMetadata commentAndMetadata, Token keyword, TypeName type) {
7597 if (type != null &&
7598 keyword != null &&
7599 _tokenMatchesKeyword(keyword, Keyword.VAR)) {
7600 _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, keyword);
7601 }
7602 List<VariableDeclaration> variables = new List<VariableDeclaration>();
7603 variables.add(_parseVariableDeclaration());
7604 while (_matches(TokenType.COMMA)) {
7605 _advance();
7606 variables.add(_parseVariableDeclaration());
7607 }
7608 return new VariableDeclarationList(
7609 commentAndMetadata != null ? commentAndMetadata.comment : null,
7610 commentAndMetadata != null ? commentAndMetadata.metadata : null,
7611 keyword, type, variables);
7612 }
7613
7614 /**
7615 * Parse a variable declaration statement. The [commentAndMetadata] is the
7616 * metadata to be associated with the variable declaration statement, or
7617 * `null` if there is no attempt at parsing the comment and metadata. Return
7618 * the variable declaration statement that was parsed.
7619 *
7620 * variableDeclarationStatement ::=
7621 * variableDeclarationList ';'
7622 */
7623 VariableDeclarationStatement _parseVariableDeclarationStatementAfterMetadata(
7624 CommentAndMetadata commentAndMetadata) {
7625 // Token startToken = currentToken;
7626 VariableDeclarationList variableList =
7627 _parseVariableDeclarationListAfterMetadata(commentAndMetadata);
7628 // if (!matches(TokenType.SEMICOLON)) {
7629 // if (matches(startToken, Keyword.VAR) && isTypedIdentifier(startToken .getNext())) {
7630 // // TODO(brianwilkerson) This appears to be of the form "var type v ariable". We should do
7631 // // a better job of recovering in this case.
7632 // }
7633 // }
7634 Token semicolon = _expect(TokenType.SEMICOLON);
7635 return new VariableDeclarationStatement(variableList, semicolon);
7636 }
7637
7638 /**
7639 * Parse a variable declaration statement. The [commentAndMetadata] is the
7640 * metadata to be associated with the variable declaration statement, or
7641 * `null` if there is no attempt at parsing the comment and metadata. The
7642 * [keyword] is the token representing the 'final', 'const' or 'var' keyword,
7643 * or `null` if there is no keyword. The [type] is the type of the variables
7644 * in the list. Return the variable declaration statement that was parsed.
7645 *
7646 * variableDeclarationStatement ::=
7647 * variableDeclarationList ';'
7648 */
7649 VariableDeclarationStatement _parseVariableDeclarationStatementAfterType(
7650 CommentAndMetadata commentAndMetadata, Token keyword, TypeName type) {
7651 VariableDeclarationList variableList =
7652 _parseVariableDeclarationListAfterType(
7653 commentAndMetadata, keyword, type);
7654 Token semicolon = _expect(TokenType.SEMICOLON);
7655 return new VariableDeclarationStatement(variableList, semicolon);
7656 }
7657
7658 /**
7659 * Parse a while statement. Return the while statement that was parsed.
7660 *
7661 * whileStatement ::=
7662 * 'while' '(' expression ')' statement
7663 */
7664 Statement _parseWhileStatement() {
7665 bool wasInLoop = _inLoop;
7666 _inLoop = true;
7667 try {
7668 Token keyword = _expectKeyword(Keyword.WHILE);
7669 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
7670 Expression condition = parseExpression2();
7671 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
7672 Statement body = parseStatement2();
7673 return new WhileStatement(
7674 keyword, leftParenthesis, condition, rightParenthesis, body);
7675 } finally {
7676 _inLoop = wasInLoop;
7677 }
7678 }
7679
7680 /**
7681 * Parse a yield statement. Return the yield statement that was parsed.
7682 *
7683 * yieldStatement ::=
7684 * 'yield' '*'? expression ';'
7685 */
7686 YieldStatement _parseYieldStatement() {
7687 Token yieldToken = getAndAdvance();
7688 Token star = null;
7689 if (_matches(TokenType.STAR)) {
7690 star = getAndAdvance();
7691 }
7692 Expression expression = parseExpression2();
7693 Token semicolon = _expect(TokenType.SEMICOLON);
7694 return new YieldStatement(yieldToken, star, expression, semicolon);
7695 }
7696
7697 /**
7698 * Return the token that is immediately after the current token. This is
7699 * equivalent to [_peekAt](1).
7700 */
7701 Token _peek() => _currentToken.next;
7702
7703 /**
7704 * Return the token that is the given [distance] after the current token,
7705 * where the distance is the number of tokens to look ahead. A distance of `0`
7706 * is the current token, `1` is the next token, etc.
7707 */
7708 Token _peekAt(int distance) {
7709 Token token = _currentToken;
7710 for (int i = 0; i < distance; i++) {
7711 token = token.next;
7712 }
7713 return token;
7714 }
7715
7716 /**
7717 * Report the given [error].
7718 */
7719 void _reportError(AnalysisError error) {
7720 if (_errorListenerLock != 0) {
7721 return;
7722 }
7723 _errorListener.onError(error);
7724 }
7725
7726 /**
7727 * Report an error with the given [errorCode] and [arguments] associated with
7728 * the current token.
7729 */
7730 void _reportErrorForCurrentToken(ParserErrorCode errorCode,
7731 [List<Object> arguments]) {
7732 _reportErrorForToken(errorCode, _currentToken, arguments);
7733 }
7734
7735 /**
7736 * Report an error with the given [errorCode] and [arguments] associated with
7737 * the given [node].
7738 */
7739 void _reportErrorForNode(ParserErrorCode errorCode, AstNode node,
7740 [List<Object> arguments]) {
7741 _reportError(new AnalysisError(
7742 _source, node.offset, node.length, errorCode, arguments));
7743 }
7744
7745 /**
7746 * Report an error with the given [errorCode] and [arguments] associated with
7747 * the given [token].
7748 */
7749 void _reportErrorForToken(ErrorCode errorCode, Token token,
7750 [List<Object> arguments]) {
7751 if (token.type == TokenType.EOF) {
7752 token = token.previous;
7753 }
7754 _reportError(new AnalysisError(_source, token.offset,
7755 math.max(token.length, 1), errorCode, arguments));
7756 }
7757
7758 /**
7759 * Skips a block with all containing blocks.
7760 */
7761 void _skipBlock() {
7762 Token endToken = (_currentToken as BeginToken).endToken;
7763 if (endToken == null) {
7764 endToken = _currentToken.next;
7765 while (!identical(endToken, _currentToken)) {
7766 _currentToken = endToken;
7767 endToken = _currentToken.next;
7768 }
7769 _reportErrorForToken(
7770 ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, ["}"]);
7771 } else {
7772 _currentToken = endToken.next;
7773 }
7774 }
7775
7776 /**
7777 * Parse the 'final', 'const', 'var' or type preceding a variable declaration,
7778 * starting at the given token, without actually creating a type or changing
7779 * the current token. Return the token following the type that was parsed, or
7780 * `null` if the given token is not the first token in a valid type. The
7781 * [startToken] is the token at which parsing is to begin. Return the token
7782 * following the type that was parsed.
7783 *
7784 * finalConstVarOrType ::=
7785 * | 'final' type?
7786 * | 'const' type?
7787 * | 'var'
7788 * | type
7789 */
7790 Token _skipFinalConstVarOrType(Token startToken) {
7791 if (_tokenMatchesKeyword(startToken, Keyword.FINAL) ||
7792 _tokenMatchesKeyword(startToken, Keyword.CONST)) {
7793 Token next = startToken.next;
7794 if (_tokenMatchesIdentifier(next)) {
7795 Token next2 = next.next;
7796 // "Type parameter" or "Type<" or "prefix.Type"
7797 if (_tokenMatchesIdentifier(next2) ||
7798 _tokenMatches(next2, TokenType.LT) ||
7799 _tokenMatches(next2, TokenType.PERIOD)) {
7800 return _skipTypeName(next);
7801 }
7802 // "parameter"
7803 return next;
7804 }
7805 } else if (_tokenMatchesKeyword(startToken, Keyword.VAR)) {
7806 return startToken.next;
7807 } else if (_tokenMatchesIdentifier(startToken)) {
7808 Token next = startToken.next;
7809 if (_tokenMatchesIdentifier(next) ||
7810 _tokenMatches(next, TokenType.LT) ||
7811 _tokenMatchesKeyword(next, Keyword.THIS) ||
7812 (_tokenMatches(next, TokenType.PERIOD) &&
7813 _tokenMatchesIdentifier(next.next) &&
7814 (_tokenMatchesIdentifier(next.next.next) ||
7815 _tokenMatches(next.next.next, TokenType.LT) ||
7816 _tokenMatchesKeyword(next.next.next, Keyword.THIS)))) {
7817 return _skipReturnType(startToken);
7818 }
7819 }
7820 return null;
7821 }
7822
7823 /**
7824 * Parse a list of formal parameters, starting at the [startToken], without
7825 * actually creating a formal parameter list or changing the current token.
7826 * Return the token following the formal parameter list that was parsed, or
7827 * `null` if the given token is not the first token in a valid list of formal
7828 * parameter.
7829 *
7830 * Note that unlike other skip methods, this method uses a heuristic. In the
7831 * worst case, the parameters could be prefixed by metadata, which would
7832 * require us to be able to skip arbitrary expressions. Rather than duplicate
7833 * the logic of most of the parse methods we simply look for something that is
7834 * likely to be a list of parameters and then skip to returning the token
7835 * after the closing parenthesis.
7836 *
7837 * This method must be kept in sync with [parseFormalParameterList].
7838 *
7839 * formalParameterList ::=
7840 * '(' ')'
7841 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
7842 * | '(' optionalFormalParameters ')'
7843 *
7844 * normalFormalParameters ::=
7845 * normalFormalParameter (',' normalFormalParameter)*
7846 *
7847 * optionalFormalParameters ::=
7848 * optionalPositionalFormalParameters
7849 * | namedFormalParameters
7850 *
7851 * optionalPositionalFormalParameters ::=
7852 * '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
7853 *
7854 * namedFormalParameters ::=
7855 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
7856 */
7857 Token _skipFormalParameterList(Token startToken) {
7858 if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) {
7859 return null;
7860 }
7861 Token next = startToken.next;
7862 if (_tokenMatches(next, TokenType.CLOSE_PAREN)) {
7863 return next.next;
7864 }
7865 //
7866 // Look to see whether the token after the open parenthesis is something
7867 // that should only occur at the beginning of a parameter list.
7868 //
7869 if (next.matchesAny([
7870 TokenType.AT,
7871 TokenType.OPEN_SQUARE_BRACKET,
7872 TokenType.OPEN_CURLY_BRACKET
7873 ]) ||
7874 _tokenMatchesKeyword(next, Keyword.VOID) ||
7875 (_tokenMatchesIdentifier(next) &&
7876 (next.next.matchesAny([TokenType.COMMA, TokenType.CLOSE_PAREN])))) {
7877 return _skipPastMatchingToken(startToken);
7878 }
7879 //
7880 // Look to see whether the first parameter is a function typed parameter
7881 // without a return type.
7882 //
7883 if (_tokenMatchesIdentifier(next) &&
7884 _tokenMatches(next.next, TokenType.OPEN_PAREN)) {
7885 Token afterParameters = _skipFormalParameterList(next.next);
7886 if (afterParameters != null &&
7887 (afterParameters
7888 .matchesAny([TokenType.COMMA, TokenType.CLOSE_PAREN]))) {
7889 return _skipPastMatchingToken(startToken);
7890 }
7891 }
7892 //
7893 // Look to see whether the first parameter has a type or is a function typed
7894 // parameter with a return type.
7895 //
7896 Token afterType = _skipFinalConstVarOrType(next);
7897 if (afterType == null) {
7898 return null;
7899 }
7900 if (_skipSimpleIdentifier(afterType) == null) {
7901 return null;
7902 }
7903 return _skipPastMatchingToken(startToken);
7904 }
7905
7906 /**
7907 * If the [startToken] is a begin token with an associated end token, then
7908 * return the token following the end token. Otherwise, return `null`.
7909 */
7910 Token _skipPastMatchingToken(Token startToken) {
7911 if (startToken is! BeginToken) {
7912 return null;
7913 }
7914 Token closeParen = (startToken as BeginToken).endToken;
7915 if (closeParen == null) {
7916 return null;
7917 }
7918 return closeParen.next;
7919 }
7920
7921 /**
7922 * Parse a prefixed identifier, starting at the [startToken], without actually
7923 * creating a prefixed identifier or changing the current token. Return the
7924 * token following the prefixed identifier that was parsed, or `null` if the
7925 * given token is not the first token in a valid prefixed identifier.
7926 *
7927 * This method must be kept in sync with [parsePrefixedIdentifier].
7928 *
7929 * prefixedIdentifier ::=
7930 * identifier ('.' identifier)?
7931 */
7932 Token _skipPrefixedIdentifier(Token startToken) {
7933 Token token = _skipSimpleIdentifier(startToken);
7934 if (token == null) {
7935 return null;
7936 } else if (!_tokenMatches(token, TokenType.PERIOD)) {
7937 return token;
7938 }
7939 token = token.next;
7940 Token nextToken = _skipSimpleIdentifier(token);
7941 if (nextToken != null) {
7942 return nextToken;
7943 } else if (_tokenMatches(token, TokenType.CLOSE_PAREN) ||
7944 _tokenMatches(token, TokenType.COMMA)) {
7945 // If the `id.` is followed by something that cannot produce a valid
7946 // structure then assume this is a prefixed identifier but missing the
7947 // trailing identifier
7948 return token;
7949 }
7950 return null;
7951 }
7952
7953 /**
7954 * Parse a return type, starting at the [startToken], without actually
7955 * creating a return type or changing the current token. Return the token
7956 * following the return type that was parsed, or `null` if the given token is
7957 * not the first token in a valid return type.
7958 *
7959 * This method must be kept in sync with [parseReturnType].
7960 *
7961 * returnType ::=
7962 * 'void'
7963 * | type
7964 */
7965 Token _skipReturnType(Token startToken) {
7966 if (_tokenMatchesKeyword(startToken, Keyword.VOID)) {
7967 return startToken.next;
7968 } else {
7969 return _skipTypeName(startToken);
7970 }
7971 }
7972
7973 /**
7974 * Parse a simple identifier, starting at the [startToken], without actually
7975 * creating a simple identifier or changing the current token. Return the
7976 * token following the simple identifier that was parsed, or `null` if the
7977 * given token is not the first token in a valid simple identifier.
7978 *
7979 * This method must be kept in sync with [parseSimpleIdentifier].
7980 *
7981 * identifier ::=
7982 * IDENTIFIER
7983 */
7984 Token _skipSimpleIdentifier(Token startToken) {
7985 if (_tokenMatches(startToken, TokenType.IDENTIFIER) ||
7986 (_tokenMatches(startToken, TokenType.KEYWORD) &&
7987 (startToken as KeywordToken).keyword.isPseudoKeyword)) {
7988 return startToken.next;
7989 }
7990 return null;
7991 }
7992
7993 /**
7994 * Parse a string literal that contains interpolations, starting at the
7995 * [startToken], without actually creating a string literal or changing the
7996 * current token. Return the token following the string literal that was
7997 * parsed, or `null` if the given token is not the first token in a valid
7998 * string literal.
7999 *
8000 * This method must be kept in sync with [parseStringInterpolation].
8001 */
8002 Token _skipStringInterpolation(Token startToken) {
8003 Token token = startToken;
8004 TokenType type = token.type;
8005 while (type == TokenType.STRING_INTERPOLATION_EXPRESSION ||
8006 type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
8007 if (type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
8008 token = token.next;
8009 type = token.type;
8010 //
8011 // Rather than verify that the following tokens represent a valid
8012 // expression, we simply skip tokens until we reach the end of the
8013 // interpolation, being careful to handle nested string literals.
8014 //
8015 int bracketNestingLevel = 1;
8016 while (bracketNestingLevel > 0) {
8017 if (type == TokenType.EOF) {
8018 return null;
8019 } else if (type == TokenType.OPEN_CURLY_BRACKET) {
8020 bracketNestingLevel++;
8021 } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
8022 bracketNestingLevel--;
8023 } else if (type == TokenType.STRING) {
8024 token = _skipStringLiteral(token);
8025 if (token == null) {
8026 return null;
8027 }
8028 } else {
8029 token = token.next;
8030 }
8031 type = token.type;
8032 }
8033 token = token.next;
8034 type = token.type;
8035 } else {
8036 token = token.next;
8037 if (token.type != TokenType.IDENTIFIER) {
8038 return null;
8039 }
8040 token = token.next;
8041 }
8042 type = token.type;
8043 if (type == TokenType.STRING) {
8044 token = token.next;
8045 type = token.type;
8046 }
8047 }
8048 return token;
8049 }
8050
8051 /**
8052 * Parse a string literal, starting at the [startToken], without actually
8053 * creating a string literal or changing the current token. Return the token
8054 * following the string literal that was parsed, or `null` if the given token
8055 * is not the first token in a valid string literal.
8056 *
8057 * This method must be kept in sync with [parseStringLiteral].
8058 *
8059 * stringLiteral ::=
8060 * MULTI_LINE_STRING+
8061 * | SINGLE_LINE_STRING+
8062 */
8063 Token _skipStringLiteral(Token startToken) {
8064 Token token = startToken;
8065 while (token != null && _tokenMatches(token, TokenType.STRING)) {
8066 token = token.next;
8067 TokenType type = token.type;
8068 if (type == TokenType.STRING_INTERPOLATION_EXPRESSION ||
8069 type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
8070 token = _skipStringInterpolation(token);
8071 }
8072 }
8073 if (identical(token, startToken)) {
8074 return null;
8075 }
8076 return token;
8077 }
8078
8079 /**
8080 * Parse a list of type arguments, starting at the [startToken], without
8081 * actually creating a type argument list or changing the current token.
8082 * Return the token following the type argument list that was parsed, or
8083 * `null` if the given token is not the first token in a valid type argument
8084 * list.
8085 *
8086 * This method must be kept in sync with [parseTypeArgumentList].
8087 *
8088 * typeArguments ::=
8089 * '<' typeList '>'
8090 *
8091 * typeList ::=
8092 * type (',' type)*
8093 */
8094 Token _skipTypeArgumentList(Token startToken) {
8095 Token token = startToken;
8096 if (!_tokenMatches(token, TokenType.LT)) {
8097 return null;
8098 }
8099 token = _skipTypeName(token.next);
8100 if (token == null) {
8101 // If the start token '<' is followed by '>'
8102 // then assume this should be type argument list but is missing a type
8103 token = startToken.next;
8104 if (_tokenMatches(token, TokenType.GT)) {
8105 return token.next;
8106 }
8107 return null;
8108 }
8109 while (_tokenMatches(token, TokenType.COMMA)) {
8110 token = _skipTypeName(token.next);
8111 if (token == null) {
8112 return null;
8113 }
8114 }
8115 if (token.type == TokenType.GT) {
8116 return token.next;
8117 } else if (token.type == TokenType.GT_GT) {
8118 Token second = new Token(TokenType.GT, token.offset + 1);
8119 second.setNextWithoutSettingPrevious(token.next);
8120 return second;
8121 }
8122 return null;
8123 }
8124
8125 /**
8126 * Parse a type name, starting at the [startToken], without actually creating
8127 * a type name or changing the current token. Return the token following the
8128 * type name that was parsed, or `null` if the given token is not the first
8129 * token in a valid type name.
8130 *
8131 * This method must be kept in sync with [parseTypeName].
8132 *
8133 * type ::=
8134 * qualified typeArguments?
8135 */
8136 Token _skipTypeName(Token startToken) {
8137 Token token = _skipPrefixedIdentifier(startToken);
8138 if (token == null) {
8139 return null;
8140 }
8141 if (_tokenMatches(token, TokenType.LT)) {
8142 token = _skipTypeArgumentList(token);
8143 }
8144 return token;
8145 }
8146
8147 /**
8148 * Parse a list of type parameters, starting at the [startToken], without
8149 * actually creating a type parameter list or changing the current token.
8150 * Return the token following the type parameter list that was parsed, or
8151 * `null` if the given token is not the first token in a valid type parameter
8152 * list.
8153 *
8154 * This method must be kept in sync with [parseTypeParameterList].
8155 *
8156 * typeParameterList ::=
8157 * '<' typeParameter (',' typeParameter)* '>'
8158 */
8159 Token _skipTypeParameterList(Token startToken) {
8160 if (!_tokenMatches(startToken, TokenType.LT)) {
8161 return null;
8162 }
8163 //
8164 // We can't skip a type parameter because it can be preceeded by metadata,
8165 // so we just assume that everything before the matching end token is valid.
8166 //
8167 int depth = 1;
8168 Token next = startToken.next;
8169 while (depth > 0) {
8170 if (_tokenMatches(next, TokenType.EOF)) {
8171 return null;
8172 } else if (_tokenMatches(next, TokenType.LT)) {
8173 depth++;
8174 } else if (_tokenMatches(next, TokenType.GT)) {
8175 depth--;
8176 } else if (_tokenMatches(next, TokenType.GT_EQ)) {
8177 if (depth == 1) {
8178 Token fakeEquals = new Token(TokenType.EQ, next.offset + 2);
8179 fakeEquals.setNextWithoutSettingPrevious(next.next);
8180 return fakeEquals;
8181 }
8182 depth--;
8183 } else if (_tokenMatches(next, TokenType.GT_GT)) {
8184 depth -= 2;
8185 } else if (_tokenMatches(next, TokenType.GT_GT_EQ)) {
8186 if (depth < 2) {
8187 return null;
8188 } else if (depth == 2) {
8189 Token fakeEquals = new Token(TokenType.EQ, next.offset + 2);
8190 fakeEquals.setNextWithoutSettingPrevious(next.next);
8191 return fakeEquals;
8192 }
8193 depth -= 2;
8194 }
8195 next = next.next;
8196 }
8197 return next;
8198 }
8199
8200 /**
8201 * Return `true` if the given [token] has the given [type].
8202 */
8203 bool _tokenMatches(Token token, TokenType type) => token.type == type;
8204
8205 /**
8206 * Return `true` if the given [token] is a valid identifier. Valid identifiers
8207 * include built-in identifiers (pseudo-keywords).
8208 */
8209 bool _tokenMatchesIdentifier(Token token) =>
8210 _tokenMatches(token, TokenType.IDENTIFIER) ||
8211 (_tokenMatches(token, TokenType.KEYWORD) &&
8212 (token as KeywordToken).keyword.isPseudoKeyword);
8213
8214 /**
8215 * Return `true` if the given [token] matches the given [keyword].
8216 */
8217 bool _tokenMatchesKeyword(Token token, Keyword keyword) =>
8218 token.type == TokenType.KEYWORD &&
8219 (token as KeywordToken).keyword == keyword;
8220
8221 /**
8222 * Return `true` if the given [token] matches the given [identifier].
8223 */
8224 bool _tokenMatchesString(Token token, String identifier) =>
8225 token.type == TokenType.IDENTIFIER && token.lexeme == identifier;
8226
8227 /**
8228 * Translate the characters at the given [index] in the given [lexeme],
8229 * appending the translated character to the given [buffer]. The index is
8230 * assumed to be valid.
8231 */
8232 int _translateCharacter(StringBuffer buffer, String lexeme, int index) {
8233 int currentChar = lexeme.codeUnitAt(index);
8234 if (currentChar != 0x5C) {
8235 buffer.writeCharCode(currentChar);
8236 return index + 1;
8237 }
8238 //
8239 // We have found an escape sequence, so we parse the string to determine
8240 // what kind of escape sequence and what character to add to the builder.
8241 //
8242 int length = lexeme.length;
8243 int currentIndex = index + 1;
8244 if (currentIndex >= length) {
8245 // Illegal escape sequence: no char after escape.
8246 // This cannot actually happen because it would require the escape
8247 // character to be the last character in the string, but if it were it
8248 // would escape the closing quote, leaving the string unclosed.
8249 // reportError(ParserErrorCode.MISSING_CHAR_IN_ESCAPE_SEQUENCE);
8250 return length;
8251 }
8252 currentChar = lexeme.codeUnitAt(currentIndex);
8253 if (currentChar == 0x6E) {
8254 buffer.writeCharCode(0xA);
8255 // newline
8256 } else if (currentChar == 0x72) {
8257 buffer.writeCharCode(0xD);
8258 // carriage return
8259 } else if (currentChar == 0x66) {
8260 buffer.writeCharCode(0xC);
8261 // form feed
8262 } else if (currentChar == 0x62) {
8263 buffer.writeCharCode(0x8);
8264 // backspace
8265 } else if (currentChar == 0x74) {
8266 buffer.writeCharCode(0x9);
8267 // tab
8268 } else if (currentChar == 0x76) {
8269 buffer.writeCharCode(0xB);
8270 // vertical tab
8271 } else if (currentChar == 0x78) {
8272 if (currentIndex + 2 >= length) {
8273 // Illegal escape sequence: not enough hex digits
8274 _reportErrorForCurrentToken(ParserErrorCode.INVALID_HEX_ESCAPE);
8275 return length;
8276 }
8277 int firstDigit = lexeme.codeUnitAt(currentIndex + 1);
8278 int secondDigit = lexeme.codeUnitAt(currentIndex + 2);
8279 if (!_isHexDigit(firstDigit) || !_isHexDigit(secondDigit)) {
8280 // Illegal escape sequence: invalid hex digit
8281 _reportErrorForCurrentToken(ParserErrorCode.INVALID_HEX_ESCAPE);
8282 } else {
8283 int charCode = (Character.digit(firstDigit, 16) << 4) +
8284 Character.digit(secondDigit, 16);
8285 buffer.writeCharCode(charCode);
8286 }
8287 return currentIndex + 3;
8288 } else if (currentChar == 0x75) {
8289 currentIndex++;
8290 if (currentIndex >= length) {
8291 // Illegal escape sequence: not enough hex digits
8292 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
8293 return length;
8294 }
8295 currentChar = lexeme.codeUnitAt(currentIndex);
8296 if (currentChar == 0x7B) {
8297 currentIndex++;
8298 if (currentIndex >= length) {
8299 // Illegal escape sequence: incomplete escape
8300 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
8301 return length;
8302 }
8303 currentChar = lexeme.codeUnitAt(currentIndex);
8304 int digitCount = 0;
8305 int value = 0;
8306 while (currentChar != 0x7D) {
8307 if (!_isHexDigit(currentChar)) {
8308 // Illegal escape sequence: invalid hex digit
8309 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
8310 currentIndex++;
8311 while (currentIndex < length &&
8312 lexeme.codeUnitAt(currentIndex) != 0x7D) {
8313 currentIndex++;
8314 }
8315 return currentIndex + 1;
8316 }
8317 digitCount++;
8318 value = (value << 4) + Character.digit(currentChar, 16);
8319 currentIndex++;
8320 if (currentIndex >= length) {
8321 // Illegal escape sequence: incomplete escape
8322 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
8323 return length;
8324 }
8325 currentChar = lexeme.codeUnitAt(currentIndex);
8326 }
8327 if (digitCount < 1 || digitCount > 6) {
8328 // Illegal escape sequence: not enough or too many hex digits
8329 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
8330 }
8331 _appendScalarValue(buffer, lexeme.substring(index, currentIndex + 1),
8332 value, index, currentIndex);
8333 return currentIndex + 1;
8334 } else {
8335 if (currentIndex + 3 >= length) {
8336 // Illegal escape sequence: not enough hex digits
8337 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
8338 return length;
8339 }
8340 int firstDigit = currentChar;
8341 int secondDigit = lexeme.codeUnitAt(currentIndex + 1);
8342 int thirdDigit = lexeme.codeUnitAt(currentIndex + 2);
8343 int fourthDigit = lexeme.codeUnitAt(currentIndex + 3);
8344 if (!_isHexDigit(firstDigit) ||
8345 !_isHexDigit(secondDigit) ||
8346 !_isHexDigit(thirdDigit) ||
8347 !_isHexDigit(fourthDigit)) {
8348 // Illegal escape sequence: invalid hex digits
8349 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
8350 } else {
8351 _appendScalarValue(
8352 buffer,
8353 lexeme
8354 .substring(
8355 index,
8356 currentIndex + 1),
8357 (((((Character.digit(firstDigit, 16) << 4) +
8358 Character.digit(secondDigit, 16)) <<
8359 4) +
8360 Character.digit(thirdDigit, 16)) <<
8361 4) +
8362 Character
8363 .digit(fourthDigit, 16),
8364 index,
8365 currentIndex +
8366 3);
8367 }
8368 return currentIndex + 4;
8369 }
8370 } else {
8371 buffer.writeCharCode(currentChar);
8372 }
8373 return currentIndex + 1;
8374 }
8375
8376 /**
8377 * Decrements the error reporting lock level. If level is more than `0`, then
8378 * [reportError] wont report any error.
8379 */
8380 void _unlockErrorListener() {
8381 if (_errorListenerLock == 0) {
8382 throw new IllegalStateException(
8383 "Attempt to unlock not locked error listener.");
8384 }
8385 _errorListenerLock--;
8386 }
8387
8388 /**
8389 * Validate that the given [parameterList] does not contain any field
8390 * initializers.
8391 */
8392 void _validateFormalParameterList(FormalParameterList parameterList) {
8393 for (FormalParameter parameter in parameterList.parameters) {
8394 if (parameter is FieldFormalParameter) {
8395 _reportErrorForNode(
8396 ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
8397 parameter.identifier);
8398 }
8399 }
8400 }
8401
8402 /**
8403 * Validate that the given set of [modifiers] is appropriate for a class and
8404 * return the 'abstract' keyword if there is one.
8405 */
8406 Token _validateModifiersForClass(Modifiers modifiers) {
8407 _validateModifiersForTopLevelDeclaration(modifiers);
8408 if (modifiers.constKeyword != null) {
8409 _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword);
8410 }
8411 if (modifiers.externalKeyword != null) {
8412 _reportErrorForToken(
8413 ParserErrorCode.EXTERNAL_CLASS, modifiers.externalKeyword);
8414 }
8415 if (modifiers.finalKeyword != null) {
8416 _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword);
8417 }
8418 if (modifiers.varKeyword != null) {
8419 _reportErrorForToken(ParserErrorCode.VAR_CLASS, modifiers.varKeyword);
8420 }
8421 return modifiers.abstractKeyword;
8422 }
8423
8424 /**
8425 * Validate that the given set of [modifiers] is appropriate for a constructor
8426 * and return the 'const' keyword if there is one.
8427 */
8428 Token _validateModifiersForConstructor(Modifiers modifiers) {
8429 if (modifiers.abstractKeyword != null) {
8430 _reportErrorForToken(
8431 ParserErrorCode.ABSTRACT_CLASS_MEMBER, modifiers.abstractKeyword);
8432 }
8433 if (modifiers.finalKeyword != null) {
8434 _reportErrorForToken(
8435 ParserErrorCode.FINAL_CONSTRUCTOR, modifiers.finalKeyword);
8436 }
8437 if (modifiers.staticKeyword != null) {
8438 _reportErrorForToken(
8439 ParserErrorCode.STATIC_CONSTRUCTOR, modifiers.staticKeyword);
8440 }
8441 if (modifiers.varKeyword != null) {
8442 _reportErrorForToken(
8443 ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, modifiers.varKeyword);
8444 }
8445 Token externalKeyword = modifiers.externalKeyword;
8446 Token constKeyword = modifiers.constKeyword;
8447 Token factoryKeyword = modifiers.factoryKeyword;
8448 if (externalKeyword != null &&
8449 constKeyword != null &&
8450 constKeyword.offset < externalKeyword.offset) {
8451 _reportErrorForToken(
8452 ParserErrorCode.EXTERNAL_AFTER_CONST, externalKeyword);
8453 }
8454 if (externalKeyword != null &&
8455 factoryKeyword != null &&
8456 factoryKeyword.offset < externalKeyword.offset) {
8457 _reportErrorForToken(
8458 ParserErrorCode.EXTERNAL_AFTER_FACTORY, externalKeyword);
8459 }
8460 return constKeyword;
8461 }
8462
8463 /**
8464 * Validate that the given set of [modifiers] is appropriate for a class and
8465 * return the 'abstract' keyword if there is one.
8466 */
8467 void _validateModifiersForEnum(Modifiers modifiers) {
8468 _validateModifiersForTopLevelDeclaration(modifiers);
8469 if (modifiers.abstractKeyword != null) {
8470 _reportErrorForToken(
8471 ParserErrorCode.ABSTRACT_ENUM, modifiers.abstractKeyword);
8472 }
8473 if (modifiers.constKeyword != null) {
8474 _reportErrorForToken(ParserErrorCode.CONST_ENUM, modifiers.constKeyword);
8475 }
8476 if (modifiers.externalKeyword != null) {
8477 _reportErrorForToken(
8478 ParserErrorCode.EXTERNAL_ENUM, modifiers.externalKeyword);
8479 }
8480 if (modifiers.finalKeyword != null) {
8481 _reportErrorForToken(ParserErrorCode.FINAL_ENUM, modifiers.finalKeyword);
8482 }
8483 if (modifiers.varKeyword != null) {
8484 _reportErrorForToken(ParserErrorCode.VAR_ENUM, modifiers.varKeyword);
8485 }
8486 }
8487
8488 /**
8489 * Validate that the given set of [modifiers] is appropriate for a field and
8490 * return the 'final', 'const' or 'var' keyword if there is one.
8491 */
8492 Token _validateModifiersForField(Modifiers modifiers) {
8493 if (modifiers.abstractKeyword != null) {
8494 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
8495 }
8496 if (modifiers.externalKeyword != null) {
8497 _reportErrorForToken(
8498 ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword);
8499 }
8500 if (modifiers.factoryKeyword != null) {
8501 _reportErrorForToken(
8502 ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKeyword);
8503 }
8504 Token staticKeyword = modifiers.staticKeyword;
8505 Token constKeyword = modifiers.constKeyword;
8506 Token finalKeyword = modifiers.finalKeyword;
8507 Token varKeyword = modifiers.varKeyword;
8508 if (constKeyword != null) {
8509 if (finalKeyword != null) {
8510 _reportErrorForToken(ParserErrorCode.CONST_AND_FINAL, finalKeyword);
8511 }
8512 if (varKeyword != null) {
8513 _reportErrorForToken(ParserErrorCode.CONST_AND_VAR, varKeyword);
8514 }
8515 if (staticKeyword != null && constKeyword.offset < staticKeyword.offset) {
8516 _reportErrorForToken(ParserErrorCode.STATIC_AFTER_CONST, staticKeyword);
8517 }
8518 } else if (finalKeyword != null) {
8519 if (varKeyword != null) {
8520 _reportErrorForToken(ParserErrorCode.FINAL_AND_VAR, varKeyword);
8521 }
8522 if (staticKeyword != null && finalKeyword.offset < staticKeyword.offset) {
8523 _reportErrorForToken(ParserErrorCode.STATIC_AFTER_FINAL, staticKeyword);
8524 }
8525 } else if (varKeyword != null &&
8526 staticKeyword != null &&
8527 varKeyword.offset < staticKeyword.offset) {
8528 _reportErrorForToken(ParserErrorCode.STATIC_AFTER_VAR, staticKeyword);
8529 }
8530 return Token.lexicallyFirst([constKeyword, finalKeyword, varKeyword]);
8531 }
8532
8533 /**
8534 * Validate that the given set of [modifiers] is appropriate for a local
8535 * function.
8536 */
8537 void _validateModifiersForFunctionDeclarationStatement(Modifiers modifiers) {
8538 if (modifiers.abstractKeyword != null ||
8539 modifiers.constKeyword != null ||
8540 modifiers.externalKeyword != null ||
8541 modifiers.factoryKeyword != null ||
8542 modifiers.finalKeyword != null ||
8543 modifiers.staticKeyword != null ||
8544 modifiers.varKeyword != null) {
8545 _reportErrorForCurrentToken(
8546 ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER);
8547 }
8548 }
8549
8550 /**
8551 * Validate that the given set of [modifiers] is appropriate for a getter,
8552 * setter, or method.
8553 */
8554 void _validateModifiersForGetterOrSetterOrMethod(Modifiers modifiers) {
8555 if (modifiers.abstractKeyword != null) {
8556 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
8557 }
8558 if (modifiers.constKeyword != null) {
8559 _reportErrorForToken(
8560 ParserErrorCode.CONST_METHOD, modifiers.constKeyword);
8561 }
8562 if (modifiers.factoryKeyword != null) {
8563 _reportErrorForToken(
8564 ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKeyword);
8565 }
8566 if (modifiers.finalKeyword != null) {
8567 _reportErrorForToken(
8568 ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword);
8569 }
8570 if (modifiers.varKeyword != null) {
8571 _reportErrorForToken(
8572 ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword);
8573 }
8574 Token externalKeyword = modifiers.externalKeyword;
8575 Token staticKeyword = modifiers.staticKeyword;
8576 if (externalKeyword != null &&
8577 staticKeyword != null &&
8578 staticKeyword.offset < externalKeyword.offset) {
8579 _reportErrorForToken(
8580 ParserErrorCode.EXTERNAL_AFTER_STATIC, externalKeyword);
8581 }
8582 }
8583
8584 /**
8585 * Validate that the given set of [modifiers] is appropriate for a getter,
8586 * setter, or method.
8587 */
8588 void _validateModifiersForOperator(Modifiers modifiers) {
8589 if (modifiers.abstractKeyword != null) {
8590 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
8591 }
8592 if (modifiers.constKeyword != null) {
8593 _reportErrorForToken(
8594 ParserErrorCode.CONST_METHOD, modifiers.constKeyword);
8595 }
8596 if (modifiers.factoryKeyword != null) {
8597 _reportErrorForToken(
8598 ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKeyword);
8599 }
8600 if (modifiers.finalKeyword != null) {
8601 _reportErrorForToken(
8602 ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword);
8603 }
8604 if (modifiers.staticKeyword != null) {
8605 _reportErrorForToken(
8606 ParserErrorCode.STATIC_OPERATOR, modifiers.staticKeyword);
8607 }
8608 if (modifiers.varKeyword != null) {
8609 _reportErrorForToken(
8610 ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword);
8611 }
8612 }
8613
8614 /**
8615 * Validate that the given set of [modifiers] is appropriate for a top-level
8616 * declaration.
8617 */
8618 void _validateModifiersForTopLevelDeclaration(Modifiers modifiers) {
8619 if (modifiers.factoryKeyword != null) {
8620 _reportErrorForToken(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION,
8621 modifiers.factoryKeyword);
8622 }
8623 if (modifiers.staticKeyword != null) {
8624 _reportErrorForToken(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION,
8625 modifiers.staticKeyword);
8626 }
8627 }
8628
8629 /**
8630 * Validate that the given set of [modifiers] is appropriate for a top-level
8631 * function.
8632 */
8633 void _validateModifiersForTopLevelFunction(Modifiers modifiers) {
8634 _validateModifiersForTopLevelDeclaration(modifiers);
8635 if (modifiers.abstractKeyword != null) {
8636 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION);
8637 }
8638 if (modifiers.constKeyword != null) {
8639 _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword);
8640 }
8641 if (modifiers.finalKeyword != null) {
8642 _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword);
8643 }
8644 if (modifiers.varKeyword != null) {
8645 _reportErrorForToken(
8646 ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword);
8647 }
8648 }
8649
8650 /**
8651 * Validate that the given set of [modifiers] is appropriate for a field and
8652 * return the 'final', 'const' or 'var' keyword if there is one.
8653 */
8654 Token _validateModifiersForTopLevelVariable(Modifiers modifiers) {
8655 _validateModifiersForTopLevelDeclaration(modifiers);
8656 if (modifiers.abstractKeyword != null) {
8657 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE);
8658 }
8659 if (modifiers.externalKeyword != null) {
8660 _reportErrorForToken(
8661 ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword);
8662 }
8663 Token constKeyword = modifiers.constKeyword;
8664 Token finalKeyword = modifiers.finalKeyword;
8665 Token varKeyword = modifiers.varKeyword;
8666 if (constKeyword != null) {
8667 if (finalKeyword != null) {
8668 _reportErrorForToken(ParserErrorCode.CONST_AND_FINAL, finalKeyword);
8669 }
8670 if (varKeyword != null) {
8671 _reportErrorForToken(ParserErrorCode.CONST_AND_VAR, varKeyword);
8672 }
8673 } else if (finalKeyword != null) {
8674 if (varKeyword != null) {
8675 _reportErrorForToken(ParserErrorCode.FINAL_AND_VAR, varKeyword);
8676 }
8677 }
8678 return Token.lexicallyFirst([constKeyword, finalKeyword, varKeyword]);
8679 }
8680
8681 /**
8682 * Validate that the given set of [modifiers] is appropriate for a class and
8683 * return the 'abstract' keyword if there is one.
8684 */
8685 void _validateModifiersForTypedef(Modifiers modifiers) {
8686 _validateModifiersForTopLevelDeclaration(modifiers);
8687 if (modifiers.abstractKeyword != null) {
8688 _reportErrorForToken(
8689 ParserErrorCode.ABSTRACT_TYPEDEF, modifiers.abstractKeyword);
8690 }
8691 if (modifiers.constKeyword != null) {
8692 _reportErrorForToken(
8693 ParserErrorCode.CONST_TYPEDEF, modifiers.constKeyword);
8694 }
8695 if (modifiers.externalKeyword != null) {
8696 _reportErrorForToken(
8697 ParserErrorCode.EXTERNAL_TYPEDEF, modifiers.externalKeyword);
8698 }
8699 if (modifiers.finalKeyword != null) {
8700 _reportErrorForToken(
8701 ParserErrorCode.FINAL_TYPEDEF, modifiers.finalKeyword);
8702 }
8703 if (modifiers.varKeyword != null) {
8704 _reportErrorForToken(ParserErrorCode.VAR_TYPEDEF, modifiers.varKeyword);
8705 }
8706 }
8707 }
8708 /**
8709 * A synthetic keyword token.
8710 */
8711 class Parser_SyntheticKeywordToken extends KeywordToken {
8712 /**
8713 * Initialize a newly created token to represent the given [keyword] at the
8714 * given [offset].
8715 */
8716 Parser_SyntheticKeywordToken(Keyword keyword, int offset)
8717 : super(keyword, offset);
8718
8719 @override
8720 int get length => 0;
8721
8722 @override
8723 Token copy() => new Parser_SyntheticKeywordToken(keyword, offset);
8724 }
8725
8726 /**
8727 * The error codes used for errors detected by the parser. The convention for
8728 * this class is for the name of the error code to indicate the problem that
8729 * caused the error to be generated and for the error message to explain what
8730 * is wrong and, when appropriate, how the problem can be corrected.
8731 */
8732 class ParserErrorCode extends ErrorCode {
8733 static const ParserErrorCode ABSTRACT_CLASS_MEMBER = const ParserErrorCode(
8734 'ABSTRACT_CLASS_MEMBER',
8735 "Members of classes cannot be declared to be 'abstract'");
8736
8737 static const ParserErrorCode ABSTRACT_ENUM = const ParserErrorCode(
8738 'ABSTRACT_ENUM', "Enums cannot be declared to be 'abstract'");
8739
8740 static const ParserErrorCode ABSTRACT_STATIC_METHOD = const ParserErrorCode(
8741 'ABSTRACT_STATIC_METHOD',
8742 "Static methods cannot be declared to be 'abstract'");
8743
8744 static const ParserErrorCode ABSTRACT_TOP_LEVEL_FUNCTION =
8745 const ParserErrorCode('ABSTRACT_TOP_LEVEL_FUNCTION',
8746 "Top-level functions cannot be declared to be 'abstract'");
8747
8748 static const ParserErrorCode ABSTRACT_TOP_LEVEL_VARIABLE =
8749 const ParserErrorCode('ABSTRACT_TOP_LEVEL_VARIABLE',
8750 "Top-level variables cannot be declared to be 'abstract'");
8751
8752 static const ParserErrorCode ABSTRACT_TYPEDEF = const ParserErrorCode(
8753 'ABSTRACT_TYPEDEF', "Type aliases cannot be declared to be 'abstract'");
8754
8755 static const ParserErrorCode ANNOTATION_ON_ENUM_CONSTANT =
8756 const ParserErrorCode('ANNOTATION_ON_ENUM_CONSTANT',
8757 "Enum constants cannot have annotations");
8758
8759 static const ParserErrorCode ASSERT_DOES_NOT_TAKE_ASSIGNMENT =
8760 const ParserErrorCode('ASSERT_DOES_NOT_TAKE_ASSIGNMENT',
8761 "Assert cannot be called on an assignment");
8762
8763 static const ParserErrorCode ASSERT_DOES_NOT_TAKE_CASCADE =
8764 const ParserErrorCode(
8765 'ASSERT_DOES_NOT_TAKE_CASCADE', "Assert cannot be called on cascade");
8766
8767 static const ParserErrorCode ASSERT_DOES_NOT_TAKE_THROW =
8768 const ParserErrorCode(
8769 'ASSERT_DOES_NOT_TAKE_THROW', "Assert cannot be called on throws");
8770
8771 static const ParserErrorCode ASSERT_DOES_NOT_TAKE_RETHROW =
8772 const ParserErrorCode('ASSERT_DOES_NOT_TAKE_RETHROW',
8773 "Assert cannot be called on rethrows");
8774
8775 /**
8776 * 16.32 Identifier Reference: It is a compile-time error if any of the
8777 * identifiers async, await, or yield is used as an identifier in a function
8778 * body marked with either async, async*, or sync*.
8779 */
8780 static const ParserErrorCode ASYNC_KEYWORD_USED_AS_IDENTIFIER =
8781 const ParserErrorCode('ASYNC_KEYWORD_USED_AS_IDENTIFIER',
8782 "The keywords 'async', 'await', and 'yield' may not be used as identif iers in an asynchronous or generator function.");
8783
8784 static const ParserErrorCode BREAK_OUTSIDE_OF_LOOP = const ParserErrorCode(
8785 'BREAK_OUTSIDE_OF_LOOP',
8786 "A break statement cannot be used outside of a loop or switch statement");
8787
8788 static const ParserErrorCode CLASS_IN_CLASS = const ParserErrorCode(
8789 'CLASS_IN_CLASS', "Classes cannot be declared inside other classes");
8790
8791 static const ParserErrorCode COLON_IN_PLACE_OF_IN = const ParserErrorCode(
8792 'COLON_IN_PLACE_OF_IN', "For-in loops use 'in' rather than a colon");
8793
8794 static const ParserErrorCode CONST_AND_FINAL = const ParserErrorCode(
8795 'CONST_AND_FINAL',
8796 "Members cannot be declared to be both 'const' and 'final'");
8797
8798 static const ParserErrorCode CONST_AND_VAR = const ParserErrorCode(
8799 'CONST_AND_VAR',
8800 "Members cannot be declared to be both 'const' and 'var'");
8801
8802 static const ParserErrorCode CONST_CLASS = const ParserErrorCode(
8803 'CONST_CLASS', "Classes cannot be declared to be 'const'");
8804
8805 static const ParserErrorCode CONST_CONSTRUCTOR_WITH_BODY =
8806 const ParserErrorCode('CONST_CONSTRUCTOR_WITH_BODY',
8807 "'const' constructors cannot have a body");
8808
8809 static const ParserErrorCode CONST_ENUM = const ParserErrorCode(
8810 'CONST_ENUM', "Enums cannot be declared to be 'const'");
8811
8812 static const ParserErrorCode CONST_FACTORY = const ParserErrorCode(
8813 'CONST_FACTORY',
8814 "Only redirecting factory constructors can be declared to be 'const'");
8815
8816 static const ParserErrorCode CONST_METHOD = const ParserErrorCode(
8817 'CONST_METHOD',
8818 "Getters, setters and methods cannot be declared to be 'const'");
8819
8820 static const ParserErrorCode CONST_TYPEDEF = const ParserErrorCode(
8821 'CONST_TYPEDEF', "Type aliases cannot be declared to be 'const'");
8822
8823 static const ParserErrorCode CONSTRUCTOR_WITH_RETURN_TYPE =
8824 const ParserErrorCode('CONSTRUCTOR_WITH_RETURN_TYPE',
8825 "Constructors cannot have a return type");
8826
8827 static const ParserErrorCode CONTINUE_OUTSIDE_OF_LOOP = const ParserErrorCode(
8828 'CONTINUE_OUTSIDE_OF_LOOP',
8829 "A continue statement cannot be used outside of a loop or switch statement ");
8830
8831 static const ParserErrorCode CONTINUE_WITHOUT_LABEL_IN_CASE =
8832 const ParserErrorCode('CONTINUE_WITHOUT_LABEL_IN_CASE',
8833 "A continue statement in a switch statement must have a label as a tar get");
8834
8835 static const ParserErrorCode DEPRECATED_CLASS_TYPE_ALIAS =
8836 const ParserErrorCode('DEPRECATED_CLASS_TYPE_ALIAS',
8837 "The 'typedef' mixin application was replaced with 'class'");
8838
8839 static const ParserErrorCode DIRECTIVE_AFTER_DECLARATION =
8840 const ParserErrorCode('DIRECTIVE_AFTER_DECLARATION',
8841 "Directives must appear before any declarations");
8842
8843 static const ParserErrorCode DUPLICATE_LABEL_IN_SWITCH_STATEMENT =
8844 const ParserErrorCode('DUPLICATE_LABEL_IN_SWITCH_STATEMENT',
8845 "The label {0} was already used in this switch statement");
8846
8847 static const ParserErrorCode DUPLICATED_MODIFIER = const ParserErrorCode(
8848 'DUPLICATED_MODIFIER', "The modifier '{0}' was already specified.");
8849
8850 static const ParserErrorCode EMPTY_ENUM_BODY = const ParserErrorCode(
8851 'EMPTY_ENUM_BODY', "An enum must declare at least one constant name");
8852
8853 static const ParserErrorCode ENUM_IN_CLASS = const ParserErrorCode(
8854 'ENUM_IN_CLASS', "Enums cannot be declared inside classes");
8855
8856 static const ParserErrorCode EQUALITY_CANNOT_BE_EQUALITY_OPERAND =
8857 const ParserErrorCode('EQUALITY_CANNOT_BE_EQUALITY_OPERAND',
8858 "Equality expression cannot be operand of another equality expression. ");
8859
8860 static const ParserErrorCode EXPECTED_CASE_OR_DEFAULT = const ParserErrorCode(
8861 'EXPECTED_CASE_OR_DEFAULT', "Expected 'case' or 'default'");
8862
8863 static const ParserErrorCode EXPECTED_CLASS_MEMBER =
8864 const ParserErrorCode('EXPECTED_CLASS_MEMBER', "Expected a class member");
8865
8866 static const ParserErrorCode EXPECTED_EXECUTABLE = const ParserErrorCode(
8867 'EXPECTED_EXECUTABLE',
8868 "Expected a method, getter, setter or operator declaration");
8869
8870 static const ParserErrorCode EXPECTED_LIST_OR_MAP_LITERAL =
8871 const ParserErrorCode(
8872 'EXPECTED_LIST_OR_MAP_LITERAL', "Expected a list or map literal");
8873
8874 static const ParserErrorCode EXPECTED_STRING_LITERAL = const ParserErrorCode(
8875 'EXPECTED_STRING_LITERAL', "Expected a string literal");
8876
8877 static const ParserErrorCode EXPECTED_TOKEN =
8878 const ParserErrorCode('EXPECTED_TOKEN', "Expected to find '{0}'");
8879
8880 static const ParserErrorCode EXPECTED_TYPE_NAME =
8881 const ParserErrorCode('EXPECTED_TYPE_NAME', "Expected a type name");
8882
8883 static const ParserErrorCode EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE =
8884 const ParserErrorCode('EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE',
8885 "Export directives must preceed part directives");
8886
8887 static const ParserErrorCode EXTERNAL_AFTER_CONST = const ParserErrorCode(
8888 'EXTERNAL_AFTER_CONST',
8889 "The modifier 'external' should be before the modifier 'const'");
8890
8891 static const ParserErrorCode EXTERNAL_AFTER_FACTORY = const ParserErrorCode(
8892 'EXTERNAL_AFTER_FACTORY',
8893 "The modifier 'external' should be before the modifier 'factory'");
8894
8895 static const ParserErrorCode EXTERNAL_AFTER_STATIC = const ParserErrorCode(
8896 'EXTERNAL_AFTER_STATIC',
8897 "The modifier 'external' should be before the modifier 'static'");
8898
8899 static const ParserErrorCode EXTERNAL_CLASS = const ParserErrorCode(
8900 'EXTERNAL_CLASS', "Classes cannot be declared to be 'external'");
8901
8902 static const ParserErrorCode EXTERNAL_CONSTRUCTOR_WITH_BODY =
8903 const ParserErrorCode('EXTERNAL_CONSTRUCTOR_WITH_BODY',
8904 "External constructors cannot have a body");
8905
8906 static const ParserErrorCode EXTERNAL_ENUM = const ParserErrorCode(
8907 'EXTERNAL_ENUM', "Enums cannot be declared to be 'external'");
8908
8909 static const ParserErrorCode EXTERNAL_FIELD = const ParserErrorCode(
8910 'EXTERNAL_FIELD', "Fields cannot be declared to be 'external'");
8911
8912 static const ParserErrorCode EXTERNAL_GETTER_WITH_BODY =
8913 const ParserErrorCode(
8914 'EXTERNAL_GETTER_WITH_BODY', "External getters cannot have a body");
8915
8916 static const ParserErrorCode EXTERNAL_METHOD_WITH_BODY =
8917 const ParserErrorCode(
8918 'EXTERNAL_METHOD_WITH_BODY', "External methods cannot have a body");
8919
8920 static const ParserErrorCode EXTERNAL_OPERATOR_WITH_BODY =
8921 const ParserErrorCode('EXTERNAL_OPERATOR_WITH_BODY',
8922 "External operators cannot have a body");
8923
8924 static const ParserErrorCode EXTERNAL_SETTER_WITH_BODY =
8925 const ParserErrorCode(
8926 'EXTERNAL_SETTER_WITH_BODY', "External setters cannot have a body");
8927
8928 static const ParserErrorCode EXTERNAL_TYPEDEF = const ParserErrorCode(
8929 'EXTERNAL_TYPEDEF', "Type aliases cannot be declared to be 'external'");
8930
8931 static const ParserErrorCode FACTORY_TOP_LEVEL_DECLARATION =
8932 const ParserErrorCode('FACTORY_TOP_LEVEL_DECLARATION',
8933 "Top-level declarations cannot be declared to be 'factory'");
8934
8935 static const ParserErrorCode FACTORY_WITH_INITIALIZERS =
8936 const ParserErrorCode('FACTORY_WITH_INITIALIZERS',
8937 "A 'factory' constructor cannot have initializers",
8938 "Either remove the 'factory' keyword to make this a generative "
8939 "constructor or remove the initializers.");
8940
8941 static const ParserErrorCode FACTORY_WITHOUT_BODY = const ParserErrorCode(
8942 'FACTORY_WITHOUT_BODY',
8943 "A non-redirecting 'factory' constructor must have a body");
8944
8945 static const ParserErrorCode FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR =
8946 const ParserErrorCode('FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR',
8947 "Field initializers can only be used in a constructor");
8948
8949 static const ParserErrorCode FINAL_AND_VAR = const ParserErrorCode(
8950 'FINAL_AND_VAR',
8951 "Members cannot be declared to be both 'final' and 'var'");
8952
8953 static const ParserErrorCode FINAL_CLASS = const ParserErrorCode(
8954 'FINAL_CLASS', "Classes cannot be declared to be 'final'");
8955
8956 static const ParserErrorCode FINAL_CONSTRUCTOR = const ParserErrorCode(
8957 'FINAL_CONSTRUCTOR', "A constructor cannot be declared to be 'final'");
8958
8959 static const ParserErrorCode FINAL_ENUM = const ParserErrorCode(
8960 'FINAL_ENUM', "Enums cannot be declared to be 'final'");
8961
8962 static const ParserErrorCode FINAL_METHOD = const ParserErrorCode(
8963 'FINAL_METHOD',
8964 "Getters, setters and methods cannot be declared to be 'final'");
8965
8966 static const ParserErrorCode FINAL_TYPEDEF = const ParserErrorCode(
8967 'FINAL_TYPEDEF', "Type aliases cannot be declared to be 'final'");
8968
8969 static const ParserErrorCode FUNCTION_TYPED_PARAMETER_VAR = const ParserErrorC ode(
8970 'FUNCTION_TYPED_PARAMETER_VAR',
8971 "Function typed parameters cannot specify 'const', 'final' or 'var' instea d of return type");
8972
8973 static const ParserErrorCode GETTER_IN_FUNCTION = const ParserErrorCode(
8974 'GETTER_IN_FUNCTION',
8975 "Getters cannot be defined within methods or functions");
8976
8977 static const ParserErrorCode GETTER_WITH_PARAMETERS = const ParserErrorCode(
8978 'GETTER_WITH_PARAMETERS',
8979 "Getter should be declared without a parameter list");
8980
8981 static const ParserErrorCode ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE =
8982 const ParserErrorCode('ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE',
8983 "Illegal assignment to non-assignable expression");
8984
8985 static const ParserErrorCode IMPLEMENTS_BEFORE_EXTENDS =
8986 const ParserErrorCode('IMPLEMENTS_BEFORE_EXTENDS',
8987 "The extends clause must be before the implements clause");
8988
8989 static const ParserErrorCode IMPLEMENTS_BEFORE_WITH = const ParserErrorCode(
8990 'IMPLEMENTS_BEFORE_WITH',
8991 "The with clause must be before the implements clause");
8992
8993 static const ParserErrorCode IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE =
8994 const ParserErrorCode('IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE',
8995 "Import directives must preceed part directives");
8996
8997 static const ParserErrorCode INITIALIZED_VARIABLE_IN_FOR_EACH =
8998 const ParserErrorCode('INITIALIZED_VARIABLE_IN_FOR_EACH',
8999 "The loop variable in a for-each loop cannot be initialized");
9000
9001 static const ParserErrorCode INVALID_AWAIT_IN_FOR = const ParserErrorCode(
9002 'INVALID_AWAIT_IN_FOR',
9003 "The modifier 'await' is not allowed for a normal 'for' statement",
9004 "Remove the keyword or use a for-each statement.");
9005
9006 static const ParserErrorCode INVALID_CODE_POINT = const ParserErrorCode(
9007 'INVALID_CODE_POINT',
9008 "The escape sequence '{0}' is not a valid code point");
9009
9010 static const ParserErrorCode INVALID_COMMENT_REFERENCE = const ParserErrorCode (
9011 'INVALID_COMMENT_REFERENCE',
9012 "Comment references should contain a possibly prefixed identifier and can start with 'new', but should not contain anything else");
9013
9014 static const ParserErrorCode INVALID_HEX_ESCAPE = const ParserErrorCode(
9015 'INVALID_HEX_ESCAPE',
9016 "An escape sequence starting with '\\x' must be followed by 2 hexidecimal digits");
9017
9018 static const ParserErrorCode INVALID_OPERATOR = const ParserErrorCode(
9019 'INVALID_OPERATOR', "The string '{0}' is not a valid operator");
9020
9021 static const ParserErrorCode INVALID_OPERATOR_FOR_SUPER =
9022 const ParserErrorCode('INVALID_OPERATOR_FOR_SUPER',
9023 "The operator '{0}' cannot be used with 'super'");
9024
9025 static const ParserErrorCode INVALID_STAR_AFTER_ASYNC = const ParserErrorCode(
9026 'INVALID_STAR_AFTER_ASYNC',
9027 "The modifier 'async*' is not allowed for an expression function body",
9028 "Convert the body to a block.");
9029
9030 static const ParserErrorCode INVALID_SYNC = const ParserErrorCode(
9031 'INVALID_SYNC',
9032 "The modifier 'sync' is not allowed for an exrpression function body",
9033 "Convert the body to a block.");
9034
9035 static const ParserErrorCode INVALID_UNICODE_ESCAPE = const ParserErrorCode(
9036 'INVALID_UNICODE_ESCAPE',
9037 "An escape sequence starting with '\\u' must be followed by 4 hexidecimal digits or from 1 to 6 digits between '{' and '}'");
9038
9039 static const ParserErrorCode LIBRARY_DIRECTIVE_NOT_FIRST =
9040 const ParserErrorCode('LIBRARY_DIRECTIVE_NOT_FIRST',
9041 "The library directive must appear before all other directives");
9042
9043 static const ParserErrorCode LOCAL_FUNCTION_DECLARATION_MODIFIER =
9044 const ParserErrorCode('LOCAL_FUNCTION_DECLARATION_MODIFIER',
9045 "Local function declarations cannot specify any modifier");
9046
9047 static const ParserErrorCode MISSING_ASSIGNABLE_SELECTOR =
9048 const ParserErrorCode('MISSING_ASSIGNABLE_SELECTOR',
9049 "Missing selector such as \".<identifier>\" or \"[0]\"");
9050
9051 static const ParserErrorCode MISSING_ASSIGNMENT_IN_INITIALIZER =
9052 const ParserErrorCode('MISSING_ASSIGNMENT_IN_INITIALIZER',
9053 "Expected an assignment after the field name");
9054
9055 static const ParserErrorCode MISSING_CATCH_OR_FINALLY = const ParserErrorCode(
9056 'MISSING_CATCH_OR_FINALLY',
9057 "A try statement must have either a catch or finally clause");
9058
9059 static const ParserErrorCode MISSING_CLASS_BODY = const ParserErrorCode(
9060 'MISSING_CLASS_BODY',
9061 "A class definition must have a body, even if it is empty");
9062
9063 static const ParserErrorCode MISSING_CLOSING_PARENTHESIS =
9064 const ParserErrorCode(
9065 'MISSING_CLOSING_PARENTHESIS', "The closing parenthesis is missing");
9066
9067 static const ParserErrorCode MISSING_CONST_FINAL_VAR_OR_TYPE =
9068 const ParserErrorCode('MISSING_CONST_FINAL_VAR_OR_TYPE',
9069 "Variables must be declared using the keywords 'const', 'final', 'var' or a type name");
9070
9071 static const ParserErrorCode MISSING_ENUM_BODY = const ParserErrorCode(
9072 'MISSING_ENUM_BODY',
9073 "An enum definition must have a body with at least one constant name");
9074
9075 static const ParserErrorCode MISSING_EXPRESSION_IN_INITIALIZER =
9076 const ParserErrorCode('MISSING_EXPRESSION_IN_INITIALIZER',
9077 "Expected an expression after the assignment operator");
9078
9079 static const ParserErrorCode MISSING_EXPRESSION_IN_THROW =
9080 const ParserErrorCode('MISSING_EXPRESSION_IN_THROW',
9081 "Throw expressions must compute the object to be thrown");
9082
9083 static const ParserErrorCode MISSING_FUNCTION_BODY = const ParserErrorCode(
9084 'MISSING_FUNCTION_BODY', "A function body must be provided");
9085
9086 static const ParserErrorCode MISSING_FUNCTION_PARAMETERS =
9087 const ParserErrorCode('MISSING_FUNCTION_PARAMETERS',
9088 "Functions must have an explicit list of parameters");
9089
9090 static const ParserErrorCode MISSING_METHOD_PARAMETERS =
9091 const ParserErrorCode('MISSING_METHOD_PARAMETERS',
9092 "Methods must have an explicit list of parameters");
9093
9094 static const ParserErrorCode MISSING_GET = const ParserErrorCode(
9095 'MISSING_GET',
9096 "Getters must have the keyword 'get' before the getter name");
9097
9098 static const ParserErrorCode MISSING_IDENTIFIER =
9099 const ParserErrorCode('MISSING_IDENTIFIER', "Expected an identifier");
9100
9101 static const ParserErrorCode MISSING_INITIALIZER =
9102 const ParserErrorCode('MISSING_INITIALIZER', "Expected an initializer");
9103
9104 static const ParserErrorCode MISSING_KEYWORD_OPERATOR = const ParserErrorCode(
9105 'MISSING_KEYWORD_OPERATOR',
9106 "Operator declarations must be preceeded by the keyword 'operator'");
9107
9108 static const ParserErrorCode MISSING_NAME_IN_LIBRARY_DIRECTIVE =
9109 const ParserErrorCode('MISSING_NAME_IN_LIBRARY_DIRECTIVE',
9110 "Library directives must include a library name");
9111
9112 static const ParserErrorCode MISSING_NAME_IN_PART_OF_DIRECTIVE =
9113 const ParserErrorCode('MISSING_NAME_IN_PART_OF_DIRECTIVE',
9114 "Library directives must include a library name");
9115
9116 static const ParserErrorCode MISSING_PREFIX_IN_DEFERRED_IMPORT =
9117 const ParserErrorCode('MISSING_PREFIX_IN_DEFERRED_IMPORT',
9118 "Deferred imports must have a prefix");
9119
9120 static const ParserErrorCode MISSING_STAR_AFTER_SYNC = const ParserErrorCode(
9121 'MISSING_STAR_AFTER_SYNC',
9122 "The modifier 'sync' must be followed by a star ('*')",
9123 "Remove the modifier or add a star.");
9124
9125 static const ParserErrorCode MISSING_STATEMENT =
9126 const ParserErrorCode('MISSING_STATEMENT', "Expected a statement");
9127
9128 static const ParserErrorCode MISSING_TERMINATOR_FOR_PARAMETER_GROUP =
9129 const ParserErrorCode('MISSING_TERMINATOR_FOR_PARAMETER_GROUP',
9130 "There is no '{0}' to close the parameter group");
9131
9132 static const ParserErrorCode MISSING_TYPEDEF_PARAMETERS =
9133 const ParserErrorCode('MISSING_TYPEDEF_PARAMETERS',
9134 "Type aliases for functions must have an explicit list of parameters") ;
9135
9136 static const ParserErrorCode MISSING_VARIABLE_IN_FOR_EACH = const ParserErrorC ode(
9137 'MISSING_VARIABLE_IN_FOR_EACH',
9138 "A loop variable must be declared in a for-each loop before the 'in', but none were found");
9139
9140 static const ParserErrorCode MIXED_PARAMETER_GROUPS = const ParserErrorCode(
9141 'MIXED_PARAMETER_GROUPS',
9142 "Cannot have both positional and named parameters in a single parameter li st");
9143
9144 static const ParserErrorCode MULTIPLE_EXTENDS_CLAUSES = const ParserErrorCode(
9145 'MULTIPLE_EXTENDS_CLAUSES',
9146 "Each class definition can have at most one extends clause");
9147
9148 static const ParserErrorCode MULTIPLE_IMPLEMENTS_CLAUSES =
9149 const ParserErrorCode('MULTIPLE_IMPLEMENTS_CLAUSES',
9150 "Each class definition can have at most one implements clause");
9151
9152 static const ParserErrorCode MULTIPLE_LIBRARY_DIRECTIVES =
9153 const ParserErrorCode('MULTIPLE_LIBRARY_DIRECTIVES',
9154 "Only one library directive may be declared in a file");
9155
9156 static const ParserErrorCode MULTIPLE_NAMED_PARAMETER_GROUPS =
9157 const ParserErrorCode('MULTIPLE_NAMED_PARAMETER_GROUPS',
9158 "Cannot have multiple groups of named parameters in a single parameter list");
9159
9160 static const ParserErrorCode MULTIPLE_PART_OF_DIRECTIVES =
9161 const ParserErrorCode('MULTIPLE_PART_OF_DIRECTIVES',
9162 "Only one part-of directive may be declared in a file");
9163
9164 static const ParserErrorCode MULTIPLE_POSITIONAL_PARAMETER_GROUPS =
9165 const ParserErrorCode('MULTIPLE_POSITIONAL_PARAMETER_GROUPS',
9166 "Cannot have multiple groups of positional parameters in a single para meter list");
9167
9168 static const ParserErrorCode MULTIPLE_VARIABLES_IN_FOR_EACH =
9169 const ParserErrorCode('MULTIPLE_VARIABLES_IN_FOR_EACH',
9170 "A single loop variable must be declared in a for-each loop before the 'in', but {0} were found");
9171
9172 static const ParserErrorCode MULTIPLE_WITH_CLAUSES = const ParserErrorCode(
9173 'MULTIPLE_WITH_CLAUSES',
9174 "Each class definition can have at most one with clause");
9175
9176 static const ParserErrorCode NAMED_FUNCTION_EXPRESSION =
9177 const ParserErrorCode(
9178 'NAMED_FUNCTION_EXPRESSION', "Function expressions cannot be named");
9179
9180 static const ParserErrorCode NAMED_PARAMETER_OUTSIDE_GROUP =
9181 const ParserErrorCode('NAMED_PARAMETER_OUTSIDE_GROUP',
9182 "Named parameters must be enclosed in curly braces ('{' and '}')");
9183
9184 static const ParserErrorCode NATIVE_CLAUSE_IN_NON_SDK_CODE =
9185 const ParserErrorCode('NATIVE_CLAUSE_IN_NON_SDK_CODE',
9186 "Native clause can only be used in the SDK and code that is loaded thr ough native extensions");
9187
9188 static const ParserErrorCode NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE =
9189 const ParserErrorCode('NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE',
9190 "Native functions can only be declared in the SDK and code that is loa ded through native extensions");
9191
9192 static const ParserErrorCode NON_CONSTRUCTOR_FACTORY = const ParserErrorCode(
9193 'NON_CONSTRUCTOR_FACTORY',
9194 "Only constructors can be declared to be a 'factory'");
9195
9196 static const ParserErrorCode NON_IDENTIFIER_LIBRARY_NAME =
9197 const ParserErrorCode('NON_IDENTIFIER_LIBRARY_NAME',
9198 "The name of a library must be an identifier");
9199
9200 static const ParserErrorCode NON_PART_OF_DIRECTIVE_IN_PART =
9201 const ParserErrorCode('NON_PART_OF_DIRECTIVE_IN_PART',
9202 "The part-of directive must be the only directive in a part");
9203
9204 static const ParserErrorCode NON_STRING_LITERAL_AS_URI =
9205 const ParserErrorCode('NON_STRING_LITERAL_AS_URI',
9206 "The URI must be a string literal",
9207 "Enclose the URI in either single or double quotes.");
9208
9209 static const ParserErrorCode NON_USER_DEFINABLE_OPERATOR =
9210 const ParserErrorCode('NON_USER_DEFINABLE_OPERATOR',
9211 "The operator '{0}' is not user definable");
9212
9213 static const ParserErrorCode NORMAL_BEFORE_OPTIONAL_PARAMETERS =
9214 const ParserErrorCode('NORMAL_BEFORE_OPTIONAL_PARAMETERS',
9215 "Normal parameters must occur before optional parameters");
9216
9217 static const ParserErrorCode POSITIONAL_AFTER_NAMED_ARGUMENT =
9218 const ParserErrorCode('POSITIONAL_AFTER_NAMED_ARGUMENT',
9219 "Positional arguments must occur before named arguments");
9220
9221 static const ParserErrorCode POSITIONAL_PARAMETER_OUTSIDE_GROUP =
9222 const ParserErrorCode('POSITIONAL_PARAMETER_OUTSIDE_GROUP',
9223 "Positional parameters must be enclosed in square brackets ('[' and '] ')");
9224
9225 static const ParserErrorCode REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR =
9226 const ParserErrorCode('REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR',
9227 "Only factory constructor can specify '=' redirection.");
9228
9229 static const ParserErrorCode SETTER_IN_FUNCTION = const ParserErrorCode(
9230 'SETTER_IN_FUNCTION',
9231 "Setters cannot be defined within methods or functions");
9232
9233 static const ParserErrorCode STATIC_AFTER_CONST = const ParserErrorCode(
9234 'STATIC_AFTER_CONST',
9235 "The modifier 'static' should be before the modifier 'const'");
9236
9237 static const ParserErrorCode STATIC_AFTER_FINAL = const ParserErrorCode(
9238 'STATIC_AFTER_FINAL',
9239 "The modifier 'static' should be before the modifier 'final'");
9240
9241 static const ParserErrorCode STATIC_AFTER_VAR = const ParserErrorCode(
9242 'STATIC_AFTER_VAR',
9243 "The modifier 'static' should be before the modifier 'var'");
9244
9245 static const ParserErrorCode STATIC_CONSTRUCTOR = const ParserErrorCode(
9246 'STATIC_CONSTRUCTOR', "Constructors cannot be static");
9247
9248 static const ParserErrorCode STATIC_GETTER_WITHOUT_BODY =
9249 const ParserErrorCode(
9250 'STATIC_GETTER_WITHOUT_BODY', "A 'static' getter must have a body");
9251
9252 static const ParserErrorCode STATIC_OPERATOR =
9253 const ParserErrorCode('STATIC_OPERATOR', "Operators cannot be static");
9254
9255 static const ParserErrorCode STATIC_SETTER_WITHOUT_BODY =
9256 const ParserErrorCode(
9257 'STATIC_SETTER_WITHOUT_BODY', "A 'static' setter must have a body");
9258
9259 static const ParserErrorCode STATIC_TOP_LEVEL_DECLARATION =
9260 const ParserErrorCode('STATIC_TOP_LEVEL_DECLARATION',
9261 "Top-level declarations cannot be declared to be 'static'");
9262
9263 static const ParserErrorCode SWITCH_HAS_CASE_AFTER_DEFAULT_CASE =
9264 const ParserErrorCode('SWITCH_HAS_CASE_AFTER_DEFAULT_CASE',
9265 "The 'default' case should be the last case in a switch statement");
9266
9267 static const ParserErrorCode SWITCH_HAS_MULTIPLE_DEFAULT_CASES =
9268 const ParserErrorCode('SWITCH_HAS_MULTIPLE_DEFAULT_CASES',
9269 "The 'default' case can only be declared once");
9270
9271 static const ParserErrorCode TOP_LEVEL_OPERATOR = const ParserErrorCode(
9272 'TOP_LEVEL_OPERATOR', "Operators must be declared within a class");
9273
9274 static const ParserErrorCode TYPEDEF_IN_CLASS = const ParserErrorCode(
9275 'TYPEDEF_IN_CLASS',
9276 "Function type aliases cannot be declared inside classes");
9277
9278 static const ParserErrorCode UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP =
9279 const ParserErrorCode('UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP',
9280 "There is no '{0}' to open a parameter group");
9281
9282 static const ParserErrorCode UNEXPECTED_TOKEN =
9283 const ParserErrorCode('UNEXPECTED_TOKEN', "Unexpected token '{0}'");
9284
9285 static const ParserErrorCode WITH_BEFORE_EXTENDS = const ParserErrorCode(
9286 'WITH_BEFORE_EXTENDS',
9287 "The extends clause must be before the with clause");
9288
9289 static const ParserErrorCode WITH_WITHOUT_EXTENDS = const ParserErrorCode(
9290 'WITH_WITHOUT_EXTENDS',
9291 "The with clause cannot be used without an extends clause");
9292
9293 static const ParserErrorCode WRONG_SEPARATOR_FOR_NAMED_PARAMETER =
9294 const ParserErrorCode('WRONG_SEPARATOR_FOR_NAMED_PARAMETER',
9295 "The default value of a named parameter should be preceeded by ':'");
9296
9297 static const ParserErrorCode WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER =
9298 const ParserErrorCode('WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER',
9299 "The default value of a positional parameter should be preceeded by '= '");
9300
9301 static const ParserErrorCode WRONG_TERMINATOR_FOR_PARAMETER_GROUP =
9302 const ParserErrorCode('WRONG_TERMINATOR_FOR_PARAMETER_GROUP',
9303 "Expected '{0}' to close parameter group");
9304
9305 static const ParserErrorCode VAR_AND_TYPE = const ParserErrorCode(
9306 'VAR_AND_TYPE',
9307 "Variables cannot be declared using both 'var' and a type name; remove the 'var'");
9308
9309 static const ParserErrorCode VAR_AS_TYPE_NAME = const ParserErrorCode(
9310 'VAR_AS_TYPE_NAME', "The keyword 'var' cannot be used as a type name");
9311
9312 static const ParserErrorCode VAR_CLASS = const ParserErrorCode(
9313 'VAR_CLASS', "Classes cannot be declared to be 'var'");
9314
9315 static const ParserErrorCode VAR_ENUM =
9316 const ParserErrorCode('VAR_ENUM', "Enums cannot be declared to be 'var'");
9317
9318 static const ParserErrorCode VAR_RETURN_TYPE = const ParserErrorCode(
9319 'VAR_RETURN_TYPE', "The return type cannot be 'var'");
9320
9321 static const ParserErrorCode VAR_TYPEDEF = const ParserErrorCode(
9322 'VAR_TYPEDEF', "Type aliases cannot be declared to be 'var'");
9323
9324 static const ParserErrorCode VOID_PARAMETER = const ParserErrorCode(
9325 'VOID_PARAMETER', "Parameters cannot have a type of 'void'");
9326
9327 static const ParserErrorCode VOID_VARIABLE = const ParserErrorCode(
9328 'VOID_VARIABLE', "Variables cannot have a type of 'void'");
9329
9330 /**
9331 * Initialize a newly created error code to have the given [name]. The message
9332 * associated with the error will be created from the given [message]
9333 * template. The correction associated with the error will be created from the
9334 * given [correction] template.
9335 */
9336 const ParserErrorCode(String name, String message, [String correction])
9337 : super(name, message, correction);
9338
9339 @override
9340 ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
9341
9342 @override
9343 ErrorType get type => ErrorType.SYNTACTIC_ERROR;
9344 }
9345
9346 /**
9347 * An object that copies resolution information from one AST structure to
9348 * another as long as the structures of the corresponding children of a pair of
9349 * nodes are the same.
9350 */
9351 class ResolutionCopier implements AstVisitor<bool> {
9352 /**
9353 * The AST node with which the node being visited is to be compared. This is
9354 * only valid at the beginning of each visit method (until [isEqualNodes] is
9355 * invoked).
9356 */
9357 AstNode _toNode;
9358
9359 @override
9360 bool visitAdjacentStrings(AdjacentStrings node) {
9361 AdjacentStrings toNode = this._toNode as AdjacentStrings;
9362 return _isEqualNodeLists(node.strings, toNode.strings);
9363 }
9364
9365 @override
9366 bool visitAnnotation(Annotation node) {
9367 Annotation toNode = this._toNode as Annotation;
9368 if (_and(_isEqualTokens(node.atSign, toNode.atSign),
9369 _isEqualNodes(node.name, toNode.name),
9370 _isEqualTokens(node.period, toNode.period),
9371 _isEqualNodes(node.constructorName, toNode.constructorName),
9372 _isEqualNodes(node.arguments, toNode.arguments))) {
9373 toNode.element = node.element;
9374 return true;
9375 }
9376 return false;
9377 }
9378
9379 @override
9380 bool visitArgumentList(ArgumentList node) {
9381 ArgumentList toNode = this._toNode as ArgumentList;
9382 return _and(_isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
9383 _isEqualNodeLists(node.arguments, toNode.arguments),
9384 _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis));
9385 }
9386
9387 @override
9388 bool visitAsExpression(AsExpression node) {
9389 AsExpression toNode = this._toNode as AsExpression;
9390 if (_and(_isEqualNodes(node.expression, toNode.expression),
9391 _isEqualTokens(node.asOperator, toNode.asOperator),
9392 _isEqualNodes(node.type, toNode.type))) {
9393 toNode.propagatedType = node.propagatedType;
9394 toNode.staticType = node.staticType;
9395 return true;
9396 }
9397 return false;
9398 }
9399
9400 @override
9401 bool visitAssertStatement(AssertStatement node) {
9402 AssertStatement toNode = this._toNode as AssertStatement;
9403 return _and(_isEqualTokens(node.assertKeyword, toNode.assertKeyword),
9404 _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
9405 _isEqualNodes(node.condition, toNode.condition),
9406 _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
9407 _isEqualTokens(node.semicolon, toNode.semicolon));
9408 }
9409
9410 @override
9411 bool visitAssignmentExpression(AssignmentExpression node) {
9412 AssignmentExpression toNode = this._toNode as AssignmentExpression;
9413 if (_and(_isEqualNodes(node.leftHandSide, toNode.leftHandSide),
9414 _isEqualTokens(node.operator, toNode.operator),
9415 _isEqualNodes(node.rightHandSide, toNode.rightHandSide))) {
9416 toNode.propagatedElement = node.propagatedElement;
9417 toNode.propagatedType = node.propagatedType;
9418 toNode.staticElement = node.staticElement;
9419 toNode.staticType = node.staticType;
9420 return true;
9421 }
9422 return false;
9423 }
9424
9425 @override
9426 bool visitAwaitExpression(AwaitExpression node) {
9427 AwaitExpression toNode = this._toNode as AwaitExpression;
9428 if (_and(_isEqualTokens(node.awaitKeyword, toNode.awaitKeyword),
9429 _isEqualNodes(node.expression, toNode.expression))) {
9430 toNode.propagatedType = node.propagatedType;
9431 toNode.staticType = node.staticType;
9432 return true;
9433 }
9434 return false;
9435 }
9436
9437 @override
9438 bool visitBinaryExpression(BinaryExpression node) {
9439 BinaryExpression toNode = this._toNode as BinaryExpression;
9440 if (_and(_isEqualNodes(node.leftOperand, toNode.leftOperand),
9441 _isEqualTokens(node.operator, toNode.operator),
9442 _isEqualNodes(node.rightOperand, toNode.rightOperand))) {
9443 toNode.propagatedElement = node.propagatedElement;
9444 toNode.propagatedType = node.propagatedType;
9445 toNode.staticElement = node.staticElement;
9446 toNode.staticType = node.staticType;
9447 return true;
9448 }
9449 return false;
9450 }
9451
9452 @override
9453 bool visitBlock(Block node) {
9454 Block toNode = this._toNode as Block;
9455 return _and(_isEqualTokens(node.leftBracket, toNode.leftBracket),
9456 _isEqualNodeLists(node.statements, toNode.statements),
9457 _isEqualTokens(node.rightBracket, toNode.rightBracket));
9458 }
9459
9460 @override
9461 bool visitBlockFunctionBody(BlockFunctionBody node) {
9462 BlockFunctionBody toNode = this._toNode as BlockFunctionBody;
9463 return _isEqualNodes(node.block, toNode.block);
9464 }
9465
9466 @override
9467 bool visitBooleanLiteral(BooleanLiteral node) {
9468 BooleanLiteral toNode = this._toNode as BooleanLiteral;
9469 if (_and(_isEqualTokens(node.literal, toNode.literal),
9470 node.value == toNode.value)) {
9471 toNode.propagatedType = node.propagatedType;
9472 toNode.staticType = node.staticType;
9473 return true;
9474 }
9475 return false;
9476 }
9477
9478 @override
9479 bool visitBreakStatement(BreakStatement node) {
9480 BreakStatement toNode = this._toNode as BreakStatement;
9481 if (_and(_isEqualTokens(node.breakKeyword, toNode.breakKeyword),
9482 _isEqualNodes(node.label, toNode.label),
9483 _isEqualTokens(node.semicolon, toNode.semicolon))) {
9484 // TODO(paulberry): map node.target to toNode.target.
9485 return true;
9486 }
9487 return false;
9488 }
9489
9490 @override
9491 bool visitCascadeExpression(CascadeExpression node) {
9492 CascadeExpression toNode = this._toNode as CascadeExpression;
9493 if (_and(_isEqualNodes(node.target, toNode.target),
9494 _isEqualNodeLists(node.cascadeSections, toNode.cascadeSections))) {
9495 toNode.propagatedType = node.propagatedType;
9496 toNode.staticType = node.staticType;
9497 return true;
9498 }
9499 return false;
9500 }
9501
9502 @override
9503 bool visitCatchClause(CatchClause node) {
9504 CatchClause toNode = this._toNode as CatchClause;
9505 return _and(_isEqualTokens(node.onKeyword, toNode.onKeyword),
9506 _isEqualNodes(node.exceptionType, toNode.exceptionType),
9507 _isEqualTokens(node.catchKeyword, toNode.catchKeyword),
9508 _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
9509 _isEqualNodes(node.exceptionParameter, toNode.exceptionParameter),
9510 _isEqualTokens(node.comma, toNode.comma),
9511 _isEqualNodes(node.stackTraceParameter, toNode.stackTraceParameter),
9512 _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
9513 _isEqualNodes(node.body, toNode.body));
9514 }
9515
9516 @override
9517 bool visitClassDeclaration(ClassDeclaration node) {
9518 ClassDeclaration toNode = this._toNode as ClassDeclaration;
9519 return _and(
9520 _isEqualNodes(node.documentationComment, toNode.documentationComment),
9521 _isEqualNodeLists(node.metadata, toNode.metadata),
9522 _isEqualTokens(node.abstractKeyword, toNode.abstractKeyword),
9523 _isEqualTokens(node.classKeyword, toNode.classKeyword),
9524 _isEqualNodes(node.name, toNode.name),
9525 _isEqualNodes(node.typeParameters, toNode.typeParameters),
9526 _isEqualNodes(node.extendsClause, toNode.extendsClause),
9527 _isEqualNodes(node.withClause, toNode.withClause),
9528 _isEqualNodes(node.implementsClause, toNode.implementsClause),
9529 _isEqualTokens(node.leftBracket, toNode.leftBracket),
9530 _isEqualNodeLists(node.members, toNode.members),
9531 _isEqualTokens(node.rightBracket, toNode.rightBracket));
9532 }
9533
9534 @override
9535 bool visitClassTypeAlias(ClassTypeAlias node) {
9536 ClassTypeAlias toNode = this._toNode as ClassTypeAlias;
9537 return _and(
9538 _isEqualNodes(node.documentationComment, toNode.documentationComment),
9539 _isEqualNodeLists(node.metadata, toNode.metadata),
9540 _isEqualTokens(node.typedefKeyword, toNode.typedefKeyword),
9541 _isEqualNodes(node.name, toNode.name),
9542 _isEqualNodes(node.typeParameters, toNode.typeParameters),
9543 _isEqualTokens(node.equals, toNode.equals),
9544 _isEqualTokens(node.abstractKeyword, toNode.abstractKeyword),
9545 _isEqualNodes(node.superclass, toNode.superclass),
9546 _isEqualNodes(node.withClause, toNode.withClause),
9547 _isEqualNodes(node.implementsClause, toNode.implementsClause),
9548 _isEqualTokens(node.semicolon, toNode.semicolon));
9549 }
9550
9551 @override
9552 bool visitComment(Comment node) {
9553 Comment toNode = this._toNode as Comment;
9554 return _isEqualNodeLists(node.references, toNode.references);
9555 }
9556
9557 @override
9558 bool visitCommentReference(CommentReference node) {
9559 CommentReference toNode = this._toNode as CommentReference;
9560 return _and(_isEqualTokens(node.newKeyword, toNode.newKeyword),
9561 _isEqualNodes(node.identifier, toNode.identifier));
9562 }
9563
9564 @override
9565 bool visitCompilationUnit(CompilationUnit node) {
9566 CompilationUnit toNode = this._toNode as CompilationUnit;
9567 if (_and(_isEqualTokens(node.beginToken, toNode.beginToken),
9568 _isEqualNodes(node.scriptTag, toNode.scriptTag),
9569 _isEqualNodeLists(node.directives, toNode.directives),
9570 _isEqualNodeLists(node.declarations, toNode.declarations),
9571 _isEqualTokens(node.endToken, toNode.endToken))) {
9572 toNode.element = node.element;
9573 return true;
9574 }
9575 return false;
9576 }
9577
9578 @override
9579 bool visitConditionalExpression(ConditionalExpression node) {
9580 ConditionalExpression toNode = this._toNode as ConditionalExpression;
9581 if (_and(_isEqualNodes(node.condition, toNode.condition),
9582 _isEqualTokens(node.question, toNode.question),
9583 _isEqualNodes(node.thenExpression, toNode.thenExpression),
9584 _isEqualTokens(node.colon, toNode.colon),
9585 _isEqualNodes(node.elseExpression, toNode.elseExpression))) {
9586 toNode.propagatedType = node.propagatedType;
9587 toNode.staticType = node.staticType;
9588 return true;
9589 }
9590 return false;
9591 }
9592
9593 @override
9594 bool visitConstructorDeclaration(ConstructorDeclaration node) {
9595 ConstructorDeclaration toNode = this._toNode as ConstructorDeclaration;
9596 if (_and(
9597 _isEqualNodes(node.documentationComment, toNode.documentationComment),
9598 _isEqualNodeLists(node.metadata, toNode.metadata),
9599 _isEqualTokens(node.externalKeyword, toNode.externalKeyword),
9600 _isEqualTokens(node.constKeyword, toNode.constKeyword),
9601 _isEqualTokens(node.factoryKeyword, toNode.factoryKeyword),
9602 _isEqualNodes(node.returnType, toNode.returnType),
9603 _isEqualTokens(node.period, toNode.period),
9604 _isEqualNodes(node.name, toNode.name),
9605 _isEqualNodes(node.parameters, toNode.parameters),
9606 _isEqualTokens(node.separator, toNode.separator),
9607 _isEqualNodeLists(node.initializers, toNode.initializers),
9608 _isEqualNodes(node.redirectedConstructor, toNode.redirectedConstructor),
9609 _isEqualNodes(node.body, toNode.body))) {
9610 toNode.element = node.element;
9611 return true;
9612 }
9613 return false;
9614 }
9615
9616 @override
9617 bool visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
9618 ConstructorFieldInitializer toNode =
9619 this._toNode as ConstructorFieldInitializer;
9620 return _and(_isEqualTokens(node.thisKeyword, toNode.thisKeyword),
9621 _isEqualTokens(node.period, toNode.period),
9622 _isEqualNodes(node.fieldName, toNode.fieldName),
9623 _isEqualTokens(node.equals, toNode.equals),
9624 _isEqualNodes(node.expression, toNode.expression));
9625 }
9626
9627 @override
9628 bool visitConstructorName(ConstructorName node) {
9629 ConstructorName toNode = this._toNode as ConstructorName;
9630 if (_and(_isEqualNodes(node.type, toNode.type),
9631 _isEqualTokens(node.period, toNode.period),
9632 _isEqualNodes(node.name, toNode.name))) {
9633 toNode.staticElement = node.staticElement;
9634 return true;
9635 }
9636 return false;
9637 }
9638
9639 @override
9640 bool visitContinueStatement(ContinueStatement node) {
9641 ContinueStatement toNode = this._toNode as ContinueStatement;
9642 if (_and(_isEqualTokens(node.continueKeyword, toNode.continueKeyword),
9643 _isEqualNodes(node.label, toNode.label),
9644 _isEqualTokens(node.semicolon, toNode.semicolon))) {
9645 // TODO(paulberry): map node.target to toNode.target.
9646 return true;
9647 }
9648 return false;
9649 }
9650
9651 @override
9652 bool visitDeclaredIdentifier(DeclaredIdentifier node) {
9653 DeclaredIdentifier toNode = this._toNode as DeclaredIdentifier;
9654 return _and(
9655 _isEqualNodes(node.documentationComment, toNode.documentationComment),
9656 _isEqualNodeLists(node.metadata, toNode.metadata),
9657 _isEqualTokens(node.keyword, toNode.keyword),
9658 _isEqualNodes(node.type, toNode.type),
9659 _isEqualNodes(node.identifier, toNode.identifier));
9660 }
9661
9662 @override
9663 bool visitDefaultFormalParameter(DefaultFormalParameter node) {
9664 DefaultFormalParameter toNode = this._toNode as DefaultFormalParameter;
9665 return _and(_isEqualNodes(node.parameter, toNode.parameter),
9666 node.kind == toNode.kind,
9667 _isEqualTokens(node.separator, toNode.separator),
9668 _isEqualNodes(node.defaultValue, toNode.defaultValue));
9669 }
9670
9671 @override
9672 bool visitDoStatement(DoStatement node) {
9673 DoStatement toNode = this._toNode as DoStatement;
9674 return _and(_isEqualTokens(node.doKeyword, toNode.doKeyword),
9675 _isEqualNodes(node.body, toNode.body),
9676 _isEqualTokens(node.whileKeyword, toNode.whileKeyword),
9677 _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
9678 _isEqualNodes(node.condition, toNode.condition),
9679 _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
9680 _isEqualTokens(node.semicolon, toNode.semicolon));
9681 }
9682
9683 @override
9684 bool visitDoubleLiteral(DoubleLiteral node) {
9685 DoubleLiteral toNode = this._toNode as DoubleLiteral;
9686 if (_and(_isEqualTokens(node.literal, toNode.literal),
9687 node.value == toNode.value)) {
9688 toNode.propagatedType = node.propagatedType;
9689 toNode.staticType = node.staticType;
9690 return true;
9691 }
9692 return false;
9693 }
9694
9695 @override
9696 bool visitEmptyFunctionBody(EmptyFunctionBody node) {
9697 EmptyFunctionBody toNode = this._toNode as EmptyFunctionBody;
9698 return _isEqualTokens(node.semicolon, toNode.semicolon);
9699 }
9700
9701 @override
9702 bool visitEmptyStatement(EmptyStatement node) {
9703 EmptyStatement toNode = this._toNode as EmptyStatement;
9704 return _isEqualTokens(node.semicolon, toNode.semicolon);
9705 }
9706
9707 @override
9708 bool visitEnumConstantDeclaration(EnumConstantDeclaration node) {
9709 EnumConstantDeclaration toNode = this._toNode as EnumConstantDeclaration;
9710 return _and(
9711 _isEqualNodes(node.documentationComment, toNode.documentationComment),
9712 _isEqualNodeLists(node.metadata, toNode.metadata),
9713 _isEqualNodes(node.name, toNode.name));
9714 }
9715
9716 @override
9717 bool visitEnumDeclaration(EnumDeclaration node) {
9718 EnumDeclaration toNode = this._toNode as EnumDeclaration;
9719 return _and(
9720 _isEqualNodes(node.documentationComment, toNode.documentationComment),
9721 _isEqualNodeLists(node.metadata, toNode.metadata),
9722 _isEqualTokens(node.enumKeyword, toNode.enumKeyword),
9723 _isEqualNodes(node.name, toNode.name),
9724 _isEqualTokens(node.leftBracket, toNode.leftBracket),
9725 _isEqualNodeLists(node.constants, toNode.constants),
9726 _isEqualTokens(node.rightBracket, toNode.rightBracket));
9727 }
9728
9729 @override
9730 bool visitExportDirective(ExportDirective node) {
9731 ExportDirective toNode = this._toNode as ExportDirective;
9732 if (_and(
9733 _isEqualNodes(node.documentationComment, toNode.documentationComment),
9734 _isEqualNodeLists(node.metadata, toNode.metadata),
9735 _isEqualTokens(node.keyword, toNode.keyword),
9736 _isEqualNodes(node.uri, toNode.uri),
9737 _isEqualNodeLists(node.combinators, toNode.combinators),
9738 _isEqualTokens(node.semicolon, toNode.semicolon))) {
9739 toNode.element = node.element;
9740 return true;
9741 }
9742 return false;
9743 }
9744
9745 @override
9746 bool visitExpressionFunctionBody(ExpressionFunctionBody node) {
9747 ExpressionFunctionBody toNode = this._toNode as ExpressionFunctionBody;
9748 return _and(
9749 _isEqualTokens(node.functionDefinition, toNode.functionDefinition),
9750 _isEqualNodes(node.expression, toNode.expression),
9751 _isEqualTokens(node.semicolon, toNode.semicolon));
9752 }
9753
9754 @override
9755 bool visitExpressionStatement(ExpressionStatement node) {
9756 ExpressionStatement toNode = this._toNode as ExpressionStatement;
9757 return _and(_isEqualNodes(node.expression, toNode.expression),
9758 _isEqualTokens(node.semicolon, toNode.semicolon));
9759 }
9760
9761 @override
9762 bool visitExtendsClause(ExtendsClause node) {
9763 ExtendsClause toNode = this._toNode as ExtendsClause;
9764 return _and(_isEqualTokens(node.extendsKeyword, toNode.extendsKeyword),
9765 _isEqualNodes(node.superclass, toNode.superclass));
9766 }
9767
9768 @override
9769 bool visitFieldDeclaration(FieldDeclaration node) {
9770 FieldDeclaration toNode = this._toNode as FieldDeclaration;
9771 return _and(
9772 _isEqualNodes(node.documentationComment, toNode.documentationComment),
9773 _isEqualNodeLists(node.metadata, toNode.metadata),
9774 _isEqualTokens(node.staticKeyword, toNode.staticKeyword),
9775 _isEqualNodes(node.fields, toNode.fields),
9776 _isEqualTokens(node.semicolon, toNode.semicolon));
9777 }
9778
9779 @override
9780 bool visitFieldFormalParameter(FieldFormalParameter node) {
9781 FieldFormalParameter toNode = this._toNode as FieldFormalParameter;
9782 return _and(
9783 _isEqualNodes(node.documentationComment, toNode.documentationComment),
9784 _isEqualNodeLists(node.metadata, toNode.metadata),
9785 _isEqualTokens(node.keyword, toNode.keyword),
9786 _isEqualNodes(node.type, toNode.type),
9787 _isEqualTokens(node.thisKeyword, toNode.thisKeyword),
9788 _isEqualTokens(node.period, toNode.period),
9789 _isEqualNodes(node.identifier, toNode.identifier));
9790 }
9791
9792 @override
9793 bool visitForEachStatement(ForEachStatement node) {
9794 ForEachStatement toNode = this._toNode as ForEachStatement;
9795 return _and(_isEqualTokens(node.forKeyword, toNode.forKeyword),
9796 _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
9797 _isEqualNodes(node.loopVariable, toNode.loopVariable),
9798 _isEqualTokens(node.inKeyword, toNode.inKeyword),
9799 _isEqualNodes(node.iterable, toNode.iterable),
9800 _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
9801 _isEqualNodes(node.body, toNode.body));
9802 }
9803
9804 @override
9805 bool visitFormalParameterList(FormalParameterList node) {
9806 FormalParameterList toNode = this._toNode as FormalParameterList;
9807 return _and(_isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
9808 _isEqualNodeLists(node.parameters, toNode.parameters),
9809 _isEqualTokens(node.leftDelimiter, toNode.leftDelimiter),
9810 _isEqualTokens(node.rightDelimiter, toNode.rightDelimiter),
9811 _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis));
9812 }
9813
9814 @override
9815 bool visitForStatement(ForStatement node) {
9816 ForStatement toNode = this._toNode as ForStatement;
9817 return _and(_isEqualTokens(node.forKeyword, toNode.forKeyword),
9818 _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
9819 _isEqualNodes(node.variables, toNode.variables),
9820 _isEqualNodes(node.initialization, toNode.initialization),
9821 _isEqualTokens(node.leftSeparator, toNode.leftSeparator),
9822 _isEqualNodes(node.condition, toNode.condition),
9823 _isEqualTokens(node.rightSeparator, toNode.rightSeparator),
9824 _isEqualNodeLists(node.updaters, toNode.updaters),
9825 _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
9826 _isEqualNodes(node.body, toNode.body));
9827 }
9828
9829 @override
9830 bool visitFunctionDeclaration(FunctionDeclaration node) {
9831 FunctionDeclaration toNode = this._toNode as FunctionDeclaration;
9832 return _and(
9833 _isEqualNodes(node.documentationComment, toNode.documentationComment),
9834 _isEqualNodeLists(node.metadata, toNode.metadata),
9835 _isEqualTokens(node.externalKeyword, toNode.externalKeyword),
9836 _isEqualNodes(node.returnType, toNode.returnType),
9837 _isEqualTokens(node.propertyKeyword, toNode.propertyKeyword),
9838 _isEqualNodes(node.name, toNode.name),
9839 _isEqualNodes(node.functionExpression, toNode.functionExpression));
9840 }
9841
9842 @override
9843 bool visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
9844 FunctionDeclarationStatement toNode =
9845 this._toNode as FunctionDeclarationStatement;
9846 return _isEqualNodes(node.functionDeclaration, toNode.functionDeclaration);
9847 }
9848
9849 @override
9850 bool visitFunctionExpression(FunctionExpression node) {
9851 FunctionExpression toNode = this._toNode as FunctionExpression;
9852 if (_and(_isEqualNodes(node.parameters, toNode.parameters),
9853 _isEqualNodes(node.body, toNode.body))) {
9854 toNode.element = node.element;
9855 toNode.propagatedType = node.propagatedType;
9856 toNode.staticType = node.staticType;
9857 return true;
9858 }
9859 return false;
9860 }
9861
9862 @override
9863 bool visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
9864 FunctionExpressionInvocation toNode =
9865 this._toNode as FunctionExpressionInvocation;
9866 if (_and(_isEqualNodes(node.function, toNode.function),
9867 _isEqualNodes(node.argumentList, toNode.argumentList))) {
9868 toNode.propagatedElement = node.propagatedElement;
9869 toNode.propagatedType = node.propagatedType;
9870 toNode.staticElement = node.staticElement;
9871 toNode.staticType = node.staticType;
9872 return true;
9873 }
9874 return false;
9875 }
9876
9877 @override
9878 bool visitFunctionTypeAlias(FunctionTypeAlias node) {
9879 FunctionTypeAlias toNode = this._toNode as FunctionTypeAlias;
9880 return _and(
9881 _isEqualNodes(node.documentationComment, toNode.documentationComment),
9882 _isEqualNodeLists(node.metadata, toNode.metadata),
9883 _isEqualTokens(node.typedefKeyword, toNode.typedefKeyword),
9884 _isEqualNodes(node.returnType, toNode.returnType),
9885 _isEqualNodes(node.name, toNode.name),
9886 _isEqualNodes(node.typeParameters, toNode.typeParameters),
9887 _isEqualNodes(node.parameters, toNode.parameters),
9888 _isEqualTokens(node.semicolon, toNode.semicolon));
9889 }
9890
9891 @override
9892 bool visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
9893 FunctionTypedFormalParameter toNode =
9894 this._toNode as FunctionTypedFormalParameter;
9895 return _and(
9896 _isEqualNodes(node.documentationComment, toNode.documentationComment),
9897 _isEqualNodeLists(node.metadata, toNode.metadata),
9898 _isEqualNodes(node.returnType, toNode.returnType),
9899 _isEqualNodes(node.identifier, toNode.identifier),
9900 _isEqualNodes(node.parameters, toNode.parameters));
9901 }
9902
9903 @override
9904 bool visitHideCombinator(HideCombinator node) {
9905 HideCombinator toNode = this._toNode as HideCombinator;
9906 return _and(_isEqualTokens(node.keyword, toNode.keyword),
9907 _isEqualNodeLists(node.hiddenNames, toNode.hiddenNames));
9908 }
9909
9910 @override
9911 bool visitIfStatement(IfStatement node) {
9912 IfStatement toNode = this._toNode as IfStatement;
9913 return _and(_isEqualTokens(node.ifKeyword, toNode.ifKeyword),
9914 _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
9915 _isEqualNodes(node.condition, toNode.condition),
9916 _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
9917 _isEqualNodes(node.thenStatement, toNode.thenStatement),
9918 _isEqualTokens(node.elseKeyword, toNode.elseKeyword),
9919 _isEqualNodes(node.elseStatement, toNode.elseStatement));
9920 }
9921
9922 @override
9923 bool visitImplementsClause(ImplementsClause node) {
9924 ImplementsClause toNode = this._toNode as ImplementsClause;
9925 return _and(
9926 _isEqualTokens(node.implementsKeyword, toNode.implementsKeyword),
9927 _isEqualNodeLists(node.interfaces, toNode.interfaces));
9928 }
9929
9930 @override
9931 bool visitImportDirective(ImportDirective node) {
9932 ImportDirective toNode = this._toNode as ImportDirective;
9933 if (_and(
9934 _isEqualNodes(node.documentationComment, toNode.documentationComment),
9935 _isEqualNodeLists(node.metadata, toNode.metadata),
9936 _isEqualTokens(node.keyword, toNode.keyword),
9937 _isEqualNodes(node.uri, toNode.uri),
9938 _isEqualTokens(node.asKeyword, toNode.asKeyword),
9939 _isEqualNodes(node.prefix, toNode.prefix),
9940 _isEqualNodeLists(node.combinators, toNode.combinators),
9941 _isEqualTokens(node.semicolon, toNode.semicolon))) {
9942 toNode.element = node.element;
9943 return true;
9944 }
9945 return false;
9946 }
9947
9948 @override
9949 bool visitIndexExpression(IndexExpression node) {
9950 IndexExpression toNode = this._toNode as IndexExpression;
9951 if (_and(_isEqualNodes(node.target, toNode.target),
9952 _isEqualTokens(node.leftBracket, toNode.leftBracket),
9953 _isEqualNodes(node.index, toNode.index),
9954 _isEqualTokens(node.rightBracket, toNode.rightBracket))) {
9955 toNode.auxiliaryElements = node.auxiliaryElements;
9956 toNode.propagatedElement = node.propagatedElement;
9957 toNode.propagatedType = node.propagatedType;
9958 toNode.staticElement = node.staticElement;
9959 toNode.staticType = node.staticType;
9960 return true;
9961 }
9962 return false;
9963 }
9964
9965 @override
9966 bool visitInstanceCreationExpression(InstanceCreationExpression node) {
9967 InstanceCreationExpression toNode =
9968 this._toNode as InstanceCreationExpression;
9969 if (_and(_isEqualTokens(node.keyword, toNode.keyword),
9970 _isEqualNodes(node.constructorName, toNode.constructorName),
9971 _isEqualNodes(node.argumentList, toNode.argumentList))) {
9972 toNode.propagatedType = node.propagatedType;
9973 toNode.staticElement = node.staticElement;
9974 toNode.staticType = node.staticType;
9975 return true;
9976 }
9977 return false;
9978 }
9979
9980 @override
9981 bool visitIntegerLiteral(IntegerLiteral node) {
9982 IntegerLiteral toNode = this._toNode as IntegerLiteral;
9983 if (_and(_isEqualTokens(node.literal, toNode.literal),
9984 node.value == toNode.value)) {
9985 toNode.propagatedType = node.propagatedType;
9986 toNode.staticType = node.staticType;
9987 return true;
9988 }
9989 return false;
9990 }
9991
9992 @override
9993 bool visitInterpolationExpression(InterpolationExpression node) {
9994 InterpolationExpression toNode = this._toNode as InterpolationExpression;
9995 return _and(_isEqualTokens(node.leftBracket, toNode.leftBracket),
9996 _isEqualNodes(node.expression, toNode.expression),
9997 _isEqualTokens(node.rightBracket, toNode.rightBracket));
9998 }
9999
10000 @override
10001 bool visitInterpolationString(InterpolationString node) {
10002 InterpolationString toNode = this._toNode as InterpolationString;
10003 return _and(_isEqualTokens(node.contents, toNode.contents),
10004 node.value == toNode.value);
10005 }
10006
10007 @override
10008 bool visitIsExpression(IsExpression node) {
10009 IsExpression toNode = this._toNode as IsExpression;
10010 if (_and(_isEqualNodes(node.expression, toNode.expression),
10011 _isEqualTokens(node.isOperator, toNode.isOperator),
10012 _isEqualTokens(node.notOperator, toNode.notOperator),
10013 _isEqualNodes(node.type, toNode.type))) {
10014 toNode.propagatedType = node.propagatedType;
10015 toNode.staticType = node.staticType;
10016 return true;
10017 }
10018 return false;
10019 }
10020
10021 @override
10022 bool visitLabel(Label node) {
10023 Label toNode = this._toNode as Label;
10024 return _and(_isEqualNodes(node.label, toNode.label),
10025 _isEqualTokens(node.colon, toNode.colon));
10026 }
10027
10028 @override
10029 bool visitLabeledStatement(LabeledStatement node) {
10030 LabeledStatement toNode = this._toNode as LabeledStatement;
10031 return _and(_isEqualNodeLists(node.labels, toNode.labels),
10032 _isEqualNodes(node.statement, toNode.statement));
10033 }
10034
10035 @override
10036 bool visitLibraryDirective(LibraryDirective node) {
10037 LibraryDirective toNode = this._toNode as LibraryDirective;
10038 if (_and(
10039 _isEqualNodes(node.documentationComment, toNode.documentationComment),
10040 _isEqualNodeLists(node.metadata, toNode.metadata),
10041 _isEqualTokens(node.libraryKeyword, toNode.libraryKeyword),
10042 _isEqualNodes(node.name, toNode.name),
10043 _isEqualTokens(node.semicolon, toNode.semicolon))) {
10044 toNode.element = node.element;
10045 return true;
10046 }
10047 return false;
10048 }
10049
10050 @override
10051 bool visitLibraryIdentifier(LibraryIdentifier node) {
10052 LibraryIdentifier toNode = this._toNode as LibraryIdentifier;
10053 if (_isEqualNodeLists(node.components, toNode.components)) {
10054 toNode.propagatedType = node.propagatedType;
10055 toNode.staticType = node.staticType;
10056 return true;
10057 }
10058 return false;
10059 }
10060
10061 @override
10062 bool visitListLiteral(ListLiteral node) {
10063 ListLiteral toNode = this._toNode as ListLiteral;
10064 if (_and(_isEqualTokens(node.constKeyword, toNode.constKeyword),
10065 _isEqualNodes(node.typeArguments, toNode.typeArguments),
10066 _isEqualTokens(node.leftBracket, toNode.leftBracket),
10067 _isEqualNodeLists(node.elements, toNode.elements),
10068 _isEqualTokens(node.rightBracket, toNode.rightBracket))) {
10069 toNode.propagatedType = node.propagatedType;
10070 toNode.staticType = node.staticType;
10071 return true;
10072 }
10073 return false;
10074 }
10075
10076 @override
10077 bool visitMapLiteral(MapLiteral node) {
10078 MapLiteral toNode = this._toNode as MapLiteral;
10079 if (_and(_isEqualTokens(node.constKeyword, toNode.constKeyword),
10080 _isEqualNodes(node.typeArguments, toNode.typeArguments),
10081 _isEqualTokens(node.leftBracket, toNode.leftBracket),
10082 _isEqualNodeLists(node.entries, toNode.entries),
10083 _isEqualTokens(node.rightBracket, toNode.rightBracket))) {
10084 toNode.propagatedType = node.propagatedType;
10085 toNode.staticType = node.staticType;
10086 return true;
10087 }
10088 return false;
10089 }
10090
10091 @override
10092 bool visitMapLiteralEntry(MapLiteralEntry node) {
10093 MapLiteralEntry toNode = this._toNode as MapLiteralEntry;
10094 return _and(_isEqualNodes(node.key, toNode.key),
10095 _isEqualTokens(node.separator, toNode.separator),
10096 _isEqualNodes(node.value, toNode.value));
10097 }
10098
10099 @override
10100 bool visitMethodDeclaration(MethodDeclaration node) {
10101 MethodDeclaration toNode = this._toNode as MethodDeclaration;
10102 return _and(
10103 _isEqualNodes(node.documentationComment, toNode.documentationComment),
10104 _isEqualNodeLists(node.metadata, toNode.metadata),
10105 _isEqualTokens(node.externalKeyword, toNode.externalKeyword),
10106 _isEqualTokens(node.modifierKeyword, toNode.modifierKeyword),
10107 _isEqualNodes(node.returnType, toNode.returnType),
10108 _isEqualTokens(node.propertyKeyword, toNode.propertyKeyword),
10109 _isEqualTokens(node.propertyKeyword, toNode.propertyKeyword),
10110 _isEqualNodes(node.name, toNode.name),
10111 _isEqualNodes(node.parameters, toNode.parameters),
10112 _isEqualNodes(node.body, toNode.body));
10113 }
10114
10115 @override
10116 bool visitMethodInvocation(MethodInvocation node) {
10117 MethodInvocation toNode = this._toNode as MethodInvocation;
10118 if (_and(_isEqualNodes(node.target, toNode.target),
10119 _isEqualTokens(node.operator, toNode.operator),
10120 _isEqualNodes(node.methodName, toNode.methodName),
10121 _isEqualNodes(node.argumentList, toNode.argumentList))) {
10122 toNode.propagatedType = node.propagatedType;
10123 toNode.staticType = node.staticType;
10124 return true;
10125 }
10126 return false;
10127 }
10128
10129 @override
10130 bool visitNamedExpression(NamedExpression node) {
10131 NamedExpression toNode = this._toNode as NamedExpression;
10132 if (_and(_isEqualNodes(node.name, toNode.name),
10133 _isEqualNodes(node.expression, toNode.expression))) {
10134 toNode.propagatedType = node.propagatedType;
10135 toNode.staticType = node.staticType;
10136 return true;
10137 }
10138 return false;
10139 }
10140
10141 @override
10142 bool visitNativeClause(NativeClause node) {
10143 NativeClause toNode = this._toNode as NativeClause;
10144 return _and(_isEqualTokens(node.nativeKeyword, toNode.nativeKeyword),
10145 _isEqualNodes(node.name, toNode.name));
10146 }
10147
10148 @override
10149 bool visitNativeFunctionBody(NativeFunctionBody node) {
10150 NativeFunctionBody toNode = this._toNode as NativeFunctionBody;
10151 return _and(_isEqualTokens(node.nativeKeyword, toNode.nativeKeyword),
10152 _isEqualNodes(node.stringLiteral, toNode.stringLiteral),
10153 _isEqualTokens(node.semicolon, toNode.semicolon));
10154 }
10155
10156 @override
10157 bool visitNullLiteral(NullLiteral node) {
10158 NullLiteral toNode = this._toNode as NullLiteral;
10159 if (_isEqualTokens(node.literal, toNode.literal)) {
10160 toNode.propagatedType = node.propagatedType;
10161 toNode.staticType = node.staticType;
10162 return true;
10163 }
10164 return false;
10165 }
10166
10167 @override
10168 bool visitParenthesizedExpression(ParenthesizedExpression node) {
10169 ParenthesizedExpression toNode = this._toNode as ParenthesizedExpression;
10170 if (_and(_isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
10171 _isEqualNodes(node.expression, toNode.expression),
10172 _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis))) {
10173 toNode.propagatedType = node.propagatedType;
10174 toNode.staticType = node.staticType;
10175 return true;
10176 }
10177 return false;
10178 }
10179
10180 @override
10181 bool visitPartDirective(PartDirective node) {
10182 PartDirective toNode = this._toNode as PartDirective;
10183 if (_and(
10184 _isEqualNodes(node.documentationComment, toNode.documentationComment),
10185 _isEqualNodeLists(node.metadata, toNode.metadata),
10186 _isEqualTokens(node.partKeyword, toNode.partKeyword),
10187 _isEqualNodes(node.uri, toNode.uri),
10188 _isEqualTokens(node.semicolon, toNode.semicolon))) {
10189 toNode.element = node.element;
10190 return true;
10191 }
10192 return false;
10193 }
10194
10195 @override
10196 bool visitPartOfDirective(PartOfDirective node) {
10197 PartOfDirective toNode = this._toNode as PartOfDirective;
10198 if (_and(
10199 _isEqualNodes(node.documentationComment, toNode.documentationComment),
10200 _isEqualNodeLists(node.metadata, toNode.metadata),
10201 _isEqualTokens(node.partKeyword, toNode.partKeyword),
10202 _isEqualTokens(node.ofKeyword, toNode.ofKeyword),
10203 _isEqualNodes(node.libraryName, toNode.libraryName),
10204 _isEqualTokens(node.semicolon, toNode.semicolon))) {
10205 toNode.element = node.element;
10206 return true;
10207 }
10208 return false;
10209 }
10210
10211 @override
10212 bool visitPostfixExpression(PostfixExpression node) {
10213 PostfixExpression toNode = this._toNode as PostfixExpression;
10214 if (_and(_isEqualNodes(node.operand, toNode.operand),
10215 _isEqualTokens(node.operator, toNode.operator))) {
10216 toNode.propagatedElement = node.propagatedElement;
10217 toNode.propagatedType = node.propagatedType;
10218 toNode.staticElement = node.staticElement;
10219 toNode.staticType = node.staticType;
10220 return true;
10221 }
10222 return false;
10223 }
10224
10225 @override
10226 bool visitPrefixedIdentifier(PrefixedIdentifier node) {
10227 PrefixedIdentifier toNode = this._toNode as PrefixedIdentifier;
10228 if (_and(_isEqualNodes(node.prefix, toNode.prefix),
10229 _isEqualTokens(node.period, toNode.period),
10230 _isEqualNodes(node.identifier, toNode.identifier))) {
10231 toNode.propagatedType = node.propagatedType;
10232 toNode.staticType = node.staticType;
10233 return true;
10234 }
10235 return false;
10236 }
10237
10238 @override
10239 bool visitPrefixExpression(PrefixExpression node) {
10240 PrefixExpression toNode = this._toNode as PrefixExpression;
10241 if (_and(_isEqualTokens(node.operator, toNode.operator),
10242 _isEqualNodes(node.operand, toNode.operand))) {
10243 toNode.propagatedElement = node.propagatedElement;
10244 toNode.propagatedType = node.propagatedType;
10245 toNode.staticElement = node.staticElement;
10246 toNode.staticType = node.staticType;
10247 return true;
10248 }
10249 return false;
10250 }
10251
10252 @override
10253 bool visitPropertyAccess(PropertyAccess node) {
10254 PropertyAccess toNode = this._toNode as PropertyAccess;
10255 if (_and(_isEqualNodes(node.target, toNode.target),
10256 _isEqualTokens(node.operator, toNode.operator),
10257 _isEqualNodes(node.propertyName, toNode.propertyName))) {
10258 toNode.propagatedType = node.propagatedType;
10259 toNode.staticType = node.staticType;
10260 return true;
10261 }
10262 return false;
10263 }
10264
10265 @override
10266 bool visitRedirectingConstructorInvocation(
10267 RedirectingConstructorInvocation node) {
10268 RedirectingConstructorInvocation toNode =
10269 this._toNode as RedirectingConstructorInvocation;
10270 if (_and(_isEqualTokens(node.thisKeyword, toNode.thisKeyword),
10271 _isEqualTokens(node.period, toNode.period),
10272 _isEqualNodes(node.constructorName, toNode.constructorName),
10273 _isEqualNodes(node.argumentList, toNode.argumentList))) {
10274 toNode.staticElement = node.staticElement;
10275 return true;
10276 }
10277 return false;
10278 }
10279
10280 @override
10281 bool visitRethrowExpression(RethrowExpression node) {
10282 RethrowExpression toNode = this._toNode as RethrowExpression;
10283 if (_isEqualTokens(node.rethrowKeyword, toNode.rethrowKeyword)) {
10284 toNode.propagatedType = node.propagatedType;
10285 toNode.staticType = node.staticType;
10286 return true;
10287 }
10288 return false;
10289 }
10290
10291 @override
10292 bool visitReturnStatement(ReturnStatement node) {
10293 ReturnStatement toNode = this._toNode as ReturnStatement;
10294 return _and(_isEqualTokens(node.returnKeyword, toNode.returnKeyword),
10295 _isEqualNodes(node.expression, toNode.expression),
10296 _isEqualTokens(node.semicolon, toNode.semicolon));
10297 }
10298
10299 @override
10300 bool visitScriptTag(ScriptTag node) {
10301 ScriptTag toNode = this._toNode as ScriptTag;
10302 return _isEqualTokens(node.scriptTag, toNode.scriptTag);
10303 }
10304
10305 @override
10306 bool visitShowCombinator(ShowCombinator node) {
10307 ShowCombinator toNode = this._toNode as ShowCombinator;
10308 return _and(_isEqualTokens(node.keyword, toNode.keyword),
10309 _isEqualNodeLists(node.shownNames, toNode.shownNames));
10310 }
10311
10312 @override
10313 bool visitSimpleFormalParameter(SimpleFormalParameter node) {
10314 SimpleFormalParameter toNode = this._toNode as SimpleFormalParameter;
10315 return _and(
10316 _isEqualNodes(node.documentationComment, toNode.documentationComment),
10317 _isEqualNodeLists(node.metadata, toNode.metadata),
10318 _isEqualTokens(node.keyword, toNode.keyword),
10319 _isEqualNodes(node.type, toNode.type),
10320 _isEqualNodes(node.identifier, toNode.identifier));
10321 }
10322
10323 @override
10324 bool visitSimpleIdentifier(SimpleIdentifier node) {
10325 SimpleIdentifier toNode = this._toNode as SimpleIdentifier;
10326 if (_isEqualTokens(node.token, toNode.token)) {
10327 toNode.staticElement = node.staticElement;
10328 toNode.staticType = node.staticType;
10329 toNode.propagatedElement = node.propagatedElement;
10330 toNode.propagatedType = node.propagatedType;
10331 toNode.auxiliaryElements = node.auxiliaryElements;
10332 return true;
10333 }
10334 return false;
10335 }
10336
10337 @override
10338 bool visitSimpleStringLiteral(SimpleStringLiteral node) {
10339 SimpleStringLiteral toNode = this._toNode as SimpleStringLiteral;
10340 if (_and(_isEqualTokens(node.literal, toNode.literal),
10341 node.value == toNode.value)) {
10342 toNode.propagatedType = node.propagatedType;
10343 toNode.staticType = node.staticType;
10344 return true;
10345 }
10346 return false;
10347 }
10348
10349 @override
10350 bool visitStringInterpolation(StringInterpolation node) {
10351 StringInterpolation toNode = this._toNode as StringInterpolation;
10352 if (_isEqualNodeLists(node.elements, toNode.elements)) {
10353 toNode.propagatedType = node.propagatedType;
10354 toNode.staticType = node.staticType;
10355 return true;
10356 }
10357 return false;
10358 }
10359
10360 @override
10361 bool visitSuperConstructorInvocation(SuperConstructorInvocation node) {
10362 SuperConstructorInvocation toNode =
10363 this._toNode as SuperConstructorInvocation;
10364 if (_and(_isEqualTokens(node.superKeyword, toNode.superKeyword),
10365 _isEqualTokens(node.period, toNode.period),
10366 _isEqualNodes(node.constructorName, toNode.constructorName),
10367 _isEqualNodes(node.argumentList, toNode.argumentList))) {
10368 toNode.staticElement = node.staticElement;
10369 return true;
10370 }
10371 return false;
10372 }
10373
10374 @override
10375 bool visitSuperExpression(SuperExpression node) {
10376 SuperExpression toNode = this._toNode as SuperExpression;
10377 if (_isEqualTokens(node.superKeyword, toNode.superKeyword)) {
10378 toNode.propagatedType = node.propagatedType;
10379 toNode.staticType = node.staticType;
10380 return true;
10381 }
10382 return false;
10383 }
10384
10385 @override
10386 bool visitSwitchCase(SwitchCase node) {
10387 SwitchCase toNode = this._toNode as SwitchCase;
10388 return _and(_isEqualNodeLists(node.labels, toNode.labels),
10389 _isEqualTokens(node.keyword, toNode.keyword),
10390 _isEqualNodes(node.expression, toNode.expression),
10391 _isEqualTokens(node.colon, toNode.colon),
10392 _isEqualNodeLists(node.statements, toNode.statements));
10393 }
10394
10395 @override
10396 bool visitSwitchDefault(SwitchDefault node) {
10397 SwitchDefault toNode = this._toNode as SwitchDefault;
10398 return _and(_isEqualNodeLists(node.labels, toNode.labels),
10399 _isEqualTokens(node.keyword, toNode.keyword),
10400 _isEqualTokens(node.colon, toNode.colon),
10401 _isEqualNodeLists(node.statements, toNode.statements));
10402 }
10403
10404 @override
10405 bool visitSwitchStatement(SwitchStatement node) {
10406 SwitchStatement toNode = this._toNode as SwitchStatement;
10407 return _and(_isEqualTokens(node.switchKeyword, toNode.switchKeyword),
10408 _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
10409 _isEqualNodes(node.expression, toNode.expression),
10410 _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
10411 _isEqualTokens(node.leftBracket, toNode.leftBracket),
10412 _isEqualNodeLists(node.members, toNode.members),
10413 _isEqualTokens(node.rightBracket, toNode.rightBracket));
10414 }
10415
10416 @override
10417 bool visitSymbolLiteral(SymbolLiteral node) {
10418 SymbolLiteral toNode = this._toNode as SymbolLiteral;
10419 if (_and(_isEqualTokens(node.poundSign, toNode.poundSign),
10420 _isEqualTokenLists(node.components, toNode.components))) {
10421 toNode.propagatedType = node.propagatedType;
10422 toNode.staticType = node.staticType;
10423 return true;
10424 }
10425 return false;
10426 }
10427
10428 @override
10429 bool visitThisExpression(ThisExpression node) {
10430 ThisExpression toNode = this._toNode as ThisExpression;
10431 if (_isEqualTokens(node.thisKeyword, toNode.thisKeyword)) {
10432 toNode.propagatedType = node.propagatedType;
10433 toNode.staticType = node.staticType;
10434 return true;
10435 }
10436 return false;
10437 }
10438
10439 @override
10440 bool visitThrowExpression(ThrowExpression node) {
10441 ThrowExpression toNode = this._toNode as ThrowExpression;
10442 if (_and(_isEqualTokens(node.throwKeyword, toNode.throwKeyword),
10443 _isEqualNodes(node.expression, toNode.expression))) {
10444 toNode.propagatedType = node.propagatedType;
10445 toNode.staticType = node.staticType;
10446 return true;
10447 }
10448 return false;
10449 }
10450
10451 @override
10452 bool visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
10453 TopLevelVariableDeclaration toNode =
10454 this._toNode as TopLevelVariableDeclaration;
10455 return _and(
10456 _isEqualNodes(node.documentationComment, toNode.documentationComment),
10457 _isEqualNodeLists(node.metadata, toNode.metadata),
10458 _isEqualNodes(node.variables, toNode.variables),
10459 _isEqualTokens(node.semicolon, toNode.semicolon));
10460 }
10461
10462 @override
10463 bool visitTryStatement(TryStatement node) {
10464 TryStatement toNode = this._toNode as TryStatement;
10465 return _and(_isEqualTokens(node.tryKeyword, toNode.tryKeyword),
10466 _isEqualNodes(node.body, toNode.body),
10467 _isEqualNodeLists(node.catchClauses, toNode.catchClauses),
10468 _isEqualTokens(node.finallyKeyword, toNode.finallyKeyword),
10469 _isEqualNodes(node.finallyBlock, toNode.finallyBlock));
10470 }
10471
10472 @override
10473 bool visitTypeArgumentList(TypeArgumentList node) {
10474 TypeArgumentList toNode = this._toNode as TypeArgumentList;
10475 return _and(_isEqualTokens(node.leftBracket, toNode.leftBracket),
10476 _isEqualNodeLists(node.arguments, toNode.arguments),
10477 _isEqualTokens(node.rightBracket, toNode.rightBracket));
10478 }
10479
10480 @override
10481 bool visitTypeName(TypeName node) {
10482 TypeName toNode = this._toNode as TypeName;
10483 if (_and(_isEqualNodes(node.name, toNode.name),
10484 _isEqualNodes(node.typeArguments, toNode.typeArguments))) {
10485 toNode.type = node.type;
10486 return true;
10487 }
10488 return false;
10489 }
10490
10491 @override
10492 bool visitTypeParameter(TypeParameter node) {
10493 TypeParameter toNode = this._toNode as TypeParameter;
10494 return _and(
10495 _isEqualNodes(node.documentationComment, toNode.documentationComment),
10496 _isEqualNodeLists(node.metadata, toNode.metadata),
10497 _isEqualNodes(node.name, toNode.name),
10498 _isEqualTokens(node.extendsKeyword, toNode.extendsKeyword),
10499 _isEqualNodes(node.bound, toNode.bound));
10500 }
10501
10502 @override
10503 bool visitTypeParameterList(TypeParameterList node) {
10504 TypeParameterList toNode = this._toNode as TypeParameterList;
10505 return _and(_isEqualTokens(node.leftBracket, toNode.leftBracket),
10506 _isEqualNodeLists(node.typeParameters, toNode.typeParameters),
10507 _isEqualTokens(node.rightBracket, toNode.rightBracket));
10508 }
10509
10510 @override
10511 bool visitVariableDeclaration(VariableDeclaration node) {
10512 VariableDeclaration toNode = this._toNode as VariableDeclaration;
10513 return _and(
10514 _isEqualNodes(node.documentationComment, toNode.documentationComment),
10515 _isEqualNodeLists(node.metadata, toNode.metadata),
10516 _isEqualNodes(node.name, toNode.name),
10517 _isEqualTokens(node.equals, toNode.equals),
10518 _isEqualNodes(node.initializer, toNode.initializer));
10519 }
10520
10521 @override
10522 bool visitVariableDeclarationList(VariableDeclarationList node) {
10523 VariableDeclarationList toNode = this._toNode as VariableDeclarationList;
10524 return _and(
10525 _isEqualNodes(node.documentationComment, toNode.documentationComment),
10526 _isEqualNodeLists(node.metadata, toNode.metadata),
10527 _isEqualTokens(node.keyword, toNode.keyword),
10528 _isEqualNodes(node.type, toNode.type),
10529 _isEqualNodeLists(node.variables, toNode.variables));
10530 }
10531
10532 @override
10533 bool visitVariableDeclarationStatement(VariableDeclarationStatement node) {
10534 VariableDeclarationStatement toNode =
10535 this._toNode as VariableDeclarationStatement;
10536 return _and(_isEqualNodes(node.variables, toNode.variables),
10537 _isEqualTokens(node.semicolon, toNode.semicolon));
10538 }
10539
10540 @override
10541 bool visitWhileStatement(WhileStatement node) {
10542 WhileStatement toNode = this._toNode as WhileStatement;
10543 return _and(_isEqualTokens(node.whileKeyword, toNode.whileKeyword),
10544 _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
10545 _isEqualNodes(node.condition, toNode.condition),
10546 _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
10547 _isEqualNodes(node.body, toNode.body));
10548 }
10549
10550 @override
10551 bool visitWithClause(WithClause node) {
10552 WithClause toNode = this._toNode as WithClause;
10553 return _and(_isEqualTokens(node.withKeyword, toNode.withKeyword),
10554 _isEqualNodeLists(node.mixinTypes, toNode.mixinTypes));
10555 }
10556
10557 @override
10558 bool visitYieldStatement(YieldStatement node) {
10559 YieldStatement toNode = this._toNode as YieldStatement;
10560 return _and(_isEqualTokens(node.yieldKeyword, toNode.yieldKeyword),
10561 _isEqualNodes(node.expression, toNode.expression),
10562 _isEqualTokens(node.semicolon, toNode.semicolon));
10563 }
10564
10565 /**
10566 * Return `true` if all of the parameters are `true`.
10567 */
10568 bool _and(bool b1, bool b2, [bool b3 = true, bool b4 = true, bool b5 = true,
10569 bool b6 = true, bool b7 = true, bool b8 = true, bool b9 = true,
10570 bool b10 = true, bool b11 = true, bool b12 = true, bool b13 = true]) {
10571 // TODO(brianwilkerson) Inline this method.
10572 return b1 &&
10573 b2 &&
10574 b3 &&
10575 b4 &&
10576 b5 &&
10577 b6 &&
10578 b7 &&
10579 b8 &&
10580 b9 &&
10581 b10 &&
10582 b11 &&
10583 b12 &&
10584 b13;
10585 }
10586
10587 /**
10588 * Return `true` if the [first] and [second] lists of AST nodes have the same
10589 * size and corresponding elements are equal.
10590 */
10591 bool _isEqualNodeLists(NodeList first, NodeList second) {
10592 if (first == null) {
10593 return second == null;
10594 } else if (second == null) {
10595 return false;
10596 }
10597 int size = first.length;
10598 if (second.length != size) {
10599 return false;
10600 }
10601 bool equal = true;
10602 for (int i = 0; i < size; i++) {
10603 if (!_isEqualNodes(first[i], second[i])) {
10604 equal = false;
10605 }
10606 }
10607 return equal;
10608 }
10609
10610 /**
10611 * Return `true` if the [fromNode] and [toNode] have the same structure. As a
10612 * side-effect, if the nodes do have the same structure, any resolution data
10613 * from the first node will be copied to the second node.
10614 */
10615 bool _isEqualNodes(AstNode fromNode, AstNode toNode) {
10616 if (fromNode == null) {
10617 return toNode == null;
10618 } else if (toNode == null) {
10619 return false;
10620 } else if (fromNode.runtimeType == toNode.runtimeType) {
10621 this._toNode = toNode;
10622 return fromNode.accept(this);
10623 }
10624 //
10625 // Check for a simple transformation caused by entering a period.
10626 //
10627 if (toNode is PrefixedIdentifier) {
10628 SimpleIdentifier prefix = toNode.prefix;
10629 if (fromNode.runtimeType == prefix.runtimeType) {
10630 this._toNode = prefix;
10631 return fromNode.accept(this);
10632 }
10633 } else if (toNode is PropertyAccess) {
10634 Expression target = toNode.target;
10635 if (fromNode.runtimeType == target.runtimeType) {
10636 this._toNode = target;
10637 return fromNode.accept(this);
10638 }
10639 }
10640 return false;
10641 }
10642
10643 /**
10644 * Return `true` if the [first] and [second] arrays of tokens have the same
10645 * length and corresponding elements are equal.
10646 */
10647 bool _isEqualTokenLists(List<Token> first, List<Token> second) {
10648 int length = first.length;
10649 if (second.length != length) {
10650 return false;
10651 }
10652 for (int i = 0; i < length; i++) {
10653 if (!_isEqualTokens(first[i], second[i])) {
10654 return false;
10655 }
10656 }
10657 return true;
10658 }
10659
10660 /**
10661 * Return `true` if the [first] and [second] tokens have the same structure.
10662 */
10663 bool _isEqualTokens(Token first, Token second) {
10664 if (first == null) {
10665 return second == null;
10666 } else if (second == null) {
10667 return false;
10668 }
10669 return first.lexeme == second.lexeme;
10670 }
10671
10672 /**
10673 * Copy resolution data from the [fromNode] to the [toNode].
10674 */
10675 static void copyResolutionData(AstNode fromNode, AstNode toNode) {
10676 ResolutionCopier copier = new ResolutionCopier();
10677 copier._isEqualNodes(fromNode, toNode);
10678 }
10679 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698