| 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 |