| Index: editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/parser/Parser.java
|
| diff --git a/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/parser/Parser.java b/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/parser/Parser.java
|
| index ce9ca19cb22c1150903eb0c6c98387581c9d25a2..cc9082e8ed3e958c5320638c97683ed5052974d5 100644
|
| --- a/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/parser/Parser.java
|
| +++ b/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/parser/Parser.java
|
| @@ -159,8 +159,6 @@ public class Parser {
|
| private static final String ON = "on"; //$NON-NLS-1$
|
| private static final String SHOW = "show"; //$NON-NLS-1$
|
|
|
| - private static final ArrayList<Expression> EMPTY_EXPRESSION_LIST = new ArrayList<Expression>(0);
|
| -
|
| /**
|
| * Initialize a newly created parser.
|
| *
|
| @@ -215,7 +213,7 @@ public class Parser {
|
| * @return the statements that were parsed, or {@code null} if the tokens do not represent a
|
| * recognizable sequence of statements
|
| */
|
| - public ArrayList<Statement> parseStatements(Token token) {
|
| + public List<Statement> parseStatements(Token token) {
|
| currentToken = token;
|
| return parseStatements();
|
| }
|
| @@ -233,16 +231,16 @@ public class Parser {
|
| * value is invalid.
|
| *
|
| * @param builder the builder to which the scalar value is to be appended
|
| + * @param escapeSequence the escape sequence that was parsed to produce the scalar value
|
| * @param scalarValue the value to be appended
|
| * @param startIndex the index of the first character representing the scalar value
|
| * @param endIndex the index of the last character representing the scalar value
|
| */
|
| - private void appendScalarValue(StringBuilder builder, int scalarValue, int startIndex,
|
| - int endIndex) {
|
| + private void appendScalarValue(StringBuilder builder, String escapeSequence, int scalarValue,
|
| + int startIndex, int endIndex) {
|
| if (scalarValue < 0 || scalarValue > Character.MAX_CODE_POINT
|
| || (scalarValue >= 0xD800 && scalarValue <= 0xDFFF)) {
|
| - // Illegal escape sequence: invalid code point
|
| - // reportError(ParserErrorCode.INVALID_CODE_POINT));
|
| + reportError(ParserErrorCode.INVALID_CODE_POINT, escapeSequence);
|
| return;
|
| }
|
| if (scalarValue < Character.MAX_VALUE) {
|
| @@ -259,10 +257,14 @@ public class Parser {
|
| * @return the actual value of the string
|
| */
|
| private String computeStringValue(String lexeme) {
|
| - if (lexeme.startsWith("@\"\"\"") || lexeme.startsWith("@'''")) { //$NON-NLS-1$ //$NON-NLS-2$
|
| - return lexeme.substring(4, lexeme.length() - 3);
|
| - } else if (lexeme.startsWith("@\"") || lexeme.startsWith("@'")) { //$NON-NLS-1$ //$NON-NLS-2$
|
| - return lexeme.substring(2, lexeme.length() - 1);
|
| + if (lexeme.startsWith("r\"\"\"") || lexeme.startsWith("r'''")) { //$NON-NLS-1$ //$NON-NLS-2$
|
| + if (lexeme.length() > 4) {
|
| + return lexeme.substring(4, lexeme.length() - 3);
|
| + }
|
| + } else if (lexeme.startsWith("r\"") || lexeme.startsWith("r'")) { //$NON-NLS-1$ //$NON-NLS-2$
|
| + if (lexeme.length() > 2) {
|
| + return lexeme.substring(2, lexeme.length() - 1);
|
| + }
|
| }
|
| int start = 0;
|
| if (lexeme.startsWith("\"\"\"") || lexeme.startsWith("'''")) { //$NON-NLS-1$ //$NON-NLS-2$
|
| @@ -415,6 +417,8 @@ public class Parser {
|
| afterIdentifier = afterReturnType;
|
| }
|
| if (afterIdentifier.getType() == TokenType.OPEN_PAREN) {
|
| + // TODO(brianwilkerson) We need to look at the tokens between the parentheses to see whether
|
| + // they look like a parameter list.
|
| Token openParen = afterIdentifier;
|
| if (openParen instanceof BeginToken) {
|
| Token closeParen = ((BeginToken) openParen).getEndToken();
|
| @@ -754,6 +758,9 @@ public class Parser {
|
| foundNamedArgument = true;
|
| }
|
| }
|
| + // TODO(brianwilkerson) Look at the left parenthesis to see whether there is a matching right
|
| + // parenthesis. If there is, then we're more likely missing a comma and should go back to
|
| + // parsing arguments.
|
| Token rightParenthesis = expect(TokenType.CLOSE_PAREN);
|
| return new ArgumentList(leftParenthesis, arguments, rightParenthesis);
|
| }
|
| @@ -1025,7 +1032,7 @@ public class Parser {
|
| Token period = expect(TokenType.PERIOD_PERIOD);
|
| Expression expression = null;
|
| SimpleIdentifier functionName = null;
|
| - if (currentToken.getType() == TokenType.IDENTIFIER) {
|
| + if (matchesIdentifier()) {
|
| functionName = parseSimpleIdentifier();
|
| } else if (currentToken.getType() == TokenType.OPEN_SQUARE_BRACKET) {
|
| Token leftBracket = getAndAdvance();
|
| @@ -1146,7 +1153,7 @@ public class Parser {
|
| // TODO(brianwilkerson) The following condition exists for backward compatibility and might want
|
| // to be removed before shipping.
|
| if (matches(Keyword.ABSTRACT)) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
|
| advance();
|
| }
|
| Token externalKeyword = null;
|
| @@ -1162,7 +1169,7 @@ public class Parser {
|
| }
|
| }
|
| if (externalKeyword != null) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.EXTERNAL_FIELD);
|
| }
|
| return new FieldDeclaration(
|
| commentAndMetadata.getComment(),
|
| @@ -1174,7 +1181,7 @@ public class Parser {
|
| return parseFactoryConstructor(commentAndMetadata, externalKeyword);
|
| } else if (matches(Keyword.FINAL)) {
|
| if (externalKeyword != null) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.EXTERNAL_FIELD);
|
| }
|
| return new FieldDeclaration(
|
| commentAndMetadata.getComment(),
|
| @@ -1187,7 +1194,7 @@ public class Parser {
|
| if (matches(Keyword.STATIC)) {
|
| if (peekMatches(Keyword.FINAL) || peekMatches(Keyword.CONST)) {
|
| if (externalKeyword != null) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.EXTERNAL_FIELD);
|
| }
|
| return new FieldDeclaration(
|
| commentAndMetadata.getComment(),
|
| @@ -1200,16 +1207,16 @@ public class Parser {
|
| }
|
| if (matches(Keyword.VAR)) {
|
| if (externalKeyword != null) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.EXTERNAL_FIELD);
|
| }
|
| return parseInitializedIdentifierList(
|
| commentAndMetadata,
|
| staticKeyword,
|
| getAndAdvance(),
|
| null);
|
| - } else if (matches(Keyword.GET)) {
|
| + } else if (matches(Keyword.GET) && !peekMatches(TokenType.OPEN_PAREN)) {
|
| return parseGetter(commentAndMetadata, externalKeyword, staticKeyword, null);
|
| - } else if (matches(Keyword.SET)) {
|
| + } else if (matches(Keyword.SET) && !peekMatches(TokenType.OPEN_PAREN)) {
|
| return parseSetter(commentAndMetadata, externalKeyword, staticKeyword, null);
|
| } else if (matches(Keyword.OPERATOR)) {
|
| if (staticKeyword != null) {
|
| @@ -1228,7 +1235,7 @@ public class Parser {
|
| }
|
| SimpleIdentifier returnType = parseSimpleIdentifier();
|
| Token period = getAndAdvance();
|
| - SimpleIdentifier name = parseSimpleIdentifier(ParserErrorCode.BUILT_IN_IDENTIFIER_AS_FUNCTION_NAME);
|
| + SimpleIdentifier name = parseSimpleIdentifier();
|
| return parseConstructor(
|
| commentAndMetadata,
|
| externalKeyword,
|
| @@ -1240,9 +1247,9 @@ public class Parser {
|
| }
|
| }
|
| TypeName returnType = parseOptionalReturnType();
|
| - if (matches(Keyword.GET)) {
|
| + if (matches(Keyword.GET) && !peekMatches(TokenType.OPEN_PAREN)) {
|
| return parseGetter(commentAndMetadata, externalKeyword, staticKeyword, returnType);
|
| - } else if (matches(Keyword.SET)) {
|
| + } else if (matches(Keyword.SET) && !peekMatches(TokenType.OPEN_PAREN)) {
|
| return parseSetter(commentAndMetadata, externalKeyword, staticKeyword, returnType);
|
| } else if (matches(Keyword.OPERATOR)) {
|
| if (staticKeyword != null) {
|
| @@ -1258,7 +1265,7 @@ public class Parser {
|
| returnType);
|
| }
|
| if (externalKeyword != null) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.EXTERNAL_FIELD);
|
| }
|
| return parseInitializedIdentifierList(commentAndMetadata, staticKeyword, null, returnType);
|
| }
|
| @@ -1363,15 +1370,15 @@ public class Parser {
|
| nextToken = firstToken.getNext();
|
| }
|
| if (nextToken.getType() != TokenType.EOF) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.INVALID_COMMENT_REFERENCE);
|
| }
|
| return new CommentReference(newKeyword, identifier);
|
| } else {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.INVALID_COMMENT_REFERENCE);
|
| }
|
| }
|
| } catch (Exception exception) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.INVALID_COMMENT_REFERENCE);
|
| }
|
| return null;
|
| }
|
| @@ -1440,6 +1447,10 @@ public class Parser {
|
| * @return the compilation unit that was parsed
|
| */
|
| private CompilationUnit parseCompilationUnit() {
|
| + Token firstToken = currentToken.getPrecedingComments();
|
| + if (firstToken == null) {
|
| + firstToken = currentToken;
|
| + }
|
| ScriptTag scriptTag = null;
|
| if (matches(TokenType.SCRIPT_TAG)) {
|
| scriptTag = new ScriptTag(getAndAdvance());
|
| @@ -1511,7 +1522,7 @@ public class Parser {
|
| }
|
| memberStart = currentToken;
|
| }
|
| - return new CompilationUnit(scriptTag, directives, declarations);
|
| + return new CompilationUnit(firstToken, scriptTag, directives, declarations, currentToken);
|
| }
|
|
|
| /**
|
| @@ -1631,7 +1642,7 @@ public class Parser {
|
| SimpleIdentifier name = null;
|
| if (matches(TokenType.PERIOD)) {
|
| period = getAndAdvance();
|
| - name = parseSimpleIdentifier(ParserErrorCode.BUILT_IN_IDENTIFIER_AS_FUNCTION_NAME);
|
| + name = parseSimpleIdentifier();
|
| }
|
| return parseConstructor(
|
| commentAndMetadata,
|
| @@ -1672,9 +1683,10 @@ public class Parser {
|
| SimpleIdentifier name, FormalParameterList parameters) {
|
| boolean bodyAllowed = externalKeyword == null;
|
| Token colon = null;
|
| - List<ConstructorInitializer> initializers = new ArrayList<ConstructorInitializer>();
|
| + List<ConstructorInitializer> initializers = null;
|
| if (matches(TokenType.COLON)) {
|
| colon = getAndAdvance();
|
| + initializers = new ArrayList<ConstructorInitializer>();
|
| do {
|
| if (matches(Keyword.THIS)) {
|
| if (peekMatches(TokenType.OPEN_PAREN)) {
|
| @@ -1695,7 +1707,7 @@ public class Parser {
|
| }
|
| FunctionBody body = parseFunctionBody(true, false);
|
| if (!bodyAllowed && !(body instanceof EmptyFunctionBody)) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY);
|
| }
|
| return new ConstructorDeclaration(
|
| commentAndMetadata.getComment(),
|
| @@ -2060,7 +2072,6 @@ public class Parser {
|
| }
|
| FormalParameterList parameters = parseFormalParameterList();
|
| Token colon = null;
|
| - List<ConstructorInitializer> initializers = new ArrayList<ConstructorInitializer>();
|
| FunctionBody body = parseFunctionBody(true, false);
|
| if (externalKeyword != null && !(body instanceof EmptyFunctionBody)) {
|
| reportError(ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY, body);
|
| @@ -2075,7 +2086,7 @@ public class Parser {
|
| name,
|
| parameters,
|
| colon,
|
| - initializers,
|
| + null,
|
| body);
|
| }
|
|
|
| @@ -2107,7 +2118,7 @@ public class Parser {
|
| if (peekMatchesIdentifier() || peekMatches(TokenType.LT) || peekMatches(Keyword.THIS)) {
|
| type = parseReturnType();
|
| } else if (!optional) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
|
| }
|
| }
|
| return new FinalConstVarOrType(keyword, type);
|
| @@ -2183,15 +2194,15 @@ public class Parser {
|
| */
|
| private FormalParameterList parseFormalParameterList() {
|
| Token leftParenthesis = expect(TokenType.OPEN_PAREN);
|
| - List<FormalParameter> parameters = new ArrayList<FormalParameter>();
|
| if (matches(TokenType.CLOSE_PAREN)) {
|
| - return new FormalParameterList(leftParenthesis, parameters, null, null, getAndAdvance());
|
| + return new FormalParameterList(leftParenthesis, null, null, null, getAndAdvance());
|
| }
|
| //
|
| // Even though it is invalid to have default parameters outside of brackets, required parameters
|
| // inside of brackets, or multiple groups of default and named parameters, we allow all of these
|
| // cases so that we can recover better.
|
| //
|
| + List<FormalParameter> parameters = new ArrayList<FormalParameter>();
|
| List<FormalParameter> normalParameters = new ArrayList<FormalParameter>();
|
| List<FormalParameter> positionalParameters = new ArrayList<FormalParameter>();
|
| List<FormalParameter> namedParameters = new ArrayList<FormalParameter>();
|
| @@ -2328,7 +2339,7 @@ public class Parser {
|
| if (!matches(TokenType.SEMICOLON)) {
|
| if (matchesIdentifier() && peekMatches(Keyword.IN)) {
|
| List<VariableDeclaration> variables = new ArrayList<VariableDeclaration>();
|
| - SimpleIdentifier variableName = parseSimpleIdentifier(ParserErrorCode.BUILT_IN_IDENTIFIER_AS_VARIABLE_NAME);
|
| + SimpleIdentifier variableName = parseSimpleIdentifier();
|
| variables.add(new VariableDeclaration(null, null, variableName, null, null));
|
| variableList = new VariableDeclarationList(null, null, variables);
|
| } else if (isInitializedVariableDeclaration()) {
|
| @@ -2339,16 +2350,18 @@ public class Parser {
|
| if (matches(Keyword.IN)) {
|
| SimpleFormalParameter loopParameter = null;
|
| if (variableList == null) {
|
| - // We found: expression 'in'
|
| - // reportError(ParserErrorCode.?);
|
| + // We found: <expression> 'in'
|
| + reportError(ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH);
|
| } else {
|
| NodeList<VariableDeclaration> variables = variableList.getVariables();
|
| if (variables.size() > 1) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(
|
| + ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH,
|
| + Integer.toString(variables.size()));
|
| }
|
| VariableDeclaration variable = variables.get(0);
|
| if (variable.getInitializer() != null) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH);
|
| }
|
| loopParameter = new SimpleFormalParameter(
|
| null,
|
| @@ -2370,7 +2383,7 @@ public class Parser {
|
| rightParenthesis,
|
| body);
|
| }
|
| - // Ensure that the loop parameter is not final.
|
| + // TODO(brianwilkerson) Ensure that the loop parameter is not final.
|
| // reportError(ParserErrorCode.?);
|
| }
|
| Token leftSeparator = expect(TokenType.SEMICOLON);
|
| @@ -2427,7 +2440,7 @@ public class Parser {
|
| try {
|
| if (matches(TokenType.SEMICOLON)) {
|
| if (!mayBeEmpty) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.MISSING_FUNCTION_BODY);
|
| }
|
| return new EmptyFunctionBody(getAndAdvance());
|
| } else if (matches(TokenType.FUNCTION)) {
|
| @@ -2442,8 +2455,8 @@ public class Parser {
|
| return new BlockFunctionBody(parseBlock());
|
| } else {
|
| // Invalid function body
|
| - // reportError(ParserErrorCode.?);
|
| - return null; //new EmptyFunctionBody(createSyntheticToken(TokenType.SEMICOLON));
|
| + reportError(ParserErrorCode.MISSING_FUNCTION_BODY);
|
| + return new EmptyFunctionBody(createSyntheticToken(TokenType.SEMICOLON));
|
| }
|
| } finally {
|
| inLoop = wasInLoop;
|
| @@ -2470,13 +2483,13 @@ public class Parser {
|
| Token externalKeyword, TypeName returnType) {
|
| Token keyword = null;
|
| boolean isGetter = false;
|
| - if (matches(Keyword.GET)) {
|
| + if (matches(Keyword.GET) && !peekMatches(TokenType.OPEN_PAREN)) {
|
| keyword = getAndAdvance();
|
| isGetter = true;
|
| - } else if (matches(Keyword.SET)) {
|
| + } else if (matches(Keyword.SET) && !peekMatches(TokenType.OPEN_PAREN)) {
|
| keyword = getAndAdvance();
|
| }
|
| - SimpleIdentifier name = parseSimpleIdentifier(ParserErrorCode.BUILT_IN_IDENTIFIER_AS_FUNCTION_NAME);
|
| + SimpleIdentifier name = parseSimpleIdentifier();
|
| FormalParameterList parameters = null;
|
| if (!isGetter) {
|
| parameters = parseFormalParameterList();
|
| @@ -2485,6 +2498,11 @@ public class Parser {
|
| if (externalKeyword == null) {
|
| body = parseFunctionBody(false, false);
|
| }
|
| + if (matches(TokenType.SEMICOLON)) {
|
| + // TODO(brianwilkerson) Improve this error message.
|
| + reportError(ParserErrorCode.UNEXPECTED_TOKEN, currentToken.getLexeme());
|
| + getAndAdvance();
|
| + }
|
| return new FunctionDeclaration(
|
| commentAndMetadata.getComment(),
|
| commentAndMetadata.getMetadata(),
|
| @@ -2524,7 +2542,7 @@ public class Parser {
|
| TypeName returnType = parseOptionalReturnType();
|
| SimpleIdentifier name = null;
|
| if (matchesIdentifier()) {
|
| - name = parseSimpleIdentifier(ParserErrorCode.BUILT_IN_IDENTIFIER_AS_FUNCTION_NAME);
|
| + name = parseSimpleIdentifier();
|
| }
|
| FormalParameterList parameters = parseFormalParameterList();
|
| FunctionBody body = parseFunctionBody(false, true);
|
| @@ -2553,15 +2571,15 @@ public class Parser {
|
| private MethodDeclaration parseGetter(CommentAndMetadata commentAndMetadata,
|
| Token externalKeyword, Token staticKeyword, TypeName returnType) {
|
| Token propertyKeyword = expect(Keyword.GET);
|
| - SimpleIdentifier name = parseSimpleIdentifier(ParserErrorCode.BUILT_IN_IDENTIFIER_AS_FUNCTION_NAME);
|
| + SimpleIdentifier name = parseSimpleIdentifier();
|
| if (matches(TokenType.OPEN_PAREN) && peekMatches(TokenType.CLOSE_PAREN)) {
|
| - // reportError(ParserErrorCode.GETTER_WITH_PARAMETERS);
|
| + reportError(ParserErrorCode.GETTER_WITH_PARAMETERS);
|
| advance();
|
| advance();
|
| }
|
| FunctionBody body = parseFunctionBody(true, false);
|
| if (externalKeyword != null && !(body instanceof EmptyFunctionBody)) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.EXTERNAL_GETTER_WITH_BODY);
|
| }
|
| return new MethodDeclaration(
|
| commentAndMetadata.getComment(),
|
| @@ -2782,23 +2800,13 @@ public class Parser {
|
| leftBracket.setNext(rightBracket);
|
| currentToken.getPrevious().setNext(leftBracket);
|
| currentToken = currentToken.getNext();
|
| - return new ListLiteral(
|
| - modifier,
|
| - typeArguments,
|
| - leftBracket,
|
| - EMPTY_EXPRESSION_LIST,
|
| - rightBracket);
|
| + return new ListLiteral(modifier, typeArguments, leftBracket, null, rightBracket);
|
| }
|
| Token leftBracket = expect(TokenType.OPEN_SQUARE_BRACKET);
|
| if (matches(TokenType.CLOSE_SQUARE_BRACKET)) {
|
| - return new ListLiteral(
|
| - modifier,
|
| - typeArguments,
|
| - leftBracket,
|
| - EMPTY_EXPRESSION_LIST,
|
| - getAndAdvance());
|
| + return new ListLiteral(modifier, typeArguments, leftBracket, null, getAndAdvance());
|
| }
|
| - ArrayList<Expression> elements = new ArrayList<Expression>();
|
| + List<Expression> elements = new ArrayList<Expression>();
|
| elements.add(parseExpression());
|
| while (optional(TokenType.COMMA)) {
|
| if (matches(TokenType.CLOSE_SQUARE_BRACKET)) {
|
| @@ -2896,7 +2904,7 @@ public class Parser {
|
| */
|
| private MapLiteral parseMapLiteral(Token modifier, TypeArgumentList typeArguments) {
|
| Token leftBracket = expect(TokenType.OPEN_CURLY_BRACKET);
|
| - ArrayList<MapLiteralEntry> entries = new ArrayList<MapLiteralEntry>();
|
| + List<MapLiteralEntry> entries = new ArrayList<MapLiteralEntry>();
|
| if (matches(TokenType.CLOSE_CURLY_BRACKET)) {
|
| return new MapLiteral(modifier, typeArguments, leftBracket, entries, getAndAdvance());
|
| }
|
| @@ -2949,7 +2957,7 @@ public class Parser {
|
| if (!peekMatches(TokenType.OPEN_PAREN)) {
|
| returnType = parseReturnType();
|
| }
|
| - SimpleIdentifier name = parseSimpleIdentifier(ParserErrorCode.BUILT_IN_IDENTIFIER_AS_FUNCTION_NAME);
|
| + SimpleIdentifier name = parseSimpleIdentifier();
|
| FormalParameterList parameters = parseFormalParameterList();
|
| FunctionBody body = parseFunctionBody(staticKeyword == null, false);
|
| if (externalKeyword != null && !(body instanceof EmptyFunctionBody)) {
|
| @@ -3000,7 +3008,7 @@ public class Parser {
|
| // reportError(ParserErrorCode.?);
|
| }
|
| Token period = getAndAdvance();
|
| - SimpleIdentifier name = parseSimpleIdentifier(ParserErrorCode.BUILT_IN_IDENTIFIER_AS_FUNCTION_NAME);
|
| + SimpleIdentifier name = parseSimpleIdentifier();
|
| FormalParameterList parameters = parseFormalParameterList();
|
| return parseConstructor(
|
| commentAndMetadata,
|
| @@ -3011,7 +3019,7 @@ public class Parser {
|
| name,
|
| parameters);
|
| }
|
| - SimpleIdentifier name = parseSimpleIdentifier(ParserErrorCode.BUILT_IN_IDENTIFIER_AS_FUNCTION_NAME);
|
| + SimpleIdentifier name = parseSimpleIdentifier();
|
| FormalParameterList parameters = parseFormalParameterList();
|
| if (matches(TokenType.COLON)) {
|
| if (staticKeyword != null) {
|
| @@ -3162,7 +3170,7 @@ public class Parser {
|
| }
|
| return parseVariableDeclarationStatement();
|
| } else if (keyword == Keyword.NEW || keyword == Keyword.TRUE || keyword == Keyword.FALSE
|
| - || keyword == Keyword.NULL || keyword == Keyword.SUPER) {
|
| + || keyword == Keyword.NULL || keyword == Keyword.SUPER || keyword == Keyword.THIS) {
|
| return new ExpressionStatement(parseExpression(), expect(TokenType.SEMICOLON));
|
| } else {
|
| // Expected a statement
|
| @@ -3213,15 +3221,15 @@ public class Parser {
|
| Token thisKeyword = null;
|
| Token period = null;
|
| if (matches(Keyword.THIS)) {
|
| - // Validate that field initializers are only used in constructors.
|
| - // reportError(ParserErrorCode.?);
|
| + // TODO(brianwilkerson) Validate that field initializers are only used in constructors.
|
| + // reportError(ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR);
|
| thisKeyword = getAndAdvance();
|
| period = expect(TokenType.PERIOD);
|
| }
|
| SimpleIdentifier identifier = parseSimpleIdentifier();
|
| if (matches(TokenType.OPEN_PAREN)) {
|
| if (thisKeyword != null) {
|
| - // Decide how to recover from this error.
|
| + // TODO(brianwilkerson) Decide how to recover from this error.
|
| // reportError(ParserErrorCode.?);
|
| }
|
| FormalParameterList parameters = parseFormalParameterList();
|
| @@ -3232,7 +3240,7 @@ public class Parser {
|
| identifier,
|
| parameters);
|
| }
|
| - // Validate that the type is not void because this is not a function signature.
|
| + // TODO(brianwilkerson) Validate that the type is not void because this is not a function signature.
|
| // reportError(ParserErrorCode.?);
|
| if (thisKeyword != null) {
|
| return new FieldFormalParameter(
|
| @@ -3280,7 +3288,7 @@ public class Parser {
|
| FormalParameterList parameters = parseFormalParameterList();
|
| FunctionBody body = parseFunctionBody(true, false);
|
| if (externalKeyword != null && !(body instanceof EmptyFunctionBody)) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY);
|
| }
|
| return new MethodDeclaration(
|
| commentAndMetadata.getComment(),
|
| @@ -3504,6 +3512,12 @@ public class Parser {
|
| return parseListOrMapLiteral(null);
|
| } else if (matches(TokenType.QUESTION)) {
|
| return parseArgumentDefinitionTest();
|
| + } else if (matches(Keyword.VOID)) {
|
| + // Recover from having a return type of "void" where a return type is not expected.
|
| + // TODO(brianwilkerson) Improve this error message.
|
| + reportError(ParserErrorCode.UNEXPECTED_TOKEN, currentToken.getLexeme());
|
| + getAndAdvance();
|
| + return parsePrimaryExpression();
|
| } else {
|
| return createSyntheticIdentifier();
|
| }
|
| @@ -3632,11 +3646,11 @@ public class Parser {
|
| private MethodDeclaration parseSetter(CommentAndMetadata commentAndMetadata,
|
| Token externalKeyword, Token staticKeyword, TypeName returnType) {
|
| Token propertyKeyword = expect(Keyword.SET);
|
| - SimpleIdentifier name = parseSimpleIdentifier(ParserErrorCode.BUILT_IN_IDENTIFIER_AS_FUNCTION_NAME);
|
| + SimpleIdentifier name = parseSimpleIdentifier();
|
| FormalParameterList parameters = parseFormalParameterList();
|
| FunctionBody body = parseFunctionBody(true, false);
|
| if (externalKeyword != null && !(body instanceof EmptyFunctionBody)) {
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.EXTERNAL_SETTER_WITH_BODY);
|
| }
|
| return new MethodDeclaration(
|
| commentAndMetadata.getComment(),
|
| @@ -3730,7 +3744,7 @@ public class Parser {
|
| private Statement parseStatement() {
|
| List<Label> labels = new ArrayList<Label>();
|
| while (matchesIdentifier() && peekMatches(TokenType.COLON)) {
|
| - SimpleIdentifier label = parseSimpleIdentifier(ParserErrorCode.BUILT_IN_IDENTIFIER_AS_LABEL);
|
| + SimpleIdentifier label = parseSimpleIdentifier();
|
| Token colon = expect(TokenType.COLON);
|
| labels.add(new Label(label, colon));
|
| }
|
| @@ -3751,8 +3765,8 @@ public class Parser {
|
| *
|
| * @return the statements that were parsed
|
| */
|
| - private ArrayList<Statement> parseStatements() {
|
| - ArrayList<Statement> statements = new ArrayList<Statement>();
|
| + private List<Statement> parseStatements() {
|
| + List<Statement> statements = new ArrayList<Statement>();
|
| Token statementStart = currentToken;
|
| while (!matches(TokenType.EOF) && !matches(TokenType.CLOSE_CURLY_BRACKET) && !isSwitchMember()) {
|
| statements.add(parseStatement());
|
| @@ -3873,11 +3887,11 @@ public class Parser {
|
| Expression expression = parseExpression();
|
| Token rightParenthesis = expect(TokenType.CLOSE_PAREN);
|
| Token leftBracket = expect(TokenType.OPEN_CURLY_BRACKET);
|
| - ArrayList<SwitchMember> members = new ArrayList<SwitchMember>();
|
| + List<SwitchMember> members = new ArrayList<SwitchMember>();
|
| while (!matches(TokenType.EOF) && !matches(TokenType.CLOSE_CURLY_BRACKET)) {
|
| List<Label> labels = new ArrayList<Label>();
|
| while (matchesIdentifier() && peekMatches(TokenType.COLON)) {
|
| - SimpleIdentifier identifier = parseSimpleIdentifier(ParserErrorCode.BUILT_IN_IDENTIFIER_AS_LABEL);
|
| + SimpleIdentifier identifier = parseSimpleIdentifier();
|
| String label = identifier.getToken().getLexeme();
|
| if (definedLabels.contains(label)) {
|
| reportError(ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT, identifier.getToken());
|
| @@ -3981,7 +3995,7 @@ public class Parser {
|
| private Statement parseTryStatement() {
|
| Token tryKeyword = expect(Keyword.TRY);
|
| Block body = parseBlock();
|
| - ArrayList<CatchClause> catchClauses = new ArrayList<CatchClause>();
|
| + List<CatchClause> catchClauses = new ArrayList<CatchClause>();
|
| Block finallyClause = null;
|
| while (matches(ON) || matches(Keyword.CATCH)) {
|
| Token onKeyword = null;
|
| @@ -4080,7 +4094,7 @@ public class Parser {
|
| */
|
| private TypeArgumentList parseTypeArgumentList() {
|
| Token leftBracket = expect(TokenType.LT);
|
| - ArrayList<TypeName> arguments = new ArrayList<TypeName>();
|
| + List<TypeName> arguments = new ArrayList<TypeName>();
|
| arguments.add(parseTypeName());
|
| while (optional(TokenType.COMMA)) {
|
| arguments.add(parseTypeName());
|
| @@ -4213,7 +4227,7 @@ public class Parser {
|
| new SuperExpression(getAndAdvance())));
|
| } else {
|
| // Invalid operator before 'super'
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.INVALID_OPERATOR_FOR_SUPER, operator.getLexeme());
|
| return new PrefixExpression(operator, new SuperExpression(getAndAdvance()));
|
| }
|
| }
|
| @@ -4236,7 +4250,7 @@ public class Parser {
|
| */
|
| private VariableDeclaration parseVariableDeclaration() {
|
| CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
|
| - SimpleIdentifier name = parseSimpleIdentifier(ParserErrorCode.BUILT_IN_IDENTIFIER_AS_VARIABLE_NAME);
|
| + SimpleIdentifier name = parseSimpleIdentifier();
|
| Token equals = null;
|
| Expression initializer = null;
|
| if (matches(TokenType.EQ)) {
|
| @@ -4697,7 +4711,10 @@ public class Parser {
|
| int currentIndex = index + 1;
|
| if (currentIndex >= length) {
|
| // Illegal escape sequence: no char after escape
|
| - // reportError(ParserErrorCode.?);
|
| + // This cannot actually happen because it would require the escape character to be the last
|
| + // character in the string, but if it were it would escape the closing quote, leaving the
|
| + // string unclosed.
|
| + // reportError(ParserErrorCode.MISSING_CHAR_IN_ESCAPE_SEQUENCE);
|
| return length;
|
| }
|
| currentChar = lexeme.charAt(currentIndex);
|
| @@ -4716,14 +4733,14 @@ public class Parser {
|
| } else if (currentChar == 'x') {
|
| if (currentIndex + 2 >= length) {
|
| // Illegal escape sequence: not enough hex digits
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.INVALID_HEX_ESCAPE);
|
| return length;
|
| }
|
| char firstDigit = lexeme.charAt(currentIndex + 1);
|
| char secondDigit = lexeme.charAt(currentIndex + 2);
|
| if (!isHexDigit(firstDigit) || !isHexDigit(secondDigit)) {
|
| // Illegal escape sequence: invalid hex digit
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.INVALID_HEX_ESCAPE);
|
| } else {
|
| builder.append((char) ((Character.digit(firstDigit, 16) << 4) + Character.digit(
|
| secondDigit,
|
| @@ -4734,7 +4751,7 @@ public class Parser {
|
| currentIndex++;
|
| if (currentIndex >= length) {
|
| // Illegal escape sequence: not enough hex digits
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.INVALID_UNICODE_ESCAPE);
|
| return length;
|
| }
|
| currentChar = lexeme.charAt(currentIndex);
|
| @@ -4742,7 +4759,7 @@ public class Parser {
|
| currentIndex++;
|
| if (currentIndex >= length) {
|
| // Illegal escape sequence: incomplete escape
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.INVALID_UNICODE_ESCAPE);
|
| return length;
|
| }
|
| currentChar = lexeme.charAt(currentIndex);
|
| @@ -4751,7 +4768,7 @@ public class Parser {
|
| while (currentChar != '}') {
|
| if (!isHexDigit(currentChar)) {
|
| // Illegal escape sequence: invalid hex digit
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.INVALID_UNICODE_ESCAPE);
|
| currentIndex++;
|
| while (currentIndex < length && lexeme.charAt(currentIndex) != '}') {
|
| currentIndex++;
|
| @@ -4763,21 +4780,26 @@ public class Parser {
|
| currentIndex++;
|
| if (currentIndex >= length) {
|
| // Illegal escape sequence: incomplete escape
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.INVALID_UNICODE_ESCAPE);
|
| return length;
|
| }
|
| currentChar = lexeme.charAt(currentIndex);
|
| }
|
| if (digitCount < 1 || digitCount > 6) {
|
| // Illegal escape sequence: not enough or too many hex digits
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.INVALID_UNICODE_ESCAPE);
|
| }
|
| - appendScalarValue(builder, value, index, currentIndex);
|
| + appendScalarValue(
|
| + builder,
|
| + lexeme.substring(index, currentIndex + 1),
|
| + value,
|
| + index,
|
| + currentIndex);
|
| return currentIndex + 1;
|
| } else {
|
| if (currentIndex + 3 >= length) {
|
| // Illegal escape sequence: not enough hex digits
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.INVALID_UNICODE_ESCAPE);
|
| return length;
|
| }
|
| char firstDigit = currentChar;
|
| @@ -4787,10 +4809,11 @@ public class Parser {
|
| if (!isHexDigit(firstDigit) || !isHexDigit(secondDigit) || !isHexDigit(thirdDigit)
|
| || !isHexDigit(fourthDigit)) {
|
| // Illegal escape sequence: invalid hex digits
|
| - // reportError(ParserErrorCode.?);
|
| + reportError(ParserErrorCode.INVALID_UNICODE_ESCAPE);
|
| } else {
|
| appendScalarValue(
|
| builder,
|
| + lexeme.substring(index, currentIndex + 1),
|
| ((((((Character.digit(firstDigit, 16) << 4) + Character.digit(secondDigit, 16)) << 4) + Character.digit(
|
| thirdDigit,
|
| 16)) << 4) + Character.digit(fourthDigit, 16)),
|
|
|