OLD | NEW |
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 library analyzer.src.generated.parser; | 5 library analyzer.src.generated.parser; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 import "dart:math" as math; | 8 import "dart:math" as math; |
9 | 9 |
10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 static String _AWAIT = Keyword.AWAIT.syntax; | 163 static String _AWAIT = Keyword.AWAIT.syntax; |
164 | 164 |
165 static String _HIDE = Keyword.HIDE.syntax; | 165 static String _HIDE = Keyword.HIDE.syntax; |
166 | 166 |
167 static String _SHOW = Keyword.SHOW.syntax; | 167 static String _SHOW = Keyword.SHOW.syntax; |
168 | 168 |
169 static String SYNC = Keyword.SYNC.syntax; | 169 static String SYNC = Keyword.SYNC.syntax; |
170 | 170 |
171 static String _YIELD = Keyword.YIELD.syntax; | 171 static String _YIELD = Keyword.YIELD.syntax; |
172 | 172 |
| 173 static const int _MAX_TREE_DEPTH = 300; |
| 174 |
173 /** | 175 /** |
174 * The source being parsed. | 176 * The source being parsed. |
175 */ | 177 */ |
176 final Source _source; | 178 final Source _source; |
177 | 179 |
178 /** | 180 /** |
179 * The error listener that will be informed of any errors that are found | 181 * The error listener that will be informed of any errors that are found |
180 * during the parse. | 182 * during the parse. |
181 */ | 183 */ |
182 final AnalysisErrorListener _errorListener; | 184 final AnalysisErrorListener _errorListener; |
(...skipping 25 matching lines...) Expand all Loading... |
208 * A flag indicating whether parser is to parse function bodies. | 210 * A flag indicating whether parser is to parse function bodies. |
209 */ | 211 */ |
210 bool _parseFunctionBodies = true; | 212 bool _parseFunctionBodies = true; |
211 | 213 |
212 /** | 214 /** |
213 * The next token to be parsed. | 215 * The next token to be parsed. |
214 */ | 216 */ |
215 Token _currentToken; | 217 Token _currentToken; |
216 | 218 |
217 /** | 219 /** |
| 220 * The depth of the current AST. When this depth is too high, so we're at the |
| 221 * risk of overflowing the stack, we stop parsing and report an error. |
| 222 */ |
| 223 int _treeDepth = 0; |
| 224 |
| 225 /** |
218 * A flag indicating whether the parser is currently in a function body marked | 226 * A flag indicating whether the parser is currently in a function body marked |
219 * as being 'async'. | 227 * as being 'async'. |
220 */ | 228 */ |
221 bool _inAsync = false; | 229 bool _inAsync = false; |
222 | 230 |
223 /** | 231 /** |
224 * A flag indicating whether the parser is currently in a function body marked | 232 * A flag indicating whether the parser is currently in a function body marked |
225 * (by a star) as being a generator. | 233 * (by a star) as being a generator. |
226 */ | 234 */ |
227 bool _inGenerator = false; | 235 bool _inGenerator = false; |
(...skipping 1725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1953 } | 1961 } |
1954 directives.add(directive); | 1962 directives.add(directive); |
1955 } else if (type == TokenType.SEMICOLON) { | 1963 } else if (type == TokenType.SEMICOLON) { |
1956 // TODO(brianwilkerson) Consider moving this error detection into | 1964 // TODO(brianwilkerson) Consider moving this error detection into |
1957 // _parseCompilationUnitMember (in the places where EXPECTED_EXECUTABLE | 1965 // _parseCompilationUnitMember (in the places where EXPECTED_EXECUTABLE |
1958 // is being generated). | 1966 // is being generated). |
1959 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, | 1967 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, |
1960 [_currentToken.lexeme]); | 1968 [_currentToken.lexeme]); |
1961 _advance(); | 1969 _advance(); |
1962 } else { | 1970 } else { |
1963 CompilationUnitMember member = | 1971 CompilationUnitMember member; |
1964 parseCompilationUnitMember(commentAndMetadata); | 1972 try { |
| 1973 member = parseCompilationUnitMember(commentAndMetadata); |
| 1974 } on _TooDeepTreeError { |
| 1975 _reportErrorForToken(ParserErrorCode.STACK_OVERFLOW, _currentToken); |
| 1976 Token eof = new Token(TokenType.EOF, 0); |
| 1977 eof.previous = eof; |
| 1978 eof.setNext(eof); |
| 1979 return astFactory.compilationUnit(eof, null, null, null, eof); |
| 1980 } |
1965 if (member != null) { | 1981 if (member != null) { |
1966 declarations.add(member); | 1982 declarations.add(member); |
1967 } | 1983 } |
1968 } | 1984 } |
1969 if (identical(_currentToken, memberStart)) { | 1985 if (identical(_currentToken, memberStart)) { |
1970 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, | 1986 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, |
1971 [_currentToken.lexeme]); | 1987 [_currentToken.lexeme]); |
1972 _advance(); | 1988 _advance(); |
1973 while (!_matches(TokenType.EOF) && | 1989 while (!_matches(TokenType.EOF) && |
1974 !_couldBeStartOfCompilationUnitMember()) { | 1990 !_couldBeStartOfCompilationUnitMember()) { |
(...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2705 /** | 2721 /** |
2706 * Parse an expression that might contain a cascade. Return the expression | 2722 * Parse an expression that might contain a cascade. Return the expression |
2707 * that was parsed. | 2723 * that was parsed. |
2708 * | 2724 * |
2709 * expression ::= | 2725 * expression ::= |
2710 * assignableExpression assignmentOperator expression | 2726 * assignableExpression assignmentOperator expression |
2711 * | conditionalExpression cascadeSection* | 2727 * | conditionalExpression cascadeSection* |
2712 * | throwExpression | 2728 * | throwExpression |
2713 */ | 2729 */ |
2714 Expression parseExpression2() { | 2730 Expression parseExpression2() { |
2715 Keyword keyword = _currentToken.keyword; | 2731 if (_treeDepth > _MAX_TREE_DEPTH) { |
2716 if (keyword == Keyword.THROW) { | 2732 throw new _TooDeepTreeError(); |
2717 return parseThrowExpression(); | |
2718 } else if (keyword == Keyword.RETHROW) { | |
2719 // TODO(brianwilkerson) Rethrow is a statement again. | |
2720 return parseRethrowExpression(); | |
2721 } | 2733 } |
2722 // | 2734 _treeDepth++; |
2723 // assignableExpression is a subset of conditionalExpression, so we can | 2735 try { |
2724 // parse a conditional expression and then determine whether it is followed | 2736 Keyword keyword = _currentToken.keyword; |
2725 // by an assignmentOperator, checking for conformance to the restricted | 2737 if (keyword == Keyword.THROW) { |
2726 // grammar after making that determination. | 2738 return parseThrowExpression(); |
2727 // | 2739 } else if (keyword == Keyword.RETHROW) { |
2728 Expression expression = parseConditionalExpression(); | 2740 // TODO(brianwilkerson) Rethrow is a statement again. |
2729 TokenType type = _currentToken.type; | 2741 return parseRethrowExpression(); |
2730 if (type == TokenType.PERIOD_PERIOD) { | 2742 } |
2731 List<Expression> cascadeSections = <Expression>[]; | 2743 // |
2732 do { | 2744 // assignableExpression is a subset of conditionalExpression, so we can |
2733 Expression section = parseCascadeSection(); | 2745 // parse a conditional expression and then determine whether it is followe
d |
2734 if (section != null) { | 2746 // by an assignmentOperator, checking for conformance to the restricted |
2735 cascadeSections.add(section); | 2747 // grammar after making that determination. |
2736 } | 2748 // |
2737 } while (_currentToken.type == TokenType.PERIOD_PERIOD); | 2749 Expression expression = parseConditionalExpression(); |
2738 return astFactory.cascadeExpression(expression, cascadeSections); | 2750 TokenType type = _currentToken.type; |
2739 } else if (type.isAssignmentOperator) { | 2751 if (type == TokenType.PERIOD_PERIOD) { |
2740 Token operator = getAndAdvance(); | 2752 List<Expression> cascadeSections = <Expression>[]; |
2741 _ensureAssignable(expression); | 2753 do { |
2742 return astFactory.assignmentExpression( | 2754 Expression section = parseCascadeSection(); |
2743 expression, operator, parseExpression2()); | 2755 if (section != null) { |
| 2756 cascadeSections.add(section); |
| 2757 } |
| 2758 } while (_currentToken.type == TokenType.PERIOD_PERIOD); |
| 2759 return astFactory.cascadeExpression(expression, cascadeSections); |
| 2760 } else if (type.isAssignmentOperator) { |
| 2761 Token operator = getAndAdvance(); |
| 2762 _ensureAssignable(expression); |
| 2763 return astFactory.assignmentExpression( |
| 2764 expression, operator, parseExpression2()); |
| 2765 } |
| 2766 return expression; |
| 2767 } finally { |
| 2768 _treeDepth--; |
2744 } | 2769 } |
2745 return expression; | |
2746 } | 2770 } |
2747 | 2771 |
2748 /** | 2772 /** |
2749 * Parse a list of expressions. Return the expression that was parsed. | 2773 * Parse a list of expressions. Return the expression that was parsed. |
2750 * | 2774 * |
2751 * expressionList ::= | 2775 * expressionList ::= |
2752 * expression (',' expression)* | 2776 * expression (',' expression)* |
2753 */ | 2777 */ |
2754 List<Expression> parseExpressionList() { | 2778 List<Expression> parseExpressionList() { |
2755 List<Expression> expressions = <Expression>[parseExpression2()]; | 2779 List<Expression> expressions = <Expression>[parseExpression2()]; |
(...skipping 2032 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4788 return parseStatement2(); | 4812 return parseStatement2(); |
4789 } | 4813 } |
4790 | 4814 |
4791 /** | 4815 /** |
4792 * Parse a statement. Return the statement that was parsed. | 4816 * Parse a statement. Return the statement that was parsed. |
4793 * | 4817 * |
4794 * statement ::= | 4818 * statement ::= |
4795 * label* nonLabeledStatement | 4819 * label* nonLabeledStatement |
4796 */ | 4820 */ |
4797 Statement parseStatement2() { | 4821 Statement parseStatement2() { |
4798 List<Label> labels = null; | 4822 if (_treeDepth > _MAX_TREE_DEPTH) { |
4799 while (_matchesIdentifier() && _currentToken.next.type == TokenType.COLON) { | 4823 throw new _TooDeepTreeError(); |
4800 Label label = parseLabel(isDeclaration: true); | 4824 } |
| 4825 _treeDepth++; |
| 4826 try { |
| 4827 List<Label> labels = null; |
| 4828 while ( |
| 4829 _matchesIdentifier() && _currentToken.next.type == TokenType.COLON) { |
| 4830 Label label = parseLabel(isDeclaration: true); |
| 4831 if (labels == null) { |
| 4832 labels = <Label>[label]; |
| 4833 } else { |
| 4834 labels.add(label); |
| 4835 } |
| 4836 } |
| 4837 Statement statement = parseNonLabeledStatement(); |
4801 if (labels == null) { | 4838 if (labels == null) { |
4802 labels = <Label>[label]; | 4839 return statement; |
4803 } else { | |
4804 labels.add(label); | |
4805 } | 4840 } |
| 4841 return astFactory.labeledStatement(labels, statement); |
| 4842 } finally { |
| 4843 _treeDepth--; |
4806 } | 4844 } |
4807 Statement statement = parseNonLabeledStatement(); | |
4808 if (labels == null) { | |
4809 return statement; | |
4810 } | |
4811 return astFactory.labeledStatement(labels, statement); | |
4812 } | 4845 } |
4813 | 4846 |
4814 /** | 4847 /** |
4815 * Parse a sequence of statements, starting with the given [token]. Return the | 4848 * Parse a sequence of statements, starting with the given [token]. Return the |
4816 * statements that were parsed, or `null` if the tokens do not represent a | 4849 * statements that were parsed, or `null` if the tokens do not represent a |
4817 * recognizable sequence of statements. | 4850 * recognizable sequence of statements. |
4818 */ | 4851 */ |
4819 List<Statement> parseStatements(Token token) { | 4852 List<Statement> parseStatements(Token token) { |
4820 _currentToken = token; | 4853 _currentToken = token; |
4821 return _parseStatementList(); | 4854 return _parseStatementList(); |
(...skipping 3738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8560 } | 8593 } |
8561 if (modifiers.finalKeyword != null) { | 8594 if (modifiers.finalKeyword != null) { |
8562 _reportErrorForToken( | 8595 _reportErrorForToken( |
8563 ParserErrorCode.FINAL_TYPEDEF, modifiers.finalKeyword); | 8596 ParserErrorCode.FINAL_TYPEDEF, modifiers.finalKeyword); |
8564 } | 8597 } |
8565 if (modifiers.varKeyword != null) { | 8598 if (modifiers.varKeyword != null) { |
8566 _reportErrorForToken(ParserErrorCode.VAR_TYPEDEF, modifiers.varKeyword); | 8599 _reportErrorForToken(ParserErrorCode.VAR_TYPEDEF, modifiers.varKeyword); |
8567 } | 8600 } |
8568 } | 8601 } |
8569 } | 8602 } |
| 8603 |
| 8604 /** |
| 8605 * Instances of this class are thrown when the parser detects that AST has |
| 8606 * too many nested expressions to be parsed safely and avoid possibility of |
| 8607 * [StackOverflowError] in the parser or during later analysis. |
| 8608 */ |
| 8609 class _TooDeepTreeError {} |
OLD | NEW |