Index: pkg/dart_parser/lib/src/listener.dart |
diff --git a/pkg/dart_parser/lib/src/listener.dart b/pkg/dart_parser/lib/src/listener.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b33bd84d2b2d4b2c9019ad806fc37ac1c27ef8bb |
--- /dev/null |
+++ b/pkg/dart_parser/lib/src/listener.dart |
@@ -0,0 +1,637 @@ |
+// 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. |
+ |
+library dart2js.parser.listener; |
+ |
+import '../common.dart'; |
+import '../diagnostics/messages.dart' show MessageTemplate; |
+import '../tokens/precedence_constants.dart' as Precedence |
+ show EOF_INFO, IDENTIFIER_INFO; |
+import '../tokens/token.dart' |
+ show |
+ BadInputToken, |
+ BeginGroupToken, |
+ ErrorToken, |
+ StringToken, |
+ Token, |
+ UnmatchedToken, |
+ UnterminatedToken; |
+import '../tree/tree.dart'; |
+ |
+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 beginEnum(Token enumKeyword) {} |
+ |
+ void endEnum(Token enumKeyword, Token endBrace, int count) {} |
+ |
+ 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 beginConditionalUris(Token token) {} |
+ |
+ void endConditionalUris(int count) {} |
+ |
+ void beginConditionalUri(Token ifKeyword) {} |
+ |
+ void endConditionalUri(Token ifKeyword, Token equalitySign) {} |
+ |
+ void beginDottedName(Token token) {} |
+ |
+ void endDottedName(int count, Token firstIdentifier) {} |
+ |
+ 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 endMember() {} |
+ |
+ 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, Token extendsOrSuper) {} |
+ |
+ 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 operator, Token endToken) {} |
+ |
+ 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 operator, Token not, Token endToken) {} |
+ |
+ 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 commaToken, 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( |
+ Precedence.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, Precedence.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 {}]) { |
+ if (spannable is ErrorToken) { |
+ reportErrorToken(spannable); |
+ } else { |
+ reportErrorHelper(spannable, messageKind, arguments); |
+ } |
+ } |
+ |
+ void reportErrorHelper(Spannable spannable, MessageKind messageKind, |
+ [Map arguments = const {}]) { |
+ MessageTemplate template = MessageTemplate.TEMPLATES[messageKind]; |
+ String message = template.message(arguments, true).toString(); |
+ Token token; |
+ 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"; |
+ } |
+ reportErrorHelper( |
+ token, MessageKind.BAD_INPUT_CHARACTER, {'characterHex': hex}); |
+ } else if (token is UnterminatedToken) { |
+ 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; |
+ } |
+ reportErrorHelper(token, kind, arguments); |
+ } else if (token is UnmatchedToken) { |
+ String begin = token.begin.value; |
+ String end = closeBraceFor(begin); |
+ reportErrorHelper( |
+ 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; |
+} |