Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: pkg/analyzer/lib/src/generated/parser.dart

Issue 137863002: Issue 8742. Preserve leading line comments during java2dart translation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Test for block-style comment translation. Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/analyzer/lib/src/generated/index.dart ('k') | pkg/analyzer/lib/src/generated/resolver.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 // This code was auto-generated, is not intended to be edited, and is subject to 5 // This code was auto-generated, is not intended to be edited, and is subject to
6 // significant change. Please see the README file for more information. 6 // significant change. Please see the README file for more information.
7 7
8 library engine.parser; 8 library engine.parser;
9 9
10 import 'dart:collection'; 10 import 'dart:collection';
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 217
218 ASTNode visitAssertStatement(AssertStatement node) { 218 ASTNode visitAssertStatement(AssertStatement node) {
219 if (identical(_oldNode, node.condition)) { 219 if (identical(_oldNode, node.condition)) {
220 return _parser.parseExpression3(); 220 return _parser.parseExpression3();
221 } 221 }
222 return notAChild(node); 222 return notAChild(node);
223 } 223 }
224 224
225 ASTNode visitAssignmentExpression(AssignmentExpression node) { 225 ASTNode visitAssignmentExpression(AssignmentExpression node) {
226 if (identical(_oldNode, node.leftHandSide)) { 226 if (identical(_oldNode, node.leftHandSide)) {
227 // TODO(brianwilkerson) If the assignment is part of a cascade section, th en we don't have a
228 // single parse method that will work. Otherwise, we can parse a condition al expression, but
229 // need to ensure that the resulting expression is assignable.
230 // return parser.parseConditionalExpression();
227 throw new InsufficientContextException(); 231 throw new InsufficientContextException();
228 } else if (identical(_oldNode, node.rightHandSide)) { 232 } else if (identical(_oldNode, node.rightHandSide)) {
229 if (isCascadeAllowed(node)) { 233 if (isCascadeAllowed(node)) {
230 return _parser.parseExpression3(); 234 return _parser.parseExpression3();
231 } 235 }
232 return _parser.parseExpressionWithoutCascade(); 236 return _parser.parseExpressionWithoutCascade();
233 } 237 }
234 return notAChild(node); 238 return notAChild(node);
235 } 239 }
236 240
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 throw new InsufficientContextException(); 506 throw new InsufficientContextException();
503 } else if (identical(_oldNode, node.identifier)) { 507 } else if (identical(_oldNode, node.identifier)) {
504 return _parser.parseSimpleIdentifier(); 508 return _parser.parseSimpleIdentifier();
505 } else if (identical(_oldNode, node.body)) { 509 } else if (identical(_oldNode, node.body)) {
506 return _parser.parseStatement2(); 510 return _parser.parseStatement2();
507 } 511 }
508 return notAChild(node); 512 return notAChild(node);
509 } 513 }
510 514
511 ASTNode visitFormalParameterList(FormalParameterList node) { 515 ASTNode visitFormalParameterList(FormalParameterList node) {
516 // We don't know which kind of parameter to parse.
512 throw new InsufficientContextException(); 517 throw new InsufficientContextException();
513 } 518 }
514 519
515 ASTNode visitForStatement(ForStatement node) { 520 ASTNode visitForStatement(ForStatement node) {
516 if (identical(_oldNode, node.variables)) { 521 if (identical(_oldNode, node.variables)) {
517 throw new InsufficientContextException(); 522 throw new InsufficientContextException();
518 } else if (identical(_oldNode, node.initialization)) { 523 } else if (identical(_oldNode, node.initialization)) {
519 throw new InsufficientContextException(); 524 throw new InsufficientContextException();
520 } else if (identical(_oldNode, node.condition)) { 525 } else if (identical(_oldNode, node.condition)) {
521 return _parser.parseExpression3(); 526 return _parser.parseExpression3();
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 } else if (node.metadata.contains(_oldNode)) { 754 } else if (node.metadata.contains(_oldNode)) {
750 return _parser.parseAnnotation(); 755 return _parser.parseAnnotation();
751 } else if (identical(_oldNode, node.returnType)) { 756 } else if (identical(_oldNode, node.returnType)) {
752 throw new InsufficientContextException(); 757 throw new InsufficientContextException();
753 } else if (identical(_oldNode, node.name)) { 758 } else if (identical(_oldNode, node.name)) {
754 if (node.operatorKeyword != null) { 759 if (node.operatorKeyword != null) {
755 throw new InsufficientContextException(); 760 throw new InsufficientContextException();
756 } 761 }
757 return _parser.parseSimpleIdentifier(); 762 return _parser.parseSimpleIdentifier();
758 } else if (identical(_oldNode, node.body)) { 763 } else if (identical(_oldNode, node.body)) {
764 //return parser.parseFunctionBody();
759 throw new InsufficientContextException(); 765 throw new InsufficientContextException();
760 } 766 }
761 return notAChild(node); 767 return notAChild(node);
762 } 768 }
763 769
764 ASTNode visitMethodInvocation(MethodInvocation node) { 770 ASTNode visitMethodInvocation(MethodInvocation node) {
765 if (identical(_oldNode, node.target)) { 771 if (identical(_oldNode, node.target)) {
766 throw new IncrementalParseException(); 772 throw new IncrementalParseException();
767 } else if (identical(_oldNode, node.methodName)) { 773 } else if (identical(_oldNode, node.methodName)) {
768 return _parser.parseSimpleIdentifier(); 774 return _parser.parseSimpleIdentifier();
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
1069 } 1075 }
1070 1076
1071 /** 1077 /**
1072 * Return `true` if the given assignment expression can have a cascade express ion on the 1078 * Return `true` if the given assignment expression can have a cascade express ion on the
1073 * right-hand side. 1079 * right-hand side.
1074 * 1080 *
1075 * @param node the assignment expression being tested 1081 * @param node the assignment expression being tested
1076 * @return `true` if the right-hand side can be a cascade expression 1082 * @return `true` if the right-hand side can be a cascade expression
1077 */ 1083 */
1078 bool isCascadeAllowed(AssignmentExpression node) { 1084 bool isCascadeAllowed(AssignmentExpression node) {
1085 // TODO(brianwilkerson) Implement this method.
1079 throw new InsufficientContextException(); 1086 throw new InsufficientContextException();
1080 } 1087 }
1081 1088
1082 /** 1089 /**
1083 * Return `true` if the given throw expression can have a cascade expression. 1090 * Return `true` if the given throw expression can have a cascade expression.
1084 * 1091 *
1085 * @param node the throw expression being tested 1092 * @param node the throw expression being tested
1086 * @return `true` if the expression can be a cascade expression 1093 * @return `true` if the expression can be a cascade expression
1087 */ 1094 */
1088 bool isCascadeAllowed2(ThrowExpression node) { 1095 bool isCascadeAllowed2(ThrowExpression node) {
1096 // TODO(brianwilkerson) Implement this method.
1089 throw new InsufficientContextException(); 1097 throw new InsufficientContextException();
1090 } 1098 }
1091 1099
1092 /** 1100 /**
1093 * Throw an exception indicating that the visited node was not the parent of t he node to be 1101 * Throw an exception indicating that the visited node was not the parent of t he node to be
1094 * replaced. 1102 * replaced.
1095 * 1103 *
1096 * @param visitedNode the visited node that should have been the parent of the node to be replaced 1104 * @param visitedNode the visited node that should have been the parent of the node to be replaced
1097 */ 1105 */
1098 ASTNode notAChild(ASTNode visitedNode) { 1106 ASTNode notAChild(ASTNode visitedNode) {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1180 * @param leftToken the token in the new token stream immediately to the left of the range of 1188 * @param leftToken the token in the new token stream immediately to the left of the range of
1181 * tokens that were inserted 1189 * tokens that were inserted
1182 * @param rightToken the token in the new token stream immediately to the righ t of the range of 1190 * @param rightToken the token in the new token stream immediately to the righ t of the range of
1183 * tokens that were inserted 1191 * tokens that were inserted
1184 * @param originalStart the offset in the original source of the first charact er that was modified 1192 * @param originalStart the offset in the original source of the first charact er that was modified
1185 * @param originalEnd the offset in the original source of the last character that was modified 1193 * @param originalEnd the offset in the original source of the last character that was modified
1186 */ 1194 */
1187 ASTNode reparse(ASTNode originalStructure, Token leftToken, Token rightToken, int originalStart, int originalEnd) { 1195 ASTNode reparse(ASTNode originalStructure, Token leftToken, Token rightToken, int originalStart, int originalEnd) {
1188 ASTNode oldNode = null; 1196 ASTNode oldNode = null;
1189 ASTNode newNode = null; 1197 ASTNode newNode = null;
1198 //
1199 // Find the first token that needs to be re-parsed.
1200 //
1190 Token firstToken = leftToken.next; 1201 Token firstToken = leftToken.next;
1191 if (identical(firstToken, rightToken)) { 1202 if (identical(firstToken, rightToken)) {
1203 // If there are no new tokens, then we need to include at least one copied node in the range.
1192 firstToken = leftToken; 1204 firstToken = leftToken;
1193 } 1205 }
1206 //
1207 // Find the smallest AST node that encompasses the range of re-scanned token s.
1208 //
1194 if (originalEnd < originalStart) { 1209 if (originalEnd < originalStart) {
1195 oldNode = new NodeLocator.con1(originalStart).searchWithin(originalStructu re); 1210 oldNode = new NodeLocator.con1(originalStart).searchWithin(originalStructu re);
1196 } else { 1211 } else {
1197 oldNode = new NodeLocator.con2(originalStart, originalEnd).searchWithin(or iginalStructure); 1212 oldNode = new NodeLocator.con2(originalStart, originalEnd).searchWithin(or iginalStructure);
1198 } 1213 }
1214 //
1215 // Find the token at which parsing is to begin.
1216 //
1199 int originalOffset = oldNode.offset; 1217 int originalOffset = oldNode.offset;
1200 Token parseToken = findTokenAt(firstToken, originalOffset); 1218 Token parseToken = findTokenAt(firstToken, originalOffset);
1201 if (parseToken == null) { 1219 if (parseToken == null) {
1202 return null; 1220 return null;
1203 } 1221 }
1222 //
1223 // Parse the appropriate AST structure starting at the appropriate place.
1224 //
1204 Parser parser = new Parser(_source, _errorListener); 1225 Parser parser = new Parser(_source, _errorListener);
1205 parser.currentToken = parseToken; 1226 parser.currentToken = parseToken;
1206 while (newNode == null) { 1227 while (newNode == null) {
1207 ASTNode parent = oldNode.parent; 1228 ASTNode parent = oldNode.parent;
1208 if (parent == null) { 1229 if (parent == null) {
1209 parseToken = findFirstToken(parseToken); 1230 parseToken = findFirstToken(parseToken);
1210 parser.currentToken = parseToken; 1231 parser.currentToken = parseToken;
1211 return parser.parseCompilationUnit2(); 1232 return parser.parseCompilationUnit2();
1212 } 1233 }
1213 bool advanceToParent = false; 1234 bool advanceToParent = false;
1214 try { 1235 try {
1215 IncrementalParseDispatcher dispatcher = new IncrementalParseDispatcher(p arser, oldNode); 1236 IncrementalParseDispatcher dispatcher = new IncrementalParseDispatcher(p arser, oldNode);
1216 newNode = parent.accept(dispatcher); 1237 newNode = parent.accept(dispatcher);
1238 //
1239 // Validate that the new node can replace the old node.
1240 //
1217 Token mappedToken = _tokenMap.get(oldNode.endToken.next); 1241 Token mappedToken = _tokenMap.get(oldNode.endToken.next);
1218 if (mappedToken == null || mappedToken.offset != newNode.endToken.next.o ffset || newNode.offset != oldNode.offset) { 1242 if (mappedToken == null || mappedToken.offset != newNode.endToken.next.o ffset || newNode.offset != oldNode.offset) {
1219 advanceToParent = true; 1243 advanceToParent = true;
1220 } 1244 }
1221 } on InsufficientContextException catch (exception) { 1245 } on InsufficientContextException catch (exception) {
1222 advanceToParent = true; 1246 advanceToParent = true;
1223 } on JavaException catch (exception) { 1247 } on JavaException catch (exception) {
1224 return null; 1248 return null;
1225 } 1249 }
1226 if (advanceToParent) { 1250 if (advanceToParent) {
1227 newNode = null; 1251 newNode = null;
1228 oldNode = parent; 1252 oldNode = parent;
1229 originalOffset = oldNode.offset; 1253 originalOffset = oldNode.offset;
1230 parseToken = findTokenAt(parseToken, originalOffset); 1254 parseToken = findTokenAt(parseToken, originalOffset);
1231 parser.currentToken = parseToken; 1255 parser.currentToken = parseToken;
1232 } 1256 }
1233 } 1257 }
1234 _updatedNode = newNode; 1258 _updatedNode = newNode;
1259 //
1260 // Replace the old node with the new node in a copy of the original AST stru cture.
1261 //
1235 if (identical(oldNode, originalStructure)) { 1262 if (identical(oldNode, originalStructure)) {
1263 // We ended up re-parsing the whole structure, so there's no need for a co py.
1236 ResolutionCopier.copyResolutionData(oldNode, newNode); 1264 ResolutionCopier.copyResolutionData(oldNode, newNode);
1237 return newNode; 1265 return newNode;
1238 } 1266 }
1239 ResolutionCopier.copyResolutionData(oldNode, newNode); 1267 ResolutionCopier.copyResolutionData(oldNode, newNode);
1240 IncrementalASTCloner cloner = new IncrementalASTCloner(oldNode, newNode, _to kenMap); 1268 IncrementalASTCloner cloner = new IncrementalASTCloner(oldNode, newNode, _to kenMap);
1241 return originalStructure.accept(cloner) as ASTNode; 1269 return originalStructure.accept(cloner) as ASTNode;
1242 } 1270 }
1243 1271
1244 /** 1272 /**
1245 * Return the first (non-EOF) token in the token stream containing the given t oken. 1273 * Return the first (non-EOF) token in the token stream containing the given t oken.
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
1469 * namedArgument 1497 * namedArgument
1470 * | expression 1498 * | expression
1471 * 1499 *
1472 * namedArgument ::= 1500 * namedArgument ::=
1473 * label expression 1501 * label expression
1474 * </pre> 1502 * </pre>
1475 * 1503 *
1476 * @return the argument that was parsed 1504 * @return the argument that was parsed
1477 */ 1505 */
1478 Expression parseArgument() { 1506 Expression parseArgument() {
1507 //
1508 // Both namedArgument and expression can start with an identifier, but only namedArgument can
1509 // have an identifier followed by a colon.
1510 //
1479 if (matchesIdentifier() && matches4(peek(), TokenType.COLON)) { 1511 if (matchesIdentifier() && matches4(peek(), TokenType.COLON)) {
1480 return new NamedExpression(parseLabel(), parseExpression3()); 1512 return new NamedExpression(parseLabel(), parseExpression3());
1481 } else { 1513 } else {
1482 return parseExpression3(); 1514 return parseExpression3();
1483 } 1515 }
1484 } 1516 }
1485 1517
1486 /** 1518 /**
1487 * Parse a list of arguments. 1519 * Parse a list of arguments.
1488 * 1520 *
1489 * <pre> 1521 * <pre>
1490 * arguments ::= 1522 * arguments ::=
1491 * '(' argumentList? ')' 1523 * '(' argumentList? ')'
1492 * 1524 *
1493 * argumentList ::= 1525 * argumentList ::=
1494 * namedArgument (',' namedArgument)* 1526 * namedArgument (',' namedArgument)*
1495 * | expressionList (',' namedArgument)* 1527 * | expressionList (',' namedArgument)*
1496 * </pre> 1528 * </pre>
1497 * 1529 *
1498 * @return the argument list that was parsed 1530 * @return the argument list that was parsed
1499 */ 1531 */
1500 ArgumentList parseArgumentList() { 1532 ArgumentList parseArgumentList() {
1501 Token leftParenthesis = expect2(TokenType.OPEN_PAREN); 1533 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
1502 List<Expression> arguments = new List<Expression>(); 1534 List<Expression> arguments = new List<Expression>();
1503 if (matches5(TokenType.CLOSE_PAREN)) { 1535 if (matches5(TokenType.CLOSE_PAREN)) {
1504 return new ArgumentList(leftParenthesis, arguments, andAdvance); 1536 return new ArgumentList(leftParenthesis, arguments, andAdvance);
1505 } 1537 }
1538 //
1539 // Even though unnamed arguments must all appear before any named arguments, we allow them to
1540 // appear in any order so that we can recover faster.
1541 //
1506 Expression argument = parseArgument(); 1542 Expression argument = parseArgument();
1507 arguments.add(argument); 1543 arguments.add(argument);
1508 bool foundNamedArgument = argument is NamedExpression; 1544 bool foundNamedArgument = argument is NamedExpression;
1509 bool generatedError = false; 1545 bool generatedError = false;
1510 while (optional(TokenType.COMMA)) { 1546 while (optional(TokenType.COMMA)) {
1511 argument = parseArgument(); 1547 argument = parseArgument();
1512 arguments.add(argument); 1548 arguments.add(argument);
1513 if (foundNamedArgument) { 1549 if (foundNamedArgument) {
1514 if (!generatedError && argument is! NamedExpression) { 1550 if (!generatedError && argument is! NamedExpression) {
1551 // Report the error, once, but allow the arguments to be in any order in the AST.
1515 reportError11(ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT, []); 1552 reportError11(ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT, []);
1516 generatedError = true; 1553 generatedError = true;
1517 } 1554 }
1518 } else if (argument is NamedExpression) { 1555 } else if (argument is NamedExpression) {
1519 foundNamedArgument = true; 1556 foundNamedArgument = true;
1520 } 1557 }
1521 } 1558 }
1559 // TODO(brianwilkerson) Recovery: Look at the left parenthesis to see whethe r there is a
1560 // matching right parenthesis. If there is, then we're more likely missing a comma and should
1561 // go back to parsing arguments.
1522 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN); 1562 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
1523 return new ArgumentList(leftParenthesis, arguments, rightParenthesis); 1563 return new ArgumentList(leftParenthesis, arguments, rightParenthesis);
1524 } 1564 }
1525 1565
1526 /** 1566 /**
1527 * Parse a bitwise or expression. 1567 * Parse a bitwise or expression.
1528 * 1568 *
1529 * <pre> 1569 * <pre>
1530 * bitwiseOrExpression ::= 1570 * bitwiseOrExpression ::=
1531 * bitwiseXorExpression ('|' bitwiseXorExpression)* 1571 * bitwiseXorExpression ('|' bitwiseXorExpression)*
(...skipping 29 matching lines...) Expand all
1561 Block parseBlock() { 1601 Block parseBlock() {
1562 Token leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET); 1602 Token leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET);
1563 List<Statement> statements = new List<Statement>(); 1603 List<Statement> statements = new List<Statement>();
1564 Token statementStart = _currentToken; 1604 Token statementStart = _currentToken;
1565 while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRACKET)) { 1605 while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRACKET)) {
1566 Statement statement = parseStatement2(); 1606 Statement statement = parseStatement2();
1567 if (statement != null) { 1607 if (statement != null) {
1568 statements.add(statement); 1608 statements.add(statement);
1569 } 1609 }
1570 if (identical(_currentToken, statementStart)) { 1610 if (identical(_currentToken, statementStart)) {
1611 // Ensure that we are making progress and report an error if we're not.
1571 reportError12(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_current Token.lexeme]); 1612 reportError12(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_current Token.lexeme]);
1572 advance(); 1613 advance();
1573 } 1614 }
1574 statementStart = _currentToken; 1615 statementStart = _currentToken;
1575 } 1616 }
1576 Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET); 1617 Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
1577 return new Block(leftBracket, statements, rightBracket); 1618 return new Block(leftBracket, statements, rightBracket);
1578 } 1619 }
1579 1620
1580 /** 1621 /**
(...skipping 23 matching lines...) Expand all
1604 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) { 1645 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
1605 validateModifiersForOperator(modifiers); 1646 validateModifiersForOperator(modifiers);
1606 return parseOperator(commentAndMetadata, modifiers.externalKeyword, retu rnType); 1647 return parseOperator(commentAndMetadata, modifiers.externalKeyword, retu rnType);
1607 } else if (matchesIdentifier() && matchesAny(peek(), [ 1648 } else if (matchesIdentifier() && matchesAny(peek(), [
1608 TokenType.OPEN_PAREN, 1649 TokenType.OPEN_PAREN,
1609 TokenType.OPEN_CURLY_BRACKET, 1650 TokenType.OPEN_CURLY_BRACKET,
1610 TokenType.FUNCTION])) { 1651 TokenType.FUNCTION])) {
1611 validateModifiersForGetterOrSetterOrMethod(modifiers); 1652 validateModifiersForGetterOrSetterOrMethod(modifiers);
1612 return parseMethodDeclaration(commentAndMetadata, modifiers.externalKeyw ord, modifiers.staticKeyword, returnType); 1653 return parseMethodDeclaration(commentAndMetadata, modifiers.externalKeyw ord, modifiers.staticKeyword, returnType);
1613 } else { 1654 } else {
1655 //
1656 // We have found an error of some kind. Try to recover.
1657 //
1614 if (matchesIdentifier()) { 1658 if (matchesIdentifier()) {
1615 if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMIC OLON])) { 1659 if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMIC OLON])) {
1660 //
1661 // We appear to have a variable declaration with a type of "void".
1662 //
1616 reportError10(ParserErrorCode.VOID_VARIABLE, returnType, []); 1663 reportError10(ParserErrorCode.VOID_VARIABLE, returnType, []);
1617 return parseInitializedIdentifierList(commentAndMetadata, modifiers. staticKeyword, validateModifiersForField(modifiers), returnType); 1664 return parseInitializedIdentifierList(commentAndMetadata, modifiers. staticKeyword, validateModifiersForField(modifiers), returnType);
1618 } 1665 }
1619 } 1666 }
1620 if (isOperator(_currentToken)) { 1667 if (isOperator(_currentToken)) {
1668 //
1669 // We appear to have found an operator declaration without the 'operat or' keyword.
1670 //
1621 validateModifiersForOperator(modifiers); 1671 validateModifiersForOperator(modifiers);
1622 return parseOperator(commentAndMetadata, modifiers.externalKeyword, re turnType); 1672 return parseOperator(commentAndMetadata, modifiers.externalKeyword, re turnType);
1623 } 1673 }
1624 reportError12(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []); 1674 reportError12(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []);
1625 return null; 1675 return null;
1626 } 1676 }
1627 } else if (matches(Keyword.GET) && matchesIdentifier2(peek())) { 1677 } else if (matches(Keyword.GET) && matchesIdentifier2(peek())) {
1628 validateModifiersForGetterOrSetterOrMethod(modifiers); 1678 validateModifiersForGetterOrSetterOrMethod(modifiers);
1629 return parseGetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, null); 1679 return parseGetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, null);
1630 } else if (matches(Keyword.SET) && matchesIdentifier2(peek())) { 1680 } else if (matches(Keyword.SET) && matchesIdentifier2(peek())) {
1631 validateModifiersForGetterOrSetterOrMethod(modifiers); 1681 validateModifiersForGetterOrSetterOrMethod(modifiers);
1632 return parseSetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, null); 1682 return parseSetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, null);
1633 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) { 1683 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
1634 validateModifiersForOperator(modifiers); 1684 validateModifiersForOperator(modifiers);
1635 return parseOperator(commentAndMetadata, modifiers.externalKeyword, null); 1685 return parseOperator(commentAndMetadata, modifiers.externalKeyword, null);
1636 } else if (!matchesIdentifier()) { 1686 } else if (!matchesIdentifier()) {
1637 if (isOperator(_currentToken)) { 1687 if (isOperator(_currentToken)) {
1688 //
1689 // We appear to have found an operator declaration without the 'operator ' keyword.
1690 //
1638 validateModifiersForOperator(modifiers); 1691 validateModifiersForOperator(modifiers);
1639 return parseOperator(commentAndMetadata, modifiers.externalKeyword, null ); 1692 return parseOperator(commentAndMetadata, modifiers.externalKeyword, null );
1640 } 1693 }
1641 reportError12(ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken, []); 1694 reportError12(ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken, []);
1642 return null; 1695 return null;
1643 } else if (matches4(peek(), TokenType.PERIOD) && matchesIdentifier2(peek2(2) ) && matches4(peek2(3), TokenType.OPEN_PAREN)) { 1696 } else if (matches4(peek(), TokenType.PERIOD) && matchesIdentifier2(peek2(2) ) && matches4(peek2(3), TokenType.OPEN_PAREN)) {
1644 return parseConstructor(commentAndMetadata, modifiers.externalKeyword, val idateModifiersForConstructor(modifiers), modifiers.factoryKeyword, parseSimpleId entifier(), andAdvance, parseSimpleIdentifier(), parseFormalParameterList()); 1697 return parseConstructor(commentAndMetadata, modifiers.externalKeyword, val idateModifiersForConstructor(modifiers), modifiers.factoryKeyword, parseSimpleId entifier(), andAdvance, parseSimpleIdentifier(), parseFormalParameterList());
1645 } else if (matches4(peek(), TokenType.OPEN_PAREN)) { 1698 } else if (matches4(peek(), TokenType.OPEN_PAREN)) {
1646 SimpleIdentifier methodName = parseSimpleIdentifier(); 1699 SimpleIdentifier methodName = parseSimpleIdentifier();
1647 FormalParameterList parameters = parseFormalParameterList(); 1700 FormalParameterList parameters = parseFormalParameterList();
(...skipping 14 matching lines...) Expand all
1662 validateModifiersForGetterOrSetterOrMethod(modifiers); 1715 validateModifiersForGetterOrSetterOrMethod(modifiers);
1663 return parseGetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, type); 1716 return parseGetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, type);
1664 } else if (matches(Keyword.SET) && matchesIdentifier2(peek())) { 1717 } else if (matches(Keyword.SET) && matchesIdentifier2(peek())) {
1665 validateModifiersForGetterOrSetterOrMethod(modifiers); 1718 validateModifiersForGetterOrSetterOrMethod(modifiers);
1666 return parseSetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, type); 1719 return parseSetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, type);
1667 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) { 1720 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
1668 validateModifiersForOperator(modifiers); 1721 validateModifiersForOperator(modifiers);
1669 return parseOperator(commentAndMetadata, modifiers.externalKeyword, type); 1722 return parseOperator(commentAndMetadata, modifiers.externalKeyword, type);
1670 } else if (!matchesIdentifier()) { 1723 } else if (!matchesIdentifier()) {
1671 if (matches5(TokenType.CLOSE_CURLY_BRACKET)) { 1724 if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
1725 //
1726 // We appear to have found an incomplete declaration at the end of the c lass. At this point
1727 // it consists of a type name, so we'll treat it as a field declaration with a missing
1728 // field name and semicolon.
1729 //
1672 return parseInitializedIdentifierList(commentAndMetadata, modifiers.stat icKeyword, validateModifiersForField(modifiers), type); 1730 return parseInitializedIdentifierList(commentAndMetadata, modifiers.stat icKeyword, validateModifiersForField(modifiers), type);
1673 } 1731 }
1674 if (isOperator(_currentToken)) { 1732 if (isOperator(_currentToken)) {
1733 //
1734 // We appear to have found an operator declaration without the 'operator ' keyword.
1735 //
1675 validateModifiersForOperator(modifiers); 1736 validateModifiersForOperator(modifiers);
1676 return parseOperator(commentAndMetadata, modifiers.externalKeyword, type ); 1737 return parseOperator(commentAndMetadata, modifiers.externalKeyword, type );
1677 } 1738 }
1739 //
1740 // We appear to have found an incomplete declaration before another declar ation.
1741 // At this point it consists of a type name, so we'll treat it as a field declaration
1742 // with a missing field name and semicolon.
1743 //
1678 reportError12(ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken, []); 1744 reportError12(ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken, []);
1679 try { 1745 try {
1680 lockErrorListener(); 1746 lockErrorListener();
1681 return parseInitializedIdentifierList(commentAndMetadata, modifiers.stat icKeyword, validateModifiersForField(modifiers), type); 1747 return parseInitializedIdentifierList(commentAndMetadata, modifiers.stat icKeyword, validateModifiersForField(modifiers), type);
1682 } finally { 1748 } finally {
1683 unlockErrorListener(); 1749 unlockErrorListener();
1684 } 1750 }
1685 } else if (matches4(peek(), TokenType.OPEN_PAREN)) { 1751 } else if (matches4(peek(), TokenType.OPEN_PAREN)) {
1686 SimpleIdentifier methodName = parseSimpleIdentifier(); 1752 SimpleIdentifier methodName = parseSimpleIdentifier();
1687 FormalParameterList parameters = parseFormalParameterList(); 1753 FormalParameterList parameters = parseFormalParameterList();
(...skipping 29 matching lines...) Expand all
1717 * </pre> 1783 * </pre>
1718 * 1784 *
1719 * @return the compilation unit that was parsed 1785 * @return the compilation unit that was parsed
1720 */ 1786 */
1721 CompilationUnit parseCompilationUnit2() { 1787 CompilationUnit parseCompilationUnit2() {
1722 Token firstToken = _currentToken; 1788 Token firstToken = _currentToken;
1723 ScriptTag scriptTag = null; 1789 ScriptTag scriptTag = null;
1724 if (matches5(TokenType.SCRIPT_TAG)) { 1790 if (matches5(TokenType.SCRIPT_TAG)) {
1725 scriptTag = new ScriptTag(andAdvance); 1791 scriptTag = new ScriptTag(andAdvance);
1726 } 1792 }
1793 //
1794 // Even though all directives must appear before declarations and must occur in a given order,
1795 // we allow directives and declarations to occur in any order so that we can recover better.
1796 //
1727 bool libraryDirectiveFound = false; 1797 bool libraryDirectiveFound = false;
1728 bool partOfDirectiveFound = false; 1798 bool partOfDirectiveFound = false;
1729 bool partDirectiveFound = false; 1799 bool partDirectiveFound = false;
1730 bool directiveFoundAfterDeclaration = false; 1800 bool directiveFoundAfterDeclaration = false;
1731 List<Directive> directives = new List<Directive>(); 1801 List<Directive> directives = new List<Directive>();
1732 List<CompilationUnitMember> declarations = new List<CompilationUnitMember>() ; 1802 List<CompilationUnitMember> declarations = new List<CompilationUnitMember>() ;
1733 Token memberStart = _currentToken; 1803 Token memberStart = _currentToken;
1734 while (!matches5(TokenType.EOF)) { 1804 while (!matches5(TokenType.EOF)) {
1735 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata(); 1805 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
1736 if ((matches(Keyword.IMPORT) || matches(Keyword.EXPORT) || matches(Keyword .LIBRARY) || matches(Keyword.PART)) && !matches4(peek(), TokenType.PERIOD) && !m atches4(peek(), TokenType.LT) && !matches4(peek(), TokenType.OPEN_PAREN)) { 1806 if ((matches(Keyword.IMPORT) || matches(Keyword.EXPORT) || matches(Keyword .LIBRARY) || matches(Keyword.PART)) && !matches4(peek(), TokenType.PERIOD) && !m atches4(peek(), TokenType.LT) && !matches4(peek(), TokenType.OPEN_PAREN)) {
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1848 * </pre> 1918 * </pre>
1849 * 1919 *
1850 * @return the expression that was parsed 1920 * @return the expression that was parsed
1851 */ 1921 */
1852 Expression parseExpression3() { 1922 Expression parseExpression3() {
1853 if (matches(Keyword.THROW)) { 1923 if (matches(Keyword.THROW)) {
1854 return parseThrowExpression(); 1924 return parseThrowExpression();
1855 } else if (matches(Keyword.RETHROW)) { 1925 } else if (matches(Keyword.RETHROW)) {
1856 return parseRethrowExpression(); 1926 return parseRethrowExpression();
1857 } 1927 }
1928 //
1929 // assignableExpression is a subset of conditionalExpression, so we can pars e a conditional
1930 // expression and then determine whether it is followed by an assignmentOper ator, checking for
1931 // conformance to the restricted grammar after making that determination.
1932 //
1858 Expression expression = parseConditionalExpression(); 1933 Expression expression = parseConditionalExpression();
1859 TokenType tokenType = _currentToken.type; 1934 TokenType tokenType = _currentToken.type;
1860 if (identical(tokenType, TokenType.PERIOD_PERIOD)) { 1935 if (identical(tokenType, TokenType.PERIOD_PERIOD)) {
1861 List<Expression> cascadeSections = new List<Expression>(); 1936 List<Expression> cascadeSections = new List<Expression>();
1862 while (identical(tokenType, TokenType.PERIOD_PERIOD)) { 1937 while (identical(tokenType, TokenType.PERIOD_PERIOD)) {
1863 Expression section = parseCascadeSection(); 1938 Expression section = parseCascadeSection();
1864 if (section != null) { 1939 if (section != null) {
1865 cascadeSections.add(section); 1940 cascadeSections.add(section);
1866 } 1941 }
1867 tokenType = _currentToken.type; 1942 tokenType = _currentToken.type;
(...skipping 18 matching lines...) Expand all
1886 * </pre> 1961 * </pre>
1887 * 1962 *
1888 * @return the expression that was parsed 1963 * @return the expression that was parsed
1889 */ 1964 */
1890 Expression parseExpressionWithoutCascade() { 1965 Expression parseExpressionWithoutCascade() {
1891 if (matches(Keyword.THROW)) { 1966 if (matches(Keyword.THROW)) {
1892 return parseThrowExpressionWithoutCascade(); 1967 return parseThrowExpressionWithoutCascade();
1893 } else if (matches(Keyword.RETHROW)) { 1968 } else if (matches(Keyword.RETHROW)) {
1894 return parseRethrowExpression(); 1969 return parseRethrowExpression();
1895 } 1970 }
1971 //
1972 // assignableExpression is a subset of conditionalExpression, so we can pars e a conditional
1973 // expression and then determine whether it is followed by an assignmentOper ator, checking for
1974 // conformance to the restricted grammar after making that determination.
1975 //
1896 Expression expression = parseConditionalExpression(); 1976 Expression expression = parseConditionalExpression();
1897 if (_currentToken.type.isAssignmentOperator) { 1977 if (_currentToken.type.isAssignmentOperator) {
1898 Token operator = andAdvance; 1978 Token operator = andAdvance;
1899 ensureAssignable(expression); 1979 ensureAssignable(expression);
1900 expression = new AssignmentExpression(expression, operator, parseExpressio nWithoutCascade()); 1980 expression = new AssignmentExpression(expression, operator, parseExpressio nWithoutCascade());
1901 } 1981 }
1902 return expression; 1982 return expression;
1903 } 1983 }
1904 1984
1905 /** 1985 /**
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1941 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}' 2021 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
1942 * </pre> 2022 * </pre>
1943 * 2023 *
1944 * @return the formal parameters that were parsed 2024 * @return the formal parameters that were parsed
1945 */ 2025 */
1946 FormalParameterList parseFormalParameterList() { 2026 FormalParameterList parseFormalParameterList() {
1947 Token leftParenthesis = expect2(TokenType.OPEN_PAREN); 2027 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
1948 if (matches5(TokenType.CLOSE_PAREN)) { 2028 if (matches5(TokenType.CLOSE_PAREN)) {
1949 return new FormalParameterList(leftParenthesis, null, null, null, andAdvan ce); 2029 return new FormalParameterList(leftParenthesis, null, null, null, andAdvan ce);
1950 } 2030 }
2031 //
2032 // Even though it is invalid to have default parameters outside of brackets, required parameters
2033 // inside of brackets, or multiple groups of default and named parameters, w e allow all of these
2034 // cases so that we can recover better.
2035 //
1951 List<FormalParameter> parameters = new List<FormalParameter>(); 2036 List<FormalParameter> parameters = new List<FormalParameter>();
1952 List<FormalParameter> normalParameters = new List<FormalParameter>(); 2037 List<FormalParameter> normalParameters = new List<FormalParameter>();
1953 List<FormalParameter> positionalParameters = new List<FormalParameter>(); 2038 List<FormalParameter> positionalParameters = new List<FormalParameter>();
1954 List<FormalParameter> namedParameters = new List<FormalParameter>(); 2039 List<FormalParameter> namedParameters = new List<FormalParameter>();
1955 List<FormalParameter> currentParameters = normalParameters; 2040 List<FormalParameter> currentParameters = normalParameters;
1956 Token leftSquareBracket = null; 2041 Token leftSquareBracket = null;
1957 Token rightSquareBracket = null; 2042 Token rightSquareBracket = null;
1958 Token leftCurlyBracket = null; 2043 Token leftCurlyBracket = null;
1959 Token rightCurlyBracket = null; 2044 Token rightCurlyBracket = null;
1960 ParameterKind kind = ParameterKind.REQUIRED; 2045 ParameterKind kind = ParameterKind.REQUIRED;
1961 bool firstParameter = true; 2046 bool firstParameter = true;
1962 bool reportedMuliplePositionalGroups = false; 2047 bool reportedMuliplePositionalGroups = false;
1963 bool reportedMulipleNamedGroups = false; 2048 bool reportedMulipleNamedGroups = false;
1964 bool reportedMixedGroups = false; 2049 bool reportedMixedGroups = false;
1965 bool wasOptionalParameter = false; 2050 bool wasOptionalParameter = false;
1966 Token initialToken = null; 2051 Token initialToken = null;
1967 do { 2052 do {
1968 if (firstParameter) { 2053 if (firstParameter) {
1969 firstParameter = false; 2054 firstParameter = false;
1970 } else if (!optional(TokenType.COMMA)) { 2055 } else if (!optional(TokenType.COMMA)) {
2056 // TODO(brianwilkerson) The token is wrong, we need to recover from this case.
1971 if (getEndToken(leftParenthesis) != null) { 2057 if (getEndToken(leftParenthesis) != null) {
1972 reportError11(ParserErrorCode.EXPECTED_TOKEN, [TokenType.COMMA.lexeme] ); 2058 reportError11(ParserErrorCode.EXPECTED_TOKEN, [TokenType.COMMA.lexeme] );
1973 } else { 2059 } else {
1974 reportError12(ParserErrorCode.MISSING_CLOSING_PARENTHESIS, _currentTok en.previous, []); 2060 reportError12(ParserErrorCode.MISSING_CLOSING_PARENTHESIS, _currentTok en.previous, []);
1975 break; 2061 break;
1976 } 2062 }
1977 } 2063 }
1978 initialToken = _currentToken; 2064 initialToken = _currentToken;
2065 //
2066 // Handle the beginning of parameter groups.
2067 //
1979 if (matches5(TokenType.OPEN_SQUARE_BRACKET)) { 2068 if (matches5(TokenType.OPEN_SQUARE_BRACKET)) {
1980 wasOptionalParameter = true; 2069 wasOptionalParameter = true;
1981 if (leftSquareBracket != null && !reportedMuliplePositionalGroups) { 2070 if (leftSquareBracket != null && !reportedMuliplePositionalGroups) {
1982 reportError11(ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS, [] ); 2071 reportError11(ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS, [] );
1983 reportedMuliplePositionalGroups = true; 2072 reportedMuliplePositionalGroups = true;
1984 } 2073 }
1985 if (leftCurlyBracket != null && !reportedMixedGroups) { 2074 if (leftCurlyBracket != null && !reportedMixedGroups) {
1986 reportError11(ParserErrorCode.MIXED_PARAMETER_GROUPS, []); 2075 reportError11(ParserErrorCode.MIXED_PARAMETER_GROUPS, []);
1987 reportedMixedGroups = true; 2076 reportedMixedGroups = true;
1988 } 2077 }
1989 leftSquareBracket = andAdvance; 2078 leftSquareBracket = andAdvance;
1990 currentParameters = positionalParameters; 2079 currentParameters = positionalParameters;
1991 kind = ParameterKind.POSITIONAL; 2080 kind = ParameterKind.POSITIONAL;
1992 } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) { 2081 } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
1993 wasOptionalParameter = true; 2082 wasOptionalParameter = true;
1994 if (leftCurlyBracket != null && !reportedMulipleNamedGroups) { 2083 if (leftCurlyBracket != null && !reportedMulipleNamedGroups) {
1995 reportError11(ParserErrorCode.MULTIPLE_NAMED_PARAMETER_GROUPS, []); 2084 reportError11(ParserErrorCode.MULTIPLE_NAMED_PARAMETER_GROUPS, []);
1996 reportedMulipleNamedGroups = true; 2085 reportedMulipleNamedGroups = true;
1997 } 2086 }
1998 if (leftSquareBracket != null && !reportedMixedGroups) { 2087 if (leftSquareBracket != null && !reportedMixedGroups) {
1999 reportError11(ParserErrorCode.MIXED_PARAMETER_GROUPS, []); 2088 reportError11(ParserErrorCode.MIXED_PARAMETER_GROUPS, []);
2000 reportedMixedGroups = true; 2089 reportedMixedGroups = true;
2001 } 2090 }
2002 leftCurlyBracket = andAdvance; 2091 leftCurlyBracket = andAdvance;
2003 currentParameters = namedParameters; 2092 currentParameters = namedParameters;
2004 kind = ParameterKind.NAMED; 2093 kind = ParameterKind.NAMED;
2005 } 2094 }
2095 //
2096 // Parse and record the parameter.
2097 //
2006 FormalParameter parameter = parseFormalParameter(kind); 2098 FormalParameter parameter = parseFormalParameter(kind);
2007 parameters.add(parameter); 2099 parameters.add(parameter);
2008 currentParameters.add(parameter); 2100 currentParameters.add(parameter);
2009 if (identical(kind, ParameterKind.REQUIRED) && wasOptionalParameter) { 2101 if (identical(kind, ParameterKind.REQUIRED) && wasOptionalParameter) {
2010 reportError10(ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, paramet er, []); 2102 reportError10(ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, paramet er, []);
2011 } 2103 }
2104 //
2105 // Handle the end of parameter groups.
2106 //
2107 // TODO(brianwilkerson) Improve the detection and reporting of missing and mismatched delimiters.
2012 if (matches5(TokenType.CLOSE_SQUARE_BRACKET)) { 2108 if (matches5(TokenType.CLOSE_SQUARE_BRACKET)) {
2013 rightSquareBracket = andAdvance; 2109 rightSquareBracket = andAdvance;
2014 currentParameters = normalParameters; 2110 currentParameters = normalParameters;
2015 if (leftSquareBracket == null) { 2111 if (leftSquareBracket == null) {
2016 if (leftCurlyBracket != null) { 2112 if (leftCurlyBracket != null) {
2017 reportError11(ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, ["}"]); 2113 reportError11(ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, ["}"]);
2018 rightCurlyBracket = rightSquareBracket; 2114 rightCurlyBracket = rightSquareBracket;
2019 rightSquareBracket = null; 2115 rightSquareBracket = null;
2020 } else { 2116 } else {
2021 reportError11(ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GR OUP, ["["]); 2117 reportError11(ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GR OUP, ["["]);
2022 } 2118 }
2023 } 2119 }
2024 kind = ParameterKind.REQUIRED; 2120 kind = ParameterKind.REQUIRED;
2025 } else if (matches5(TokenType.CLOSE_CURLY_BRACKET)) { 2121 } else if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
2026 rightCurlyBracket = andAdvance; 2122 rightCurlyBracket = andAdvance;
2027 currentParameters = normalParameters; 2123 currentParameters = normalParameters;
2028 if (leftCurlyBracket == null) { 2124 if (leftCurlyBracket == null) {
2029 if (leftSquareBracket != null) { 2125 if (leftSquareBracket != null) {
2030 reportError11(ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, ["]"]); 2126 reportError11(ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, ["]"]);
2031 rightSquareBracket = rightCurlyBracket; 2127 rightSquareBracket = rightCurlyBracket;
2032 rightCurlyBracket = null; 2128 rightCurlyBracket = null;
2033 } else { 2129 } else {
2034 reportError11(ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GR OUP, ["{"]); 2130 reportError11(ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GR OUP, ["{"]);
2035 } 2131 }
2036 } 2132 }
2037 kind = ParameterKind.REQUIRED; 2133 kind = ParameterKind.REQUIRED;
2038 } 2134 }
2039 } while (!matches5(TokenType.CLOSE_PAREN) && initialToken != _currentToken); 2135 } while (!matches5(TokenType.CLOSE_PAREN) && initialToken != _currentToken);
2040 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN); 2136 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
2137 //
2138 // Check that the groups were closed correctly.
2139 //
2041 if (leftSquareBracket != null && rightSquareBracket == null) { 2140 if (leftSquareBracket != null && rightSquareBracket == null) {
2042 reportError11(ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["]" ]); 2141 reportError11(ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["]" ]);
2043 } 2142 }
2044 if (leftCurlyBracket != null && rightCurlyBracket == null) { 2143 if (leftCurlyBracket != null && rightCurlyBracket == null) {
2045 reportError11(ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["}" ]); 2144 reportError11(ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["}" ]);
2046 } 2145 }
2146 //
2147 // Build the parameter list.
2148 //
2047 if (leftSquareBracket == null) { 2149 if (leftSquareBracket == null) {
2048 leftSquareBracket = leftCurlyBracket; 2150 leftSquareBracket = leftCurlyBracket;
2049 } 2151 }
2050 if (rightSquareBracket == null) { 2152 if (rightSquareBracket == null) {
2051 rightSquareBracket = rightCurlyBracket; 2153 rightSquareBracket = rightCurlyBracket;
2052 } 2154 }
2053 return new FormalParameterList(leftParenthesis, parameters, leftSquareBracke t, rightSquareBracket, rightParenthesis); 2155 return new FormalParameterList(leftParenthesis, parameters, leftSquareBracke t, rightSquareBracket, rightParenthesis);
2054 } 2156 }
2055 2157
2056 /** 2158 /**
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after
2535 2637
2536 /** 2638 /**
2537 * Return `true` if the current token could be the start of a compilation unit member. This 2639 * Return `true` if the current token could be the start of a compilation unit member. This
2538 * method is used for recovery purposes to decide when to stop skipping tokens after finding an 2640 * method is used for recovery purposes to decide when to stop skipping tokens after finding an
2539 * error while parsing a compilation unit member. 2641 * error while parsing a compilation unit member.
2540 * 2642 *
2541 * @return `true` if the current token could be the start of a compilation uni t member 2643 * @return `true` if the current token could be the start of a compilation uni t member
2542 */ 2644 */
2543 bool couldBeStartOfCompilationUnitMember() { 2645 bool couldBeStartOfCompilationUnitMember() {
2544 if ((matches(Keyword.IMPORT) || matches(Keyword.EXPORT) || matches(Keyword.L IBRARY) || matches(Keyword.PART)) && !matches4(peek(), TokenType.PERIOD) && !mat ches4(peek(), TokenType.LT)) { 2646 if ((matches(Keyword.IMPORT) || matches(Keyword.EXPORT) || matches(Keyword.L IBRARY) || matches(Keyword.PART)) && !matches4(peek(), TokenType.PERIOD) && !mat ches4(peek(), TokenType.LT)) {
2647 // This looks like the start of a directive
2545 return true; 2648 return true;
2546 } else if (matches(Keyword.CLASS)) { 2649 } else if (matches(Keyword.CLASS)) {
2650 // This looks like the start of a class definition
2547 return true; 2651 return true;
2548 } else if (matches(Keyword.TYPEDEF) && !matches4(peek(), TokenType.PERIOD) & & !matches4(peek(), TokenType.LT)) { 2652 } else if (matches(Keyword.TYPEDEF) && !matches4(peek(), TokenType.PERIOD) & & !matches4(peek(), TokenType.LT)) {
2653 // This looks like the start of a typedef
2549 return true; 2654 return true;
2550 } else if (matches(Keyword.VOID) || ((matches(Keyword.GET) || matches(Keywor d.SET)) && matchesIdentifier2(peek())) || (matches(Keyword.OPERATOR) && isOperat or(peek()))) { 2655 } else if (matches(Keyword.VOID) || ((matches(Keyword.GET) || matches(Keywor d.SET)) && matchesIdentifier2(peek())) || (matches(Keyword.OPERATOR) && isOperat or(peek()))) {
2656 // This looks like the start of a function
2551 return true; 2657 return true;
2552 } else if (matchesIdentifier()) { 2658 } else if (matchesIdentifier()) {
2553 if (matches4(peek(), TokenType.OPEN_PAREN)) { 2659 if (matches4(peek(), TokenType.OPEN_PAREN)) {
2660 // This looks like the start of a function
2554 return true; 2661 return true;
2555 } 2662 }
2556 Token token = skipReturnType(_currentToken); 2663 Token token = skipReturnType(_currentToken);
2557 if (token == null) { 2664 if (token == null) {
2558 return false; 2665 return false;
2559 } 2666 }
2560 if (matches(Keyword.GET) || matches(Keyword.SET) || (matches(Keyword.OPERA TOR) && isOperator(peek())) || matchesIdentifier()) { 2667 if (matches(Keyword.GET) || matches(Keyword.SET) || (matches(Keyword.OPERA TOR) && isOperator(peek())) || matchesIdentifier()) {
2561 return true; 2668 return true;
2562 } 2669 }
2563 } 2670 }
2564 return false; 2671 return false;
2565 } 2672 }
2566 2673
2567 /** 2674 /**
2568 * Create a synthetic identifier. 2675 * Create a synthetic identifier.
2569 * 2676 *
2570 * @return the synthetic identifier that was created 2677 * @return the synthetic identifier that was created
2571 */ 2678 */
2572 SimpleIdentifier createSyntheticIdentifier() { 2679 SimpleIdentifier createSyntheticIdentifier() {
2573 Token syntheticToken; 2680 Token syntheticToken;
2574 if (identical(_currentToken.type, TokenType.KEYWORD)) { 2681 if (identical(_currentToken.type, TokenType.KEYWORD)) {
2682 // Consider current keyword token as an identifier.
2683 // It is not always true, e.g. "^is T" where "^" is place the place for sy nthetic identifier.
2684 // By creating SyntheticStringToken we can distinguish a real identifier f rom synthetic.
2685 // In the code completion behavior will depend on a cursor position - befo re or on "is".
2575 syntheticToken = injectToken(new SyntheticStringToken(TokenType.IDENTIFIER , _currentToken.lexeme, _currentToken.offset)); 2686 syntheticToken = injectToken(new SyntheticStringToken(TokenType.IDENTIFIER , _currentToken.lexeme, _currentToken.offset));
2576 } else { 2687 } else {
2577 syntheticToken = createSyntheticToken2(TokenType.IDENTIFIER); 2688 syntheticToken = createSyntheticToken2(TokenType.IDENTIFIER);
2578 } 2689 }
2579 return new SimpleIdentifier(syntheticToken); 2690 return new SimpleIdentifier(syntheticToken);
2580 } 2691 }
2581 2692
2582 /** 2693 /**
2583 * Create a synthetic string literal. 2694 * Create a synthetic string literal.
2584 * 2695 *
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2626 * If the current token is a keyword matching the given string, return it afte r advancing to the 2737 * If the current token is a keyword matching the given string, return it afte r advancing to the
2627 * next token. Otherwise report an error and return the current token without advancing. 2738 * next token. Otherwise report an error and return the current token without advancing.
2628 * 2739 *
2629 * @param keyword the keyword that is expected 2740 * @param keyword the keyword that is expected
2630 * @return the token that matched the given type 2741 * @return the token that matched the given type
2631 */ 2742 */
2632 Token expect(Keyword keyword) { 2743 Token expect(Keyword keyword) {
2633 if (matches(keyword)) { 2744 if (matches(keyword)) {
2634 return andAdvance; 2745 return andAdvance;
2635 } 2746 }
2747 // Remove uses of this method in favor of matches?
2748 // Pass in the error code to use to report the error?
2636 reportError11(ParserErrorCode.EXPECTED_TOKEN, [keyword.syntax]); 2749 reportError11(ParserErrorCode.EXPECTED_TOKEN, [keyword.syntax]);
2637 return _currentToken; 2750 return _currentToken;
2638 } 2751 }
2639 2752
2640 /** 2753 /**
2641 * If the current token has the expected type, return it after advancing to th e next token. 2754 * If the current token has the expected type, return it after advancing to th e next token.
2642 * Otherwise report an error and return the current token without advancing. 2755 * Otherwise report an error and return the current token without advancing.
2643 * 2756 *
2644 * @param type the type of token that is expected 2757 * @param type the type of token that is expected
2645 * @return the token that matched the given type 2758 * @return the token that matched the given type
2646 */ 2759 */
2647 Token expect2(TokenType type) { 2760 Token expect2(TokenType type) {
2648 if (matches5(type)) { 2761 if (matches5(type)) {
2649 return andAdvance; 2762 return andAdvance;
2650 } 2763 }
2764 // Remove uses of this method in favor of matches?
2765 // Pass in the error code to use to report the error?
2651 if (identical(type, TokenType.SEMICOLON)) { 2766 if (identical(type, TokenType.SEMICOLON)) {
2652 reportError12(ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, [typ e.lexeme]); 2767 reportError12(ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, [typ e.lexeme]);
2653 } else { 2768 } else {
2654 reportError11(ParserErrorCode.EXPECTED_TOKEN, [type.lexeme]); 2769 reportError11(ParserErrorCode.EXPECTED_TOKEN, [type.lexeme]);
2655 } 2770 }
2656 return _currentToken; 2771 return _currentToken;
2657 } 2772 }
2658 2773
2659 /** 2774 /**
2660 * Search the given list of ranges for a range that contains the given index. Return the range 2775 * Search the given list of ranges for a range that contains the given index. Return the range
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
2779 * Return `true` if the current token appears to be the beginning of a functio n declaration. 2894 * Return `true` if the current token appears to be the beginning of a functio n declaration.
2780 * 2895 *
2781 * @return `true` if the current token appears to be the beginning of a functi on declaration 2896 * @return `true` if the current token appears to be the beginning of a functi on declaration
2782 */ 2897 */
2783 bool isFunctionDeclaration() { 2898 bool isFunctionDeclaration() {
2784 if (matches(Keyword.VOID)) { 2899 if (matches(Keyword.VOID)) {
2785 return true; 2900 return true;
2786 } 2901 }
2787 Token afterReturnType = skipTypeName(_currentToken); 2902 Token afterReturnType = skipTypeName(_currentToken);
2788 if (afterReturnType == null) { 2903 if (afterReturnType == null) {
2904 // There was no return type, but it is optional, so go back to where we st arted.
2789 afterReturnType = _currentToken; 2905 afterReturnType = _currentToken;
2790 } 2906 }
2791 Token afterIdentifier = skipSimpleIdentifier(afterReturnType); 2907 Token afterIdentifier = skipSimpleIdentifier(afterReturnType);
2792 if (afterIdentifier == null) { 2908 if (afterIdentifier == null) {
2909 // It's possible that we parsed the function name as if it were a type nam e, so see whether
2910 // it makes sense if we assume that there is no type.
2793 afterIdentifier = skipSimpleIdentifier(_currentToken); 2911 afterIdentifier = skipSimpleIdentifier(_currentToken);
2794 } 2912 }
2795 if (afterIdentifier == null) { 2913 if (afterIdentifier == null) {
2796 return false; 2914 return false;
2797 } 2915 }
2798 if (isFunctionExpression(afterIdentifier)) { 2916 if (isFunctionExpression(afterIdentifier)) {
2799 return true; 2917 return true;
2800 } 2918 }
2919 // It's possible that we have found a getter. While this isn't valid at this point we test for
2920 // it in order to recover better.
2801 if (matches(Keyword.GET)) { 2921 if (matches(Keyword.GET)) {
2802 Token afterName = skipSimpleIdentifier(_currentToken.next); 2922 Token afterName = skipSimpleIdentifier(_currentToken.next);
2803 if (afterName == null) { 2923 if (afterName == null) {
2804 return false; 2924 return false;
2805 } 2925 }
2806 return matches4(afterName, TokenType.FUNCTION) || matches4(afterName, Toke nType.OPEN_CURLY_BRACKET); 2926 return matches4(afterName, TokenType.FUNCTION) || matches4(afterName, Toke nType.OPEN_CURLY_BRACKET);
2807 } 2927 }
2808 return false; 2928 return false;
2809 } 2929 }
2810 2930
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2853 * 2973 *
2854 * initializedIdentifier ::= 2974 * initializedIdentifier ::=
2855 * identifier ('=' expression)? 2975 * identifier ('=' expression)?
2856 * </pre> 2976 * </pre>
2857 * 2977 *
2858 * @return `true` if the current token is the first token in an initialized va riable 2978 * @return `true` if the current token is the first token in an initialized va riable
2859 * declaration 2979 * declaration
2860 */ 2980 */
2861 bool isInitializedVariableDeclaration() { 2981 bool isInitializedVariableDeclaration() {
2862 if (matches(Keyword.FINAL) || matches(Keyword.VAR)) { 2982 if (matches(Keyword.FINAL) || matches(Keyword.VAR)) {
2983 // An expression cannot start with a keyword other than 'const', 'rethrow' , or 'throw'.
2863 return true; 2984 return true;
2864 } 2985 }
2865 if (matches(Keyword.CONST)) { 2986 if (matches(Keyword.CONST)) {
2987 // Look to see whether we might be at the start of a list or map literal, otherwise this
2988 // should be the start of a variable declaration.
2866 return !matchesAny(peek(), [ 2989 return !matchesAny(peek(), [
2867 TokenType.LT, 2990 TokenType.LT,
2868 TokenType.OPEN_CURLY_BRACKET, 2991 TokenType.OPEN_CURLY_BRACKET,
2869 TokenType.OPEN_SQUARE_BRACKET, 2992 TokenType.OPEN_SQUARE_BRACKET,
2870 TokenType.INDEX]); 2993 TokenType.INDEX]);
2871 } 2994 }
2995 // We know that we have an identifier, and need to see whether it might be a type name.
2872 Token token = skipTypeName(_currentToken); 2996 Token token = skipTypeName(_currentToken);
2873 if (token == null) { 2997 if (token == null) {
2998 // There was no type name, so this can't be a declaration.
2874 return false; 2999 return false;
2875 } 3000 }
2876 token = skipSimpleIdentifier(token); 3001 token = skipSimpleIdentifier(token);
2877 if (token == null) { 3002 if (token == null) {
2878 return false; 3003 return false;
2879 } 3004 }
2880 TokenType type = token.type; 3005 TokenType type = token.type;
2881 return identical(type, TokenType.EQ) || identical(type, TokenType.COMMA) || identical(type, TokenType.SEMICOLON) || matches3(token, Keyword.IN); 3006 return identical(type, TokenType.EQ) || identical(type, TokenType.COMMA) || identical(type, TokenType.SEMICOLON) || matches3(token, Keyword.IN);
2882 } 3007 }
2883 3008
(...skipping 29 matching lines...) Expand all
2913 return nextChar == 0x5B; 3038 return nextChar == 0x5B;
2914 } 3039 }
2915 3040
2916 /** 3041 /**
2917 * Return `true` if the given token appears to be the beginning of an operator declaration. 3042 * Return `true` if the given token appears to be the beginning of an operator declaration.
2918 * 3043 *
2919 * @param startToken the token that might be the start of an operator declarat ion 3044 * @param startToken the token that might be the start of an operator declarat ion
2920 * @return `true` if the given token appears to be the beginning of an operato r declaration 3045 * @return `true` if the given token appears to be the beginning of an operato r declaration
2921 */ 3046 */
2922 bool isOperator(Token startToken) { 3047 bool isOperator(Token startToken) {
3048 // Accept any operator here, even if it is not user definable.
2923 if (!startToken.isOperator) { 3049 if (!startToken.isOperator) {
2924 return false; 3050 return false;
2925 } 3051 }
3052 // Token "=" means that it is actually field initializer.
2926 if (identical(startToken.type, TokenType.EQ)) { 3053 if (identical(startToken.type, TokenType.EQ)) {
2927 return false; 3054 return false;
2928 } 3055 }
3056 // Consume all operator tokens.
2929 Token token = startToken.next; 3057 Token token = startToken.next;
2930 while (token.isOperator) { 3058 while (token.isOperator) {
2931 token = token.next; 3059 token = token.next;
2932 } 3060 }
3061 // Formal parameter list is expect now.
2933 return matches4(token, TokenType.OPEN_PAREN); 3062 return matches4(token, TokenType.OPEN_PAREN);
2934 } 3063 }
2935 3064
2936 /** 3065 /**
2937 * Return `true` if the current token appears to be the beginning of a switch member. 3066 * Return `true` if the current token appears to be the beginning of a switch member.
2938 * 3067 *
2939 * @return `true` if the current token appears to be the beginning of a switch member 3068 * @return `true` if the current token appears to be the beginning of a switch member
2940 */ 3069 */
2941 bool isSwitchMember() { 3070 bool isSwitchMember() {
2942 Token token = _currentToken; 3071 Token token = _currentToken;
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
3213 * </pre> 3342 * </pre>
3214 * 3343 *
3215 * @param primaryAllowed `true` if the expression is allowed to be a primary w ithout any 3344 * @param primaryAllowed `true` if the expression is allowed to be a primary w ithout any
3216 * assignable selector 3345 * assignable selector
3217 * @return the assignable expression that was parsed 3346 * @return the assignable expression that was parsed
3218 */ 3347 */
3219 Expression parseAssignableExpression(bool primaryAllowed) { 3348 Expression parseAssignableExpression(bool primaryAllowed) {
3220 if (matches(Keyword.SUPER)) { 3349 if (matches(Keyword.SUPER)) {
3221 return parseAssignableSelector(new SuperExpression(andAdvance), false); 3350 return parseAssignableSelector(new SuperExpression(andAdvance), false);
3222 } 3351 }
3352 //
3353 // A primary expression can start with an identifier. We resolve the ambigui ty by determining
3354 // whether the primary consists of anything other than an identifier and/or is followed by an
3355 // assignableSelector.
3356 //
3223 Expression expression = parsePrimaryExpression(); 3357 Expression expression = parsePrimaryExpression();
3224 bool isOptional = primaryAllowed || expression is SimpleIdentifier; 3358 bool isOptional = primaryAllowed || expression is SimpleIdentifier;
3225 while (true) { 3359 while (true) {
3226 while (matches5(TokenType.OPEN_PAREN)) { 3360 while (matches5(TokenType.OPEN_PAREN)) {
3227 ArgumentList argumentList = parseArgumentList(); 3361 ArgumentList argumentList = parseArgumentList();
3228 if (expression is SimpleIdentifier) { 3362 if (expression is SimpleIdentifier) {
3229 expression = new MethodInvocation(null, null, expression as SimpleIden tifier, argumentList); 3363 expression = new MethodInvocation(null, null, expression as SimpleIden tifier, argumentList);
3230 } else if (expression is PrefixedIdentifier) { 3364 } else if (expression is PrefixedIdentifier) {
3231 PrefixedIdentifier identifier = expression as PrefixedIdentifier; 3365 PrefixedIdentifier identifier = expression as PrefixedIdentifier;
3232 expression = new MethodInvocation(identifier.prefix, identifier.period , identifier.identifier, argumentList); 3366 expression = new MethodInvocation(identifier.prefix, identifier.period , identifier.identifier, argumentList);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
3270 if (matches5(TokenType.OPEN_SQUARE_BRACKET)) { 3404 if (matches5(TokenType.OPEN_SQUARE_BRACKET)) {
3271 Token leftBracket = andAdvance; 3405 Token leftBracket = andAdvance;
3272 Expression index = parseExpression3(); 3406 Expression index = parseExpression3();
3273 Token rightBracket = expect2(TokenType.CLOSE_SQUARE_BRACKET); 3407 Token rightBracket = expect2(TokenType.CLOSE_SQUARE_BRACKET);
3274 return new IndexExpression.forTarget(prefix, leftBracket, index, rightBrac ket); 3408 return new IndexExpression.forTarget(prefix, leftBracket, index, rightBrac ket);
3275 } else if (matches5(TokenType.PERIOD)) { 3409 } else if (matches5(TokenType.PERIOD)) {
3276 Token period = andAdvance; 3410 Token period = andAdvance;
3277 return new PropertyAccess(prefix, period, parseSimpleIdentifier()); 3411 return new PropertyAccess(prefix, period, parseSimpleIdentifier());
3278 } else { 3412 } else {
3279 if (!optional) { 3413 if (!optional) {
3414 // Report the missing selector.
3280 reportError11(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, []); 3415 reportError11(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, []);
3281 } 3416 }
3282 return prefix; 3417 return prefix;
3283 } 3418 }
3284 } 3419 }
3285 3420
3286 /** 3421 /**
3287 * Parse a bitwise and expression. 3422 * Parse a bitwise and expression.
3288 * 3423 *
3289 * <pre> 3424 * <pre>
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
3389 reportError12(ParserErrorCode.MISSING_IDENTIFIER, _currentToken, [_current Token.lexeme]); 3524 reportError12(ParserErrorCode.MISSING_IDENTIFIER, _currentToken, [_current Token.lexeme]);
3390 functionName = createSyntheticIdentifier(); 3525 functionName = createSyntheticIdentifier();
3391 } 3526 }
3392 if (identical(_currentToken.type, TokenType.OPEN_PAREN)) { 3527 if (identical(_currentToken.type, TokenType.OPEN_PAREN)) {
3393 while (identical(_currentToken.type, TokenType.OPEN_PAREN)) { 3528 while (identical(_currentToken.type, TokenType.OPEN_PAREN)) {
3394 if (functionName != null) { 3529 if (functionName != null) {
3395 expression = new MethodInvocation(expression, period, functionName, pa rseArgumentList()); 3530 expression = new MethodInvocation(expression, period, functionName, pa rseArgumentList());
3396 period = null; 3531 period = null;
3397 functionName = null; 3532 functionName = null;
3398 } else if (expression == null) { 3533 } else if (expression == null) {
3534 // It should not be possible to get here.
3399 expression = new MethodInvocation(expression, period, createSyntheticI dentifier(), parseArgumentList()); 3535 expression = new MethodInvocation(expression, period, createSyntheticI dentifier(), parseArgumentList());
3400 } else { 3536 } else {
3401 expression = new FunctionExpressionInvocation(expression, parseArgumen tList()); 3537 expression = new FunctionExpressionInvocation(expression, parseArgumen tList());
3402 } 3538 }
3403 } 3539 }
3404 } else if (functionName != null) { 3540 } else if (functionName != null) {
3405 expression = new PropertyAccess(expression, period, functionName); 3541 expression = new PropertyAccess(expression, period, functionName);
3406 period = null; 3542 period = null;
3407 } 3543 }
3408 bool progress = true; 3544 bool progress = true;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3456 } else if (matches4(next, TokenType.EQ)) { 3592 } else if (matches4(next, TokenType.EQ)) {
3457 return parseClassTypeAlias(commentAndMetadata, abstractKeyword, keyword) ; 3593 return parseClassTypeAlias(commentAndMetadata, abstractKeyword, keyword) ;
3458 } 3594 }
3459 } 3595 }
3460 SimpleIdentifier name = parseSimpleIdentifier(); 3596 SimpleIdentifier name = parseSimpleIdentifier();
3461 String className = name.name; 3597 String className = name.name;
3462 TypeParameterList typeParameters = null; 3598 TypeParameterList typeParameters = null;
3463 if (matches5(TokenType.LT)) { 3599 if (matches5(TokenType.LT)) {
3464 typeParameters = parseTypeParameterList(); 3600 typeParameters = parseTypeParameterList();
3465 } 3601 }
3602 //
3603 // Parse the clauses. The parser accepts clauses in any order, but will gene rate errors if they
3604 // are not in the order required by the specification.
3605 //
3466 ExtendsClause extendsClause = null; 3606 ExtendsClause extendsClause = null;
3467 WithClause withClause = null; 3607 WithClause withClause = null;
3468 ImplementsClause implementsClause = null; 3608 ImplementsClause implementsClause = null;
3469 bool foundClause = true; 3609 bool foundClause = true;
3470 while (foundClause) { 3610 while (foundClause) {
3471 if (matches(Keyword.EXTENDS)) { 3611 if (matches(Keyword.EXTENDS)) {
3472 if (extendsClause == null) { 3612 if (extendsClause == null) {
3473 extendsClause = parseExtendsClause(); 3613 extendsClause = parseExtendsClause();
3474 if (withClause != null) { 3614 if (withClause != null) {
3475 reportError12(ParserErrorCode.WITH_BEFORE_EXTENDS, withClause.withKe yword, []); 3615 reportError12(ParserErrorCode.WITH_BEFORE_EXTENDS, withClause.withKe yword, []);
(...skipping 21 matching lines...) Expand all
3497 reportError12(ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES, implementsC lause.keyword, []); 3637 reportError12(ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES, implementsC lause.keyword, []);
3498 parseImplementsClause(); 3638 parseImplementsClause();
3499 } 3639 }
3500 } else { 3640 } else {
3501 foundClause = false; 3641 foundClause = false;
3502 } 3642 }
3503 } 3643 }
3504 if (withClause != null && extendsClause == null) { 3644 if (withClause != null && extendsClause == null) {
3505 reportError12(ParserErrorCode.WITH_WITHOUT_EXTENDS, withClause.withKeyword , []); 3645 reportError12(ParserErrorCode.WITH_WITHOUT_EXTENDS, withClause.withKeyword , []);
3506 } 3646 }
3647 //
3648 // Look for and skip over the extra-lingual 'native' specification.
3649 //
3507 NativeClause nativeClause = null; 3650 NativeClause nativeClause = null;
3508 if (matches2(_NATIVE) && matches4(peek(), TokenType.STRING)) { 3651 if (matches2(_NATIVE) && matches4(peek(), TokenType.STRING)) {
3509 nativeClause = parseNativeClause(); 3652 nativeClause = parseNativeClause();
3510 } 3653 }
3654 //
3655 // Parse the body of the class.
3656 //
3511 Token leftBracket = null; 3657 Token leftBracket = null;
3512 List<ClassMember> members = null; 3658 List<ClassMember> members = null;
3513 Token rightBracket = null; 3659 Token rightBracket = null;
3514 if (matches5(TokenType.OPEN_CURLY_BRACKET)) { 3660 if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
3515 leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET); 3661 leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET);
3516 members = parseClassMembers(className, getEndToken(leftBracket)); 3662 members = parseClassMembers(className, getEndToken(leftBracket));
3517 rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET); 3663 rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
3518 } else { 3664 } else {
3519 leftBracket = createSyntheticToken2(TokenType.OPEN_CURLY_BRACKET); 3665 leftBracket = createSyntheticToken2(TokenType.OPEN_CURLY_BRACKET);
3520 rightBracket = createSyntheticToken2(TokenType.CLOSE_CURLY_BRACKET); 3666 rightBracket = createSyntheticToken2(TokenType.CLOSE_CURLY_BRACKET);
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
3670 * commentReference ::= 3816 * commentReference ::=
3671 * 'new'? prefixedIdentifier 3817 * 'new'? prefixedIdentifier
3672 * </pre> 3818 * </pre>
3673 * 3819 *
3674 * @param referenceSource the source occurring between the square brackets wit hin a documentation 3820 * @param referenceSource the source occurring between the square brackets wit hin a documentation
3675 * comment 3821 * comment
3676 * @param sourceOffset the offset of the first character of the reference sour ce 3822 * @param sourceOffset the offset of the first character of the reference sour ce
3677 * @return the comment reference that was parsed, or `null` if no reference co uld be found 3823 * @return the comment reference that was parsed, or `null` if no reference co uld be found
3678 */ 3824 */
3679 CommentReference parseCommentReference(String referenceSource, int sourceOffse t) { 3825 CommentReference parseCommentReference(String referenceSource, int sourceOffse t) {
3826 // TODO(brianwilkerson) The errors are not getting the right offset/length a nd are being duplicated.
3680 if (referenceSource.length == 0) { 3827 if (referenceSource.length == 0) {
3681 return null; 3828 return null;
3682 } 3829 }
3683 try { 3830 try {
3684 BooleanErrorListener listener = new BooleanErrorListener(); 3831 BooleanErrorListener listener = new BooleanErrorListener();
3685 Scanner scanner = new Scanner(null, new SubSequenceReader(new CharSequence (referenceSource), sourceOffset), listener); 3832 Scanner scanner = new Scanner(null, new SubSequenceReader(new CharSequence (referenceSource), sourceOffset), listener);
3686 scanner.setSourceStart(1, 1); 3833 scanner.setSourceStart(1, 1);
3687 Token firstToken = scanner.tokenize(); 3834 Token firstToken = scanner.tokenize();
3688 if (listener.errorReported) { 3835 if (listener.errorReported) {
3689 return null; 3836 return null;
(...skipping 13 matching lines...) Expand all
3703 nextToken = thirdToken.next; 3850 nextToken = thirdToken.next;
3704 } else { 3851 } else {
3705 identifier = new SimpleIdentifier(firstToken); 3852 identifier = new SimpleIdentifier(firstToken);
3706 nextToken = firstToken.next; 3853 nextToken = firstToken.next;
3707 } 3854 }
3708 if (nextToken.type != TokenType.EOF) { 3855 if (nextToken.type != TokenType.EOF) {
3709 return null; 3856 return null;
3710 } 3857 }
3711 return new CommentReference(newKeyword, identifier); 3858 return new CommentReference(newKeyword, identifier);
3712 } else if (matches3(firstToken, Keyword.THIS) || matches3(firstToken, Keyw ord.NULL) || matches3(firstToken, Keyword.TRUE) || matches3(firstToken, Keyword. FALSE)) { 3859 } else if (matches3(firstToken, Keyword.THIS) || matches3(firstToken, Keyw ord.NULL) || matches3(firstToken, Keyword.TRUE) || matches3(firstToken, Keyword. FALSE)) {
3860 // TODO(brianwilkerson) If we want to support this we will need to exten d the definition
3861 // of CommentReference to take an expression rather than an identifier. For now we just
3862 // ignore it to reduce the number of errors produced, but that's probabl y not a valid
3863 // long term approach.
3713 return null; 3864 return null;
3714 } 3865 }
3715 } on JavaException catch (exception) { 3866 } on JavaException catch (exception) {
3716 } 3867 }
3717 return null; 3868 return null;
3718 } 3869 }
3719 3870
3720 /** 3871 /**
3721 * Parse all of the comment references occurring in the given array of documen tation comments. 3872 * Parse all of the comment references occurring in the given array of documen tation comments.
3722 * 3873 *
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
3801 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) { 3952 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
3802 reportError12(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken, []); 3953 reportError12(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken, []);
3803 return convertToFunctionDeclaration(parseOperator(commentAndMetadata, mo difiers.externalKeyword, returnType)); 3954 return convertToFunctionDeclaration(parseOperator(commentAndMetadata, mo difiers.externalKeyword, returnType));
3804 } else if (matchesIdentifier() && matchesAny(peek(), [ 3955 } else if (matchesIdentifier() && matchesAny(peek(), [
3805 TokenType.OPEN_PAREN, 3956 TokenType.OPEN_PAREN,
3806 TokenType.OPEN_CURLY_BRACKET, 3957 TokenType.OPEN_CURLY_BRACKET,
3807 TokenType.FUNCTION])) { 3958 TokenType.FUNCTION])) {
3808 validateModifiersForTopLevelFunction(modifiers); 3959 validateModifiersForTopLevelFunction(modifiers);
3809 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKe yword, returnType); 3960 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKe yword, returnType);
3810 } else { 3961 } else {
3962 //
3963 // We have found an error of some kind. Try to recover.
3964 //
3811 if (matchesIdentifier()) { 3965 if (matchesIdentifier()) {
3812 if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMIC OLON])) { 3966 if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMIC OLON])) {
3967 //
3968 // We appear to have a variable declaration with a type of "void".
3969 //
3813 reportError10(ParserErrorCode.VOID_VARIABLE, returnType, []); 3970 reportError10(ParserErrorCode.VOID_VARIABLE, returnType, []);
3814 return new TopLevelVariableDeclaration(commentAndMetadata.comment, c ommentAndMetadata.metadata, parseVariableDeclarationList2(null, validateModifier sForTopLevelVariable(modifiers), null), expect2(TokenType.SEMICOLON)); 3971 return new TopLevelVariableDeclaration(commentAndMetadata.comment, c ommentAndMetadata.metadata, parseVariableDeclarationList2(null, validateModifier sForTopLevelVariable(modifiers), null), expect2(TokenType.SEMICOLON));
3815 } 3972 }
3816 } 3973 }
3817 reportError12(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []); 3974 reportError12(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []);
3818 return null; 3975 return null;
3819 } 3976 }
3820 } else if ((matches(Keyword.GET) || matches(Keyword.SET)) && matchesIdentifi er2(peek())) { 3977 } else if ((matches(Keyword.GET) || matches(Keyword.SET)) && matchesIdentifi er2(peek())) {
3821 validateModifiersForTopLevelFunction(modifiers); 3978 validateModifiersForTopLevelFunction(modifiers);
3822 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyw ord, null); 3979 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyw ord, null);
(...skipping 15 matching lines...) Expand all
3838 TypeName returnType = parseReturnType(); 3995 TypeName returnType = parseReturnType();
3839 if ((matches(Keyword.GET) || matches(Keyword.SET)) && matchesIdentifier2(pee k())) { 3996 if ((matches(Keyword.GET) || matches(Keyword.SET)) && matchesIdentifier2(pee k())) {
3840 validateModifiersForTopLevelFunction(modifiers); 3997 validateModifiersForTopLevelFunction(modifiers);
3841 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyw ord, returnType); 3998 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyw ord, returnType);
3842 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) { 3999 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
3843 reportError12(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken, []); 4000 reportError12(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken, []);
3844 return convertToFunctionDeclaration(parseOperator(commentAndMetadata, modi fiers.externalKeyword, returnType)); 4001 return convertToFunctionDeclaration(parseOperator(commentAndMetadata, modi fiers.externalKeyword, returnType));
3845 } else if (matches5(TokenType.AT)) { 4002 } else if (matches5(TokenType.AT)) {
3846 return new TopLevelVariableDeclaration(commentAndMetadata.comment, comment AndMetadata.metadata, parseVariableDeclarationList2(null, validateModifiersForTo pLevelVariable(modifiers), returnType), expect2(TokenType.SEMICOLON)); 4003 return new TopLevelVariableDeclaration(commentAndMetadata.comment, comment AndMetadata.metadata, parseVariableDeclarationList2(null, validateModifiersForTo pLevelVariable(modifiers), returnType), expect2(TokenType.SEMICOLON));
3847 } else if (!matchesIdentifier()) { 4004 } else if (!matchesIdentifier()) {
4005 // TODO(brianwilkerson) Generalize this error. We could also be parsing a top-level variable at this point.
3848 reportError12(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []); 4006 reportError12(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []);
3849 Token semicolon; 4007 Token semicolon;
3850 if (matches5(TokenType.SEMICOLON)) { 4008 if (matches5(TokenType.SEMICOLON)) {
3851 semicolon = andAdvance; 4009 semicolon = andAdvance;
3852 } else { 4010 } else {
3853 semicolon = createSyntheticToken2(TokenType.SEMICOLON); 4011 semicolon = createSyntheticToken2(TokenType.SEMICOLON);
3854 } 4012 }
3855 List<VariableDeclaration> variables = new List<VariableDeclaration>(); 4013 List<VariableDeclaration> variables = new List<VariableDeclaration>();
3856 variables.add(new VariableDeclaration(null, null, createSyntheticIdentifie r(), null, null)); 4014 variables.add(new VariableDeclaration(null, null, createSyntheticIdentifie r(), null, null));
3857 return new TopLevelVariableDeclaration(commentAndMetadata.comment, comment AndMetadata.metadata, new VariableDeclarationList(null, null, null, returnType, variables), semicolon); 4015 return new TopLevelVariableDeclaration(commentAndMetadata.comment, comment AndMetadata.metadata, new VariableDeclarationList(null, null, null, returnType, variables), semicolon);
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
4021 Directive parseDirective(CommentAndMetadata commentAndMetadata) { 4179 Directive parseDirective(CommentAndMetadata commentAndMetadata) {
4022 if (matches(Keyword.IMPORT)) { 4180 if (matches(Keyword.IMPORT)) {
4023 return parseImportDirective(commentAndMetadata); 4181 return parseImportDirective(commentAndMetadata);
4024 } else if (matches(Keyword.EXPORT)) { 4182 } else if (matches(Keyword.EXPORT)) {
4025 return parseExportDirective(commentAndMetadata); 4183 return parseExportDirective(commentAndMetadata);
4026 } else if (matches(Keyword.LIBRARY)) { 4184 } else if (matches(Keyword.LIBRARY)) {
4027 return parseLibraryDirective(commentAndMetadata); 4185 return parseLibraryDirective(commentAndMetadata);
4028 } else if (matches(Keyword.PART)) { 4186 } else if (matches(Keyword.PART)) {
4029 return parsePartDirective(commentAndMetadata); 4187 return parsePartDirective(commentAndMetadata);
4030 } else { 4188 } else {
4189 // Internal error: this method should not have been invoked if the current token was something
4190 // other than one of the above.
4031 throw new IllegalStateException("parseDirective invoked in an invalid stat e; currentToken = ${_currentToken}"); 4191 throw new IllegalStateException("parseDirective invoked in an invalid stat e; currentToken = ${_currentToken}");
4032 } 4192 }
4033 } 4193 }
4034 4194
4035 /** 4195 /**
4036 * Parse a documentation comment. 4196 * Parse a documentation comment.
4037 * 4197 *
4038 * <pre> 4198 * <pre>
4039 * documentationComment ::= 4199 * documentationComment ::=
4040 * multiLineComment? 4200 * multiLineComment?
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
4289 variableList = new VariableDeclarationList(commentAndMetadata.comment, commentAndMetadata.metadata, null, null, variables); 4449 variableList = new VariableDeclarationList(commentAndMetadata.comment, commentAndMetadata.metadata, null, null, variables);
4290 } else if (isInitializedVariableDeclaration()) { 4450 } else if (isInitializedVariableDeclaration()) {
4291 variableList = parseVariableDeclarationList(commentAndMetadata); 4451 variableList = parseVariableDeclarationList(commentAndMetadata);
4292 } else { 4452 } else {
4293 initialization = parseExpression3(); 4453 initialization = parseExpression3();
4294 } 4454 }
4295 if (matches(Keyword.IN)) { 4455 if (matches(Keyword.IN)) {
4296 DeclaredIdentifier loopVariable = null; 4456 DeclaredIdentifier loopVariable = null;
4297 SimpleIdentifier identifier = null; 4457 SimpleIdentifier identifier = null;
4298 if (variableList == null) { 4458 if (variableList == null) {
4459 // We found: <expression> 'in'
4299 reportError11(ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH, []); 4460 reportError11(ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH, []);
4300 } else { 4461 } else {
4301 NodeList<VariableDeclaration> variables = variableList.variables; 4462 NodeList<VariableDeclaration> variables = variableList.variables;
4302 if (variables.length > 1) { 4463 if (variables.length > 1) {
4303 reportError11(ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH, [var iables.length.toString()]); 4464 reportError11(ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH, [var iables.length.toString()]);
4304 } 4465 }
4305 VariableDeclaration variable = variables[0]; 4466 VariableDeclaration variable = variables[0];
4306 if (variable.initializer != null) { 4467 if (variable.initializer != null) {
4307 reportError11(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, [] ); 4468 reportError11(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, [] );
4308 } 4469 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
4392 } 4553 }
4393 return new BlockFunctionBody(parseBlock()); 4554 return new BlockFunctionBody(parseBlock());
4394 } else if (matches2(_NATIVE)) { 4555 } else if (matches2(_NATIVE)) {
4395 Token nativeToken = andAdvance; 4556 Token nativeToken = andAdvance;
4396 StringLiteral stringLiteral = null; 4557 StringLiteral stringLiteral = null;
4397 if (matches5(TokenType.STRING)) { 4558 if (matches5(TokenType.STRING)) {
4398 stringLiteral = parseStringLiteral(); 4559 stringLiteral = parseStringLiteral();
4399 } 4560 }
4400 return new NativeFunctionBody(nativeToken, stringLiteral, expect2(TokenT ype.SEMICOLON)); 4561 return new NativeFunctionBody(nativeToken, stringLiteral, expect2(TokenT ype.SEMICOLON));
4401 } else { 4562 } else {
4563 // Invalid function body
4402 reportError11(emptyErrorCode, []); 4564 reportError11(emptyErrorCode, []);
4403 return new EmptyFunctionBody(createSyntheticToken2(TokenType.SEMICOLON)) ; 4565 return new EmptyFunctionBody(createSyntheticToken2(TokenType.SEMICOLON)) ;
4404 } 4566 }
4405 } finally { 4567 } finally {
4406 _inLoop = wasInLoop; 4568 _inLoop = wasInLoop;
4407 _inSwitch = wasInSwitch; 4569 _inSwitch = wasInSwitch;
4408 } 4570 }
4409 } 4571 }
4410 4572
4411 /** 4573 /**
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4445 } else if (matches5(TokenType.OPEN_PAREN)) { 4607 } else if (matches5(TokenType.OPEN_PAREN)) {
4446 reportError11(ParserErrorCode.GETTER_WITH_PARAMETERS, []); 4608 reportError11(ParserErrorCode.GETTER_WITH_PARAMETERS, []);
4447 parseFormalParameterList(); 4609 parseFormalParameterList();
4448 } 4610 }
4449 FunctionBody body; 4611 FunctionBody body;
4450 if (externalKeyword == null) { 4612 if (externalKeyword == null) {
4451 body = parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, fal se); 4613 body = parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, fal se);
4452 } else { 4614 } else {
4453 body = new EmptyFunctionBody(expect2(TokenType.SEMICOLON)); 4615 body = new EmptyFunctionBody(expect2(TokenType.SEMICOLON));
4454 } 4616 }
4617 // if (!isStatement && matches(TokenType.SEMICOLON)) {
4618 // // TODO(brianwilkerson) Improve this error message.
4619 // reportError(ParserErrorCode.UNEXPECTED_TOKEN, currentToken.getLexeme ());
4620 // advance();
4621 // }
4455 return new FunctionDeclaration(commentAndMetadata.comment, commentAndMetadat a.metadata, externalKeyword, returnType, keyword, name, new FunctionExpression(p arameters, body)); 4622 return new FunctionDeclaration(commentAndMetadata.comment, commentAndMetadat a.metadata, externalKeyword, returnType, keyword, name, new FunctionExpression(p arameters, body));
4456 } 4623 }
4457 4624
4458 /** 4625 /**
4459 * Parse a function declaration statement. 4626 * Parse a function declaration statement.
4460 * 4627 *
4461 * <pre> 4628 * <pre>
4462 * functionDeclarationStatement ::= 4629 * functionDeclarationStatement ::=
4463 * functionSignature functionBody 4630 * functionSignature functionBody
4464 * </pre> 4631 * </pre>
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
4522 if (matches5(TokenType.LT)) { 4689 if (matches5(TokenType.LT)) {
4523 typeParameters = parseTypeParameterList(); 4690 typeParameters = parseTypeParameterList();
4524 } 4691 }
4525 if (matches5(TokenType.SEMICOLON) || matches5(TokenType.EOF)) { 4692 if (matches5(TokenType.SEMICOLON) || matches5(TokenType.EOF)) {
4526 reportError11(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, []); 4693 reportError11(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, []);
4527 FormalParameterList parameters = new FormalParameterList(createSyntheticTo ken2(TokenType.OPEN_PAREN), null, null, null, createSyntheticToken2(TokenType.CL OSE_PAREN)); 4694 FormalParameterList parameters = new FormalParameterList(createSyntheticTo ken2(TokenType.OPEN_PAREN), null, null, null, createSyntheticToken2(TokenType.CL OSE_PAREN));
4528 Token semicolon = expect2(TokenType.SEMICOLON); 4695 Token semicolon = expect2(TokenType.SEMICOLON);
4529 return new FunctionTypeAlias(commentAndMetadata.comment, commentAndMetadat a.metadata, keyword, returnType, name, typeParameters, parameters, semicolon); 4696 return new FunctionTypeAlias(commentAndMetadata.comment, commentAndMetadat a.metadata, keyword, returnType, name, typeParameters, parameters, semicolon);
4530 } else if (!matches5(TokenType.OPEN_PAREN)) { 4697 } else if (!matches5(TokenType.OPEN_PAREN)) {
4531 reportError11(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, []); 4698 reportError11(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, []);
4699 // TODO(brianwilkerson) Recover from this error. At the very least we shou ld skip to the start
4700 // of the next valid compilation unit member, allowing for the possibility of finding the
4701 // typedef parameters before that point.
4532 return new FunctionTypeAlias(commentAndMetadata.comment, commentAndMetadat a.metadata, keyword, returnType, name, typeParameters, new FormalParameterList(c reateSyntheticToken2(TokenType.OPEN_PAREN), null, null, null, createSyntheticTok en2(TokenType.CLOSE_PAREN)), createSyntheticToken2(TokenType.SEMICOLON)); 4702 return new FunctionTypeAlias(commentAndMetadata.comment, commentAndMetadat a.metadata, keyword, returnType, name, typeParameters, new FormalParameterList(c reateSyntheticToken2(TokenType.OPEN_PAREN), null, null, null, createSyntheticTok en2(TokenType.CLOSE_PAREN)), createSyntheticToken2(TokenType.SEMICOLON));
4533 } 4703 }
4534 FormalParameterList parameters = parseFormalParameterList(); 4704 FormalParameterList parameters = parseFormalParameterList();
4535 validateFormalParameterList(parameters); 4705 validateFormalParameterList(parameters);
4536 Token semicolon = expect2(TokenType.SEMICOLON); 4706 Token semicolon = expect2(TokenType.SEMICOLON);
4537 return new FunctionTypeAlias(commentAndMetadata.comment, commentAndMetadata. metadata, keyword, returnType, name, typeParameters, parameters, semicolon); 4707 return new FunctionTypeAlias(commentAndMetadata.comment, commentAndMetadata. metadata, keyword, returnType, name, typeParameters, parameters, semicolon);
4538 } 4708 }
4539 4709
4540 /** 4710 /**
4541 * Parse a getter. 4711 * Parse a getter.
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
4714 * 4884 *
4715 * @param missingNameError the error code to be used if the library name is mi ssing 4885 * @param missingNameError the error code to be used if the library name is mi ssing
4716 * @param missingNameToken the token associated with the error produced if the library name is 4886 * @param missingNameToken the token associated with the error produced if the library name is
4717 * missing 4887 * missing
4718 * @return the library name that was parsed 4888 * @return the library name that was parsed
4719 */ 4889 */
4720 LibraryIdentifier parseLibraryName(ParserErrorCode missingNameError, Token mis singNameToken) { 4890 LibraryIdentifier parseLibraryName(ParserErrorCode missingNameError, Token mis singNameToken) {
4721 if (matchesIdentifier()) { 4891 if (matchesIdentifier()) {
4722 return parseLibraryIdentifier(); 4892 return parseLibraryIdentifier();
4723 } else if (matches5(TokenType.STRING)) { 4893 } else if (matches5(TokenType.STRING)) {
4894 // TODO(brianwilkerson) Recovery: This should be extended to handle arbitr ary tokens until we
4895 // can find a token that can start a compilation unit member.
4724 StringLiteral string = parseStringLiteral(); 4896 StringLiteral string = parseStringLiteral();
4725 reportError10(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, string, []); 4897 reportError10(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, string, []);
4726 } else { 4898 } else {
4727 reportError12(missingNameError, missingNameToken, []); 4899 reportError12(missingNameError, missingNameToken, []);
4728 } 4900 }
4729 List<SimpleIdentifier> components = new List<SimpleIdentifier>(); 4901 List<SimpleIdentifier> components = new List<SimpleIdentifier>();
4730 components.add(createSyntheticIdentifier()); 4902 components.add(createSyntheticIdentifier());
4731 return new LibraryIdentifier(components); 4903 return new LibraryIdentifier(components);
4732 } 4904 }
4733 4905
4734 /** 4906 /**
4735 * Parse a list literal. 4907 * Parse a list literal.
4736 * 4908 *
4737 * <pre> 4909 * <pre>
4738 * listLiteral ::= 4910 * listLiteral ::=
4739 * 'const'? typeArguments? '[' (expressionList ','?)? ']' 4911 * 'const'? typeArguments? '[' (expressionList ','?)? ']'
4740 * </pre> 4912 * </pre>
4741 * 4913 *
4742 * @param modifier the 'const' modifier appearing before the literal, or `null ` if there is 4914 * @param modifier the 'const' modifier appearing before the literal, or `null ` if there is
4743 * no modifier 4915 * no modifier
4744 * @param typeArguments the type arguments appearing before the literal, or `n ull` if there 4916 * @param typeArguments the type arguments appearing before the literal, or `n ull` if there
4745 * are no type arguments 4917 * are no type arguments
4746 * @return the list literal that was parsed 4918 * @return the list literal that was parsed
4747 */ 4919 */
4748 ListLiteral parseListLiteral(Token modifier, TypeArgumentList typeArguments) { 4920 ListLiteral parseListLiteral(Token modifier, TypeArgumentList typeArguments) {
4921 // may be empty list literal
4749 if (matches5(TokenType.INDEX)) { 4922 if (matches5(TokenType.INDEX)) {
4750 BeginToken leftBracket = new BeginToken(TokenType.OPEN_SQUARE_BRACKET, _cu rrentToken.offset); 4923 BeginToken leftBracket = new BeginToken(TokenType.OPEN_SQUARE_BRACKET, _cu rrentToken.offset);
4751 Token rightBracket = new Token(TokenType.CLOSE_SQUARE_BRACKET, _currentTok en.offset + 1); 4924 Token rightBracket = new Token(TokenType.CLOSE_SQUARE_BRACKET, _currentTok en.offset + 1);
4752 leftBracket.endToken = rightBracket; 4925 leftBracket.endToken = rightBracket;
4753 rightBracket.setNext(_currentToken.next); 4926 rightBracket.setNext(_currentToken.next);
4754 leftBracket.setNext(rightBracket); 4927 leftBracket.setNext(rightBracket);
4755 _currentToken.previous.setNext(leftBracket); 4928 _currentToken.previous.setNext(leftBracket);
4756 _currentToken = _currentToken.next; 4929 _currentToken = _currentToken.next;
4757 return new ListLiteral(modifier, typeArguments, leftBracket, null, rightBr acket); 4930 return new ListLiteral(modifier, typeArguments, leftBracket, null, rightBr acket);
4758 } 4931 }
4932 // open
4759 Token leftBracket = expect2(TokenType.OPEN_SQUARE_BRACKET); 4933 Token leftBracket = expect2(TokenType.OPEN_SQUARE_BRACKET);
4760 if (matches5(TokenType.CLOSE_SQUARE_BRACKET)) { 4934 if (matches5(TokenType.CLOSE_SQUARE_BRACKET)) {
4761 return new ListLiteral(modifier, typeArguments, leftBracket, null, andAdva nce); 4935 return new ListLiteral(modifier, typeArguments, leftBracket, null, andAdva nce);
4762 } 4936 }
4763 List<Expression> elements = new List<Expression>(); 4937 List<Expression> elements = new List<Expression>();
4764 elements.add(parseExpression3()); 4938 elements.add(parseExpression3());
4765 while (optional(TokenType.COMMA)) { 4939 while (optional(TokenType.COMMA)) {
4766 if (matches5(TokenType.CLOSE_SQUARE_BRACKET)) { 4940 if (matches5(TokenType.CLOSE_SQUARE_BRACKET)) {
4767 return new ListLiteral(modifier, typeArguments, leftBracket, elements, a ndAdvance); 4941 return new ListLiteral(modifier, typeArguments, leftBracket, elements, a ndAdvance);
4768 } 4942 }
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
5050 * | tryStatement 5224 * | tryStatement
5051 * | whileStatement 5225 * | whileStatement
5052 * | variableDeclarationList ';' 5226 * | variableDeclarationList ';'
5053 * | expressionStatement 5227 * | expressionStatement
5054 * | functionSignature functionBody 5228 * | functionSignature functionBody
5055 * </pre> 5229 * </pre>
5056 * 5230 *
5057 * @return the non-labeled statement that was parsed 5231 * @return the non-labeled statement that was parsed
5058 */ 5232 */
5059 Statement parseNonLabeledStatement() { 5233 Statement parseNonLabeledStatement() {
5234 // TODO(brianwilkerson) Pass the comment and metadata on where appropriate.
5060 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata(); 5235 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
5061 if (matches5(TokenType.OPEN_CURLY_BRACKET)) { 5236 if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
5062 if (matches4(peek(), TokenType.STRING)) { 5237 if (matches4(peek(), TokenType.STRING)) {
5063 Token afterString = skipStringLiteral(_currentToken.next); 5238 Token afterString = skipStringLiteral(_currentToken.next);
5064 if (afterString != null && identical(afterString.type, TokenType.COLON)) { 5239 if (afterString != null && identical(afterString.type, TokenType.COLON)) {
5065 return new ExpressionStatement(parseExpression3(), expect2(TokenType.S EMICOLON)); 5240 return new ExpressionStatement(parseExpression3(), expect2(TokenType.S EMICOLON));
5066 } 5241 }
5067 } 5242 }
5068 return parseBlock(); 5243 return parseBlock();
5069 } else if (matches5(TokenType.KEYWORD) && !(_currentToken as KeywordToken).k eyword.isPseudoKeyword) { 5244 } else if (matches5(TokenType.KEYWORD) && !(_currentToken as KeywordToken).k eyword.isPseudoKeyword) {
5070 Keyword keyword = (_currentToken as KeywordToken).keyword; 5245 Keyword keyword = (_currentToken as KeywordToken).keyword;
5246 // TODO(jwren) compute some metrics to figure out a better order for this if-then sequence to optimize performance
5071 if (identical(keyword, Keyword.ASSERT)) { 5247 if (identical(keyword, Keyword.ASSERT)) {
5072 return parseAssertStatement(); 5248 return parseAssertStatement();
5073 } else if (identical(keyword, Keyword.BREAK)) { 5249 } else if (identical(keyword, Keyword.BREAK)) {
5074 return parseBreakStatement(); 5250 return parseBreakStatement();
5075 } else if (identical(keyword, Keyword.CONTINUE)) { 5251 } else if (identical(keyword, Keyword.CONTINUE)) {
5076 return parseContinueStatement(); 5252 return parseContinueStatement();
5077 } else if (identical(keyword, Keyword.DO)) { 5253 } else if (identical(keyword, Keyword.DO)) {
5078 return parseDoStatement(); 5254 return parseDoStatement();
5079 } else if (identical(keyword, Keyword.FOR)) { 5255 } else if (identical(keyword, Keyword.FOR)) {
5080 return parseForStatement(); 5256 return parseForStatement();
(...skipping 14 matching lines...) Expand all
5095 } else if (identical(keyword, Keyword.VAR) || identical(keyword, Keyword.F INAL)) { 5271 } else if (identical(keyword, Keyword.VAR) || identical(keyword, Keyword.F INAL)) {
5096 return parseVariableDeclarationStatement(commentAndMetadata); 5272 return parseVariableDeclarationStatement(commentAndMetadata);
5097 } else if (identical(keyword, Keyword.VOID)) { 5273 } else if (identical(keyword, Keyword.VOID)) {
5098 TypeName returnType = parseReturnType(); 5274 TypeName returnType = parseReturnType();
5099 if (matchesIdentifier() && matchesAny(peek(), [ 5275 if (matchesIdentifier() && matchesAny(peek(), [
5100 TokenType.OPEN_PAREN, 5276 TokenType.OPEN_PAREN,
5101 TokenType.OPEN_CURLY_BRACKET, 5277 TokenType.OPEN_CURLY_BRACKET,
5102 TokenType.FUNCTION])) { 5278 TokenType.FUNCTION])) {
5103 return parseFunctionDeclarationStatement2(commentAndMetadata, returnTy pe); 5279 return parseFunctionDeclarationStatement2(commentAndMetadata, returnTy pe);
5104 } else { 5280 } else {
5281 //
5282 // We have found an error of some kind. Try to recover.
5283 //
5105 if (matchesIdentifier()) { 5284 if (matchesIdentifier()) {
5106 if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEM ICOLON])) { 5285 if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEM ICOLON])) {
5286 //
5287 // We appear to have a variable declaration with a type of "void".
5288 //
5107 reportError10(ParserErrorCode.VOID_VARIABLE, returnType, []); 5289 reportError10(ParserErrorCode.VOID_VARIABLE, returnType, []);
5108 return parseVariableDeclarationStatement(commentAndMetadata); 5290 return parseVariableDeclarationStatement(commentAndMetadata);
5109 } 5291 }
5110 } else if (matches5(TokenType.CLOSE_CURLY_BRACKET)) { 5292 } else if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
5293 //
5294 // We appear to have found an incomplete statement at the end of a b lock. Parse it as a
5295 // variable declaration.
5296 //
5111 return parseVariableDeclarationStatement2(commentAndMetadata, null, returnType); 5297 return parseVariableDeclarationStatement2(commentAndMetadata, null, returnType);
5112 } 5298 }
5113 reportError11(ParserErrorCode.MISSING_STATEMENT, []); 5299 reportError11(ParserErrorCode.MISSING_STATEMENT, []);
5300 // TODO(brianwilkerson) Recover from this error.
5114 return new EmptyStatement(createSyntheticToken2(TokenType.SEMICOLON)); 5301 return new EmptyStatement(createSyntheticToken2(TokenType.SEMICOLON));
5115 } 5302 }
5116 } else if (identical(keyword, Keyword.CONST)) { 5303 } else if (identical(keyword, Keyword.CONST)) {
5117 if (matchesAny(peek(), [ 5304 if (matchesAny(peek(), [
5118 TokenType.LT, 5305 TokenType.LT,
5119 TokenType.OPEN_CURLY_BRACKET, 5306 TokenType.OPEN_CURLY_BRACKET,
5120 TokenType.OPEN_SQUARE_BRACKET, 5307 TokenType.OPEN_SQUARE_BRACKET,
5121 TokenType.INDEX])) { 5308 TokenType.INDEX])) {
5122 return new ExpressionStatement(parseExpression3(), expect2(TokenType.S EMICOLON)); 5309 return new ExpressionStatement(parseExpression3(), expect2(TokenType.S EMICOLON));
5123 } else if (matches4(peek(), TokenType.IDENTIFIER)) { 5310 } else if (matches4(peek(), TokenType.IDENTIFIER)) {
5124 Token afterType = skipTypeName(peek()); 5311 Token afterType = skipTypeName(peek());
5125 if (afterType != null) { 5312 if (afterType != null) {
5126 if (matches4(afterType, TokenType.OPEN_PAREN) || (matches4(afterType , TokenType.PERIOD) && matches4(afterType.next, TokenType.IDENTIFIER) && matches 4(afterType.next.next, TokenType.OPEN_PAREN))) { 5313 if (matches4(afterType, TokenType.OPEN_PAREN) || (matches4(afterType , TokenType.PERIOD) && matches4(afterType.next, TokenType.IDENTIFIER) && matches 4(afterType.next.next, TokenType.OPEN_PAREN))) {
5127 return new ExpressionStatement(parseExpression3(), expect2(TokenTy pe.SEMICOLON)); 5314 return new ExpressionStatement(parseExpression3(), expect2(TokenTy pe.SEMICOLON));
5128 } 5315 }
5129 } 5316 }
5130 } 5317 }
5131 return parseVariableDeclarationStatement(commentAndMetadata); 5318 return parseVariableDeclarationStatement(commentAndMetadata);
5132 } else if (identical(keyword, Keyword.NEW) || identical(keyword, Keyword.T RUE) || identical(keyword, Keyword.FALSE) || identical(keyword, Keyword.NULL) || identical(keyword, Keyword.SUPER) || identical(keyword, Keyword.THIS)) { 5319 } else if (identical(keyword, Keyword.NEW) || identical(keyword, Keyword.T RUE) || identical(keyword, Keyword.FALSE) || identical(keyword, Keyword.NULL) || identical(keyword, Keyword.SUPER) || identical(keyword, Keyword.THIS)) {
5133 return new ExpressionStatement(parseExpression3(), expect2(TokenType.SEM ICOLON)); 5320 return new ExpressionStatement(parseExpression3(), expect2(TokenType.SEM ICOLON));
5134 } else { 5321 } else {
5322 //
5323 // We have found an error of some kind. Try to recover.
5324 //
5135 reportError11(ParserErrorCode.MISSING_STATEMENT, []); 5325 reportError11(ParserErrorCode.MISSING_STATEMENT, []);
5136 return new EmptyStatement(createSyntheticToken2(TokenType.SEMICOLON)); 5326 return new EmptyStatement(createSyntheticToken2(TokenType.SEMICOLON));
5137 } 5327 }
5138 } else if (matches5(TokenType.SEMICOLON)) { 5328 } else if (matches5(TokenType.SEMICOLON)) {
5139 return parseEmptyStatement(); 5329 return parseEmptyStatement();
5140 } else if (isInitializedVariableDeclaration()) { 5330 } else if (isInitializedVariableDeclaration()) {
5141 return parseVariableDeclarationStatement(commentAndMetadata); 5331 return parseVariableDeclarationStatement(commentAndMetadata);
5142 } else if (isFunctionDeclaration()) { 5332 } else if (isFunctionDeclaration()) {
5143 return parseFunctionDeclarationStatement(); 5333 return parseFunctionDeclarationStatement();
5144 } else if (matches5(TokenType.CLOSE_CURLY_BRACKET)) { 5334 } else if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
5343 } on FormatException catch (exception) { 5533 } on FormatException catch (exception) {
5344 } 5534 }
5345 return new IntegerLiteral(token, value); 5535 return new IntegerLiteral(token, value);
5346 } else if (matches5(TokenType.STRING)) { 5536 } else if (matches5(TokenType.STRING)) {
5347 return parseStringLiteral(); 5537 return parseStringLiteral();
5348 } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) { 5538 } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
5349 return parseMapLiteral(null, null); 5539 return parseMapLiteral(null, null);
5350 } else if (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.IND EX)) { 5540 } else if (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.IND EX)) {
5351 return parseListLiteral(null, null); 5541 return parseListLiteral(null, null);
5352 } else if (matchesIdentifier()) { 5542 } else if (matchesIdentifier()) {
5543 // TODO(brianwilkerson) The code below was an attempt to recover from an e rror case, but it
5544 // needs to be applied as a recovery only after we know that parsing it as an identifier
5545 // doesn't work. Leaving the code as a reminder of how to recover.
5546 // if (isFunctionExpression(peek())) {
5547 // //
5548 // // Function expressions were allowed to have names at one point, but this is now illegal.
5549 // //
5550 // reportError(ParserErrorCode.NAMED_FUNCTION_EXPRESSION, getAndAdv ance());
5551 // return parseFunctionExpression();
5552 // }
5353 return parsePrefixedIdentifier(); 5553 return parsePrefixedIdentifier();
5354 } else if (matches(Keyword.NEW)) { 5554 } else if (matches(Keyword.NEW)) {
5355 return parseNewExpression(); 5555 return parseNewExpression();
5356 } else if (matches(Keyword.CONST)) { 5556 } else if (matches(Keyword.CONST)) {
5357 return parseConstExpression(); 5557 return parseConstExpression();
5358 } else if (matches5(TokenType.OPEN_PAREN)) { 5558 } else if (matches5(TokenType.OPEN_PAREN)) {
5359 if (isFunctionExpression(_currentToken)) { 5559 if (isFunctionExpression(_currentToken)) {
5360 return parseFunctionExpression(); 5560 return parseFunctionExpression();
5361 } 5561 }
5362 Token leftParenthesis = andAdvance; 5562 Token leftParenthesis = andAdvance;
5363 Expression expression = parseExpression3(); 5563 Expression expression = parseExpression3();
5364 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN); 5564 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
5365 return new ParenthesizedExpression(leftParenthesis, expression, rightParen thesis); 5565 return new ParenthesizedExpression(leftParenthesis, expression, rightParen thesis);
5366 } else if (matches5(TokenType.LT)) { 5566 } else if (matches5(TokenType.LT)) {
5367 return parseListOrMapLiteral(null); 5567 return parseListOrMapLiteral(null);
5368 } else if (matches5(TokenType.QUESTION)) { 5568 } else if (matches5(TokenType.QUESTION)) {
5369 return parseArgumentDefinitionTest(); 5569 return parseArgumentDefinitionTest();
5370 } else if (matches(Keyword.VOID)) { 5570 } else if (matches(Keyword.VOID)) {
5571 //
5572 // Recover from having a return type of "void" where a return type is not expected.
5573 //
5574 // TODO(brianwilkerson) Improve this error message.
5371 reportError11(ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]); 5575 reportError11(ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
5372 advance(); 5576 advance();
5373 return parsePrimaryExpression(); 5577 return parsePrimaryExpression();
5374 } else if (matches5(TokenType.HASH)) { 5578 } else if (matches5(TokenType.HASH)) {
5375 return parseSymbolLiteral(); 5579 return parseSymbolLiteral();
5376 } else { 5580 } else {
5377 reportError11(ParserErrorCode.MISSING_IDENTIFIER, []); 5581 reportError11(ParserErrorCode.MISSING_IDENTIFIER, []);
5378 return createSyntheticIdentifier(); 5582 return createSyntheticIdentifier();
5379 } 5583 }
5380 } 5584 }
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
5655 reportError12(ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE, ca seKeyword, []); 5859 reportError12(ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE, ca seKeyword, []);
5656 } 5860 }
5657 } else if (matches(Keyword.DEFAULT)) { 5861 } else if (matches(Keyword.DEFAULT)) {
5658 if (defaultKeyword != null) { 5862 if (defaultKeyword != null) {
5659 reportError12(ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES, pee k(), []); 5863 reportError12(ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES, pee k(), []);
5660 } 5864 }
5661 defaultKeyword = andAdvance; 5865 defaultKeyword = andAdvance;
5662 Token colon = expect2(TokenType.COLON); 5866 Token colon = expect2(TokenType.COLON);
5663 members.add(new SwitchDefault(labels, defaultKeyword, colon, parseStat ements2())); 5867 members.add(new SwitchDefault(labels, defaultKeyword, colon, parseStat ements2()));
5664 } else { 5868 } else {
5869 // We need to advance, otherwise we could end up in an infinite loop, but this could be a
5870 // lot smarter about recovering from the error.
5665 reportError11(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT, []); 5871 reportError11(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT, []);
5666 while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRA CKET) && !matches(Keyword.CASE) && !matches(Keyword.DEFAULT)) { 5872 while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRA CKET) && !matches(Keyword.CASE) && !matches(Keyword.DEFAULT)) {
5667 advance(); 5873 advance();
5668 } 5874 }
5669 } 5875 }
5670 } 5876 }
5671 Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET); 5877 Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
5672 return new SwitchStatement(keyword, leftParenthesis, expression, rightPare nthesis, leftBracket, members, rightBracket); 5878 return new SwitchStatement(keyword, leftParenthesis, expression, rightPare nthesis, leftBracket, members, rightBracket);
5673 } finally { 5879 } finally {
5674 _inSwitch = wasInSwitch; 5880 _inSwitch = wasInSwitch;
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
5871 * | incrementOperator assignableExpression 6077 * | incrementOperator assignableExpression
5872 * </pre> 6078 * </pre>
5873 * 6079 *
5874 * @return the unary expression that was parsed 6080 * @return the unary expression that was parsed
5875 */ 6081 */
5876 Expression parseUnaryExpression() { 6082 Expression parseUnaryExpression() {
5877 if (matches5(TokenType.MINUS) || matches5(TokenType.BANG) || matches5(TokenT ype.TILDE)) { 6083 if (matches5(TokenType.MINUS) || matches5(TokenType.BANG) || matches5(TokenT ype.TILDE)) {
5878 Token operator = andAdvance; 6084 Token operator = andAdvance;
5879 if (matches(Keyword.SUPER)) { 6085 if (matches(Keyword.SUPER)) {
5880 if (matches4(peek(), TokenType.OPEN_SQUARE_BRACKET) || matches4(peek(), TokenType.PERIOD)) { 6086 if (matches4(peek(), TokenType.OPEN_SQUARE_BRACKET) || matches4(peek(), TokenType.PERIOD)) {
6087 // "prefixOperator unaryExpression"
6088 // --> "prefixOperator postfixExpression"
6089 // --> "prefixOperator primary selector*"
6090 // --> "prefixOperator 'super' assignableSelector selector*"
5881 return new PrefixExpression(operator, parseUnaryExpression()); 6091 return new PrefixExpression(operator, parseUnaryExpression());
5882 } 6092 }
5883 return new PrefixExpression(operator, new SuperExpression(andAdvance)); 6093 return new PrefixExpression(operator, new SuperExpression(andAdvance));
5884 } 6094 }
5885 return new PrefixExpression(operator, parseUnaryExpression()); 6095 return new PrefixExpression(operator, parseUnaryExpression());
5886 } else if (_currentToken.type.isIncrementOperator) { 6096 } else if (_currentToken.type.isIncrementOperator) {
5887 Token operator = andAdvance; 6097 Token operator = andAdvance;
5888 if (matches(Keyword.SUPER)) { 6098 if (matches(Keyword.SUPER)) {
5889 if (matches4(peek(), TokenType.OPEN_SQUARE_BRACKET) || matches4(peek(), TokenType.PERIOD)) { 6099 if (matches4(peek(), TokenType.OPEN_SQUARE_BRACKET) || matches4(peek(), TokenType.PERIOD)) {
6100 // --> "prefixOperator 'super' assignableSelector selector*"
5890 return new PrefixExpression(operator, parseUnaryExpression()); 6101 return new PrefixExpression(operator, parseUnaryExpression());
5891 } 6102 }
6103 //
6104 // Even though it is not valid to use an incrementing operator ('++' or '--') before 'super',
6105 // we can (and therefore must) interpret "--super" as semantically equiv alent to "-(-super)".
6106 // Unfortunately, we cannot do the same for "++super" because "+super" i s also not valid.
6107 //
5892 if (identical(operator.type, TokenType.MINUS_MINUS)) { 6108 if (identical(operator.type, TokenType.MINUS_MINUS)) {
5893 int offset = operator.offset; 6109 int offset = operator.offset;
5894 Token firstOperator = new Token(TokenType.MINUS, offset); 6110 Token firstOperator = new Token(TokenType.MINUS, offset);
5895 Token secondOperator = new Token(TokenType.MINUS, offset + 1); 6111 Token secondOperator = new Token(TokenType.MINUS, offset + 1);
5896 secondOperator.setNext(_currentToken); 6112 secondOperator.setNext(_currentToken);
5897 firstOperator.setNext(secondOperator); 6113 firstOperator.setNext(secondOperator);
5898 operator.previous.setNext(firstOperator); 6114 operator.previous.setNext(firstOperator);
5899 return new PrefixExpression(firstOperator, new PrefixExpression(second Operator, new SuperExpression(andAdvance))); 6115 return new PrefixExpression(firstOperator, new PrefixExpression(second Operator, new SuperExpression(andAdvance)));
5900 } else { 6116 } else {
6117 // Invalid operator before 'super'
5901 reportError11(ParserErrorCode.INVALID_OPERATOR_FOR_SUPER, [operator.le xeme]); 6118 reportError11(ParserErrorCode.INVALID_OPERATOR_FOR_SUPER, [operator.le xeme]);
5902 return new PrefixExpression(operator, new SuperExpression(andAdvance)) ; 6119 return new PrefixExpression(operator, new SuperExpression(andAdvance)) ;
5903 } 6120 }
5904 } 6121 }
5905 return new PrefixExpression(operator, parseAssignableExpression(false)); 6122 return new PrefixExpression(operator, parseAssignableExpression(false));
5906 } else if (matches5(TokenType.PLUS)) { 6123 } else if (matches5(TokenType.PLUS)) {
5907 reportError11(ParserErrorCode.MISSING_IDENTIFIER, []); 6124 reportError11(ParserErrorCode.MISSING_IDENTIFIER, []);
5908 return createSyntheticIdentifier(); 6125 return createSyntheticIdentifier();
5909 } 6126 }
5910 return parsePostfixExpression(); 6127 return parsePostfixExpression();
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
5982 * <pre> 6199 * <pre>
5983 * variableDeclarationStatement ::= 6200 * variableDeclarationStatement ::=
5984 * variableDeclarationList ';' 6201 * variableDeclarationList ';'
5985 * </pre> 6202 * </pre>
5986 * 6203 *
5987 * @param commentAndMetadata the metadata to be associated with the variable d eclaration 6204 * @param commentAndMetadata the metadata to be associated with the variable d eclaration
5988 * statement, or `null` if there is no attempt at parsing the comment and metadata 6205 * statement, or `null` if there is no attempt at parsing the comment and metadata
5989 * @return the variable declaration statement that was parsed 6206 * @return the variable declaration statement that was parsed
5990 */ 6207 */
5991 VariableDeclarationStatement parseVariableDeclarationStatement(CommentAndMetad ata commentAndMetadata) { 6208 VariableDeclarationStatement parseVariableDeclarationStatement(CommentAndMetad ata commentAndMetadata) {
6209 // Token startToken = currentToken;
5992 VariableDeclarationList variableList = parseVariableDeclarationList(commentA ndMetadata); 6210 VariableDeclarationList variableList = parseVariableDeclarationList(commentA ndMetadata);
6211 // if (!matches(TokenType.SEMICOLON)) {
6212 // if (matches(startToken, Keyword.VAR) && isTypedIdentifier(startToken .getNext())) {
6213 // // TODO(brianwilkerson) This appears to be of the form "var type v ariable". We should do
6214 // // a better job of recovering in this case.
6215 // }
6216 // }
5993 Token semicolon = expect2(TokenType.SEMICOLON); 6217 Token semicolon = expect2(TokenType.SEMICOLON);
5994 return new VariableDeclarationStatement(variableList, semicolon); 6218 return new VariableDeclarationStatement(variableList, semicolon);
5995 } 6219 }
5996 6220
5997 /** 6221 /**
5998 * Parse a variable declaration statement. 6222 * Parse a variable declaration statement.
5999 * 6223 *
6000 * <pre> 6224 * <pre>
6001 * variableDeclarationStatement ::= 6225 * variableDeclarationStatement ::=
6002 * variableDeclarationList ';' 6226 * variableDeclarationList ';'
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
6129 * </pre> 6353 * </pre>
6130 * 6354 *
6131 * @param startToken the token at which parsing is to begin 6355 * @param startToken the token at which parsing is to begin
6132 * @return the token following the type that was parsed 6356 * @return the token following the type that was parsed
6133 */ 6357 */
6134 Token skipFinalConstVarOrType(Token startToken) { 6358 Token skipFinalConstVarOrType(Token startToken) {
6135 if (matches3(startToken, Keyword.FINAL) || matches3(startToken, Keyword.CONS T)) { 6359 if (matches3(startToken, Keyword.FINAL) || matches3(startToken, Keyword.CONS T)) {
6136 Token next = startToken.next; 6360 Token next = startToken.next;
6137 if (matchesIdentifier2(next)) { 6361 if (matchesIdentifier2(next)) {
6138 Token next2 = next.next; 6362 Token next2 = next.next;
6363 // "Type parameter" or "Type<" or "prefix.Type"
6139 if (matchesIdentifier2(next2) || matches4(next2, TokenType.LT) || matche s4(next2, TokenType.PERIOD)) { 6364 if (matchesIdentifier2(next2) || matches4(next2, TokenType.LT) || matche s4(next2, TokenType.PERIOD)) {
6140 return skipTypeName(next); 6365 return skipTypeName(next);
6141 } 6366 }
6367 // "parameter"
6142 return next; 6368 return next;
6143 } 6369 }
6144 } else if (matches3(startToken, Keyword.VAR)) { 6370 } else if (matches3(startToken, Keyword.VAR)) {
6145 return startToken.next; 6371 return startToken.next;
6146 } else if (matchesIdentifier2(startToken)) { 6372 } else if (matchesIdentifier2(startToken)) {
6147 Token next = startToken.next; 6373 Token next = startToken.next;
6148 if (matchesIdentifier2(next) || matches4(next, TokenType.LT) || matches3(n ext, Keyword.THIS) || (matches4(next, TokenType.PERIOD) && matchesIdentifier2(ne xt.next) && (matchesIdentifier2(next.next.next) || matches4(next.next.next, Toke nType.LT) || matches3(next.next.next, Keyword.THIS)))) { 6374 if (matchesIdentifier2(next) || matches4(next, TokenType.LT) || matches3(n ext, Keyword.THIS) || (matches4(next, TokenType.PERIOD) && matchesIdentifier2(ne xt.next) && (matchesIdentifier2(next.next.next) || matches4(next.next.next, Toke nType.LT) || matches3(next.next.next, Keyword.THIS)))) {
6149 return skipReturnType(startToken); 6375 return skipReturnType(startToken);
6150 } 6376 }
6151 } 6377 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
6190 * @return the token following the formal parameter list that was parsed 6416 * @return the token following the formal parameter list that was parsed
6191 */ 6417 */
6192 Token skipFormalParameterList(Token startToken) { 6418 Token skipFormalParameterList(Token startToken) {
6193 if (!matches4(startToken, TokenType.OPEN_PAREN)) { 6419 if (!matches4(startToken, TokenType.OPEN_PAREN)) {
6194 return null; 6420 return null;
6195 } 6421 }
6196 Token next = startToken.next; 6422 Token next = startToken.next;
6197 if (matches4(next, TokenType.CLOSE_PAREN)) { 6423 if (matches4(next, TokenType.CLOSE_PAREN)) {
6198 return next.next; 6424 return next.next;
6199 } 6425 }
6426 //
6427 // Look to see whether the token after the open parenthesis is something tha t should only occur
6428 // at the beginning of a parameter list.
6429 //
6200 if (matchesAny(next, [ 6430 if (matchesAny(next, [
6201 TokenType.AT, 6431 TokenType.AT,
6202 TokenType.OPEN_SQUARE_BRACKET, 6432 TokenType.OPEN_SQUARE_BRACKET,
6203 TokenType.OPEN_CURLY_BRACKET]) || matches3(next, Keyword.VOID) || (match esIdentifier2(next) && (matchesAny(next.next, [TokenType.COMMA, TokenType.CLOSE_ PAREN])))) { 6433 TokenType.OPEN_CURLY_BRACKET]) || matches3(next, Keyword.VOID) || (match esIdentifier2(next) && (matchesAny(next.next, [TokenType.COMMA, TokenType.CLOSE_ PAREN])))) {
6204 return skipPastMatchingToken(startToken); 6434 return skipPastMatchingToken(startToken);
6205 } 6435 }
6436 //
6437 // Look to see whether the first parameter is a function typed parameter wit hout a return type.
6438 //
6206 if (matchesIdentifier2(next) && matches4(next.next, TokenType.OPEN_PAREN)) { 6439 if (matchesIdentifier2(next) && matches4(next.next, TokenType.OPEN_PAREN)) {
6207 Token afterParameters = skipFormalParameterList(next.next); 6440 Token afterParameters = skipFormalParameterList(next.next);
6208 if (afterParameters != null && (matchesAny(afterParameters, [TokenType.COM MA, TokenType.CLOSE_PAREN]))) { 6441 if (afterParameters != null && (matchesAny(afterParameters, [TokenType.COM MA, TokenType.CLOSE_PAREN]))) {
6209 return skipPastMatchingToken(startToken); 6442 return skipPastMatchingToken(startToken);
6210 } 6443 }
6211 } 6444 }
6445 //
6446 // Look to see whether the first parameter has a type or is a function typed parameter with a
6447 // return type.
6448 //
6212 Token afterType = skipFinalConstVarOrType(next); 6449 Token afterType = skipFinalConstVarOrType(next);
6213 if (afterType == null) { 6450 if (afterType == null) {
6214 return null; 6451 return null;
6215 } 6452 }
6216 if (skipSimpleIdentifier(afterType) == null) { 6453 if (skipSimpleIdentifier(afterType) == null) {
6217 return null; 6454 return null;
6218 } 6455 }
6219 return skipPastMatchingToken(startToken); 6456 return skipPastMatchingToken(startToken);
6220 } 6457 }
6221 6458
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
6321 * @param startToken the token at which parsing is to begin 6558 * @param startToken the token at which parsing is to begin
6322 * @return the string literal that was parsed 6559 * @return the string literal that was parsed
6323 */ 6560 */
6324 Token skipStringInterpolation(Token startToken) { 6561 Token skipStringInterpolation(Token startToken) {
6325 Token token = startToken; 6562 Token token = startToken;
6326 TokenType type = token.type; 6563 TokenType type = token.type;
6327 while (identical(type, TokenType.STRING_INTERPOLATION_EXPRESSION) || identic al(type, TokenType.STRING_INTERPOLATION_IDENTIFIER)) { 6564 while (identical(type, TokenType.STRING_INTERPOLATION_EXPRESSION) || identic al(type, TokenType.STRING_INTERPOLATION_IDENTIFIER)) {
6328 if (identical(type, TokenType.STRING_INTERPOLATION_EXPRESSION)) { 6565 if (identical(type, TokenType.STRING_INTERPOLATION_EXPRESSION)) {
6329 token = token.next; 6566 token = token.next;
6330 type = token.type; 6567 type = token.type;
6568 //
6569 // Rather than verify that the following tokens represent a valid expres sion, we simply skip
6570 // tokens until we reach the end of the interpolation, being careful to handle nested string
6571 // literals.
6572 //
6331 int bracketNestingLevel = 1; 6573 int bracketNestingLevel = 1;
6332 while (bracketNestingLevel > 0) { 6574 while (bracketNestingLevel > 0) {
6333 if (identical(type, TokenType.EOF)) { 6575 if (identical(type, TokenType.EOF)) {
6334 return null; 6576 return null;
6335 } else if (identical(type, TokenType.OPEN_CURLY_BRACKET)) { 6577 } else if (identical(type, TokenType.OPEN_CURLY_BRACKET)) {
6336 bracketNestingLevel++; 6578 bracketNestingLevel++;
6337 } else if (identical(type, TokenType.CLOSE_CURLY_BRACKET)) { 6579 } else if (identical(type, TokenType.CLOSE_CURLY_BRACKET)) {
6338 bracketNestingLevel--; 6580 bracketNestingLevel--;
6339 } else if (identical(type, TokenType.STRING)) { 6581 } else if (identical(type, TokenType.STRING)) {
6340 token = skipStringLiteral(token); 6582 token = skipStringLiteral(token);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
6477 * '<' typeParameter (',' typeParameter)* '>' 6719 * '<' typeParameter (',' typeParameter)* '>'
6478 * </pre> 6720 * </pre>
6479 * 6721 *
6480 * @param startToken the token at which parsing is to begin 6722 * @param startToken the token at which parsing is to begin
6481 * @return the token following the type parameter list that was parsed 6723 * @return the token following the type parameter list that was parsed
6482 */ 6724 */
6483 Token skipTypeParameterList(Token startToken) { 6725 Token skipTypeParameterList(Token startToken) {
6484 if (!matches4(startToken, TokenType.LT)) { 6726 if (!matches4(startToken, TokenType.LT)) {
6485 return null; 6727 return null;
6486 } 6728 }
6729 //
6730 // We can't skip a type parameter because it can be preceeded by metadata, s o we just assume
6731 // that everything before the matching end token is valid.
6732 //
6487 int depth = 1; 6733 int depth = 1;
6488 Token next = startToken.next; 6734 Token next = startToken.next;
6489 while (depth > 0) { 6735 while (depth > 0) {
6490 if (matches4(next, TokenType.EOF)) { 6736 if (matches4(next, TokenType.EOF)) {
6491 return null; 6737 return null;
6492 } else if (matches4(next, TokenType.LT)) { 6738 } else if (matches4(next, TokenType.LT)) {
6493 depth++; 6739 depth++;
6494 } else if (matches4(next, TokenType.GT)) { 6740 } else if (matches4(next, TokenType.GT)) {
6495 depth--; 6741 depth--;
6496 } else if (matches4(next, TokenType.GT_EQ)) { 6742 } else if (matches4(next, TokenType.GT_EQ)) {
(...skipping 28 matching lines...) Expand all
6525 * @param lexeme the string containing the character(s) to be translated 6771 * @param lexeme the string containing the character(s) to be translated
6526 * @param index the index of the character to be translated 6772 * @param index the index of the character to be translated
6527 * @return the index of the next character to be translated 6773 * @return the index of the next character to be translated
6528 */ 6774 */
6529 int translateCharacter(JavaStringBuilder builder, String lexeme, int index) { 6775 int translateCharacter(JavaStringBuilder builder, String lexeme, int index) {
6530 int currentChar = lexeme.codeUnitAt(index); 6776 int currentChar = lexeme.codeUnitAt(index);
6531 if (currentChar != 0x5C) { 6777 if (currentChar != 0x5C) {
6532 builder.appendChar(currentChar); 6778 builder.appendChar(currentChar);
6533 return index + 1; 6779 return index + 1;
6534 } 6780 }
6781 //
6782 // We have found an escape sequence, so we parse the string to determine wha t kind of escape
6783 // sequence and what character to add to the builder.
6784 //
6535 int length = lexeme.length; 6785 int length = lexeme.length;
6536 int currentIndex = index + 1; 6786 int currentIndex = index + 1;
6537 if (currentIndex >= length) { 6787 if (currentIndex >= length) {
6788 // Illegal escape sequence: no char after escape
6789 // This cannot actually happen because it would require the escape charact er to be the last
6790 // character in the string, but if it were it would escape the closing quo te, leaving the
6791 // string unclosed.
6792 // reportError(ParserErrorCode.MISSING_CHAR_IN_ESCAPE_SEQUENCE);
6538 return length; 6793 return length;
6539 } 6794 }
6540 currentChar = lexeme.codeUnitAt(currentIndex); 6795 currentChar = lexeme.codeUnitAt(currentIndex);
6541 if (currentChar == 0x6E) { 6796 if (currentChar == 0x6E) {
6542 builder.appendChar(0xA); 6797 builder.appendChar(0xA);
6543 } else if (currentChar == 0x72) { 6798 } else if (currentChar == 0x72) {
6544 builder.appendChar(0xD); 6799 builder.appendChar(0xD);
6545 } else if (currentChar == 0x66) { 6800 } else if (currentChar == 0x66) {
6546 builder.appendChar(0xC); 6801 builder.appendChar(0xC);
6547 } else if (currentChar == 0x62) { 6802 } else if (currentChar == 0x62) {
6548 builder.appendChar(0x8); 6803 builder.appendChar(0x8);
6549 } else if (currentChar == 0x74) { 6804 } else if (currentChar == 0x74) {
6550 builder.appendChar(0x9); 6805 builder.appendChar(0x9);
6551 } else if (currentChar == 0x76) { 6806 } else if (currentChar == 0x76) {
6552 builder.appendChar(0xB); 6807 builder.appendChar(0xB);
6553 } else if (currentChar == 0x78) { 6808 } else if (currentChar == 0x78) {
6554 if (currentIndex + 2 >= length) { 6809 if (currentIndex + 2 >= length) {
6810 // Illegal escape sequence: not enough hex digits
6555 reportError11(ParserErrorCode.INVALID_HEX_ESCAPE, []); 6811 reportError11(ParserErrorCode.INVALID_HEX_ESCAPE, []);
6556 return length; 6812 return length;
6557 } 6813 }
6558 int firstDigit = lexeme.codeUnitAt(currentIndex + 1); 6814 int firstDigit = lexeme.codeUnitAt(currentIndex + 1);
6559 int secondDigit = lexeme.codeUnitAt(currentIndex + 2); 6815 int secondDigit = lexeme.codeUnitAt(currentIndex + 2);
6560 if (!isHexDigit(firstDigit) || !isHexDigit(secondDigit)) { 6816 if (!isHexDigit(firstDigit) || !isHexDigit(secondDigit)) {
6817 // Illegal escape sequence: invalid hex digit
6561 reportError11(ParserErrorCode.INVALID_HEX_ESCAPE, []); 6818 reportError11(ParserErrorCode.INVALID_HEX_ESCAPE, []);
6562 } else { 6819 } else {
6563 builder.appendChar(((Character.digit(firstDigit, 16) << 4) + Character.d igit(secondDigit, 16))); 6820 builder.appendChar(((Character.digit(firstDigit, 16) << 4) + Character.d igit(secondDigit, 16)));
6564 } 6821 }
6565 return currentIndex + 3; 6822 return currentIndex + 3;
6566 } else if (currentChar == 0x75) { 6823 } else if (currentChar == 0x75) {
6567 currentIndex++; 6824 currentIndex++;
6568 if (currentIndex >= length) { 6825 if (currentIndex >= length) {
6826 // Illegal escape sequence: not enough hex digits
6569 reportError11(ParserErrorCode.INVALID_UNICODE_ESCAPE, []); 6827 reportError11(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
6570 return length; 6828 return length;
6571 } 6829 }
6572 currentChar = lexeme.codeUnitAt(currentIndex); 6830 currentChar = lexeme.codeUnitAt(currentIndex);
6573 if (currentChar == 0x7B) { 6831 if (currentChar == 0x7B) {
6574 currentIndex++; 6832 currentIndex++;
6575 if (currentIndex >= length) { 6833 if (currentIndex >= length) {
6834 // Illegal escape sequence: incomplete escape
6576 reportError11(ParserErrorCode.INVALID_UNICODE_ESCAPE, []); 6835 reportError11(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
6577 return length; 6836 return length;
6578 } 6837 }
6579 currentChar = lexeme.codeUnitAt(currentIndex); 6838 currentChar = lexeme.codeUnitAt(currentIndex);
6580 int digitCount = 0; 6839 int digitCount = 0;
6581 int value = 0; 6840 int value = 0;
6582 while (currentChar != 0x7D) { 6841 while (currentChar != 0x7D) {
6583 if (!isHexDigit(currentChar)) { 6842 if (!isHexDigit(currentChar)) {
6843 // Illegal escape sequence: invalid hex digit
6584 reportError11(ParserErrorCode.INVALID_UNICODE_ESCAPE, []); 6844 reportError11(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
6585 currentIndex++; 6845 currentIndex++;
6586 while (currentIndex < length && lexeme.codeUnitAt(currentIndex) != 0 x7D) { 6846 while (currentIndex < length && lexeme.codeUnitAt(currentIndex) != 0 x7D) {
6587 currentIndex++; 6847 currentIndex++;
6588 } 6848 }
6589 return currentIndex + 1; 6849 return currentIndex + 1;
6590 } 6850 }
6591 digitCount++; 6851 digitCount++;
6592 value = (value << 4) + Character.digit(currentChar, 16); 6852 value = (value << 4) + Character.digit(currentChar, 16);
6593 currentIndex++; 6853 currentIndex++;
6594 if (currentIndex >= length) { 6854 if (currentIndex >= length) {
6855 // Illegal escape sequence: incomplete escape
6595 reportError11(ParserErrorCode.INVALID_UNICODE_ESCAPE, []); 6856 reportError11(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
6596 return length; 6857 return length;
6597 } 6858 }
6598 currentChar = lexeme.codeUnitAt(currentIndex); 6859 currentChar = lexeme.codeUnitAt(currentIndex);
6599 } 6860 }
6600 if (digitCount < 1 || digitCount > 6) { 6861 if (digitCount < 1 || digitCount > 6) {
6862 // Illegal escape sequence: not enough or too many hex digits
6601 reportError11(ParserErrorCode.INVALID_UNICODE_ESCAPE, []); 6863 reportError11(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
6602 } 6864 }
6603 appendScalarValue(builder, lexeme.substring(index, currentIndex + 1), va lue, index, currentIndex); 6865 appendScalarValue(builder, lexeme.substring(index, currentIndex + 1), va lue, index, currentIndex);
6604 return currentIndex + 1; 6866 return currentIndex + 1;
6605 } else { 6867 } else {
6606 if (currentIndex + 3 >= length) { 6868 if (currentIndex + 3 >= length) {
6869 // Illegal escape sequence: not enough hex digits
6607 reportError11(ParserErrorCode.INVALID_UNICODE_ESCAPE, []); 6870 reportError11(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
6608 return length; 6871 return length;
6609 } 6872 }
6610 int firstDigit = currentChar; 6873 int firstDigit = currentChar;
6611 int secondDigit = lexeme.codeUnitAt(currentIndex + 1); 6874 int secondDigit = lexeme.codeUnitAt(currentIndex + 1);
6612 int thirdDigit = lexeme.codeUnitAt(currentIndex + 2); 6875 int thirdDigit = lexeme.codeUnitAt(currentIndex + 2);
6613 int fourthDigit = lexeme.codeUnitAt(currentIndex + 3); 6876 int fourthDigit = lexeme.codeUnitAt(currentIndex + 3);
6614 if (!isHexDigit(firstDigit) || !isHexDigit(secondDigit) || !isHexDigit(t hirdDigit) || !isHexDigit(fourthDigit)) { 6877 if (!isHexDigit(firstDigit) || !isHexDigit(secondDigit) || !isHexDigit(t hirdDigit) || !isHexDigit(fourthDigit)) {
6878 // Illegal escape sequence: invalid hex digits
6615 reportError11(ParserErrorCode.INVALID_UNICODE_ESCAPE, []); 6879 reportError11(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
6616 } else { 6880 } else {
6617 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) , index, currentIndex + 3); 6881 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) , index, currentIndex + 3);
6618 } 6882 }
6619 return currentIndex + 4; 6883 return currentIndex + 4;
6620 } 6884 }
6621 } else { 6885 } else {
6622 builder.appendChar(currentChar); 6886 builder.appendChar(currentChar);
6623 } 6887 }
6624 return currentIndex + 1; 6888 return currentIndex + 1;
(...skipping 1537 matching lines...) Expand 10 before | Expand all | Expand 10 after
8162 */ 8426 */
8163 bool isEqual(ASTNode fromNode, ASTNode toNode) { 8427 bool isEqual(ASTNode fromNode, ASTNode toNode) {
8164 if (fromNode == null) { 8428 if (fromNode == null) {
8165 return toNode == null; 8429 return toNode == null;
8166 } else if (toNode == null) { 8430 } else if (toNode == null) {
8167 return false; 8431 return false;
8168 } else if (fromNode.runtimeType == toNode.runtimeType) { 8432 } else if (fromNode.runtimeType == toNode.runtimeType) {
8169 this._toNode = toNode; 8433 this._toNode = toNode;
8170 return fromNode.accept(this); 8434 return fromNode.accept(this);
8171 } 8435 }
8436 //
8437 // Check for a simple transformation caused by entering a period.
8438 //
8172 if (toNode is PrefixedIdentifier) { 8439 if (toNode is PrefixedIdentifier) {
8173 SimpleIdentifier prefix = toNode.prefix; 8440 SimpleIdentifier prefix = toNode.prefix;
8174 if (fromNode.runtimeType == prefix.runtimeType) { 8441 if (fromNode.runtimeType == prefix.runtimeType) {
8175 this._toNode = prefix; 8442 this._toNode = prefix;
8176 return fromNode.accept(this); 8443 return fromNode.accept(this);
8177 } 8444 }
8178 } else if (toNode is PropertyAccess) { 8445 } else if (toNode is PropertyAccess) {
8179 Expression target = toNode.target; 8446 Expression target = toNode.target;
8180 if (fromNode.runtimeType == target.runtimeType) { 8447 if (fromNode.runtimeType == target.runtimeType) {
8181 this._toNode = target; 8448 this._toNode = target;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
8250 } 8517 }
8251 return true; 8518 return true;
8252 } 8519 }
8253 } 8520 }
8254 8521
8255 /** 8522 /**
8256 * Instances of the class {link ToFormattedSourceVisitor} write a source represe ntation of a visited 8523 * Instances of the class {link ToFormattedSourceVisitor} write a source represe ntation of a visited
8257 * AST node (and all of it's children) to a writer. 8524 * AST node (and all of it's children) to a writer.
8258 */ 8525 */
8259 class ToFormattedSourceVisitor implements ASTVisitor<Object> { 8526 class ToFormattedSourceVisitor implements ASTVisitor<Object> {
8527 static String COMMENTS_KEY = "List of comments before statement";
8528
8260 /** 8529 /**
8261 * The writer to which the source is to be written. 8530 * The writer to which the source is to be written.
8262 */ 8531 */
8263 PrintWriter _writer; 8532 PrintWriter _writer;
8264 8533
8265 int _indentLevel = 0; 8534 int _indentLevel = 0;
8266 8535
8267 String _indentString = ""; 8536 String _indentString = "";
8268 8537
8269 /** 8538 /**
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
8441 } 8710 }
8442 return null; 8711 return null;
8443 } 8712 }
8444 8713
8445 Object visitCommentReference(CommentReference node) => null; 8714 Object visitCommentReference(CommentReference node) => null;
8446 8715
8447 Object visitCompilationUnit(CompilationUnit node) { 8716 Object visitCompilationUnit(CompilationUnit node) {
8448 ScriptTag scriptTag = node.scriptTag; 8717 ScriptTag scriptTag = node.scriptTag;
8449 NodeList<Directive> directives = node.directives; 8718 NodeList<Directive> directives = node.directives;
8450 visit(scriptTag); 8719 visit(scriptTag);
8720 // directives
8451 String prefix = scriptTag == null ? "" : " "; 8721 String prefix = scriptTag == null ? "" : " ";
8452 visitList7(prefix, directives, "\n"); 8722 visitList7(prefix, directives, "\n");
8453 nl(); 8723 nl();
8724 // declarations
8454 prefix = scriptTag == null && directives.isEmpty ? "" : "\n"; 8725 prefix = scriptTag == null && directives.isEmpty ? "" : "\n";
8455 visitList7(prefix, node.declarations, "\n\n"); 8726 visitList7(prefix, node.declarations, "\n\n");
8456 return null; 8727 return null;
8457 } 8728 }
8458 8729
8459 Object visitConditionalExpression(ConditionalExpression node) { 8730 Object visitConditionalExpression(ConditionalExpression node) {
8460 visit(node.condition); 8731 visit(node.condition);
8461 _writer.print(" ? "); 8732 _writer.print(" ? ");
8462 visit(node.thenExpression); 8733 visit(node.thenExpression);
8463 _writer.print(" : "); 8734 _writer.print(" : ");
(...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after
9157 9428
9158 void nl() { 9429 void nl() {
9159 _writer.print("\n"); 9430 _writer.print("\n");
9160 } 9431 }
9161 9432
9162 void nl2() { 9433 void nl2() {
9163 nl(); 9434 nl();
9164 indent(); 9435 indent();
9165 } 9436 }
9166 9437
9438 void printLeadingComments(Statement statement) {
9439 List<String> comments = statement.getProperty(COMMENTS_KEY) as List<String>;
9440 if (comments == null) {
9441 return;
9442 }
9443 for (String comment in comments) {
9444 _writer.print(comment);
9445 _writer.print("\n");
9446 indent();
9447 }
9448 }
9449
9167 /** 9450 /**
9168 * Safely visit the given node. 9451 * Safely visit the given node.
9169 * 9452 *
9170 * @param node the node to be visited 9453 * @param node the node to be visited
9171 */ 9454 */
9172 void visit(ASTNode node) { 9455 void visit(ASTNode node) {
9173 if (node != null) { 9456 if (node != null) {
9174 node.accept(this); 9457 node.accept(this);
9175 } 9458 }
9176 } 9459 }
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
9262 * 9545 *
9263 * @param prefix the prefix to be printed if the list is not empty 9546 * @param prefix the prefix to be printed if the list is not empty
9264 * @param nodes the nodes to be printed 9547 * @param nodes the nodes to be printed
9265 * @param separator the separator to be printed between adjacent nodes 9548 * @param separator the separator to be printed between adjacent nodes
9266 * @param suffix the suffix to be printed if the list is not empty 9549 * @param suffix the suffix to be printed if the list is not empty
9267 */ 9550 */
9268 void visitList8(String prefix, NodeList<ASTNode> nodes, String separator, Stri ng suffix) { 9551 void visitList8(String prefix, NodeList<ASTNode> nodes, String separator, Stri ng suffix) {
9269 if (nodes != null) { 9552 if (nodes != null) {
9270 int size = nodes.length; 9553 int size = nodes.length;
9271 if (size != 0) { 9554 if (size != 0) {
9555 // prefix
9272 _writer.print(prefix); 9556 _writer.print(prefix);
9273 if (prefix.endsWith("\n")) { 9557 if (prefix.endsWith("\n")) {
9274 indent(); 9558 indent();
9275 } 9559 }
9560 // nodes
9276 bool newLineSeparator = separator.endsWith("\n"); 9561 bool newLineSeparator = separator.endsWith("\n");
9277 for (int i = 0; i < size; i++) { 9562 for (int i = 0; i < size; i++) {
9278 if (i > 0) { 9563 if (i > 0) {
9279 _writer.print(separator); 9564 _writer.print(separator);
9280 if (newLineSeparator) { 9565 if (newLineSeparator) {
9281 indent(); 9566 indent();
9282 } 9567 }
9283 } 9568 }
9284 nodes[i].accept(this); 9569 ASTNode node = nodes[i];
9570 if (node is Statement) {
9571 printLeadingComments(node);
9572 }
9573 node.accept(this);
9285 } 9574 }
9575 // suffix
9286 _writer.print(suffix); 9576 _writer.print(suffix);
9287 } 9577 }
9288 } 9578 }
9289 } 9579 }
9290 9580
9291 /** 9581 /**
9292 * Print a list of tokens, separated by the given separator. 9582 * Print a list of tokens, separated by the given separator.
9293 * 9583 *
9294 * @param tokens the tokens to be printed 9584 * @param tokens the tokens to be printed
9295 * @param separator the separator to be printed between adjacent tokens 9585 * @param separator the separator to be printed between adjacent tokens
9296 */ 9586 */
9297 void visitList9(List<Token> tokens, String separator) { 9587 void visitList9(List<Token> tokens, String separator) {
9298 int size = tokens.length; 9588 int size = tokens.length;
9299 for (int i = 0; i < size; i++) { 9589 for (int i = 0; i < size; i++) {
9300 if ("\n" == separator) { 9590 if ("\n" == separator) {
9301 _writer.print("\n"); 9591 _writer.print("\n");
9302 indent(); 9592 indent();
9303 } else if (i > 0) { 9593 } else if (i > 0) {
9304 _writer.print(separator); 9594 _writer.print(separator);
9305 } 9595 }
9306 _writer.print(tokens[i].lexeme); 9596 _writer.print(tokens[i].lexeme);
9307 } 9597 }
9308 } 9598 }
9309 } 9599 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/index.dart ('k') | pkg/analyzer/lib/src/generated/resolver.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698