OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart2js.parser.element_listener; | 5 library dart2js.parser.element_listener; |
6 | 6 |
7 import '../compiler.dart' show | 7 import '../compiler.dart' show Compiler; |
8 Compiler; | |
9 import '../common.dart'; | 8 import '../common.dart'; |
10 import '../diagnostics/messages.dart' show | 9 import '../diagnostics/messages.dart' show MessageTemplate; |
11 MessageTemplate; | 10 import '../elements/elements.dart' |
12 import '../elements/elements.dart' show | 11 show Element, LibraryElement, MetadataAnnotation; |
13 Element, | 12 import '../elements/modelx.dart' |
14 LibraryElement, | 13 show |
15 MetadataAnnotation; | 14 CompilationUnitElementX, |
16 import '../elements/modelx.dart' show | 15 DeclarationSite, |
17 CompilationUnitElementX, | 16 ElementX, |
18 DeclarationSite, | 17 EnumClassElementX, |
19 ElementX, | 18 FieldElementX, |
20 EnumClassElementX, | 19 LibraryElementX, |
21 FieldElementX, | 20 NamedMixinApplicationElementX, |
22 LibraryElementX, | 21 VariableList; |
23 NamedMixinApplicationElementX, | |
24 VariableList; | |
25 import '../native/native.dart' as native; | 22 import '../native/native.dart' as native; |
26 import '../string_validator.dart' show | 23 import '../string_validator.dart' show StringValidator; |
27 StringValidator; | 24 import '../tokens/keyword.dart' show Keyword; |
28 import '../tokens/keyword.dart' show | 25 import '../tokens/precedence_constants.dart' as Precedence show BAD_INPUT_INFO; |
29 Keyword; | 26 import '../tokens/token.dart' |
30 import '../tokens/precedence_constants.dart' as Precedence show | 27 show BeginGroupToken, ErrorToken, KeywordToken, Token; |
31 BAD_INPUT_INFO; | 28 import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN; |
32 import '../tokens/token.dart' show | |
33 BeginGroupToken, | |
34 ErrorToken, | |
35 KeywordToken, | |
36 Token; | |
37 import '../tokens/token_constants.dart' as Tokens show | |
38 EOF_TOKEN; | |
39 import '../tree/tree.dart'; | 29 import '../tree/tree.dart'; |
40 import '../util/util.dart' show | 30 import '../util/util.dart' show Link, LinkBuilder; |
41 Link, | |
42 LinkBuilder; | |
43 | 31 |
44 import 'partial_elements.dart' show | 32 import 'partial_elements.dart' |
45 PartialClassElement, | 33 show |
46 PartialElement, | 34 PartialClassElement, |
47 PartialFieldList, | 35 PartialElement, |
48 PartialFunctionElement, | 36 PartialFieldList, |
49 PartialMetadataAnnotation, | 37 PartialFunctionElement, |
50 PartialTypedefElement; | 38 PartialMetadataAnnotation, |
51 import 'listener.dart' show | 39 PartialTypedefElement; |
52 closeBraceFor, | 40 import 'listener.dart' show closeBraceFor, Listener, ParserError, VERBOSE; |
53 Listener, | |
54 ParserError, | |
55 VERBOSE; | |
56 | 41 |
57 typedef int IdGenerator(); | 42 typedef int IdGenerator(); |
58 | 43 |
59 /// Options used for scanning. | 44 /// Options used for scanning. |
60 /// | 45 /// |
61 /// Use this to conditionally support special tokens. | 46 /// Use this to conditionally support special tokens. |
62 /// | 47 /// |
63 /// TODO(johnniwinther): This class should be renamed, it is not about options | 48 /// TODO(johnniwinther): This class should be renamed, it is not about options |
64 /// in the same sense as `CompilerOptions` or `DiagnosticOptions`. | 49 /// in the same sense as `CompilerOptions` or `DiagnosticOptions`. |
65 class ScannerOptions { | 50 class ScannerOptions { |
66 /// If `true` the pseudo keyword `native` is supported. | 51 /// If `true` the pseudo keyword `native` is supported. |
67 final bool canUseNative; | 52 final bool canUseNative; |
68 | 53 |
69 const ScannerOptions({this.canUseNative: false}); | 54 const ScannerOptions({this.canUseNative: false}); |
70 | 55 |
71 ScannerOptions.from(Compiler compiler, LibraryElement libraryElement) : | 56 ScannerOptions.from(Compiler compiler, LibraryElement libraryElement) |
72 canUseNative = compiler.backend.canLibraryUseNative(libraryElement); | 57 : canUseNative = compiler.backend.canLibraryUseNative(libraryElement); |
73 } | 58 } |
74 | 59 |
75 /** | 60 /** |
76 * A parser event listener designed to work with [PartialParser]. It | 61 * A parser event listener designed to work with [PartialParser]. It |
77 * builds elements representing the top-level declarations found in | 62 * builds elements representing the top-level declarations found in |
78 * the parsed compilation unit and records them in | 63 * the parsed compilation unit and records them in |
79 * [compilationUnitElement]. | 64 * [compilationUnitElement]. |
80 */ | 65 */ |
81 class ElementListener extends Listener { | 66 class ElementListener extends Listener { |
82 final IdGenerator idGenerator; | 67 final IdGenerator idGenerator; |
(...skipping 12 matching lines...) Expand all Loading... |
95 /// support nested members which isn't currently possible, but it also serves | 80 /// support nested members which isn't currently possible, but it also serves |
96 /// as a simple way to tell we're currently parsing a member). In this case, | 81 /// as a simple way to tell we're currently parsing a member). In this case, |
97 /// member refers to members of a library or a class (but currently, classes | 82 /// member refers to members of a library or a class (but currently, classes |
98 /// themselves are not considered members). If the top of the stack | 83 /// themselves are not considered members). If the top of the stack |
99 /// (memberErrors.head) is true, the current member has already reported at | 84 /// (memberErrors.head) is true, the current member has already reported at |
100 /// least one parse error. | 85 /// least one parse error. |
101 Link<bool> memberErrors = const Link<bool>(); | 86 Link<bool> memberErrors = const Link<bool>(); |
102 | 87 |
103 bool suppressParseErrors = false; | 88 bool suppressParseErrors = false; |
104 | 89 |
105 ElementListener( | 90 ElementListener(this.scannerOptions, DiagnosticReporter reporter, |
106 this.scannerOptions, | 91 this.compilationUnitElement, this.idGenerator) |
107 DiagnosticReporter reporter, | |
108 this.compilationUnitElement, | |
109 this.idGenerator) | |
110 : this.reporter = reporter, | 92 : this.reporter = reporter, |
111 stringValidator = new StringValidator(reporter), | 93 stringValidator = new StringValidator(reporter), |
112 interpolationScope = const Link<StringQuoting>(); | 94 interpolationScope = const Link<StringQuoting>(); |
113 | 95 |
114 bool get currentMemberHasParseError { | 96 bool get currentMemberHasParseError { |
115 return !memberErrors.isEmpty && memberErrors.head; | 97 return !memberErrors.isEmpty && memberErrors.head; |
116 } | 98 } |
117 | 99 |
118 void pushQuoting(StringQuoting quoting) { | 100 void pushQuoting(StringQuoting quoting) { |
119 interpolationScope = interpolationScope.prepend(quoting); | 101 interpolationScope = interpolationScope.prepend(quoting); |
120 } | 102 } |
121 | 103 |
122 StringQuoting popQuoting() { | 104 StringQuoting popQuoting() { |
123 StringQuoting result = interpolationScope.head; | 105 StringQuoting result = interpolationScope.head; |
124 interpolationScope = interpolationScope.tail; | 106 interpolationScope = interpolationScope.tail; |
125 return result; | 107 return result; |
126 } | 108 } |
127 | 109 |
128 StringNode popLiteralString() { | 110 StringNode popLiteralString() { |
129 StringNode node = popNode(); | 111 StringNode node = popNode(); |
130 // TODO(lrn): Handle interpolations in script tags. | 112 // TODO(lrn): Handle interpolations in script tags. |
131 if (node.isInterpolation) { | 113 if (node.isInterpolation) { |
132 reporter.internalError(node, | 114 reporter.internalError( |
133 "String interpolation not supported in library tags."); | 115 node, "String interpolation not supported in library tags."); |
134 return null; | 116 return null; |
135 } | 117 } |
136 return node; | 118 return node; |
137 } | 119 } |
138 | 120 |
139 bool allowLibraryTags() { | 121 bool allowLibraryTags() { |
140 // Library tags are only allowed in the library file itself, not | 122 // Library tags are only allowed in the library file itself, not |
141 // in sourced files. | 123 // in sourced files. |
142 LibraryElement library = compilationUnitElement.implementationLibrary; | 124 LibraryElement library = compilationUnitElement.implementationLibrary; |
143 return !compilationUnitElement.hasMembers && | 125 return !compilationUnitElement.hasMembers && |
144 library.entryCompilationUnit == compilationUnitElement; | 126 library.entryCompilationUnit == compilationUnitElement; |
145 } | 127 } |
146 | 128 |
147 void endLibraryName(Token libraryKeyword, Token semicolon) { | 129 void endLibraryName(Token libraryKeyword, Token semicolon) { |
148 Expression name = popNode(); | 130 Expression name = popNode(); |
149 addLibraryTag(new LibraryName(libraryKeyword, name, | 131 addLibraryTag(new LibraryName( |
150 popMetadata(compilationUnitElement))); | 132 libraryKeyword, name, popMetadata(compilationUnitElement))); |
151 } | 133 } |
152 | 134 |
153 void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword, | 135 void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword, |
154 Token semicolon) { | 136 Token semicolon) { |
155 NodeList combinators = popNode(); | 137 NodeList combinators = popNode(); |
156 bool isDeferred = deferredKeyword != null; | 138 bool isDeferred = deferredKeyword != null; |
157 Identifier prefix; | 139 Identifier prefix; |
158 if (asKeyword != null) { | 140 if (asKeyword != null) { |
159 prefix = popNode(); | 141 prefix = popNode(); |
160 } | 142 } |
161 NodeList conditionalUris = popNode(); | 143 NodeList conditionalUris = popNode(); |
162 StringNode uri = popLiteralString(); | 144 StringNode uri = popLiteralString(); |
163 addLibraryTag(new Import(importKeyword, uri, conditionalUris, | 145 addLibraryTag(new Import(importKeyword, uri, conditionalUris, prefix, |
164 prefix, combinators, | 146 combinators, popMetadata(compilationUnitElement), |
165 popMetadata(compilationUnitElement), | 147 isDeferred: isDeferred)); |
166 isDeferred: isDeferred)); | |
167 } | 148 } |
168 | 149 |
169 void endDottedName(int count, Token token) { | 150 void endDottedName(int count, Token token) { |
170 NodeList identifiers = makeNodeList(count, null, null, '.'); | 151 NodeList identifiers = makeNodeList(count, null, null, '.'); |
171 pushNode(new DottedName(token, identifiers)); | 152 pushNode(new DottedName(token, identifiers)); |
172 } | 153 } |
173 | 154 |
174 void endConditionalUris(int count) { | 155 void endConditionalUris(int count) { |
175 if (count == 0) { | 156 if (count == 0) { |
176 pushNode(null); | 157 pushNode(null); |
177 } else { | 158 } else { |
178 pushNode(makeNodeList(count, null, null, " ")); | 159 pushNode(makeNodeList(count, null, null, " ")); |
179 } | 160 } |
180 } | 161 } |
181 | 162 |
182 void endConditionalUri(Token ifToken, Token equalSign) { | 163 void endConditionalUri(Token ifToken, Token equalSign) { |
183 StringNode uri = popNode(); | 164 StringNode uri = popNode(); |
184 LiteralString conditionValue = (equalSign != null) ? popNode() : null; | 165 LiteralString conditionValue = (equalSign != null) ? popNode() : null; |
185 DottedName identifier = popNode(); | 166 DottedName identifier = popNode(); |
186 pushNode(new ConditionalUri(ifToken, identifier, conditionValue, uri)); | 167 pushNode(new ConditionalUri(ifToken, identifier, conditionValue, uri)); |
187 } | 168 } |
188 | 169 |
189 void endEnum(Token enumKeyword, Token endBrace, int count) { | 170 void endEnum(Token enumKeyword, Token endBrace, int count) { |
190 NodeList names = makeNodeList(count, enumKeyword.next.next, endBrace, ","); | 171 NodeList names = makeNodeList(count, enumKeyword.next.next, endBrace, ","); |
191 Identifier name = popNode(); | 172 Identifier name = popNode(); |
192 | 173 |
193 int id = idGenerator(); | 174 int id = idGenerator(); |
194 Element enclosing = compilationUnitElement; | 175 Element enclosing = compilationUnitElement; |
195 pushElement(new EnumClassElementX(name.source, enclosing, id, | 176 pushElement(new EnumClassElementX( |
196 new Enum(enumKeyword, name, names))); | 177 name.source, enclosing, id, new Enum(enumKeyword, name, names))); |
197 rejectBuiltInIdentifier(name); | 178 rejectBuiltInIdentifier(name); |
198 } | 179 } |
199 | 180 |
200 void endExport(Token exportKeyword, Token semicolon) { | 181 void endExport(Token exportKeyword, Token semicolon) { |
201 NodeList combinators = popNode(); | 182 NodeList combinators = popNode(); |
202 NodeList conditionalUris = popNode(); | 183 NodeList conditionalUris = popNode(); |
203 StringNode uri = popNode(); | 184 StringNode uri = popNode(); |
204 addLibraryTag(new Export(exportKeyword, uri, conditionalUris, combinators, | 185 addLibraryTag(new Export(exportKeyword, uri, conditionalUris, combinators, |
205 popMetadata(compilationUnitElement))); | 186 popMetadata(compilationUnitElement))); |
206 } | 187 } |
207 | 188 |
208 void endCombinators(int count) { | 189 void endCombinators(int count) { |
209 if (0 == count) { | 190 if (0 == count) { |
210 pushNode(null); | 191 pushNode(null); |
211 } else { | 192 } else { |
212 pushNode(makeNodeList(count, null, null, " ")); | 193 pushNode(makeNodeList(count, null, null, " ")); |
213 } | 194 } |
214 } | 195 } |
215 | 196 |
216 void endHide(Token hideKeyword) => pushCombinator(hideKeyword); | 197 void endHide(Token hideKeyword) => pushCombinator(hideKeyword); |
217 | 198 |
218 void endShow(Token showKeyword) => pushCombinator(showKeyword); | 199 void endShow(Token showKeyword) => pushCombinator(showKeyword); |
219 | 200 |
220 void pushCombinator(Token keywordToken) { | 201 void pushCombinator(Token keywordToken) { |
221 NodeList identifiers = popNode(); | 202 NodeList identifiers = popNode(); |
222 pushNode(new Combinator(identifiers, keywordToken)); | 203 pushNode(new Combinator(identifiers, keywordToken)); |
223 } | 204 } |
224 | 205 |
225 void endIdentifierList(int count) { | 206 void endIdentifierList(int count) { |
226 pushNode(makeNodeList(count, null, null, ",")); | 207 pushNode(makeNodeList(count, null, null, ",")); |
227 } | 208 } |
228 | 209 |
229 void endTypeList(int count) { | 210 void endTypeList(int count) { |
230 pushNode(makeNodeList(count, null, null, ",")); | 211 pushNode(makeNodeList(count, null, null, ",")); |
231 } | 212 } |
232 | 213 |
233 void endPart(Token partKeyword, Token semicolon) { | 214 void endPart(Token partKeyword, Token semicolon) { |
234 StringNode uri = popLiteralString(); | 215 StringNode uri = popLiteralString(); |
235 addLibraryTag(new Part(partKeyword, uri, | 216 addLibraryTag( |
236 popMetadata(compilationUnitElement))); | 217 new Part(partKeyword, uri, popMetadata(compilationUnitElement))); |
237 } | 218 } |
238 | 219 |
239 void endPartOf(Token partKeyword, Token semicolon) { | 220 void endPartOf(Token partKeyword, Token semicolon) { |
240 Expression name = popNode(); | 221 Expression name = popNode(); |
241 addPartOfTag(new PartOf(partKeyword, name, | 222 addPartOfTag( |
242 popMetadata(compilationUnitElement))); | 223 new PartOf(partKeyword, name, popMetadata(compilationUnitElement))); |
243 } | 224 } |
244 | 225 |
245 void addPartOfTag(PartOf tag) { | 226 void addPartOfTag(PartOf tag) { |
246 compilationUnitElement.setPartOf(tag, reporter); | 227 compilationUnitElement.setPartOf(tag, reporter); |
247 } | 228 } |
248 | 229 |
249 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) { | 230 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) { |
250 if (periodBeforeName != null) { | 231 if (periodBeforeName != null) { |
251 popNode(); // Discard name. | 232 popNode(); // Discard name. |
252 } | 233 } |
253 popNode(); // Discard node (Send or Identifier). | 234 popNode(); // Discard node (Send or Identifier). |
254 pushMetadata(new PartialMetadataAnnotation(beginToken, endToken)); | 235 pushMetadata(new PartialMetadataAnnotation(beginToken, endToken)); |
255 } | 236 } |
256 | 237 |
257 void endTopLevelDeclaration(Token token) { | 238 void endTopLevelDeclaration(Token token) { |
258 if (!metadata.isEmpty) { | 239 if (!metadata.isEmpty) { |
259 recoverableError(metadata.first.beginToken, | 240 recoverableError( |
260 'Metadata not supported here.'); | 241 metadata.first.beginToken, 'Metadata not supported here.'); |
261 metadata.clear(); | 242 metadata.clear(); |
262 } | 243 } |
263 } | 244 } |
264 | 245 |
265 void endClassDeclaration(int interfacesCount, Token beginToken, | 246 void endClassDeclaration(int interfacesCount, Token beginToken, |
266 Token extendsKeyword, Token implementsKeyword, | 247 Token extendsKeyword, Token implementsKeyword, Token endToken) { |
267 Token endToken) { | |
268 makeNodeList(interfacesCount, implementsKeyword, null, ","); // interfaces | 248 makeNodeList(interfacesCount, implementsKeyword, null, ","); // interfaces |
269 popNode(); // superType | 249 popNode(); // superType |
270 popNode(); // typeParameters | 250 popNode(); // typeParameters |
271 Identifier name = popNode(); | 251 Identifier name = popNode(); |
272 int id = idGenerator(); | 252 int id = idGenerator(); |
273 PartialClassElement element = new PartialClassElement( | 253 PartialClassElement element = new PartialClassElement( |
274 name.source, beginToken, endToken, compilationUnitElement, id); | 254 name.source, beginToken, endToken, compilationUnitElement, id); |
275 pushElement(element); | 255 pushElement(element); |
276 rejectBuiltInIdentifier(name); | 256 rejectBuiltInIdentifier(name); |
277 } | 257 } |
278 | 258 |
279 void rejectBuiltInIdentifier(Identifier name) { | 259 void rejectBuiltInIdentifier(Identifier name) { |
280 if (name.token is KeywordToken) { | 260 if (name.token is KeywordToken) { |
281 Keyword keyword = (name.token as KeywordToken).keyword; | 261 Keyword keyword = (name.token as KeywordToken).keyword; |
282 if (!keyword.isPseudo) { | 262 if (!keyword.isPseudo) { |
283 recoverableError(name, "Illegal name '${keyword.syntax}'."); | 263 recoverableError(name, "Illegal name '${keyword.syntax}'."); |
284 } | 264 } |
285 } | 265 } |
286 } | 266 } |
287 | 267 |
288 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { | 268 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { |
289 popNode(); // TODO(karlklose): do not throw away typeVariables. | 269 popNode(); // TODO(karlklose): do not throw away typeVariables. |
290 Identifier name = popNode(); | 270 Identifier name = popNode(); |
291 popNode(); // returnType | 271 popNode(); // returnType |
292 pushElement( | 272 pushElement(new PartialTypedefElement( |
293 new PartialTypedefElement( | 273 name.source, compilationUnitElement, typedefKeyword, endToken)); |
294 name.source, compilationUnitElement, typedefKeyword, endToken)); | |
295 rejectBuiltInIdentifier(name); | 274 rejectBuiltInIdentifier(name); |
296 } | 275 } |
297 | 276 |
298 void endNamedMixinApplication(Token classKeyword, | 277 void endNamedMixinApplication( |
299 Token implementsKeyword, | 278 Token classKeyword, Token implementsKeyword, Token endToken) { |
300 Token endToken) { | |
301 NodeList interfaces = (implementsKeyword != null) ? popNode() : null; | 279 NodeList interfaces = (implementsKeyword != null) ? popNode() : null; |
302 MixinApplication mixinApplication = popNode(); | 280 MixinApplication mixinApplication = popNode(); |
303 Modifiers modifiers = popNode(); | 281 Modifiers modifiers = popNode(); |
304 NodeList typeParameters = popNode(); | 282 NodeList typeParameters = popNode(); |
305 Identifier name = popNode(); | 283 Identifier name = popNode(); |
306 NamedMixinApplication namedMixinApplication = new NamedMixinApplication( | 284 NamedMixinApplication namedMixinApplication = new NamedMixinApplication( |
307 name, typeParameters, modifiers, mixinApplication, interfaces, | 285 name, |
308 classKeyword, endToken); | 286 typeParameters, |
| 287 modifiers, |
| 288 mixinApplication, |
| 289 interfaces, |
| 290 classKeyword, |
| 291 endToken); |
309 | 292 |
310 int id = idGenerator(); | 293 int id = idGenerator(); |
311 Element enclosing = compilationUnitElement; | 294 Element enclosing = compilationUnitElement; |
312 pushElement(new NamedMixinApplicationElementX( | 295 pushElement(new NamedMixinApplicationElementX( |
313 name.source, enclosing, id, namedMixinApplication)); | 296 name.source, enclosing, id, namedMixinApplication)); |
314 rejectBuiltInIdentifier(name); | 297 rejectBuiltInIdentifier(name); |
315 } | 298 } |
316 | 299 |
317 void endMixinApplication() { | 300 void endMixinApplication() { |
318 NodeList mixins = popNode(); | 301 NodeList mixins = popNode(); |
319 TypeAnnotation superclass = popNode(); | 302 TypeAnnotation superclass = popNode(); |
320 pushNode(new MixinApplication(superclass, mixins)); | 303 pushNode(new MixinApplication(superclass, mixins)); |
321 } | 304 } |
322 | 305 |
323 void handleVoidKeyword(Token token) { | 306 void handleVoidKeyword(Token token) { |
324 pushNode(new TypeAnnotation(new Identifier(token), null)); | 307 pushNode(new TypeAnnotation(new Identifier(token), null)); |
325 } | 308 } |
326 | 309 |
327 void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) { | 310 void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) { |
328 bool hasParseError = currentMemberHasParseError; | 311 bool hasParseError = currentMemberHasParseError; |
329 memberErrors = memberErrors.tail; | 312 memberErrors = memberErrors.tail; |
330 Identifier name = popNode(); | 313 Identifier name = popNode(); |
331 popNode(); // type | 314 popNode(); // type |
332 Modifiers modifiers = popNode(); | 315 Modifiers modifiers = popNode(); |
333 PartialFunctionElement element = new PartialFunctionElement( | 316 PartialFunctionElement element = new PartialFunctionElement(name.source, |
334 name.source, beginToken, getOrSet, endToken, | 317 beginToken, getOrSet, endToken, modifiers, compilationUnitElement); |
335 modifiers, compilationUnitElement); | |
336 element.hasParseError = hasParseError; | 318 element.hasParseError = hasParseError; |
337 pushElement(element); | 319 pushElement(element); |
338 } | 320 } |
339 | 321 |
340 void endTopLevelFields(int count, Token beginToken, Token endToken) { | 322 void endTopLevelFields(int count, Token beginToken, Token endToken) { |
341 bool hasParseError = currentMemberHasParseError; | 323 bool hasParseError = currentMemberHasParseError; |
342 memberErrors = memberErrors.tail; | 324 memberErrors = memberErrors.tail; |
343 void buildFieldElement(Identifier name, VariableList fields) { | 325 void buildFieldElement(Identifier name, VariableList fields) { |
344 pushElement( | 326 pushElement(new FieldElementX(name, compilationUnitElement, fields)); |
345 new FieldElementX(name, compilationUnitElement, fields)); | |
346 } | 327 } |
347 NodeList variables = makeNodeList(count, null, null, ","); | 328 NodeList variables = makeNodeList(count, null, null, ","); |
348 popNode(); // type | 329 popNode(); // type |
349 Modifiers modifiers = popNode(); | 330 Modifiers modifiers = popNode(); |
350 buildFieldElements(modifiers, variables, compilationUnitElement, | 331 buildFieldElements(modifiers, variables, compilationUnitElement, |
351 buildFieldElement, | 332 buildFieldElement, beginToken, endToken, hasParseError); |
352 beginToken, endToken, hasParseError); | |
353 } | 333 } |
354 | 334 |
355 void buildFieldElements(Modifiers modifiers, | 335 void buildFieldElements( |
356 NodeList variables, | 336 Modifiers modifiers, |
357 Element enclosingElement, | 337 NodeList variables, |
358 void buildFieldElement(Identifier name, | 338 Element enclosingElement, |
359 VariableList fields), | 339 void buildFieldElement(Identifier name, VariableList fields), |
360 Token beginToken, Token endToken, | 340 Token beginToken, |
361 bool hasParseError) { | 341 Token endToken, |
| 342 bool hasParseError) { |
362 VariableList fields = | 343 VariableList fields = |
363 new PartialFieldList(beginToken, endToken, modifiers, hasParseError); | 344 new PartialFieldList(beginToken, endToken, modifiers, hasParseError); |
364 for (Link<Node> variableNodes = variables.nodes; | 345 for (Link<Node> variableNodes = variables.nodes; |
365 !variableNodes.isEmpty; | 346 !variableNodes.isEmpty; |
366 variableNodes = variableNodes.tail) { | 347 variableNodes = variableNodes.tail) { |
367 Expression initializedIdentifier = variableNodes.head; | 348 Expression initializedIdentifier = variableNodes.head; |
368 Identifier identifier = initializedIdentifier.asIdentifier(); | 349 Identifier identifier = initializedIdentifier.asIdentifier(); |
369 if (identifier == null) { | 350 if (identifier == null) { |
370 identifier = initializedIdentifier.asSendSet().selector.asIdentifier(); | 351 identifier = initializedIdentifier.asSendSet().selector.asIdentifier(); |
371 } | 352 } |
372 buildFieldElement(identifier, fields); | 353 buildFieldElement(identifier, fields); |
373 } | 354 } |
374 } | 355 } |
375 | 356 |
376 void handleIdentifier(Token token) { | 357 void handleIdentifier(Token token) { |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 } | 492 } |
512 if (current.kind != Tokens.EOF_TOKEN) { | 493 if (current.kind != Tokens.EOF_TOKEN) { |
513 return current; | 494 return current; |
514 } | 495 } |
515 } | 496 } |
516 return null; | 497 return null; |
517 } | 498 } |
518 | 499 |
519 Token expectedIdentifier(Token token) { | 500 Token expectedIdentifier(Token token) { |
520 if (token is KeywordToken) { | 501 if (token is KeywordToken) { |
521 reportError( | 502 reportError(token, MessageKind.EXPECTED_IDENTIFIER_NOT_RESERVED_WORD, |
522 token, MessageKind.EXPECTED_IDENTIFIER_NOT_RESERVED_WORD, | |
523 {'keyword': token.value}); | 503 {'keyword': token.value}); |
524 } else if (token is ErrorToken) { | 504 } else if (token is ErrorToken) { |
525 reportErrorToken(token); | 505 reportErrorToken(token); |
526 return synthesizeIdentifier(token); | 506 return synthesizeIdentifier(token); |
527 } else { | 507 } else { |
528 reportFatalError(token, | 508 reportFatalError(token, "Expected identifier, but got '${token.value}'."); |
529 "Expected identifier, but got '${token.value}'."); | |
530 } | 509 } |
531 return token; | 510 return token; |
532 } | 511 } |
533 | 512 |
534 Token expectedType(Token token) { | 513 Token expectedType(Token token) { |
535 pushNode(null); | 514 pushNode(null); |
536 if (token is ErrorToken) { | 515 if (token is ErrorToken) { |
537 reportErrorToken(token); | 516 reportErrorToken(token); |
538 return synthesizeIdentifier(token); | 517 return synthesizeIdentifier(token); |
539 } else { | 518 } else { |
540 reportFatalError( | 519 reportFatalError(token, "Expected a type, but got '${token.value}'."); |
541 token, "Expected a type, but got '${token.value}'."); | |
542 return skipToEof(token); | 520 return skipToEof(token); |
543 } | 521 } |
544 } | 522 } |
545 | 523 |
546 Token expectedExpression(Token token) { | 524 Token expectedExpression(Token token) { |
547 if (token is ErrorToken) { | 525 if (token is ErrorToken) { |
548 reportErrorToken(token); | 526 reportErrorToken(token); |
549 pushNode(new ErrorExpression(token)); | 527 pushNode(new ErrorExpression(token)); |
550 return token.next; | 528 return token.next; |
551 } else { | 529 } else { |
552 reportFatalError(token, | 530 reportFatalError( |
553 "Expected an expression, but got '${token.value}'."); | 531 token, "Expected an expression, but got '${token.value}'."); |
554 pushNode(null); | 532 pushNode(null); |
555 return skipToEof(token); | 533 return skipToEof(token); |
556 } | 534 } |
557 } | 535 } |
558 | 536 |
559 Token unexpected(Token token) { | 537 Token unexpected(Token token) { |
560 if (token is ErrorToken) { | 538 if (token is ErrorToken) { |
561 reportErrorToken(token); | 539 reportErrorToken(token); |
562 } else { | 540 } else { |
563 String message = "Unexpected token '${token.value}'."; | 541 String message = "Unexpected token '${token.value}'."; |
(...skipping 11 matching lines...) Expand all Loading... |
575 } else { | 553 } else { |
576 return unexpected(token); | 554 return unexpected(token); |
577 } | 555 } |
578 } | 556 } |
579 | 557 |
580 Token expectedFunctionBody(Token token) { | 558 Token expectedFunctionBody(Token token) { |
581 if (token is ErrorToken) { | 559 if (token is ErrorToken) { |
582 reportErrorToken(token); | 560 reportErrorToken(token); |
583 } else { | 561 } else { |
584 String printString = token.value; | 562 String printString = token.value; |
585 reportFatalError(token, | 563 reportFatalError( |
586 "Expected a function body, but got '$printString'."); | 564 token, "Expected a function body, but got '$printString'."); |
587 } | 565 } |
588 return skipToEof(token); | 566 return skipToEof(token); |
589 } | 567 } |
590 | 568 |
591 Token expectedClassBody(Token token) { | 569 Token expectedClassBody(Token token) { |
592 if (token is ErrorToken) { | 570 if (token is ErrorToken) { |
593 reportErrorToken(token); | 571 reportErrorToken(token); |
594 } else { | 572 } else { |
595 reportFatalError(token, | 573 reportFatalError( |
596 "Expected a class body, but got '${token.value}'."); | 574 token, "Expected a class body, but got '${token.value}'."); |
597 } | 575 } |
598 return skipToEof(token); | 576 return skipToEof(token); |
599 } | 577 } |
600 | 578 |
601 Token expectedClassBodyToSkip(Token token) { | 579 Token expectedClassBodyToSkip(Token token) { |
602 return unexpected(token); | 580 return unexpected(token); |
603 } | 581 } |
604 | 582 |
605 Token expectedDeclaration(Token token) { | 583 Token expectedDeclaration(Token token) { |
606 if (token is ErrorToken) { | 584 if (token is ErrorToken) { |
607 reportErrorToken(token); | 585 reportErrorToken(token); |
608 } else { | 586 } else { |
609 reportFatalError(token, | 587 reportFatalError( |
610 "Expected a declaration, but got '${token.value}'."); | 588 token, "Expected a declaration, but got '${token.value}'."); |
611 } | 589 } |
612 return skipToEof(token); | 590 return skipToEof(token); |
613 } | 591 } |
614 | 592 |
615 Token unmatched(Token token) { | 593 Token unmatched(Token token) { |
616 if (token is ErrorToken) { | 594 if (token is ErrorToken) { |
617 reportErrorToken(token); | 595 reportErrorToken(token); |
618 } else { | 596 } else { |
619 String begin = token.value; | 597 String begin = token.value; |
620 String end = closeBraceFor(begin); | 598 String end = closeBraceFor(begin); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 Node node = nodes.head; | 648 Node node = nodes.head; |
671 nodes = nodes.tail; | 649 nodes = nodes.tail; |
672 if (VERBOSE) log("pop $nodes"); | 650 if (VERBOSE) log("pop $nodes"); |
673 return node; | 651 return node; |
674 } | 652 } |
675 | 653 |
676 void log(message) { | 654 void log(message) { |
677 print(message); | 655 print(message); |
678 } | 656 } |
679 | 657 |
680 NodeList makeNodeList(int count, Token beginToken, Token endToken, | 658 NodeList makeNodeList( |
681 String delimiter) { | 659 int count, Token beginToken, Token endToken, String delimiter) { |
682 Link<Node> poppedNodes = const Link<Node>(); | 660 Link<Node> poppedNodes = const Link<Node>(); |
683 for (; count > 0; --count) { | 661 for (; count > 0; --count) { |
684 // This effectively reverses the order of nodes so they end up | 662 // This effectively reverses the order of nodes so they end up |
685 // in correct (source) order. | 663 // in correct (source) order. |
686 poppedNodes = poppedNodes.prepend(popNode()); | 664 poppedNodes = poppedNodes.prepend(popNode()); |
687 } | 665 } |
688 return new NodeList(beginToken, poppedNodes, endToken, delimiter); | 666 return new NodeList(beginToken, poppedNodes, endToken, delimiter); |
689 } | 667 } |
690 | 668 |
691 void beginLiteralString(Token token) { | 669 void beginLiteralString(Token token) { |
692 String source = token.value; | 670 String source = token.value; |
693 StringQuoting quoting = StringValidator.quotingFromString(source); | 671 StringQuoting quoting = StringValidator.quotingFromString(source); |
694 pushQuoting(quoting); | 672 pushQuoting(quoting); |
695 // Just wrap the token for now. At the end of the interpolation, | 673 // Just wrap the token for now. At the end of the interpolation, |
696 // when we know how many there are, go back and validate the tokens. | 674 // when we know how many there are, go back and validate the tokens. |
697 pushNode(new LiteralString(token, null)); | 675 pushNode(new LiteralString(token, null)); |
698 } | 676 } |
699 | 677 |
700 void handleStringPart(Token token) { | 678 void handleStringPart(Token token) { |
701 // Just push an unvalidated token now, and replace it when we know the | 679 // Just push an unvalidated token now, and replace it when we know the |
702 // end of the interpolation. | 680 // end of the interpolation. |
703 pushNode(new LiteralString(token, null)); | 681 pushNode(new LiteralString(token, null)); |
704 } | 682 } |
705 | 683 |
706 void endLiteralString(int count) { | 684 void endLiteralString(int count) { |
707 StringQuoting quoting = popQuoting(); | 685 StringQuoting quoting = popQuoting(); |
708 | 686 |
709 Link<StringInterpolationPart> parts = | 687 Link<StringInterpolationPart> parts = const Link<StringInterpolationPart>(); |
710 const Link<StringInterpolationPart>(); | |
711 // Parts of the string interpolation are popped in reverse order, | 688 // Parts of the string interpolation are popped in reverse order, |
712 // starting with the last literal string part. | 689 // starting with the last literal string part. |
713 bool isLast = true; | 690 bool isLast = true; |
714 for (int i = 0; i < count; i++) { | 691 for (int i = 0; i < count; i++) { |
715 LiteralString string = popNode(); | 692 LiteralString string = popNode(); |
716 DartString validation = | 693 DartString validation = stringValidator.validateInterpolationPart( |
717 stringValidator.validateInterpolationPart(string.token, quoting, | 694 string.token, quoting, |
718 isFirst: false, | 695 isFirst: false, isLast: isLast); |
719 isLast: isLast); | |
720 // Replace the unvalidated LiteralString with a new LiteralString | 696 // Replace the unvalidated LiteralString with a new LiteralString |
721 // object that has the validation result included. | 697 // object that has the validation result included. |
722 string = new LiteralString(string.token, validation); | 698 string = new LiteralString(string.token, validation); |
723 Expression expression = popNode(); | 699 Expression expression = popNode(); |
724 parts = parts.prepend(new StringInterpolationPart(expression, string)); | 700 parts = parts.prepend(new StringInterpolationPart(expression, string)); |
725 isLast = false; | 701 isLast = false; |
726 } | 702 } |
727 | 703 |
728 LiteralString string = popNode(); | 704 LiteralString string = popNode(); |
729 DartString validation = | 705 DartString validation = stringValidator.validateInterpolationPart( |
730 stringValidator.validateInterpolationPart(string.token, quoting, | 706 string.token, quoting, |
731 isFirst: true, | 707 isFirst: true, isLast: isLast); |
732 isLast: isLast); | |
733 string = new LiteralString(string.token, validation); | 708 string = new LiteralString(string.token, validation); |
734 if (isLast) { | 709 if (isLast) { |
735 pushNode(string); | 710 pushNode(string); |
736 } else { | 711 } else { |
737 NodeList partNodes = new NodeList(null, parts, null, ""); | 712 NodeList partNodes = new NodeList(null, parts, null, ""); |
738 pushNode(new StringInterpolation(string, partNodes)); | 713 pushNode(new StringInterpolation(string, partNodes)); |
739 } | 714 } |
740 } | 715 } |
741 | 716 |
742 void handleStringJuxtaposition(int stringCount) { | 717 void handleStringJuxtaposition(int stringCount) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
776 } | 751 } |
777 | 752 |
778 /// Don't call this method. Should only be used as a last resort when there | 753 /// Don't call this method. Should only be used as a last resort when there |
779 /// is no feasible way to recover from a parser error. | 754 /// is no feasible way to recover from a parser error. |
780 void reportFatalError(Spannable spannable, String message) { | 755 void reportFatalError(Spannable spannable, String message) { |
781 reportError(spannable, MessageKind.GENERIC, {'text': message}); | 756 reportError(spannable, MessageKind.GENERIC, {'text': message}); |
782 // Some parse errors are infeasible to recover from, so we throw an error. | 757 // Some parse errors are infeasible to recover from, so we throw an error. |
783 throw new ParserError(message); | 758 throw new ParserError(message); |
784 } | 759 } |
785 | 760 |
786 void reportError(Spannable spannable, | 761 void reportError(Spannable spannable, MessageKind errorCode, |
787 MessageKind errorCode, | 762 [Map arguments = const {}]) { |
788 [Map arguments = const {}]) { | |
789 if (currentMemberHasParseError) return; // Error already reported. | 763 if (currentMemberHasParseError) return; // Error already reported. |
790 if (suppressParseErrors) return; | 764 if (suppressParseErrors) return; |
791 if (!memberErrors.isEmpty) { | 765 if (!memberErrors.isEmpty) { |
792 memberErrors = memberErrors.tail.prepend(true); | 766 memberErrors = memberErrors.tail.prepend(true); |
793 } | 767 } |
794 reporter.reportErrorMessage(spannable, errorCode, arguments); | 768 reporter.reportErrorMessage(spannable, errorCode, arguments); |
795 } | 769 } |
796 } | 770 } |
OLD | NEW |