blob: 618b86a1b09e36fbe74d6c55cb9a28b3b251a0c7 [file] [log] [blame]
// 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 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 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 {}]) {
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";
}
reportError(
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;
}
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;
}