Index: pkg/dart_parser/lib/src/parser.dart |
diff --git a/pkg/dart_parser/lib/src/parser.dart b/pkg/dart_parser/lib/src/parser.dart |
index 3cac0379d321f2d2565c3c07e1b668d5e8aaf2b9..b2b17164daf6bdb587d2a1692eccb07d7a50771a 100644 |
--- a/pkg/dart_parser/lib/src/parser.dart |
+++ b/pkg/dart_parser/lib/src/parser.dart |
@@ -2,63 +2,76 @@ |
// 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; |
- |
-import '../common.dart'; |
-import '../options.dart' show ParserOptions; |
-import '../tokens/keyword.dart' show Keyword; |
-import '../tokens/precedence.dart' show PrecedenceInfo; |
-import '../tokens/precedence_constants.dart' |
- show |
- AS_INFO, |
- ASSIGNMENT_PRECEDENCE, |
- CASCADE_PRECEDENCE, |
- EQUALITY_PRECEDENCE, |
- GT_INFO, |
- IS_INFO, |
- MINUS_MINUS_INFO, |
- OPEN_PAREN_INFO, |
- OPEN_SQUARE_BRACKET_INFO, |
- PERIOD_INFO, |
- PLUS_PLUS_INFO, |
- POSTFIX_PRECEDENCE, |
- QUESTION_INFO, |
- QUESTION_PERIOD_INFO, |
- RELATIONAL_PRECEDENCE; |
-import '../tokens/token.dart' |
- show |
- BeginGroupToken, |
- isUserDefinableOperator, |
- KeywordToken, |
- SymbolToken, |
- Token; |
-import '../tokens/token_constants.dart' |
- show |
- BAD_INPUT_TOKEN, |
- COMMA_TOKEN, |
- DOUBLE_TOKEN, |
- EOF_TOKEN, |
- EQ_TOKEN, |
- FUNCTION_TOKEN, |
- GT_TOKEN, |
- GT_GT_TOKEN, |
- HASH_TOKEN, |
- HEXADECIMAL_TOKEN, |
- IDENTIFIER_TOKEN, |
- INT_TOKEN, |
- KEYWORD_TOKEN, |
- LT_TOKEN, |
- OPEN_CURLY_BRACKET_TOKEN, |
- OPEN_PAREN_TOKEN, |
- OPEN_SQUARE_BRACKET_TOKEN, |
- PERIOD_TOKEN, |
- SEMICOLON_TOKEN, |
- STRING_INTERPOLATION_IDENTIFIER_TOKEN, |
- STRING_INTERPOLATION_TOKEN, |
- STRING_TOKEN; |
-import '../util/characters.dart' as Characters show $CLOSE_CURLY_BRACKET; |
-import '../util/util.dart' show Link; |
-import 'listener.dart' show Listener; |
+library parser; |
+ |
+import 'package:scanner/src/keyword.dart' show |
+ Keyword; |
+ |
+import 'package:scanner/src/precedence.dart' show |
+ ASSIGNMENT_PRECEDENCE, |
+ AS_INFO, |
+ CASCADE_PRECEDENCE, |
+ EQUALITY_PRECEDENCE, |
+ GT_INFO, |
+ IS_INFO, |
+ MINUS_MINUS_INFO, |
+ OPEN_PAREN_INFO, |
+ OPEN_SQUARE_BRACKET_INFO, |
+ PERIOD_INFO, |
+ PLUS_PLUS_INFO, |
+ POSTFIX_PRECEDENCE, |
+ PrecedenceInfo, |
+ QUESTION_INFO, |
+ QUESTION_PERIOD_INFO, |
+ RELATIONAL_PRECEDENCE; |
+ |
+import 'package:scanner/src/token.dart' show |
+ BeginGroupToken, |
+ isUserDefinableOperator, |
+ KeywordToken, |
+ SymbolToken, |
+ Token; |
+ |
+import 'package:scanner/src/token_constants.dart' show |
+ BAD_INPUT_TOKEN, |
+ COMMA_TOKEN, |
+ DOUBLE_TOKEN, |
+ EOF_TOKEN, |
+ EQ_TOKEN, |
+ FUNCTION_TOKEN, |
+ GT_TOKEN, |
+ GT_GT_TOKEN, |
+ HASH_TOKEN, |
+ HEXADECIMAL_TOKEN, |
+ IDENTIFIER_TOKEN, |
+ INT_TOKEN, |
+ KEYWORD_TOKEN, |
+ LT_TOKEN, |
+ OPEN_CURLY_BRACKET_TOKEN, |
+ OPEN_PAREN_TOKEN, |
+ OPEN_SQUARE_BRACKET_TOKEN, |
+ PERIOD_TOKEN, |
+ SEMICOLON_TOKEN, |
+ STRING_INTERPOLATION_IDENTIFIER_TOKEN, |
+ STRING_INTERPOLATION_TOKEN, |
+ STRING_TOKEN; |
+ |
+import 'package:scanner/src/characters.dart' show |
+ $CLOSE_CURLY_BRACKET; |
+ |
+import 'package:link/link.dart' show |
+ Link; |
+ |
+import 'listener.dart' show |
+ Listener; |
+ |
+import 'error_kind.dart' show |
+ ErrorKind; |
+ |
+/// Returns true if [token] is the symbol or keyword [value]. |
+bool optional(String value, Token token) { |
+ return identical(value, token.stringValue); |
+} |
class FormalParameterType { |
final String type; |
@@ -96,16 +109,16 @@ class FormalParameterType { |
*/ |
class Parser { |
final Listener listener; |
- final ParserOptions parserOptions; |
+ |
bool mayParseFunctionExpressions = true; |
+ |
bool asyncAwaitKeywordsEnabled; |
final bool enableGenericMethodSyntax; |
- Parser(this.listener, ParserOptions parserOptions, |
- {this.asyncAwaitKeywordsEnabled: false}) |
- : parserOptions = parserOptions, |
- enableGenericMethodSyntax = parserOptions.enableGenericMethodSyntax; |
+ Parser(this.listener, |
+ {this.asyncAwaitKeywordsEnabled: false, |
+ this.enableGenericMethodSyntax: false}); |
Token parseUnit(Token token) { |
listener.beginCompilationUnit(token); |
@@ -463,10 +476,12 @@ class Parser { |
} |
token = parseIdentifier(token); |
if (optional('(', token)) { |
+ listener.beginFunctionTypedFormalParameter(token); |
listener.handleNoTypeVariables(token); |
token = parseFormalParameters(token); |
listener.handleFunctionTypedFormalParameter(token); |
} else if (enableGenericMethodSyntax && optional('<', token)) { |
+ listener.beginFunctionTypedFormalParameter(token); |
token = parseTypeVariablesOpt(token); |
token = parseFormalParameters(token); |
listener.handleFunctionTypedFormalParameter(token); |
@@ -479,10 +494,10 @@ class Parser { |
listener.handleValuedFormalParameter(equal, token); |
if (type.isRequired) { |
listener.reportError( |
- equal, MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT); |
+ equal, ErrorKind.REQUIRED_PARAMETER_WITH_DEFAULT); |
} else if (type.isPositional && identical(':', value)) { |
listener.reportError( |
- equal, MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS); |
+ equal, ErrorKind.POSITIONAL_PARAMETER_WITH_EQUALS); |
} |
} |
listener.endFormalParameter(thisKeyword); |
@@ -510,8 +525,8 @@ class Parser { |
listener.reportError( |
token, |
isNamed |
- ? MessageKind.EMPTY_NAMED_PARAMETER_LIST |
- : MessageKind.EMPTY_OPTIONAL_PARAMETER_LIST); |
+ ? ErrorKind.EMPTY_NAMED_PARAMETER_LIST |
+ : ErrorKind.EMPTY_OPTIONAL_PARAMETER_LIST); |
} |
listener.endOptionalFormalParameters(parameterCount, begin, token); |
if (isNamed) { |
@@ -650,7 +665,7 @@ class Parser { |
Token endGroup = beginGroupToken.endGroup; |
if (endGroup == null) { |
return listener.unmatched(beginGroupToken); |
- } else if (!identical(endGroup.kind, Characters.$CLOSE_CURLY_BRACKET)) { |
+ } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { |
return listener.unmatched(beginGroupToken); |
} |
return beginGroupToken.endGroup; |
@@ -795,13 +810,6 @@ class Parser { |
} |
/** |
- * Returns true if the stringValue of the [token] is [value]. |
- */ |
- bool optional(String value, Token token) { |
- return identical(value, token.stringValue); |
- } |
- |
- /** |
* Returns true if the stringValue of the [token] is either [value1], |
* [value2], or [value3]. |
*/ |
@@ -1010,8 +1018,8 @@ class Parser { |
} |
listener.handleModifiers(modifierCount); |
var kind = hasTypeOrModifier |
- ? MessageKind.EXTRANEOUS_MODIFIER |
- : MessageKind.EXTRANEOUS_MODIFIER_REPLACE; |
+ ? ErrorKind.EXTRANEOUS_MODIFIER |
+ : ErrorKind.EXTRANEOUS_MODIFIER_REPLACE; |
for (Token modifier in modifierList) { |
listener.reportError(modifier, kind, {'modifier': modifier}); |
} |
@@ -1032,8 +1040,8 @@ class Parser { |
if (getOrSet != null) { |
var kind = (hasModifier || hasType) |
- ? MessageKind.EXTRANEOUS_MODIFIER |
- : MessageKind.EXTRANEOUS_MODIFIER_REPLACE; |
+ ? ErrorKind.EXTRANEOUS_MODIFIER |
+ : ErrorKind.EXTRANEOUS_MODIFIER_REPLACE; |
listener.reportError(getOrSet, kind, {'modifier': getOrSet}); |
} |
@@ -1044,11 +1052,11 @@ class Parser { |
// TODO(ahe): This error is reported twice, second time is from |
// [parseVariablesDeclarationMaybeSemicolon] via |
// [PartialFieldListElement.parseNode]. |
- listener.reportError(type, MessageKind.VOID_NOT_ALLOWED); |
+ listener.reportError(type, ErrorKind.INVALID_VOID); |
} else { |
parseType(type); |
if (isVar) { |
- listener.reportError(modifiers.head, MessageKind.EXTRANEOUS_MODIFIER, |
+ listener.reportError(modifiers.head, ErrorKind.EXTRANEOUS_MODIFIER, |
{'modifier': modifiers.head}); |
} |
} |
@@ -1082,7 +1090,7 @@ class Parser { |
externalModifier = modifier; |
} else { |
listener.reportError( |
- modifier, MessageKind.EXTRANEOUS_MODIFIER, {'modifier': modifier}); |
+ modifier, ErrorKind.EXTRANEOUS_MODIFIER, {'modifier': modifier}); |
} |
} |
if (externalModifier != null) { |
@@ -1203,8 +1211,10 @@ class Parser { |
Token parseVariableInitializerOpt(Token token) { |
if (optional('=', token)) { |
Token assignment = token; |
+ // TODO(ahe): Rename this to beginVariableInitializer. |
listener.beginInitializer(token); |
token = parseExpression(token.next); |
+ // TODO(ahe): Rename this to endVariableInitializer. |
listener.endInitializer(assignment); |
} |
return token; |
@@ -1227,7 +1237,10 @@ class Parser { |
bool old = mayParseFunctionExpressions; |
mayParseFunctionExpressions = false; |
do { |
- token = parseExpression(token.next); |
+ token = token.next; |
+ listener.beginConstructorInitializer(token); |
+ token = parseExpression(token); |
+ listener.endConstructorInitializer(token); |
++count; |
} while (optional(',', token)); |
mayParseFunctionExpressions = old; |
@@ -1239,7 +1252,7 @@ class Parser { |
if (identical(token.kind, STRING_TOKEN)) { |
return parseLiteralString(token); |
} else { |
- listener.recoverableError(token, "unexpected"); |
+ listener.reportError(token, ErrorKind.EXPECTED_STRING); |
return parseExpression(token); |
} |
} |
@@ -1461,7 +1474,7 @@ class Parser { |
modifierCount++; |
externalModifier = modifier; |
if (modifierCount != allowedModifierCount) { |
- listener.reportError(modifier, MessageKind.EXTRANEOUS_MODIFIER, |
+ listener.reportError(modifier, ErrorKind.EXTRANEOUS_MODIFIER, |
{'modifier': modifier}); |
} |
allowedModifierCount++; |
@@ -1469,23 +1482,23 @@ class Parser { |
modifierCount++; |
staticModifier = modifier; |
if (modifierCount != allowedModifierCount) { |
- listener.reportError(modifier, MessageKind.EXTRANEOUS_MODIFIER, |
+ listener.reportError(modifier, ErrorKind.EXTRANEOUS_MODIFIER, |
{'modifier': modifier}); |
} |
} else if (constModifier == null && optional('const', modifier)) { |
modifierCount++; |
constModifier = modifier; |
if (modifierCount != allowedModifierCount) { |
- listener.reportError(modifier, MessageKind.EXTRANEOUS_MODIFIER, |
+ listener.reportError(modifier, ErrorKind.EXTRANEOUS_MODIFIER, |
{'modifier': modifier}); |
} |
} else { |
listener.reportError( |
- modifier, MessageKind.EXTRANEOUS_MODIFIER, {'modifier': modifier}); |
+ modifier, ErrorKind.EXTRANEOUS_MODIFIER, {'modifier': modifier}); |
} |
} |
if (getOrSet != null && constModifier != null) { |
- listener.reportError(constModifier, MessageKind.EXTRANEOUS_MODIFIER, |
+ listener.reportError(constModifier, ErrorKind.EXTRANEOUS_MODIFIER, |
{'modifier': constModifier}); |
} |
parseModifierList(modifiers); |
@@ -1499,7 +1512,7 @@ class Parser { |
if (optional('operator', name)) { |
token = parseOperatorName(name); |
if (staticModifier != null) { |
- listener.reportError(staticModifier, MessageKind.EXTRANEOUS_MODIFIER, |
+ listener.reportError(staticModifier, ErrorKind.EXTRANEOUS_MODIFIER, |
{'modifier': staticModifier}); |
} |
} else { |
@@ -1688,7 +1701,7 @@ class Parser { |
Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { |
if (optional(';', token)) { |
if (!allowAbstract) { |
- listener.reportError(token, MessageKind.BODY_EXPECTED); |
+ listener.reportError(token, ErrorKind.EXPECTED_BODY); |
} |
listener.endFunctionBody(0, null, token); |
return token; |
@@ -1740,7 +1753,7 @@ class Parser { |
star = token; |
token = token.next; |
} else { |
- listener.reportError(async, MessageKind.INVALID_SYNC_MODIFIER); |
+ listener.reportError(async, ErrorKind.INVALID_SYNC_MODIFIER); |
} |
} |
listener.handleAsyncModifier(async, star); |
@@ -1989,12 +2002,14 @@ class Parser { |
} |
Token parseExpression(Token token) { |
+ listener.beginExpression(token); |
return optional('throw', token) |
? parseThrowExpression(token, true) |
: parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, true); |
} |
Token parseExpressionWithoutCascade(Token token) { |
+ listener.beginExpression(token); |
return optional('throw', token) |
? parseThrowExpression(token, false) |
: parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, false); |
@@ -2029,6 +2044,7 @@ class Parser { |
} else if (identical(tokenLevel, ASSIGNMENT_PRECEDENCE)) { |
// Right associative, so we recurse at the same precedence |
// level. |
+ listener.beginExpression(token.next); |
token = parsePrecedenceExpression(token.next, level, allowCascades); |
listener.handleAssignmentExpression(operator); |
} else if (identical(tokenLevel, POSTFIX_PRECEDENCE)) { |
@@ -2059,6 +2075,7 @@ class Parser { |
} else { |
// Left associative, so we recurse at the next higher |
// precedence level. |
+ listener.beginExpression(token.next); |
token = |
parsePrecedenceExpression(token.next, level + 1, allowCascades); |
listener.handleBinaryExpression(operator); |
@@ -2116,7 +2133,7 @@ class Parser { |
return parseAwaitExpression(token, allowCascades); |
} else if (identical(value, '+')) { |
// Dart no longer allows prefix-plus. |
- listener.reportError(token, MessageKind.UNSUPPORTED_PREFIX_PLUS); |
+ listener.reportError(token, ErrorKind.UNSUPPORTED_PREFIX_PLUS); |
return parseUnaryExpression(token.next, allowCascades); |
} else if ((identical(value, '!')) || |
(identical(value, '-')) || |
@@ -2678,11 +2695,15 @@ class Parser { |
listener.beginIfStatement(ifToken); |
token = expect('if', token); |
token = parseParenthesizedExpression(token); |
+ listener.beginThenStatement(token); |
token = parseStatement(token); |
+ listener.endThenStatement(token); |
Token elseToken = null; |
if (optional('else', token)) { |
elseToken = token; |
+ listener.beginElseStatement(token); |
token = parseStatement(token.next); |
+ listener.endElseStatement(token); |
} |
listener.endIfStatement(ifToken, elseToken); |
return token; |
@@ -2698,7 +2719,7 @@ class Parser { |
return parseForInRest(awaitToken, forToken, token); |
} else { |
if (awaitToken != null) { |
- listener.reportError(awaitToken, MessageKind.INVALID_AWAIT_FOR); |
+ listener.reportError(awaitToken, ErrorKind.INVALID_AWAIT_FOR); |
} |
return parseForRest(forToken, token); |
} |
@@ -2741,7 +2762,9 @@ class Parser { |
} |
} |
token = expect(')', token); |
+ listener.beginForStatementBody(token); |
token = parseStatement(token); |
+ listener.endForStatementBody(token); |
listener.endForStatement(expressionCount, forToken, token); |
return token; |
} |
@@ -2751,7 +2774,9 @@ class Parser { |
Token inKeyword = token; |
token = parseExpression(token.next); |
token = expect(')', token); |
+ listener.beginForInBody(token); |
token = parseStatement(token); |
+ listener.endForInBody(token); |
listener.endForIn(awaitToken, forToken, inKeyword, token); |
return token; |
} |
@@ -2761,7 +2786,9 @@ class Parser { |
listener.beginWhileStatement(whileToken); |
token = expect('while', token); |
token = parseParenthesizedExpression(token); |
+ listener.beginWhileStatementBody(token); |
token = parseStatement(token); |
+ listener.endWhileStatementBody(token); |
listener.endWhileStatement(whileToken, token); |
return token; |
} |
@@ -2770,7 +2797,9 @@ class Parser { |
Token doToken = token; |
listener.beginDoWhileStatement(doToken); |
token = expect('do', token); |
+ listener.beginDoWhileStatementBody(token); |
token = parseStatement(token); |
+ listener.endDoWhileStatementBody(token); |
Token whileToken = token; |
token = expect('while', token); |
token = parseParenthesizedExpression(token); |
@@ -2833,6 +2862,7 @@ class Parser { |
String value = token.stringValue; |
while (identical(value, 'catch') || identical(value, 'on')) { |
+ listener.beginCatchClause(token); |
var onKeyword = null; |
if (identical(value, 'on')) { |
// on qualified catchPart? |
@@ -2846,6 +2876,7 @@ class Parser { |
// TODO(ahe): Validate the "parameters". |
token = parseFormalParameters(token.next); |
} |
+ listener.endCatchClause(token); |
token = parseBlock(token); |
++catchCount; |
listener.handleCatchBlock(onKeyword, catchKeyword); |
@@ -2942,6 +2973,7 @@ class Parser { |
break; |
} |
} |
+ listener.beginSwitchCase(labelCount, expressionCount, begin); |
// Finally zero or more statements. |
int statementCount = 0; |
while (!identical(token.kind, EOF_TOKEN)) { |