Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 library fasta.analyzer.ast_builder; | 5 library fasta.analyzer.ast_builder; |
| 6 | 6 |
| 7 import 'package:analyzer/analyzer.dart'; | 7 import 'package:analyzer/analyzer.dart'; |
| 8 import 'package:analyzer/dart/ast/ast_factory.dart' show AstFactory; | 8 import 'package:analyzer/dart/ast/ast_factory.dart' show AstFactory; |
| 9 import 'package:analyzer/dart/ast/standard_ast_factory.dart' as standard; | 9 import 'package:analyzer/dart/ast/standard_ast_factory.dart' as standard; |
| 10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; | 10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 bool hasExpression, Token beginToken, Token endToken) { | 387 bool hasExpression, Token beginToken, Token endToken) { |
| 388 debugEvent("ReturnStatement"); | 388 debugEvent("ReturnStatement"); |
| 389 Expression expression = hasExpression ? pop() : null; | 389 Expression expression = hasExpression ? pop() : null; |
| 390 push(ast.returnStatement(beginToken, expression, endToken)); | 390 push(ast.returnStatement(beginToken, expression, endToken)); |
| 391 } | 391 } |
| 392 | 392 |
| 393 void endIfStatement(Token ifToken, Token elseToken) { | 393 void endIfStatement(Token ifToken, Token elseToken) { |
| 394 Statement elsePart = popIfNotNull(elseToken); | 394 Statement elsePart = popIfNotNull(elseToken); |
| 395 Statement thenPart = pop(); | 395 Statement thenPart = pop(); |
| 396 Expression condition = pop(); | 396 Expression condition = pop(); |
| 397 analyzer.BeginToken leftParenthesis = ifToken.next; | 397 analyzer.BeginToken leftParenthesis = |
| 398 unsafeToken(ifToken.next, TokenType.OPEN_PAREN); | |
| 398 push(ast.ifStatement(ifToken, ifToken.next, condition, | 399 push(ast.ifStatement(ifToken, ifToken.next, condition, |
| 399 leftParenthesis.endGroup, thenPart, elseToken, elsePart)); | 400 leftParenthesis.endGroup, thenPart, elseToken, elsePart)); |
| 400 } | 401 } |
| 401 | 402 |
| 402 void handleNoInitializers() { | 403 void handleNoInitializers() { |
| 403 debugEvent("NoInitializers"); | 404 debugEvent("NoInitializers"); |
| 404 if (!isFullAst) return; | 405 if (!isFullAst) return; |
| 405 push(NullValue.ConstructorInitializerSeparator); | 406 push(NullValue.ConstructorInitializerSeparator); |
| 406 push(NullValue.ConstructorInitializers); | 407 push(NullValue.ConstructorInitializers); |
| 407 } | 408 } |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 549 void endForStatement(Token forKeyword, Token leftSeparator, | 550 void endForStatement(Token forKeyword, Token leftSeparator, |
| 550 int updateExpressionCount, Token endToken) { | 551 int updateExpressionCount, Token endToken) { |
| 551 debugEvent("ForStatement"); | 552 debugEvent("ForStatement"); |
| 552 Statement body = pop(); | 553 Statement body = pop(); |
| 553 List<Expression> updates = popList(updateExpressionCount); | 554 List<Expression> updates = popList(updateExpressionCount); |
| 554 Statement conditionStatement = pop(); | 555 Statement conditionStatement = pop(); |
| 555 Object initializerPart = pop(); | 556 Object initializerPart = pop(); |
| 556 exitLocalScope(); | 557 exitLocalScope(); |
| 557 exitContinueTarget(); | 558 exitContinueTarget(); |
| 558 exitBreakTarget(); | 559 exitBreakTarget(); |
| 559 analyzer.BeginToken leftParenthesis = forKeyword.next; | 560 analyzer.BeginToken leftParenthesis = |
| 561 unsafeToken(forKeyword.next, TokenType.OPEN_PAREN); | |
| 560 | 562 |
| 561 VariableDeclarationList variableList; | 563 VariableDeclarationList variableList; |
| 562 Expression initializer; | 564 Expression initializer; |
| 563 if (initializerPart is VariableDeclarationStatement) { | 565 if (initializerPart is VariableDeclarationStatement) { |
| 564 variableList = initializerPart.variables; | 566 variableList = initializerPart.variables; |
| 565 } else { | 567 } else { |
| 566 initializer = initializerPart as Expression; | 568 initializer = initializerPart as Expression; |
| 567 } | 569 } |
| 568 | 570 |
| 569 Expression condition; | 571 Expression condition; |
| 570 Token rightSeparator; | 572 Token rightSeparator; |
| 571 if (conditionStatement is ExpressionStatement) { | 573 if (conditionStatement is ExpressionStatement) { |
| 572 condition = conditionStatement.expression; | 574 condition = conditionStatement.expression; |
| 573 rightSeparator = conditionStatement.semicolon; | 575 rightSeparator = conditionStatement.semicolon; |
| 574 } else { | 576 } else { |
| 575 rightSeparator = (conditionStatement as EmptyStatement).semicolon; | 577 rightSeparator = (conditionStatement as EmptyStatement).semicolon; |
| 576 } | 578 } |
| 577 | 579 |
| 578 push(ast.forStatement( | 580 push(ast.forStatement( |
| 579 forKeyword, | 581 forKeyword, |
| 580 leftParenthesis, | 582 leftParenthesis, |
| 581 variableList, | 583 variableList, |
| 582 initializer, | 584 initializer, |
| 583 leftSeparator, | 585 leftSeparator, |
| 584 condition, | 586 condition, |
| 585 rightSeparator, | 587 rightSeparator, |
| 586 updates, | 588 updates, |
| 587 leftParenthesis.endGroup, | 589 leftParenthesis?.endGroup, |
| 588 body)); | 590 body)); |
| 589 } | 591 } |
| 590 | 592 |
| 591 void handleLiteralList( | 593 void handleLiteralList( |
| 592 int count, Token beginToken, Token constKeyword, Token endToken) { | 594 int count, Token beginToken, Token constKeyword, Token endToken) { |
| 593 debugEvent("LiteralList"); | 595 debugEvent("LiteralList"); |
| 594 List<Expression> expressions = popList(count); | 596 List<Expression> expressions = popList(count); |
| 595 TypeArgumentList typeArguments = pop(); | 597 TypeArgumentList typeArguments = pop(); |
| 596 push(ast.listLiteral( | 598 push(ast.listLiteral( |
| 597 constKeyword, typeArguments, beginToken, expressions, endToken)); | 599 constKeyword, typeArguments, beginToken, expressions, endToken)); |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 839 returnType: typeOrFunctionTypedParameter.returnType, | 841 returnType: typeOrFunctionTypedParameter.returnType, |
| 840 typeParameters: typeOrFunctionTypedParameter.typeParameters, | 842 typeParameters: typeOrFunctionTypedParameter.typeParameters, |
| 841 parameters: typeOrFunctionTypedParameter.parameters); | 843 parameters: typeOrFunctionTypedParameter.parameters); |
| 842 } else { | 844 } else { |
| 843 node = ast.fieldFormalParameter2( | 845 node = ast.fieldFormalParameter2( |
| 844 identifier: name, | 846 identifier: name, |
| 845 comment: comment, | 847 comment: comment, |
| 846 covariantKeyword: covariantKeyword, | 848 covariantKeyword: covariantKeyword, |
| 847 type: typeOrFunctionTypedParameter.returnType, | 849 type: typeOrFunctionTypedParameter.returnType, |
| 848 thisKeyword: thisKeyword, | 850 thisKeyword: thisKeyword, |
| 849 period: thisKeyword.next, | 851 period: unsafeToken(thisKeyword.next, TokenType.PERIOD), |
| 850 typeParameters: typeOrFunctionTypedParameter.typeParameters, | 852 typeParameters: typeOrFunctionTypedParameter.typeParameters, |
| 851 parameters: typeOrFunctionTypedParameter.parameters); | 853 parameters: typeOrFunctionTypedParameter.parameters); |
| 852 } | 854 } |
| 853 } else { | 855 } else { |
| 854 TypeAnnotation type = typeOrFunctionTypedParameter; | 856 TypeAnnotation type = typeOrFunctionTypedParameter; |
| 855 if (thisKeyword == null) { | 857 if (thisKeyword == null) { |
| 856 node = ast.simpleFormalParameter2( | 858 node = ast.simpleFormalParameter2( |
| 857 comment: comment, | 859 comment: comment, |
| 858 covariantKeyword: covariantKeyword, | 860 covariantKeyword: covariantKeyword, |
| 859 keyword: keyword, | 861 keyword: keyword, |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1053 void handleInvalidFunctionBody(Token token) { | 1055 void handleInvalidFunctionBody(Token token) { |
| 1054 debugEvent("InvalidFunctionBody"); | 1056 debugEvent("InvalidFunctionBody"); |
| 1055 } | 1057 } |
| 1056 | 1058 |
| 1057 @override | 1059 @override |
| 1058 Token handleUnrecoverableError(Token token, Message message) { | 1060 Token handleUnrecoverableError(Token token, Message message) { |
| 1059 if (message.code == codeExpectedFunctionBody) { | 1061 if (message.code == codeExpectedFunctionBody) { |
| 1060 if (identical('native', token.stringValue) && parser != null) { | 1062 if (identical('native', token.stringValue) && parser != null) { |
| 1061 Token nativeKeyword = token; | 1063 Token nativeKeyword = token; |
| 1062 Token semicolon = parser.parseLiteralString(token.next); | 1064 Token semicolon = parser.parseLiteralString(token.next); |
| 1065 // TODO(brianwilkerson) Should this be using ensureSemicolon? | |
|
danrubel
2017/08/31 17:27:50
Just FYI... I'm working on removing this code beca
Brian Wilkerson
2017/08/31 17:29:37
Agreed.
| |
| 1063 token = parser.expectSemicolon(semicolon); | 1066 token = parser.expectSemicolon(semicolon); |
| 1064 StringLiteral name = pop(); | 1067 StringLiteral name = pop(); |
| 1065 pop(); // star | 1068 pop(); // star |
| 1066 pop(); // async | 1069 pop(); // async |
| 1067 push(ast.nativeFunctionBody(nativeKeyword, name, semicolon)); | 1070 push(ast.nativeFunctionBody(nativeKeyword, name, semicolon)); |
| 1068 return token; | 1071 return token; |
| 1069 } | 1072 } |
| 1070 } else if (message.code == codeExpectedExpression) { | 1073 } else if (message.code == codeExpectedExpression) { |
| 1071 String lexeme = token.lexeme; | 1074 String lexeme = token.lexeme; |
| 1072 if (identical('async', lexeme) || identical('yield', lexeme)) { | 1075 if (identical('async', lexeme) || identical('yield', lexeme)) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1160 checkEmpty(endToken.charOffset); | 1163 checkEmpty(endToken.charOffset); |
| 1161 | 1164 |
| 1162 push(ast.compilationUnit( | 1165 push(ast.compilationUnit( |
| 1163 beginToken, scriptTag, directives, declarations, endToken)); | 1166 beginToken, scriptTag, directives, declarations, endToken)); |
| 1164 } | 1167 } |
| 1165 | 1168 |
| 1166 void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword, | 1169 void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword, |
| 1167 Token semicolon) { | 1170 Token semicolon) { |
| 1168 debugEvent("Import"); | 1171 debugEvent("Import"); |
| 1169 List<Combinator> combinators = pop(); | 1172 List<Combinator> combinators = pop(); |
| 1170 SimpleIdentifier prefix; | 1173 SimpleIdentifier prefix = popIfNotNull(asKeyword); |
| 1171 if (asKeyword != null) prefix = pop(); | |
| 1172 List<Configuration> configurations = pop(); | 1174 List<Configuration> configurations = pop(); |
| 1173 StringLiteral uri = pop(); | 1175 StringLiteral uri = pop(); |
| 1174 List<Annotation> metadata = pop(); | 1176 List<Annotation> metadata = pop(); |
| 1175 assert(metadata == null); // TODO(paulberry): fix. | 1177 assert(metadata == null); // TODO(paulberry): fix. |
| 1176 Comment comment = pop(); | 1178 Comment comment = pop(); |
| 1177 directives.add(ast.importDirective( | 1179 directives.add(ast.importDirective( |
| 1178 comment, | 1180 comment, |
| 1179 metadata, | 1181 metadata, |
| 1180 importKeyword, | 1182 importKeyword, |
| 1181 uri, | 1183 uri, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1220 whileKeyword, | 1222 whileKeyword, |
| 1221 condition.leftParenthesis, | 1223 condition.leftParenthesis, |
| 1222 condition.expression, | 1224 condition.expression, |
| 1223 condition.rightParenthesis, | 1225 condition.rightParenthesis, |
| 1224 semicolon)); | 1226 semicolon)); |
| 1225 } | 1227 } |
| 1226 | 1228 |
| 1227 void endConditionalUri(Token ifKeyword, Token equalitySign) { | 1229 void endConditionalUri(Token ifKeyword, Token equalitySign) { |
| 1228 debugEvent("ConditionalUri"); | 1230 debugEvent("ConditionalUri"); |
| 1229 StringLiteral libraryUri = pop(); | 1231 StringLiteral libraryUri = pop(); |
| 1230 StringLiteral value; | 1232 StringLiteral value = popIfNotNull(equalitySign); |
| 1231 if (equalitySign != null) { | |
| 1232 value = pop(); | |
| 1233 } | |
| 1234 DottedName name = pop(); | 1233 DottedName name = pop(); |
| 1235 // TODO(paulberry,ahe): what if there is no `(` token due to an error in the | 1234 // TODO(paulberry,ahe): what if there is no `(` token due to an error in the |
| 1236 // file being parsed? It seems like we need the parser to do adequate error | 1235 // file being parsed? It seems like we need the parser to do adequate error |
| 1237 // recovery and then report both the ifKeyword and leftParen tokens to the | 1236 // recovery and then report both the ifKeyword and leftParen tokens to the |
| 1238 // listener. | 1237 // listener. |
| 1239 Token leftParen = ifKeyword.next; | 1238 Token leftParen = unsafeToken(ifKeyword.next, TokenType.OPEN_PAREN); |
| 1240 // TODO(paulberry,ahe): the parser should report the right paren token to | 1239 // TODO(paulberry,ahe): the parser should report the right paren token to |
| 1241 // the listener. | 1240 // the listener. |
| 1242 Token rightParen = name.endToken.next; | 1241 Token lastToken = value?.endToken ?? equalitySign ?? name?.endToken; |
| 1242 Token rightParen = unsafeToken(lastToken.next, TokenType.CLOSE_PAREN); | |
| 1243 push(ast.configuration(ifKeyword, leftParen, name, equalitySign, value, | 1243 push(ast.configuration(ifKeyword, leftParen, name, equalitySign, value, |
| 1244 rightParen, libraryUri)); | 1244 rightParen, libraryUri)); |
| 1245 } | 1245 } |
| 1246 | 1246 |
| 1247 @override | 1247 @override |
| 1248 void endConditionalUris(int count) { | 1248 void endConditionalUris(int count) { |
| 1249 debugEvent("ConditionalUris"); | 1249 debugEvent("ConditionalUris"); |
| 1250 push(popList(count) ?? NullValue.ConditionalUris); | 1250 push(popList(count) ?? NullValue.ConditionalUris); |
| 1251 } | 1251 } |
| 1252 | 1252 |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1445 var libraryNameOrUri = pop(); | 1445 var libraryNameOrUri = pop(); |
| 1446 LibraryIdentifier name; | 1446 LibraryIdentifier name; |
| 1447 StringLiteral uri; | 1447 StringLiteral uri; |
| 1448 if (libraryNameOrUri is StringLiteral) { | 1448 if (libraryNameOrUri is StringLiteral) { |
| 1449 uri = libraryNameOrUri; | 1449 uri = libraryNameOrUri; |
| 1450 } else { | 1450 } else { |
| 1451 name = ast.libraryIdentifier(libraryNameOrUri); | 1451 name = ast.libraryIdentifier(libraryNameOrUri); |
| 1452 } | 1452 } |
| 1453 // TODO(paulberry,ahe): seems hacky. It would be nice if the parser passed | 1453 // TODO(paulberry,ahe): seems hacky. It would be nice if the parser passed |
| 1454 // in a reference to the "of" keyword. | 1454 // in a reference to the "of" keyword. |
| 1455 var ofKeyword = partKeyword.next; | 1455 var ofKeyword = unsafeToken(partKeyword.next, analyzer.Keyword.OF); |
| 1456 List<Annotation> metadata = pop(); | 1456 List<Annotation> metadata = pop(); |
| 1457 Comment comment = pop(); | 1457 Comment comment = pop(); |
| 1458 directives.add(ast.partOfDirective( | 1458 directives.add(ast.partOfDirective( |
| 1459 comment, metadata, partKeyword, ofKeyword, uri, name, semicolon)); | 1459 comment, metadata, partKeyword, ofKeyword, uri, name, semicolon)); |
| 1460 } | 1460 } |
| 1461 | 1461 |
| 1462 @override | 1462 @override |
| 1463 void endFunctionExpression(Token beginToken, Token token) { | 1463 void endFunctionExpression(Token beginToken, Token token) { |
| 1464 // TODO(paulberry): set up scopes properly to resolve parameters and type | 1464 // TODO(paulberry): set up scopes properly to resolve parameters and type |
| 1465 // variables. Note that this is tricky due to the handling of initializers | 1465 // variables. Note that this is tricky due to the handling of initializers |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1712 declarations.add(ast.genericTypeAlias(comment, metadata, typedefKeyword, | 1712 declarations.add(ast.genericTypeAlias(comment, metadata, typedefKeyword, |
| 1713 name, templateParameters, equals, type, endToken)); | 1713 name, templateParameters, equals, type, endToken)); |
| 1714 } | 1714 } |
| 1715 } | 1715 } |
| 1716 | 1716 |
| 1717 @override | 1717 @override |
| 1718 void endEnum(Token enumKeyword, Token endBrace, int count) { | 1718 void endEnum(Token enumKeyword, Token endBrace, int count) { |
| 1719 debugEvent("Enum"); | 1719 debugEvent("Enum"); |
| 1720 List<EnumConstantDeclaration> constants = popList(count); | 1720 List<EnumConstantDeclaration> constants = popList(count); |
| 1721 // TODO(paulberry,ahe): the parser should pass in the openBrace token. | 1721 // TODO(paulberry,ahe): the parser should pass in the openBrace token. |
| 1722 var openBrace = enumKeyword.next.next as analyzer.BeginToken; | 1722 var openBrace = |
| 1723 unsafeToken(enumKeyword.next.next, TokenType.OPEN_CURLY_BRACKET) | |
| 1724 as analyzer.BeginToken; | |
| 1723 // TODO(paulberry): what if the '}' is missing and the parser has performed | 1725 // TODO(paulberry): what if the '}' is missing and the parser has performed |
| 1724 // error recovery? | 1726 // error recovery? |
| 1725 Token closeBrace = openBrace.endGroup; | 1727 Token closeBrace = openBrace?.endGroup; |
| 1726 SimpleIdentifier name = pop(); | 1728 SimpleIdentifier name = pop(); |
| 1727 List<Annotation> metadata = pop(); | 1729 List<Annotation> metadata = pop(); |
| 1728 Comment comment = pop(); | 1730 Comment comment = pop(); |
| 1729 declarations.add(ast.enumDeclaration(comment, metadata, enumKeyword, name, | 1731 declarations.add(ast.enumDeclaration(comment, metadata, enumKeyword, name, |
| 1730 openBrace, constants, closeBrace)); | 1732 openBrace, constants, closeBrace)); |
| 1731 } | 1733 } |
| 1732 | 1734 |
| 1733 @override | 1735 @override |
| 1734 void endTypeArguments(int count, Token beginToken, Token endToken) { | 1736 void endTypeArguments(int count, Token beginToken, Token endToken) { |
| 1735 debugEvent("TypeArguments"); | 1737 debugEvent("TypeArguments"); |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1949 } else { | 1951 } else { |
| 1950 errorReporter?.reportErrorForOffset(ParserErrorCode.UNEXPECTED_TOKEN, | 1952 errorReporter?.reportErrorForOffset(ParserErrorCode.UNEXPECTED_TOKEN, |
| 1951 charOffset, text.length, [text]); | 1953 charOffset, text.length, [text]); |
| 1952 } | 1954 } |
| 1953 return; | 1955 return; |
| 1954 default: | 1956 default: |
| 1955 // fall through | 1957 // fall through |
| 1956 } | 1958 } |
| 1957 library.addCompileTimeError(message, charOffset, uri); | 1959 library.addCompileTimeError(message, charOffset, uri); |
| 1958 } | 1960 } |
| 1961 | |
| 1962 /// A marker method used to mark locations where a token is being located in | |
| 1963 /// an unsafe way. In all such cases the parser needs to be fixed to pass in | |
| 1964 /// the token. | |
| 1965 Token unsafeToken(Token token, TokenType tokenType) { | |
| 1966 // TODO(brianwilkerson) Eliminate the need for this method. | |
| 1967 return token.type == tokenType ? token : null; | |
| 1968 } | |
| 1959 } | 1969 } |
| 1960 | 1970 |
| 1961 /// Data structure placed on the stack to represent a class body. | 1971 /// Data structure placed on the stack to represent a class body. |
| 1962 /// | 1972 /// |
| 1963 /// This is needed because analyzer has no separate AST representation of a | 1973 /// This is needed because analyzer has no separate AST representation of a |
| 1964 /// class body; it simply stores all of the relevant data in the | 1974 /// class body; it simply stores all of the relevant data in the |
| 1965 /// [ClassDeclaration] object. | 1975 /// [ClassDeclaration] object. |
| 1966 class _ClassBody { | 1976 class _ClassBody { |
| 1967 final Token beginToken; | 1977 final Token beginToken; |
| 1968 | 1978 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2056 } else if (identical('var', s)) { | 2066 } else if (identical('var', s)) { |
| 2057 finalConstOrVarKeyword = token; | 2067 finalConstOrVarKeyword = token; |
| 2058 } else if (identical('covariant', s)) { | 2068 } else if (identical('covariant', s)) { |
| 2059 covariantKeyword = token; | 2069 covariantKeyword = token; |
| 2060 } else { | 2070 } else { |
| 2061 unhandled("$s", "modifier", token.charOffset, null); | 2071 unhandled("$s", "modifier", token.charOffset, null); |
| 2062 } | 2072 } |
| 2063 } | 2073 } |
| 2064 } | 2074 } |
| 2065 } | 2075 } |
| OLD | NEW |