Index: pkg/compiler/lib/src/scanner/listener.dart |
diff --git a/pkg/compiler/lib/src/scanner/listener.dart b/pkg/compiler/lib/src/scanner/listener.dart |
deleted file mode 100644 |
index 89f20d4587b7a605f15503f7824d1283912115ed..0000000000000000000000000000000000000000 |
--- a/pkg/compiler/lib/src/scanner/listener.dart |
+++ /dev/null |
@@ -1,2493 +0,0 @@ |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-part of scanner; |
- |
-const bool VERBOSE = false; |
- |
-/** |
- * A parser event listener that does nothing except throw exceptions |
- * on parser errors. |
- */ |
-class Listener { |
- set suppressParseErrors(bool value) { |
- } |
- |
- void beginArguments(Token token) { |
- } |
- |
- void endArguments(int count, Token beginToken, Token endToken) { |
- } |
- |
- /// Handle async modifiers `async`, `async*`, `sync`. |
- void handleAsyncModifier(Token asyncToken, Token startToken) { |
- } |
- |
- void beginAwaitExpression(Token token) { |
- } |
- |
- void endAwaitExpression(Token beginToken, Token endToken) { |
- } |
- |
- void beginBlock(Token token) { |
- } |
- |
- void endBlock(int count, Token beginToken, Token endToken) { |
- } |
- |
- void beginCascade(Token token) { |
- } |
- |
- void endCascade() { |
- } |
- |
- void beginClassBody(Token token) { |
- } |
- |
- void endClassBody(int memberCount, Token beginToken, Token endToken) { |
- } |
- |
- void beginClassDeclaration(Token token) { |
- } |
- |
- void endClassDeclaration(int interfacesCount, Token beginToken, |
- Token extendsKeyword, Token implementsKeyword, |
- Token endToken) { |
- } |
- |
- void beginCombinators(Token token) { |
- } |
- |
- void endCombinators(int count) { |
- } |
- |
- void beginCompilationUnit(Token token) { |
- } |
- |
- void endCompilationUnit(int count, Token token) { |
- } |
- |
- void beginConstructorReference(Token start) { |
- } |
- |
- void endConstructorReference(Token start, Token periodBeforeName, |
- Token endToken) { |
- } |
- |
- void beginDoWhileStatement(Token token) { |
- } |
- |
- void endDoWhileStatement(Token doKeyword, Token whileKeyword, |
- Token endToken) { |
- } |
- |
- void beginExport(Token token) { |
- } |
- |
- void endExport(Token exportKeyword, Token semicolon) { |
- } |
- |
- void beginExpressionStatement(Token token) { |
- } |
- |
- void endExpressionStatement(Token token) { |
- } |
- |
- void beginFactoryMethod(Token token) { |
- } |
- |
- void endFactoryMethod(Token beginToken, Token endToken) { |
- } |
- |
- void beginFormalParameter(Token token) { |
- } |
- |
- void endFormalParameter(Token thisKeyword) { |
- } |
- |
- void handleNoFormalParameters(Token token) { |
- } |
- |
- void beginFormalParameters(Token token) { |
- } |
- |
- void endFormalParameters(int count, Token beginToken, Token endToken) { |
- } |
- |
- void endFields(int count, Token beginToken, Token endToken) { |
- } |
- |
- void beginForStatement(Token token) { |
- } |
- |
- void endForStatement(int updateExpressionCount, |
- Token beginToken, Token endToken) { |
- } |
- |
- void endForIn(Token awaitToken, Token forToken, |
- Token inKeyword, Token endToken) { |
- } |
- |
- void beginFunction(Token token) { |
- } |
- |
- void endFunction(Token getOrSet, Token endToken) { |
- } |
- |
- void beginFunctionDeclaration(Token token) { |
- } |
- |
- void endFunctionDeclaration(Token token) { |
- } |
- |
- void beginFunctionBody(Token token) { |
- } |
- |
- void endFunctionBody(int count, Token beginToken, Token endToken) { |
- } |
- |
- void handleNoFunctionBody(Token token) { |
- } |
- |
- void skippedFunctionBody(Token token) { |
- } |
- |
- void beginFunctionName(Token token) { |
- } |
- |
- void endFunctionName(Token token) { |
- } |
- |
- void beginFunctionTypeAlias(Token token) { |
- } |
- |
- void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { |
- } |
- |
- void beginMixinApplication(Token token) { |
- } |
- |
- void endMixinApplication() { |
- } |
- |
- void beginNamedMixinApplication(Token token) { |
- } |
- |
- void endNamedMixinApplication(Token classKeyword, |
- Token implementsKeyword, |
- Token endToken) { |
- } |
- |
- void beginHide(Token hideKeyword) { |
- } |
- |
- void endHide(Token hideKeyword) { |
- } |
- |
- void beginIdentifierList(Token token) { |
- } |
- |
- void endIdentifierList(int count) { |
- } |
- |
- void beginTypeList(Token token) { |
- } |
- |
- void endTypeList(int count) { |
- } |
- |
- void beginIfStatement(Token token) { |
- } |
- |
- void endIfStatement(Token ifToken, Token elseToken) { |
- } |
- |
- void beginImport(Token importKeyword) { |
- } |
- |
- void endImport(Token importKeyword, Token DeferredKeyword, |
- Token asKeyword, Token semicolon) { |
- } |
- |
- void beginInitializedIdentifier(Token token) { |
- } |
- |
- void endInitializedIdentifier() { |
- } |
- |
- void beginInitializer(Token token) { |
- } |
- |
- void endInitializer(Token assignmentOperator) { |
- } |
- |
- void beginInitializers(Token token) { |
- } |
- |
- void endInitializers(int count, Token beginToken, Token endToken) { |
- } |
- |
- void handleNoInitializers() { |
- } |
- |
- void handleLabel(Token token) { |
- } |
- |
- void beginLabeledStatement(Token token, int labelCount) { |
- } |
- |
- void endLabeledStatement(int labelCount) { |
- } |
- |
- void beginLibraryName(Token token) { |
- } |
- |
- void endLibraryName(Token libraryKeyword, Token semicolon) { |
- } |
- |
- void beginLiteralMapEntry(Token token) { |
- } |
- |
- void endLiteralMapEntry(Token colon, Token endToken) { |
- } |
- |
- void beginLiteralString(Token token) { |
- } |
- |
- void endLiteralString(int interpolationCount) { |
- } |
- |
- void handleStringJuxtaposition(int literalCount) { |
- } |
- |
- void beginMember(Token token) { |
- } |
- |
- void endMethod(Token getOrSet, Token beginToken, Token endToken) { |
- } |
- |
- void beginMetadataStar(Token token) { |
- } |
- |
- void endMetadataStar(int count, bool forParameter) { |
- } |
- |
- void beginMetadata(Token token) { |
- } |
- |
- void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) { |
- } |
- |
- void beginOptionalFormalParameters(Token token) { |
- } |
- |
- void endOptionalFormalParameters(int count, |
- Token beginToken, Token endToken) { |
- } |
- |
- void beginPart(Token token) { |
- } |
- |
- void endPart(Token partKeyword, Token semicolon) { |
- } |
- |
- void beginPartOf(Token token) { |
- } |
- |
- void endPartOf(Token partKeyword, Token semicolon) { |
- } |
- |
- void beginRedirectingFactoryBody(Token token) { |
- } |
- |
- void endRedirectingFactoryBody(Token beginToken, Token endToken) { |
- } |
- |
- void beginReturnStatement(Token token) { |
- } |
- |
- void endReturnStatement(bool hasExpression, |
- Token beginToken, Token endToken) { |
- } |
- |
- void beginSend(Token token) { |
- } |
- |
- void endSend(Token token) { |
- } |
- |
- void beginShow(Token showKeyword) { |
- } |
- |
- void endShow(Token showKeyword) { |
- } |
- |
- void beginSwitchStatement(Token token) { |
- } |
- |
- void endSwitchStatement(Token switchKeyword, Token endToken) { |
- } |
- |
- void beginSwitchBlock(Token token) { |
- } |
- |
- void endSwitchBlock(int caseCount, Token beginToken, Token endToken) { |
- } |
- |
- void beginLiteralSymbol(Token token) { |
- } |
- |
- void endLiteralSymbol(Token hashToken, int identifierCount) { |
- } |
- |
- void beginThrowExpression(Token token) { |
- } |
- |
- void endThrowExpression(Token throwToken, Token endToken) { |
- } |
- |
- void beginRethrowStatement(Token token) { |
- } |
- |
- void endRethrowStatement(Token throwToken, Token endToken) { |
- } |
- |
- void endTopLevelDeclaration(Token token) { |
- } |
- |
- void beginTopLevelMember(Token token) { |
- } |
- |
- void endTopLevelFields(int count, Token beginToken, Token endToken) { |
- } |
- |
- void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) { |
- } |
- |
- void beginTryStatement(Token token) { |
- } |
- |
- void handleCaseMatch(Token caseKeyword, Token colon) { |
- } |
- |
- void handleCatchBlock(Token onKeyword, Token catchKeyword) { |
- } |
- |
- void handleFinallyBlock(Token finallyKeyword) { |
- } |
- |
- void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) { |
- } |
- |
- void endType(Token beginToken, Token endToken) { |
- } |
- |
- void beginTypeArguments(Token token) { |
- } |
- |
- void endTypeArguments(int count, Token beginToken, Token endToken) { |
- } |
- |
- void handleNoTypeArguments(Token token) { |
- } |
- |
- void beginTypeVariable(Token token) { |
- } |
- |
- void endTypeVariable(Token token) { |
- } |
- |
- void beginTypeVariables(Token token) { |
- } |
- |
- void endTypeVariables(int count, Token beginToken, Token endToken) { |
- } |
- |
- void beginUnnamedFunction(Token token) { |
- } |
- |
- void endUnnamedFunction(Token token) { |
- } |
- |
- void beginVariablesDeclaration(Token token) { |
- } |
- |
- void endVariablesDeclaration(int count, Token endToken) { |
- } |
- |
- void beginWhileStatement(Token token) { |
- } |
- |
- void endWhileStatement(Token whileKeyword, Token endToken) { |
- } |
- |
- void handleAsOperator(Token operathor, Token endToken) { |
- // TODO(ahe): Rename [operathor] to "operator" when VM bug is fixed. |
- } |
- |
- void handleAssignmentExpression(Token token) { |
- } |
- |
- void handleBinaryExpression(Token token) { |
- } |
- |
- void handleConditionalExpression(Token question, Token colon) { |
- } |
- |
- void handleConstExpression(Token token) { |
- } |
- |
- void handleFunctionTypedFormalParameter(Token token) { |
- } |
- |
- void handleIdentifier(Token token) { |
- } |
- |
- void handleIndexedExpression(Token openCurlyBracket, |
- Token closeCurlyBracket) { |
- } |
- |
- void handleIsOperator(Token operathor, Token not, Token endToken) { |
- // TODO(ahe): Rename [operathor] to "operator" when VM bug is fixed. |
- } |
- |
- void handleLiteralBool(Token token) { |
- } |
- |
- void handleBreakStatement(bool hasTarget, |
- Token breakKeyword, Token endToken) { |
- } |
- |
- void handleContinueStatement(bool hasTarget, |
- Token continueKeyword, Token endToken) { |
- } |
- |
- void handleEmptyStatement(Token token) { |
- } |
- |
- void handleAssertStatement(Token assertKeyword, Token semicolonToken) { |
- } |
- |
- /** Called with either the token containing a double literal, or |
- * an immediately preceding "unary plus" token. |
- */ |
- void handleLiteralDouble(Token token) { |
- } |
- |
- /** Called with either the token containing an integer literal, |
- * or an immediately preceding "unary plus" token. |
- */ |
- void handleLiteralInt(Token token) { |
- } |
- |
- void handleLiteralList(int count, Token beginToken, Token constKeyword, |
- Token endToken) { |
- } |
- |
- void handleLiteralMap(int count, Token beginToken, Token constKeyword, |
- Token endToken) { |
- } |
- |
- void handleLiteralNull(Token token) { |
- } |
- |
- void handleModifier(Token token) { |
- } |
- |
- void handleModifiers(int count) { |
- } |
- |
- void handleNamedArgument(Token colon) { |
- } |
- |
- void handleNewExpression(Token token) { |
- } |
- |
- void handleNoArguments(Token token) { |
- } |
- |
- void handleNoExpression(Token token) { |
- } |
- |
- void handleNoType(Token token) { |
- } |
- |
- void handleNoTypeVariables(Token token) { |
- } |
- |
- void handleOperator(Token token) { |
- } |
- |
- void handleOperatorName(Token operatorKeyword, Token token) { |
- } |
- |
- void handleParenthesizedExpression(BeginGroupToken token) { |
- } |
- |
- void handleQualified(Token period) { |
- } |
- |
- void handleStringPart(Token token) { |
- } |
- |
- void handleSuperExpression(Token token) { |
- } |
- |
- void handleSwitchCase(int labelCount, int expressionCount, |
- Token defaultKeyword, int statementCount, |
- Token firstToken, Token endToken) { |
- } |
- |
- void handleThisExpression(Token token) { |
- } |
- |
- void handleUnaryPostfixAssignmentExpression(Token token) { |
- } |
- |
- void handleUnaryPrefixExpression(Token token) { |
- } |
- |
- void handleUnaryPrefixAssignmentExpression(Token token) { |
- } |
- |
- void handleValuedFormalParameter(Token equals, Token token) { |
- } |
- |
- void handleVoidKeyword(Token token) { |
- } |
- |
- void beginYieldStatement(Token token) { |
- } |
- |
- void endYieldStatement(Token yieldToken, Token starToken, Token endToken) { |
- } |
- |
- Token expected(String string, Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- error("expected '$string', but got '${token.value}'", token); |
- } |
- return skipToEof(token); |
- } |
- |
- Token synthesizeIdentifier(Token token) { |
- Token synthesizedToken = |
- new StringToken.fromString(IDENTIFIER_INFO, '?', token.charOffset); |
- synthesizedToken.next = token.next; |
- return synthesizedToken; |
- } |
- |
- Token expectedIdentifier(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- error("expected identifier, but got '${token.value}'", token); |
- } |
- return skipToEof(token); |
- } |
- |
- Token expectedType(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- error("expected a type, but got '${token.value}'", token); |
- } |
- return skipToEof(token); |
- } |
- |
- Token expectedExpression(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- error("expected an expression, but got '${token.value}'", token); |
- } |
- return skipToEof(token); |
- } |
- |
- Token unexpected(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- error("unexpected token '${token.value}'", token); |
- } |
- return skipToEof(token); |
- } |
- |
- Token expectedBlockToSkip(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- error("expected a block, but got '${token.value}'", token); |
- } |
- return skipToEof(token); |
- } |
- |
- Token expectedFunctionBody(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- error("expected a function body, but got '${token.value}'", token); |
- } |
- return skipToEof(token); |
- } |
- |
- Token expectedClassBody(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- error("expected a class body, but got '${token.value}'", token); |
- } |
- return skipToEof(token); |
- } |
- |
- Token expectedClassBodyToSkip(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- error("expected a class body, but got '${token.value}'", token); |
- } |
- return skipToEof(token); |
- } |
- |
- Token expectedDeclaration(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- error("expected a declaration, but got '${token.value}'", token); |
- } |
- return skipToEof(token); |
- } |
- |
- Token unmatched(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- error("unmatched '${token.value}'", token); |
- } |
- return skipToEof(token); |
- } |
- |
- skipToEof(Token token) { |
- while (!identical(token.info, EOF_INFO)) { |
- token = token.next; |
- } |
- return token; |
- } |
- |
- void recoverableError(Token token, String message) { |
- error(message, token); |
- } |
- |
- void error(String message, Token token) { |
- throw new ParserError("$message @ ${token.charOffset}"); |
- } |
- |
- void reportError(Spannable spannable, |
- MessageKind messageKind, |
- [Map arguments = const {}]) { |
- String message = messageKind.message(arguments, true).toString(); |
- Token token; |
- Node node; |
- if (spannable is Token) { |
- token = spannable; |
- } else if (spannable is Node) { |
- token = spannable.getBeginToken(); |
- } else { |
- throw new ParserError(message); |
- } |
- recoverableError(token, message); |
- } |
- |
- void reportErrorToken(ErrorToken token) { |
- if (token is BadInputToken) { |
- String hex = token.character.toRadixString(16); |
- if (hex.length < 4) { |
- String padding = "0000".substring(hex.length); |
- hex = "$padding$hex"; |
- } |
- reportError( |
- token, MessageKind.BAD_INPUT_CHARACTER, {'characterHex': hex}); |
- } else if (token is UnterminatedToken) { |
- String start = token.start; |
- MessageKind kind; |
- var arguments = const {}; |
- switch (token.start) { |
- case '1e': |
- kind = MessageKind.EXPONENT_MISSING; |
- break; |
- case '"': |
- case "'": |
- case '"""': |
- case "'''": |
- case 'r"': |
- case "r'": |
- case 'r"""': |
- case "r'''": |
- kind = MessageKind.UNTERMINATED_STRING; |
- arguments = {'quote': token.start}; |
- break; |
- case '0x': |
- kind = MessageKind.HEX_DIGIT_EXPECTED; |
- break; |
- case r'$': |
- kind = MessageKind.MALFORMED_STRING_LITERAL; |
- break; |
- case '/*': |
- kind = MessageKind.UNTERMINATED_COMMENT; |
- break; |
- default: |
- kind = MessageKind.UNTERMINATED_TOKEN; |
- break; |
- } |
- reportError(token, kind, arguments); |
- } else if (token is UnmatchedToken) { |
- String begin = token.begin.value; |
- String end = closeBraceFor(begin); |
- reportError( |
- token, MessageKind.UNMATCHED_TOKEN, {'begin': begin, 'end': end}); |
- } else { |
- throw new SpannableAssertionFailure(token, token.assertionMessage); |
- } |
- } |
-} |
- |
-String closeBraceFor(String openBrace) { |
- return const { |
- '(': ')', |
- '[': ']', |
- '{': '}', |
- '<': '>', |
- r'${': '}', |
- }[openBrace]; |
-} |
- |
-class ParserError { |
- final String reason; |
- ParserError(this.reason); |
- toString() => reason; |
-} |
- |
-typedef int IdGenerator(); |
- |
-/** |
- * A parser event listener designed to work with [PartialParser]. It |
- * builds elements representing the top-level declarations found in |
- * the parsed compilation unit and records them in |
- * [compilationUnitElement]. |
- */ |
-class ElementListener extends Listener { |
- final IdGenerator idGenerator; |
- final DiagnosticListener listener; |
- final CompilationUnitElement compilationUnitElement; |
- final StringValidator stringValidator; |
- Link<StringQuoting> interpolationScope; |
- |
- Link<Node> nodes = const Link<Node>(); |
- |
- Link<MetadataAnnotation> metadata = const Link<MetadataAnnotation>(); |
- |
- /// Records a stack of booleans for each member parsed (a stack is used to |
- /// support nested members which isn't currently possible, but it also serves |
- /// as a simple way to tell we're currently parsing a member). In this case, |
- /// member refers to members of a library or a class (but currently, classes |
- /// themselves are not considered members). If the top of the stack |
- /// (memberErrors.head) is true, the current member has already reported at |
- /// least one parse error. |
- Link<bool> memberErrors = const Link<bool>(); |
- |
- bool suppressParseErrors = false; |
- |
- ElementListener(DiagnosticListener listener, |
- this.compilationUnitElement, |
- this.idGenerator) |
- : this.listener = listener, |
- stringValidator = new StringValidator(listener), |
- interpolationScope = const Link<StringQuoting>(); |
- |
- bool get currentMemberHasParseError { |
- return !memberErrors.isEmpty && memberErrors.head; |
- } |
- |
- void pushQuoting(StringQuoting quoting) { |
- interpolationScope = interpolationScope.prepend(quoting); |
- } |
- |
- StringQuoting popQuoting() { |
- StringQuoting result = interpolationScope.head; |
- interpolationScope = interpolationScope.tail; |
- return result; |
- } |
- |
- StringNode popLiteralString() { |
- StringNode node = popNode(); |
- // TODO(lrn): Handle interpolations in script tags. |
- if (node.isInterpolation) { |
- listener.internalError(node, |
- "String interpolation not supported in library tags."); |
- return null; |
- } |
- return node; |
- } |
- |
- bool allowLibraryTags() { |
- // Library tags are only allowed in the library file itself, not |
- // in sourced files. |
- LibraryElement library = compilationUnitElement.implementationLibrary; |
- return !compilationUnitElement.hasMembers && |
- library.entryCompilationUnit == compilationUnitElement; |
- } |
- |
- void endLibraryName(Token libraryKeyword, Token semicolon) { |
- Expression name = popNode(); |
- addLibraryTag(new LibraryName(libraryKeyword, name, |
- popMetadata(compilationUnitElement))); |
- } |
- |
- void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword, |
- Token semicolon) { |
- NodeList combinators = popNode(); |
- bool isDeferred = deferredKeyword != null; |
- Identifier prefix; |
- if (asKeyword != null) { |
- prefix = popNode(); |
- } |
- StringNode uri = popLiteralString(); |
- addLibraryTag(new Import(importKeyword, uri, prefix, combinators, |
- popMetadata(compilationUnitElement), |
- isDeferred: isDeferred)); |
- } |
- |
- void endExport(Token exportKeyword, Token semicolon) { |
- NodeList combinators = popNode(); |
- StringNode uri = popNode(); |
- addLibraryTag(new Export(exportKeyword, uri, combinators, |
- popMetadata(compilationUnitElement))); |
- } |
- |
- void endCombinators(int count) { |
- if (0 == count) { |
- pushNode(null); |
- } else { |
- pushNode(makeNodeList(count, null, null, " ")); |
- } |
- } |
- |
- void endHide(Token hideKeyword) => pushCombinator(hideKeyword); |
- |
- void endShow(Token showKeyword) => pushCombinator(showKeyword); |
- |
- void pushCombinator(Token keywordToken) { |
- NodeList identifiers = popNode(); |
- pushNode(new Combinator(identifiers, keywordToken)); |
- } |
- |
- void endIdentifierList(int count) { |
- pushNode(makeNodeList(count, null, null, ",")); |
- } |
- |
- void endTypeList(int count) { |
- pushNode(makeNodeList(count, null, null, ",")); |
- } |
- |
- void endPart(Token partKeyword, Token semicolon) { |
- StringNode uri = popLiteralString(); |
- addLibraryTag(new Part(partKeyword, uri, |
- popMetadata(compilationUnitElement))); |
- } |
- |
- void endPartOf(Token partKeyword, Token semicolon) { |
- Expression name = popNode(); |
- addPartOfTag(new PartOf(partKeyword, name, |
- popMetadata(compilationUnitElement))); |
- } |
- |
- void addPartOfTag(PartOf tag) { |
- compilationUnitElement.setPartOf(tag, listener); |
- } |
- |
- void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) { |
- if (periodBeforeName != null) { |
- popNode(); // Discard name. |
- } |
- popNode(); // Discard node (Send or Identifier). |
- pushMetadata(new PartialMetadataAnnotation(beginToken, endToken)); |
- } |
- |
- void endTopLevelDeclaration(Token token) { |
- if (!metadata.isEmpty) { |
- recoverableError(metadata.head.beginToken, |
- 'Metadata not supported here.'); |
- metadata = const Link<MetadataAnnotation>(); |
- } |
- } |
- |
- void endClassDeclaration(int interfacesCount, Token beginToken, |
- Token extendsKeyword, Token implementsKeyword, |
- Token endToken) { |
- NodeList interfaces = |
- makeNodeList(interfacesCount, implementsKeyword, null, ","); |
- Node supertype = popNode(); |
- NodeList typeParameters = popNode(); |
- Identifier name = popNode(); |
- int id = idGenerator(); |
- PartialClassElement element = new PartialClassElement( |
- name.source, beginToken, endToken, compilationUnitElement, id); |
- pushElement(element); |
- rejectBuiltInIdentifier(name); |
- } |
- |
- void rejectBuiltInIdentifier(Identifier name) { |
- if (name.token is KeywordToken) { |
- Keyword keyword = (name.token as KeywordToken).keyword; |
- if (!keyword.isPseudo) { |
- recoverableError(name, "Illegal name '${keyword.syntax}'."); |
- } |
- } |
- } |
- |
- void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { |
- NodeList typeVariables = popNode(); // TOOD(karlklose): do not throw away. |
- Identifier name = popNode(); |
- TypeAnnotation returnType = popNode(); |
- pushElement( |
- new PartialTypedefElement( |
- name.source, compilationUnitElement, typedefKeyword, endToken)); |
- rejectBuiltInIdentifier(name); |
- } |
- |
- void endNamedMixinApplication(Token classKeyword, |
- Token implementsKeyword, |
- Token endToken) { |
- NodeList interfaces = (implementsKeyword != null) ? popNode() : null; |
- MixinApplication mixinApplication = popNode(); |
- Modifiers modifiers = popNode(); |
- NodeList typeParameters = popNode(); |
- Identifier name = popNode(); |
- NamedMixinApplication namedMixinApplication = new NamedMixinApplication( |
- name, typeParameters, modifiers, mixinApplication, interfaces, |
- classKeyword, endToken); |
- |
- int id = idGenerator(); |
- Element enclosing = compilationUnitElement; |
- pushElement(new MixinApplicationElementX(name.source, enclosing, id, |
- namedMixinApplication, |
- modifiers)); |
- rejectBuiltInIdentifier(name); |
- } |
- |
- void endMixinApplication() { |
- NodeList mixins = popNode(); |
- TypeAnnotation superclass = popNode(); |
- pushNode(new MixinApplication(superclass, mixins)); |
- } |
- |
- void handleVoidKeyword(Token token) { |
- pushNode(new TypeAnnotation(new Identifier(token), null)); |
- } |
- |
- void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) { |
- bool hasParseError = currentMemberHasParseError; |
- memberErrors = memberErrors.tail; |
- Identifier name = popNode(); |
- TypeAnnotation type = popNode(); |
- Modifiers modifiers = popNode(); |
- ElementKind kind; |
- if (getOrSet == null) { |
- kind = ElementKind.FUNCTION; |
- } else if (identical(getOrSet.stringValue, 'get')) { |
- kind = ElementKind.GETTER; |
- } else if (identical(getOrSet.stringValue, 'set')) { |
- kind = ElementKind.SETTER; |
- } |
- PartialFunctionElement element = new PartialFunctionElement( |
- name.source, beginToken, getOrSet, endToken, kind, modifiers, |
- compilationUnitElement, false); |
- element.hasParseError = hasParseError; |
- pushElement(element); |
- } |
- |
- void endTopLevelFields(int count, Token beginToken, Token endToken) { |
- bool hasParseError = currentMemberHasParseError; |
- memberErrors = memberErrors.tail; |
- void buildFieldElement(Identifier name, VariableList fields) { |
- pushElement( |
- new FieldElementX(name, compilationUnitElement, fields)); |
- } |
- NodeList variables = makeNodeList(count, null, null, ","); |
- TypeAnnotation type = popNode(); |
- Modifiers modifiers = popNode(); |
- buildFieldElements(modifiers, variables, compilationUnitElement, |
- buildFieldElement, |
- beginToken, endToken, hasParseError); |
- } |
- |
- void buildFieldElements(Modifiers modifiers, |
- NodeList variables, |
- Element enclosingElement, |
- void buildFieldElement(Identifier name, |
- VariableList fields), |
- Token beginToken, Token endToken, |
- bool hasParseError) { |
- VariableList fields = |
- new PartialFieldList(beginToken, endToken, modifiers, hasParseError); |
- for (Link<Node> variableNodes = variables.nodes; |
- !variableNodes.isEmpty; |
- variableNodes = variableNodes.tail) { |
- Expression initializedIdentifier = variableNodes.head; |
- Identifier identifier = initializedIdentifier.asIdentifier(); |
- if (identifier == null) { |
- identifier = initializedIdentifier.asSendSet().selector.asIdentifier(); |
- } |
- buildFieldElement(identifier, fields); |
- } |
- } |
- |
- void handleIdentifier(Token token) { |
- pushNode(new Identifier(token)); |
- } |
- |
- void handleQualified(Token period) { |
- Identifier last = popNode(); |
- Expression first = popNode(); |
- pushNode(new Send(first, last)); |
- } |
- |
- void handleNoType(Token token) { |
- pushNode(null); |
- } |
- |
- void endTypeVariable(Token token) { |
- TypeAnnotation bound = popNode(); |
- Identifier name = popNode(); |
- pushNode(new TypeVariable(name, bound)); |
- rejectBuiltInIdentifier(name); |
- } |
- |
- void endTypeVariables(int count, Token beginToken, Token endToken) { |
- pushNode(makeNodeList(count, beginToken, endToken, ',')); |
- } |
- |
- void handleNoTypeVariables(token) { |
- pushNode(null); |
- } |
- |
- void endTypeArguments(int count, Token beginToken, Token endToken) { |
- pushNode(makeNodeList(count, beginToken, endToken, ',')); |
- } |
- |
- void handleNoTypeArguments(Token token) { |
- pushNode(null); |
- } |
- |
- void endType(Token beginToken, Token endToken) { |
- NodeList typeArguments = popNode(); |
- Expression typeName = popNode(); |
- pushNode(new TypeAnnotation(typeName, typeArguments)); |
- } |
- |
- void handleParenthesizedExpression(BeginGroupToken token) { |
- Expression expression = popNode(); |
- pushNode(new ParenthesizedExpression(expression, token)); |
- } |
- |
- void handleModifier(Token token) { |
- pushNode(new Identifier(token)); |
- } |
- |
- void handleModifiers(int count) { |
- if (count == 0) { |
- pushNode(Modifiers.EMPTY); |
- } else { |
- NodeList modifierNodes = makeNodeList(count, null, null, ' '); |
- pushNode(new Modifiers(modifierNodes)); |
- } |
- } |
- |
- Token expected(String string, Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else if (identical(';', string)) { |
- // When a semicolon is missing, it often leads to an error on the |
- // following line. So we try to find the token preceding the semicolon |
- // and report that something is missing *after* it. |
- Token preceding = findPrecedingToken(token); |
- if (preceding == token) { |
- reportError( |
- token, MessageKind.MISSING_TOKEN_BEFORE_THIS, {'token': string}); |
- } else { |
- reportError( |
- preceding, MessageKind.MISSING_TOKEN_AFTER_THIS, {'token': string}); |
- } |
- return token; |
- } else { |
- reportFatalError( |
- token, |
- MessageKind.MISSING_TOKEN_BEFORE_THIS.message( |
- {'token': string}, true).toString()); |
- } |
- return skipToEof(token); |
- } |
- |
- /// Finds the preceding token via the begin token of the last AST node pushed |
- /// on the [nodes] stack. |
- Token findPrecedingToken(Token token) { |
- Token result; |
- Link<Node> nodes = this.nodes; |
- while (!nodes.isEmpty) { |
- result = findPrecedingTokenFromNode(nodes.head, token); |
- if (result != null) { |
- return result; |
- } |
- nodes = nodes.tail; |
- } |
- if (compilationUnitElement != null) { |
- if (compilationUnitElement is CompilationUnitElementX) { |
- CompilationUnitElementX unit = compilationUnitElement; |
- Link<Element> members = unit.localMembers; |
- while (!members.isEmpty) { |
- ElementX member = members.head; |
- DeclarationSite site = member.declarationSite; |
- if (site is PartialElement) { |
- result = findPrecedingTokenFromToken(site.endToken, token); |
- if (result != null) { |
- return result; |
- } |
- } |
- members = members.tail; |
- } |
- result = |
- findPrecedingTokenFromNode(compilationUnitElement.partTag, token); |
- if (result != null) { |
- return result; |
- } |
- } |
- } |
- return token; |
- } |
- |
- Token findPrecedingTokenFromNode(Node node, Token token) { |
- if (node != null) { |
- return findPrecedingTokenFromToken(node.getBeginToken(), token); |
- } |
- return null; |
- } |
- |
- Token findPrecedingTokenFromToken(Token start, Token token) { |
- if (start != null) { |
- Token current = start; |
- while (current.kind != EOF_TOKEN && current.next != token) { |
- current = current.next; |
- } |
- if (current.kind != EOF_TOKEN) { |
- return current; |
- } |
- } |
- return null; |
- } |
- |
- Token expectedIdentifier(Token token) { |
- if (token is KeywordToken) { |
- reportError( |
- token, MessageKind.EXPECTED_IDENTIFIER_NOT_RESERVED_WORD, |
- {'keyword': token.value}); |
- } else if (token is ErrorToken) { |
- reportErrorToken(token); |
- return synthesizeIdentifier(token); |
- } else { |
- reportFatalError(token, |
- "Expected identifier, but got '${token.value}'."); |
- } |
- return token; |
- } |
- |
- Token expectedType(Token token) { |
- pushNode(null); |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- return synthesizeIdentifier(token); |
- } else { |
- reportFatalError( |
- token, "Expected a type, but got '${token.value}'."); |
- return skipToEof(token); |
- } |
- } |
- |
- Token expectedExpression(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- pushNode(new ErrorExpression(token)); |
- return token.next; |
- } else { |
- reportFatalError(token, |
- "Expected an expression, but got '${token.value}'."); |
- pushNode(null); |
- return skipToEof(token); |
- } |
- } |
- |
- Token unexpected(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- String message = "Unexpected token '${token.value}'."; |
- if (token.info == BAD_INPUT_INFO) { |
- message = token.value; |
- } |
- reportFatalError(token, message); |
- } |
- return skipToEof(token); |
- } |
- |
- Token expectedBlockToSkip(Token token) { |
- if (identical(token.stringValue, 'native')) { |
- return native.handleNativeBlockToSkip(this, token); |
- } else { |
- return unexpected(token); |
- } |
- } |
- |
- Token expectedFunctionBody(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- String printString = token.value; |
- reportFatalError(token, |
- "Expected a function body, but got '$printString'."); |
- } |
- return skipToEof(token); |
- } |
- |
- Token expectedClassBody(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- reportFatalError(token, |
- "Expected a class body, but got '${token.value}'."); |
- } |
- return skipToEof(token); |
- } |
- |
- Token expectedClassBodyToSkip(Token token) { |
- return unexpected(token); |
- } |
- |
- Token expectedDeclaration(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- reportFatalError(token, |
- "Expected a declaration, but got '${token.value}'."); |
- } |
- return skipToEof(token); |
- } |
- |
- Token unmatched(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- } else { |
- String begin = token.value; |
- String end = closeBraceFor(begin); |
- reportError( |
- token, MessageKind.UNMATCHED_TOKEN, {'begin': begin, 'end': end}); |
- } |
- Token next = token.next; |
- while (next is ErrorToken) { |
- next = next.next; |
- } |
- return next; |
- } |
- |
- void recoverableError(Spannable node, String message) { |
- // TODO(johnniwinther): Make recoverable errors non-fatal. |
- reportFatalError(node, message); |
- } |
- |
- void pushElement(Element element) { |
- popMetadata(element); |
- compilationUnitElement.addMember(element, listener); |
- } |
- |
- Link<MetadataAnnotation> popMetadata(Element element) { |
- var result = const Link<MetadataAnnotation>(); |
- for (Link link = metadata; !link.isEmpty; link = link.tail) { |
- element.addMetadata(link.head); |
- // Reverse the list as is implicitly done by addMetadata. |
- result = result.prepend(link.head); |
- } |
- metadata = const Link<MetadataAnnotation>(); |
- return result; |
- } |
- |
- void pushMetadata(MetadataAnnotation annotation) { |
- metadata = metadata.prepend(annotation); |
- } |
- |
- void addLibraryTag(LibraryTag tag) { |
- if (!allowLibraryTags()) { |
- recoverableError(tag, 'Library tags not allowed here.'); |
- } |
- compilationUnitElement.implementationLibrary.addTag(tag, listener); |
- } |
- |
- void pushNode(Node node) { |
- nodes = nodes.prepend(node); |
- if (VERBOSE) log("push $nodes"); |
- } |
- |
- Node popNode() { |
- assert(!nodes.isEmpty); |
- Node node = nodes.head; |
- nodes = nodes.tail; |
- if (VERBOSE) log("pop $nodes"); |
- return node; |
- } |
- |
- void log(message) { |
- print(message); |
- } |
- |
- NodeList makeNodeList(int count, Token beginToken, Token endToken, |
- String delimiter) { |
- Link<Node> poppedNodes = const Link<Node>(); |
- for (; count > 0; --count) { |
- // This effectively reverses the order of nodes so they end up |
- // in correct (source) order. |
- poppedNodes = poppedNodes.prepend(popNode()); |
- } |
- return new NodeList(beginToken, poppedNodes, endToken, delimiter); |
- } |
- |
- void beginLiteralString(Token token) { |
- String source = token.value; |
- StringQuoting quoting = StringValidator.quotingFromString(source); |
- pushQuoting(quoting); |
- // Just wrap the token for now. At the end of the interpolation, |
- // when we know how many there are, go back and validate the tokens. |
- pushNode(new LiteralString(token, null)); |
- } |
- |
- void handleStringPart(Token token) { |
- // Just push an unvalidated token now, and replace it when we know the |
- // end of the interpolation. |
- pushNode(new LiteralString(token, null)); |
- } |
- |
- void endLiteralString(int count) { |
- StringQuoting quoting = popQuoting(); |
- |
- Link<StringInterpolationPart> parts = |
- const Link<StringInterpolationPart>(); |
- // Parts of the string interpolation are popped in reverse order, |
- // starting with the last literal string part. |
- bool isLast = true; |
- for (int i = 0; i < count; i++) { |
- LiteralString string = popNode(); |
- DartString validation = |
- stringValidator.validateInterpolationPart(string.token, quoting, |
- isFirst: false, |
- isLast: isLast); |
- // Replace the unvalidated LiteralString with a new LiteralString |
- // object that has the validation result included. |
- string = new LiteralString(string.token, validation); |
- Expression expression = popNode(); |
- parts = parts.prepend(new StringInterpolationPart(expression, string)); |
- isLast = false; |
- } |
- |
- LiteralString string = popNode(); |
- DartString validation = |
- stringValidator.validateInterpolationPart(string.token, quoting, |
- isFirst: true, |
- isLast: isLast); |
- string = new LiteralString(string.token, validation); |
- if (isLast) { |
- pushNode(string); |
- } else { |
- NodeList partNodes = new NodeList(null, parts, null, ""); |
- pushNode(new StringInterpolation(string, partNodes)); |
- } |
- } |
- |
- void handleStringJuxtaposition(int stringCount) { |
- assert(stringCount != 0); |
- Expression accumulator = popNode(); |
- stringCount--; |
- while (stringCount > 0) { |
- Expression expression = popNode(); |
- accumulator = new StringJuxtaposition(expression, accumulator); |
- stringCount--; |
- } |
- pushNode(accumulator); |
- } |
- |
- void beginMember(Token token) { |
- memberErrors = memberErrors.prepend(false); |
- } |
- |
- void beginTopLevelMember(Token token) { |
- beginMember(token); |
- } |
- |
- void endFields(fieldCount, start, token) { |
- memberErrors = memberErrors.tail; |
- } |
- |
- void endMethod(getOrSet, start, token) { |
- memberErrors = memberErrors.tail; |
- } |
- |
- void beginFactoryMethod(Token token) { |
- memberErrors = memberErrors.prepend(false); |
- } |
- |
- void endFactoryMethod(Token beginToken, Token endToken) { |
- memberErrors = memberErrors.tail; |
- } |
- |
- void reportFatalError(Spannable spannable, |
- String message) { |
- listener.reportFatalError( |
- spannable, MessageKind.GENERIC, {'text': message}); |
- } |
- |
- void reportError(Spannable spannable, |
- MessageKind errorCode, |
- [Map arguments = const {}]) { |
- if (currentMemberHasParseError) return; // Error already reported. |
- if (suppressParseErrors) return; |
- if (!memberErrors.isEmpty) { |
- memberErrors = memberErrors.tail.prepend(true); |
- } |
- listener.reportError(spannable, errorCode, arguments); |
- } |
-} |
- |
-class NodeListener extends ElementListener { |
- final bool throwOnFatalError; |
- |
- NodeListener( |
- DiagnosticListener listener, |
- CompilationUnitElement element, |
- {bool this.throwOnFatalError: false}) |
- : super(listener, element, null); |
- |
- void reportFatalError(Spannable spannable, |
- String message) { |
- if (throwOnFatalError) { |
- if (!currentMemberHasParseError && !suppressParseErrors) { |
- reportError(spannable, MessageKind.GENERIC, {'text': message}); |
- } |
- throw new ParserError(message); |
- } else { |
- super.reportFatalError(spannable, message); |
- } |
- } |
- |
- void addLibraryTag(LibraryTag tag) { |
- pushNode(tag); |
- } |
- |
- void addPartOfTag(PartOf tag) { |
- pushNode(tag); |
- } |
- |
- void endClassDeclaration(int interfacesCount, Token beginToken, |
- Token extendsKeyword, Token implementsKeyword, |
- Token endToken) { |
- NodeList body = popNode(); |
- NodeList interfaces = |
- makeNodeList(interfacesCount, implementsKeyword, null, ","); |
- Node supertype = popNode(); |
- NodeList typeParameters = popNode(); |
- Identifier name = popNode(); |
- Modifiers modifiers = popNode(); |
- pushNode(new ClassNode(modifiers, name, typeParameters, supertype, |
- interfaces, beginToken, extendsKeyword, body, |
- endToken)); |
- } |
- |
- void endCompilationUnit(int count, Token token) { |
- pushNode(makeNodeList(count, null, null, '\n')); |
- } |
- |
- void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { |
- NodeList formals = popNode(); |
- NodeList typeParameters = popNode(); |
- Identifier name = popNode(); |
- TypeAnnotation returnType = popNode(); |
- pushNode(new Typedef(returnType, name, typeParameters, formals, |
- typedefKeyword, endToken)); |
- } |
- |
- void endNamedMixinApplication(Token classKeyword, |
- Token implementsKeyword, |
- Token endToken) { |
- NodeList interfaces = (implementsKeyword != null) ? popNode() : null; |
- Node mixinApplication = popNode(); |
- Modifiers modifiers = popNode(); |
- NodeList typeParameters = popNode(); |
- Identifier name = popNode(); |
- pushNode(new NamedMixinApplication(name, typeParameters, |
- modifiers, mixinApplication, |
- interfaces, |
- classKeyword, endToken)); |
- } |
- |
- void endClassBody(int memberCount, Token beginToken, Token endToken) { |
- pushNode(makeNodeList(memberCount, beginToken, endToken, null)); |
- } |
- |
- void endTopLevelFields(int count, Token beginToken, Token endToken) { |
- NodeList variables = makeNodeList(count, null, endToken, ","); |
- TypeAnnotation type = popNode(); |
- Modifiers modifiers = popNode(); |
- pushNode(new VariableDefinitions(type, modifiers, variables)); |
- } |
- |
- void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) { |
- Statement body = popNode(); |
- NodeList formalParameters = popNode(); |
- Identifier name = popNode(); |
- TypeAnnotation type = popNode(); |
- Modifiers modifiers = popNode(); |
- ElementKind kind; |
- if (getOrSet == null) { |
- kind = ElementKind.FUNCTION; |
- } else if (identical(getOrSet.stringValue, 'get')) { |
- kind = ElementKind.GETTER; |
- } else if (identical(getOrSet.stringValue, 'set')) { |
- kind = ElementKind.SETTER; |
- } |
- pushElement(new PartialFunctionElement(name.source, beginToken, getOrSet, |
- endToken, kind, modifiers, |
- compilationUnitElement, false)); |
- } |
- |
- void endFormalParameter(Token thisKeyword) { |
- Expression name = popNode(); |
- if (thisKeyword != null) { |
- Identifier thisIdentifier = new Identifier(thisKeyword); |
- if (name.asSend() == null) { |
- name = new Send(thisIdentifier, name); |
- } else { |
- name = name.asSend().copyWithReceiver(thisIdentifier); |
- } |
- } |
- TypeAnnotation type = popNode(); |
- Modifiers modifiers = popNode(); |
- NodeList metadata = popNode(); |
- pushNode(new VariableDefinitions.forParameter( |
- metadata, type, modifiers, new NodeList.singleton(name))); |
- } |
- |
- void endFormalParameters(int count, Token beginToken, Token endToken) { |
- pushNode(makeNodeList(count, beginToken, endToken, ",")); |
- } |
- |
- void handleNoFormalParameters(Token token) { |
- pushNode(null); |
- } |
- |
- void endArguments(int count, Token beginToken, Token endToken) { |
- pushNode(makeNodeList(count, beginToken, endToken, ",")); |
- } |
- |
- void handleNoArguments(Token token) { |
- pushNode(null); |
- } |
- |
- void endConstructorReference(Token start, Token periodBeforeName, |
- Token endToken) { |
- Identifier name = null; |
- if (periodBeforeName != null) { |
- name = popNode(); |
- } |
- NodeList typeArguments = popNode(); |
- Node classReference = popNode(); |
- if (typeArguments != null) { |
- classReference = new TypeAnnotation(classReference, typeArguments); |
- } else { |
- Identifier identifier = classReference.asIdentifier(); |
- Send send = classReference.asSend(); |
- if (identifier != null) { |
- // TODO(ahe): Should be: |
- // classReference = new Send(null, identifier); |
- classReference = identifier; |
- } else if (send != null) { |
- classReference = send; |
- } else { |
- internalError(node: classReference); |
- } |
- } |
- Node constructor = classReference; |
- if (name != null) { |
- // Either typeName<args>.name or x.y.name. |
- constructor = new Send(classReference, name); |
- } |
- pushNode(constructor); |
- } |
- |
- void endRedirectingFactoryBody(Token beginToken, |
- Token endToken) { |
- pushNode(new RedirectingFactoryBody(beginToken, endToken, popNode())); |
- } |
- |
- void endReturnStatement(bool hasExpression, |
- Token beginToken, Token endToken) { |
- Expression expression = hasExpression ? popNode() : null; |
- pushNode(new Return(beginToken, endToken, expression)); |
- } |
- |
- void endYieldStatement(Token yieldToken, Token starToken, Token endToken) { |
- Expression expression = popNode(); |
- pushNode(new Yield(yieldToken, starToken, expression, endToken)); |
- } |
- |
- void endExpressionStatement(Token token) { |
- pushNode(new ExpressionStatement(popNode(), token)); |
- } |
- |
- void handleOnError(Token token, var errorInformation) { |
- listener.internalError(token, "'${token.value}': ${errorInformation}"); |
- } |
- |
- Token expectedFunctionBody(Token token) { |
- if (identical(token.stringValue, 'native')) { |
- return native.handleNativeFunctionBody(this, token); |
- } else if (token is ErrorToken) { |
- pushNode(null); |
- reportErrorToken(token); |
- } else { |
- reportFatalError(token, |
- "Expected a function body, but got '${token.value}'."); |
- } |
- return skipToEof(token); |
- } |
- |
- Token expectedClassBody(Token token) { |
- if (token is ErrorToken) { |
- reportErrorToken(token); |
- return skipToEof(token); |
- } else { |
- reportFatalError(token, |
- "Expected a class body, but got '${token.value}'."); |
- return skipToEof(token); |
- } |
- } |
- |
- void handleLiteralInt(Token token) { |
- pushNode(new LiteralInt(token, (t, e) => handleOnError(t, e))); |
- } |
- |
- void handleLiteralDouble(Token token) { |
- pushNode(new LiteralDouble(token, (t, e) => handleOnError(t, e))); |
- } |
- |
- void handleLiteralBool(Token token) { |
- pushNode(new LiteralBool(token, (t, e) => handleOnError(t, e))); |
- } |
- |
- void handleLiteralNull(Token token) { |
- pushNode(new LiteralNull(token)); |
- } |
- |
- void endLiteralSymbol(Token hashToken, int identifierCount) { |
- NodeList identifiers = makeNodeList(identifierCount, null, null, '.'); |
- pushNode(new LiteralSymbol(hashToken, identifiers)); |
- } |
- |
- void handleBinaryExpression(Token token) { |
- Node argument = popNode(); |
- Node receiver = popNode(); |
- String tokenString = token.stringValue; |
- if (identical(tokenString, '.') || identical(tokenString, '..')) { |
- Send argumentSend = argument.asSend(); |
- if (argumentSend == null) { |
- // TODO(ahe): The parser should diagnose this problem, not |
- // this listener. |
- reportFatalError(argument, |
- 'Expected an identifier.'); |
- } |
- if (argumentSend.receiver != null) internalError(node: argument); |
- if (argument is SendSet) internalError(node: argument); |
- pushNode(argument.asSend().copyWithReceiver(receiver)); |
- } else { |
- NodeList arguments = new NodeList.singleton(argument); |
- pushNode(new Send(receiver, new Operator(token), arguments)); |
- } |
- if (identical(tokenString, '===')) { |
- listener.reportError(token, MessageKind.UNSUPPORTED_EQ_EQ_EQ, |
- {'lhs': receiver, 'rhs': argument}); |
- } |
- if (identical(tokenString, '!==')) { |
- listener.reportError(token, MessageKind.UNSUPPORTED_BANG_EQ_EQ, |
- {'lhs': receiver, 'rhs': argument}); |
- } |
- } |
- |
- void beginCascade(Token token) { |
- pushNode(new CascadeReceiver(popNode(), token)); |
- } |
- |
- void endCascade() { |
- pushNode(new Cascade(popNode())); |
- } |
- |
- void handleAsOperator(Token operathor, Token endToken) { |
- TypeAnnotation type = popNode(); |
- Expression expression = popNode(); |
- NodeList arguments = new NodeList.singleton(type); |
- pushNode(new Send(expression, new Operator(operathor), arguments)); |
- } |
- |
- void handleAssignmentExpression(Token token) { |
- Node arg = popNode(); |
- Node node = popNode(); |
- Send send = node.asSend(); |
- if (send == null || !(send.isPropertyAccess || send.isIndex)) { |
- reportNotAssignable(node); |
- } |
- if (send.asSendSet() != null) internalError(node: send); |
- NodeList arguments; |
- if (send.isIndex) { |
- Link<Node> link = const Link<Node>().prepend(arg); |
- link = link.prepend(send.arguments.head); |
- arguments = new NodeList(null, link); |
- } else { |
- arguments = new NodeList.singleton(arg); |
- } |
- Operator op = new Operator(token); |
- pushNode(new SendSet(send.receiver, send.selector, op, arguments)); |
- } |
- |
- void reportNotAssignable(Node node) { |
- // TODO(ahe): The parser should diagnose this problem, not this |
- // listener. |
- reportFatalError(node, |
- 'Not assignable.'); |
- } |
- |
- void handleConditionalExpression(Token question, Token colon) { |
- Node elseExpression = popNode(); |
- Node thenExpression = popNode(); |
- Node condition = popNode(); |
- pushNode(new Conditional( |
- condition, thenExpression, elseExpression, question, colon)); |
- } |
- |
- void endSend(Token token) { |
- NodeList arguments = popNode(); |
- Node selector = popNode(); |
- // TODO(ahe): Handle receiver. |
- pushNode(new Send(null, selector, arguments)); |
- } |
- |
- void endFunctionBody(int count, Token beginToken, Token endToken) { |
- if (count == 0 && beginToken == null) { |
- pushNode(new EmptyStatement(endToken)); |
- } else { |
- pushNode(new Block(makeNodeList(count, beginToken, endToken, null))); |
- } |
- } |
- |
- void handleAsyncModifier(Token asyncToken, Token starToken) { |
- if (asyncToken != null) { |
- pushNode(new AsyncModifier(asyncToken, starToken)); |
- } else { |
- pushNode(null); |
- } |
- } |
- |
- void skippedFunctionBody(Token token) { |
- pushNode(new Block(new NodeList.empty())); |
- } |
- |
- void handleNoFunctionBody(Token token) { |
- pushNode(new EmptyStatement(token)); |
- } |
- |
- void endFunction(Token getOrSet, Token endToken) { |
- Statement body = popNode(); |
- AsyncModifier asyncModifier = popNode(); |
- NodeList initializers = popNode(); |
- NodeList formals = popNode(); |
- // The name can be an identifier or a send in case of named constructors. |
- Expression name = popNode(); |
- TypeAnnotation type = popNode(); |
- Modifiers modifiers = popNode(); |
- pushNode(new FunctionExpression(name, formals, body, type, |
- modifiers, initializers, getOrSet, |
- asyncModifier)); |
- } |
- |
- void endFunctionDeclaration(Token endToken) { |
- pushNode(new FunctionDeclaration(popNode())); |
- } |
- |
- void endVariablesDeclaration(int count, Token endToken) { |
- // TODO(ahe): Pick one name for this concept, either |
- // VariablesDeclaration or VariableDefinitions. |
- NodeList variables = makeNodeList(count, null, endToken, ","); |
- TypeAnnotation type = popNode(); |
- Modifiers modifiers = popNode(); |
- pushNode(new VariableDefinitions(type, modifiers, variables)); |
- } |
- |
- void endInitializer(Token assignmentOperator) { |
- Expression initializer = popNode(); |
- NodeList arguments = |
- initializer == null ? null : new NodeList.singleton(initializer); |
- Expression name = popNode(); |
- Operator op = new Operator(assignmentOperator); |
- pushNode(new SendSet(null, name, op, arguments)); |
- } |
- |
- void endIfStatement(Token ifToken, Token elseToken) { |
- Statement elsePart = (elseToken == null) ? null : popNode(); |
- Statement thenPart = popNode(); |
- ParenthesizedExpression condition = popNode(); |
- pushNode(new If(condition, thenPart, elsePart, ifToken, elseToken)); |
- } |
- |
- void endForStatement(int updateExpressionCount, |
- Token beginToken, Token endToken) { |
- Statement body = popNode(); |
- NodeList updates = makeNodeList(updateExpressionCount, null, null, ','); |
- Statement condition = popNode(); |
- Node initializer = popNode(); |
- pushNode(new For(initializer, condition, updates, body, beginToken)); |
- } |
- |
- void handleNoExpression(Token token) { |
- pushNode(null); |
- } |
- |
- void endDoWhileStatement(Token doKeyword, Token whileKeyword, |
- Token endToken) { |
- Expression condition = popNode(); |
- Statement body = popNode(); |
- pushNode(new DoWhile(body, condition, doKeyword, whileKeyword, endToken)); |
- } |
- |
- void endWhileStatement(Token whileKeyword, Token endToken) { |
- Statement body = popNode(); |
- Expression condition = popNode(); |
- pushNode(new While(condition, body, whileKeyword)); |
- } |
- |
- void endBlock(int count, Token beginToken, Token endToken) { |
- pushNode(new Block(makeNodeList(count, beginToken, endToken, null))); |
- } |
- |
- void endThrowExpression(Token throwToken, Token endToken) { |
- Expression expression = popNode(); |
- pushNode(new Throw(expression, throwToken, endToken)); |
- } |
- |
- void endAwaitExpression(Token awaitToken, Token endToken) { |
- Expression expression = popNode(); |
- pushNode(new Await(awaitToken, expression)); |
- } |
- |
- void endRethrowStatement(Token throwToken, Token endToken) { |
- pushNode(new Rethrow(throwToken, endToken)); |
- if (identical(throwToken.stringValue, 'throw')) { |
- listener.reportError(throwToken, |
- MessageKind.UNSUPPORTED_THROW_WITHOUT_EXP); |
- } |
- } |
- |
- void handleUnaryPrefixExpression(Token token) { |
- pushNode(new Send.prefix(popNode(), new Operator(token))); |
- } |
- |
- void handleSuperExpression(Token token) { |
- pushNode(new Identifier(token)); |
- } |
- |
- void handleThisExpression(Token token) { |
- pushNode(new Identifier(token)); |
- } |
- |
- void handleUnaryAssignmentExpression(Token token, bool isPrefix) { |
- Node node = popNode(); |
- Send send = node.asSend(); |
- if (send == null) { |
- reportNotAssignable(node); |
- } |
- if (!(send.isPropertyAccess || send.isIndex)) { |
- reportNotAssignable(node); |
- } |
- if (send.asSendSet() != null) internalError(node: send); |
- Node argument = null; |
- if (send.isIndex) argument = send.arguments.head; |
- Operator op = new Operator(token); |
- |
- if (isPrefix) { |
- pushNode(new SendSet.prefix(send.receiver, send.selector, op, argument)); |
- } else { |
- pushNode(new SendSet.postfix(send.receiver, send.selector, op, argument)); |
- } |
- } |
- |
- void handleUnaryPostfixAssignmentExpression(Token token) { |
- handleUnaryAssignmentExpression(token, false); |
- } |
- |
- void handleUnaryPrefixAssignmentExpression(Token token) { |
- handleUnaryAssignmentExpression(token, true); |
- } |
- |
- void endInitializers(int count, Token beginToken, Token endToken) { |
- pushNode(makeNodeList(count, beginToken, null, ',')); |
- } |
- |
- void handleNoInitializers() { |
- pushNode(null); |
- } |
- |
- void endFields(int count, Token beginToken, Token endToken) { |
- NodeList variables = makeNodeList(count, null, endToken, ","); |
- TypeAnnotation type = popNode(); |
- Modifiers modifiers = popNode(); |
- pushNode(new VariableDefinitions(type, modifiers, variables)); |
- } |
- |
- void endMethod(Token getOrSet, Token beginToken, Token endToken) { |
- Statement body = popNode(); |
- AsyncModifier asyncModifier = popNode(); |
- NodeList initializers = popNode(); |
- NodeList formalParameters = popNode(); |
- Expression name = popNode(); |
- TypeAnnotation returnType = popNode(); |
- Modifiers modifiers = popNode(); |
- pushNode(new FunctionExpression(name, formalParameters, body, returnType, |
- modifiers, initializers, getOrSet, |
- asyncModifier)); |
- } |
- |
- void handleLiteralMap(int count, Token beginToken, Token constKeyword, |
- Token endToken) { |
- NodeList entries = makeNodeList(count, beginToken, endToken, ','); |
- NodeList typeArguments = popNode(); |
- pushNode(new LiteralMap(typeArguments, entries, constKeyword)); |
- } |
- |
- void endLiteralMapEntry(Token colon, Token endToken) { |
- Expression value = popNode(); |
- Expression key = popNode(); |
- pushNode(new LiteralMapEntry(key, colon, value)); |
- } |
- |
- void handleLiteralList(int count, Token beginToken, Token constKeyword, |
- Token endToken) { |
- NodeList elements = makeNodeList(count, beginToken, endToken, ','); |
- pushNode(new LiteralList(popNode(), elements, constKeyword)); |
- } |
- |
- void handleIndexedExpression(Token openSquareBracket, |
- Token closeSquareBracket) { |
- NodeList arguments = |
- makeNodeList(1, openSquareBracket, closeSquareBracket, null); |
- Node receiver = popNode(); |
- Token token = new StringToken.fromString(INDEX_INFO, '[]', |
- openSquareBracket.charOffset); |
- Node selector = new Operator(token); |
- pushNode(new Send(receiver, selector, arguments)); |
- } |
- |
- void handleNewExpression(Token token) { |
- NodeList arguments = popNode(); |
- Node name = popNode(); |
- pushNode(new NewExpression(token, new Send(null, name, arguments))); |
- } |
- |
- void handleConstExpression(Token token) { |
- // [token] carries the 'const' information. |
- handleNewExpression(token); |
- } |
- |
- void handleOperator(Token token) { |
- pushNode(new Operator(token)); |
- } |
- |
- void handleOperatorName(Token operatorKeyword, Token token) { |
- Operator op = new Operator(token); |
- pushNode(new Send(new Identifier(operatorKeyword), op, null)); |
- } |
- |
- void handleNamedArgument(Token colon) { |
- Expression expression = popNode(); |
- Identifier name = popNode(); |
- pushNode(new NamedArgument(name, colon, expression)); |
- } |
- |
- void endOptionalFormalParameters(int count, |
- Token beginToken, Token endToken) { |
- pushNode(makeNodeList(count, beginToken, endToken, ',')); |
- } |
- |
- void handleFunctionTypedFormalParameter(Token endToken) { |
- NodeList formals = popNode(); |
- Identifier name = popNode(); |
- TypeAnnotation returnType = popNode(); |
- pushNode(null); // Signal "no type" to endFormalParameter. |
- pushNode(new FunctionExpression(name, formals, null, returnType, |
- Modifiers.EMPTY, null, null, null)); |
- } |
- |
- void handleValuedFormalParameter(Token equals, Token token) { |
- Expression defaultValue = popNode(); |
- Expression parameterName = popNode(); |
- pushNode(new SendSet(null, parameterName, new Operator(equals), |
- new NodeList.singleton(defaultValue))); |
- } |
- |
- void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) { |
- Block finallyBlock = null; |
- if (finallyKeyword != null) { |
- finallyBlock = popNode(); |
- } |
- NodeList catchBlocks = makeNodeList(catchCount, null, null, null); |
- Block tryBlock = popNode(); |
- pushNode(new TryStatement(tryBlock, catchBlocks, finallyBlock, |
- tryKeyword, finallyKeyword)); |
- } |
- |
- void handleCaseMatch(Token caseKeyword, Token colon) { |
- pushNode(new CaseMatch(caseKeyword, popNode(), colon)); |
- } |
- |
- void handleCatchBlock(Token onKeyword, Token catchKeyword) { |
- Block block = popNode(); |
- NodeList formals = catchKeyword != null? popNode(): null; |
- TypeAnnotation type = onKeyword != null ? popNode() : null; |
- pushNode(new CatchBlock(type, formals, block, onKeyword, catchKeyword)); |
- } |
- |
- void endSwitchStatement(Token switchKeyword, Token endToken) { |
- NodeList cases = popNode(); |
- ParenthesizedExpression expression = popNode(); |
- pushNode(new SwitchStatement(expression, cases, switchKeyword)); |
- } |
- |
- void endSwitchBlock(int caseCount, Token beginToken, Token endToken) { |
- Link<Node> caseNodes = const Link<Node>(); |
- while (caseCount > 0) { |
- SwitchCase switchCase = popNode(); |
- caseNodes = caseNodes.prepend(switchCase); |
- caseCount--; |
- } |
- pushNode(new NodeList(beginToken, caseNodes, endToken, null)); |
- } |
- |
- void handleSwitchCase(int labelCount, int caseCount, |
- Token defaultKeyword, int statementCount, |
- Token firstToken, Token endToken) { |
- NodeList statements = makeNodeList(statementCount, null, null, null); |
- NodeList labelsAndCases = |
- makeNodeList(labelCount + caseCount, null, null, null); |
- pushNode(new SwitchCase(labelsAndCases, defaultKeyword, statements, |
- firstToken)); |
- } |
- |
- void handleBreakStatement(bool hasTarget, |
- Token breakKeyword, Token endToken) { |
- Identifier target = null; |
- if (hasTarget) { |
- target = popNode(); |
- } |
- pushNode(new BreakStatement(target, breakKeyword, endToken)); |
- } |
- |
- void handleContinueStatement(bool hasTarget, |
- Token continueKeyword, Token endToken) { |
- Identifier target = null; |
- if (hasTarget) { |
- target = popNode(); |
- } |
- pushNode(new ContinueStatement(target, continueKeyword, endToken)); |
- } |
- |
- void handleEmptyStatement(Token token) { |
- pushNode(new EmptyStatement(token)); |
- } |
- |
- void endFactoryMethod(Token beginToken, Token endToken) { |
- super.endFactoryMethod(beginToken, endToken); |
- Statement body = popNode(); |
- AsyncModifier asyncModifier = popNode(); |
- NodeList formals = popNode(); |
- Node name = popNode(); |
- |
- // TODO(ahe): Move this parsing to the parser. |
- int modifierCount = 0; |
- Token modifier = beginToken; |
- if (modifier.stringValue == "external") { |
- handleModifier(modifier); |
- modifierCount++; |
- modifier = modifier.next; |
- } |
- if (modifier.stringValue == "const") { |
- handleModifier(modifier); |
- modifierCount++; |
- modifier = modifier.next; |
- } |
- assert(modifier.stringValue == "factory"); |
- handleModifier(modifier); |
- modifierCount++; |
- handleModifiers(modifierCount); |
- Modifiers modifiers = popNode(); |
- |
- pushNode(new FunctionExpression(name, formals, body, null, |
- modifiers, null, null, asyncModifier)); |
- } |
- |
- void endForIn(Token awaitToken, Token forToken, |
- Token inKeyword, Token endToken) { |
- Statement body = popNode(); |
- Expression expression = popNode(); |
- Node declaredIdentifier = popNode(); |
- pushNode(new ForIn(declaredIdentifier, expression, body, |
- awaitToken, forToken, inKeyword)); |
- } |
- |
- void endMetadataStar(int count, bool forParameter) { |
- // TODO(johnniwinther): Handle metadata for all node kinds. |
- if (forParameter) { |
- if (0 == count) { |
- pushNode(null); |
- } else { |
- pushNode(makeNodeList(count, null, null, ' ')); |
- } |
- } |
- } |
- |
- void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) { |
- NodeList arguments = popNode(); |
- if (arguments == null) { |
- // This is a constant expression. |
- Identifier name; |
- if (periodBeforeName != null) { |
- name = popNode(); |
- } |
- NodeList typeArguments = popNode(); |
- Node receiver = popNode(); |
- if (typeArguments != null) { |
- receiver = new TypeAnnotation(receiver, typeArguments); |
- recoverableError(typeArguments, |
- 'Type arguments are not allowed here.'); |
- } else { |
- Identifier identifier = receiver.asIdentifier(); |
- Send send = receiver.asSend(); |
- if (identifier != null) { |
- receiver = new Send(null, identifier); |
- } else if (send == null) { |
- internalError(node: receiver); |
- } |
- } |
- Send send = receiver; |
- if (name != null) { |
- send = new Send(receiver, name); |
- } |
- pushNode(new Metadata(beginToken, send)); |
- } else { |
- // This is a const constructor call. |
- endConstructorReference(beginToken, periodBeforeName, endToken); |
- Node constructor = popNode(); |
- pushNode(new Metadata(beginToken, |
- new NewExpression(null, |
- new Send(null, constructor, arguments)))); |
- } |
- } |
- |
- void handleAssertStatement(Token assertKeyword, Token semicolonToken) { |
- NodeList arguments = popNode(); |
- Node selector = new Identifier(assertKeyword); |
- Node send = new Send(null, selector, arguments); |
- pushNode(new ExpressionStatement(send, semicolonToken)); |
- } |
- |
- void endUnnamedFunction(Token token) { |
- Statement body = popNode(); |
- AsyncModifier asyncModifier = popNode(); |
- NodeList formals = popNode(); |
- pushNode(new FunctionExpression(null, formals, body, null, |
- Modifiers.EMPTY, null, null, |
- asyncModifier)); |
- } |
- |
- void handleIsOperator(Token operathor, Token not, Token endToken) { |
- TypeAnnotation type = popNode(); |
- Expression expression = popNode(); |
- Node argument; |
- if (not != null) { |
- argument = new Send.prefix(type, new Operator(not)); |
- } else { |
- argument = type; |
- } |
- |
- NodeList arguments = new NodeList.singleton(argument); |
- pushNode(new Send(expression, new Operator(operathor), arguments)); |
- } |
- |
- void handleLabel(Token colon) { |
- Identifier name = popNode(); |
- pushNode(new Label(name, colon)); |
- } |
- |
- void endLabeledStatement(int labelCount) { |
- Statement statement = popNode(); |
- NodeList labels = makeNodeList(labelCount, null, null, null); |
- pushNode(new LabeledStatement(labels, statement)); |
- } |
- |
- void log(message) { |
- listener.log(message); |
- } |
- |
- void internalError({Token token, Node node}) { |
- // TODO(ahe): This should call listener.internalError. |
- Spannable spannable = (token == null) ? node : token; |
- throw new SpannableAssertionFailure(spannable, 'Internal error in parser.'); |
- } |
-} |
- |
-abstract class PartialElement implements DeclarationSite { |
- Token beginToken; |
- Token endToken; |
- |
- bool hasParseError = false; |
- |
- bool get isErroneous => hasParseError; |
- |
- DeclarationSite get declarationSite => this; |
-} |
- |
-abstract class PartialFunctionMixin implements FunctionElement { |
- FunctionExpression cachedNode; |
- Modifiers get modifiers; |
- Token beginToken; |
- Token getOrSet; |
- Token endToken; |
- |
- /** |
- * The position is computed in the constructor using [findMyName]. Computing |
- * it on demand fails in case tokens are GC'd. |
- */ |
- Token _position; |
- |
- void init(Token beginToken, Token getOrSet, Token endToken) { |
- this.beginToken = beginToken; |
- this.getOrSet = getOrSet; |
- this.endToken = endToken; |
- _position = ElementX.findNameToken( |
- beginToken, |
- modifiers.isFactory || |
- identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR), |
- name, enclosingElement.name); |
- } |
- |
- bool get hasNode => cachedNode != null; |
- |
- FunctionExpression get node { |
- assert(invariant(this, cachedNode != null, |
- message: "Node has not been computed for $this.")); |
- return cachedNode; |
- } |
- |
- FunctionExpression parseNode(DiagnosticListener listener) { |
- if (cachedNode != null) return cachedNode; |
- parseFunction(Parser p) { |
- if (isClassMember && modifiers.isFactory) { |
- p.parseFactoryMethod(beginToken); |
- } else { |
- p.parseFunction(beginToken, getOrSet); |
- } |
- } |
- cachedNode = parse(listener, this, parseFunction); |
- return cachedNode; |
- } |
- |
- Token get position => _position; |
- |
- void reusePartialFunctionMixin() { |
- cachedNode = null; |
- } |
-} |
- |
-class PartialFunctionElement extends FunctionElementX |
- with PartialElement, PartialFunctionMixin { |
- PartialFunctionElement(String name, |
- Token beginToken, |
- Token getOrSet, |
- Token endToken, |
- ElementKind kind, |
- Modifiers modifiers, |
- Element enclosing, |
- bool hasNoBody) |
- : super(name, kind, modifiers, enclosing, hasNoBody) { |
- init(beginToken, getOrSet, endToken); |
- } |
- |
- void reuseElement() { |
- super.reuseElement(); |
- reusePartialFunctionMixin(); |
- } |
-} |
- |
-class PartialConstructorElement extends ConstructorElementX |
- with PartialElement, PartialFunctionMixin { |
- PartialConstructorElement(String name, |
- Token beginToken, |
- Token endToken, |
- ElementKind kind, |
- Modifiers modifiers, |
- Element enclosing) |
- : super(name, kind, modifiers, enclosing) { |
- init(beginToken, null, endToken); |
- } |
- |
- void reuseElement() { |
- super.reuseElement(); |
- reusePartialFunctionMixin(); |
- } |
-} |
- |
-class PartialFieldList extends VariableList with PartialElement { |
- PartialFieldList(Token beginToken, |
- Token endToken, |
- Modifiers modifiers, |
- bool hasParseError) |
- : super(modifiers) { |
- super.beginToken = beginToken; |
- super.endToken = endToken; |
- super.hasParseError = hasParseError; |
- } |
- |
- VariableDefinitions parseNode(Element element, DiagnosticListener listener) { |
- if (definitions != null) return definitions; |
- listener.withCurrentElement(element, () { |
- definitions = parse( |
- listener, element, |
- (Parser parser) { |
- if (hasParseError) { |
- parser.listener.suppressParseErrors = true; |
- } |
- return parser.parseMember(beginToken); |
- }); |
- |
- if (!hasParseError && |
- !definitions.modifiers.isVar && |
- !definitions.modifiers.isFinal && |
- !definitions.modifiers.isConst && |
- definitions.type == null && |
- !definitions.isErroneous) { |
- listener.reportError( |
- definitions, |
- MessageKind.GENERIC, |
- { 'text': 'A field declaration must start with var, final, ' |
- 'const, or a type annotation.' }); |
- } |
- }); |
- return definitions; |
- } |
- |
- computeType(Element element, Compiler compiler) { |
- if (type != null) return type; |
- // TODO(johnniwinther): Compute this in the resolver. |
- compiler.withCurrentElement(element, () { |
- VariableDefinitions node = parseNode(element, compiler); |
- if (node.type != null) { |
- type = compiler.resolver.resolveTypeAnnotation(element, node.type); |
- } else { |
- type = const DynamicType(); |
- } |
- }); |
- assert(type != null); |
- return type; |
- } |
-} |
- |
-class PartialTypedefElement extends TypedefElementX with PartialElement { |
- |
- PartialTypedefElement( |
- String name, |
- Element enclosing, |
- Token beginToken, |
- Token endToken) |
- : super(name, enclosing) { |
- this.beginToken = beginToken; |
- this.endToken = endToken; |
- } |
- |
- Token get token => beginToken; |
- |
- Node parseNode(DiagnosticListener listener) { |
- if (cachedNode != null) return cachedNode; |
- cachedNode = parse(listener, |
- this, |
- (p) => p.parseTopLevelDeclaration(token)); |
- return cachedNode; |
- } |
- |
- Token get position => findMyName(token); |
-} |
- |
-/// A [MetadataAnnotation] which is constructed on demand. |
-class PartialMetadataAnnotation extends MetadataAnnotationX { |
- final Token beginToken; |
- final Token tokenAfterEndToken; |
- Expression cachedNode; |
- |
- PartialMetadataAnnotation(this.beginToken, this.tokenAfterEndToken); |
- |
- Token get endToken { |
- Token token = beginToken; |
- while (token.kind != EOF_TOKEN) { |
- if (identical(token.next, tokenAfterEndToken)) break; |
- token = token.next; |
- } |
- assert(token != null); |
- return token; |
- } |
- |
- Node parseNode(DiagnosticListener listener) { |
- if (cachedNode != null) return cachedNode; |
- Metadata metadata = parse(listener, |
- annotatedElement, |
- (p) => p.parseMetadata(beginToken)); |
- cachedNode = metadata.expression; |
- return cachedNode; |
- } |
- |
- bool get hasNode => cachedNode != null; |
- |
- Node get node { |
- assert(invariant(this, hasNode)); |
- return cachedNode; |
- } |
-} |
- |
-Node parse(DiagnosticListener diagnosticListener, |
- Element element, |
- doParse(Parser parser)) { |
- CompilationUnitElement unit = element.compilationUnit; |
- NodeListener listener = |
- new NodeListener(diagnosticListener, unit, throwOnFatalError: true); |
- listener.memberErrors = listener.memberErrors.prepend(false); |
- try { |
- doParse(new Parser(listener)); |
- } on ParserError catch (e) { |
- if (element is PartialElement) { |
- PartialElement partial = element as PartialElement; |
- partial.hasParseError = true; |
- } |
- return new ErrorNode(element.position, e.reason); |
- } |
- Node node = listener.popNode(); |
- assert(listener.nodes.isEmpty); |
- return node; |
-} |