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 |