| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 package com.google.dart.compiler.parser; | 5 package com.google.dart.compiler.parser; |
| 6 | 6 |
| 7 import com.google.common.annotations.VisibleForTesting; | 7 import com.google.common.annotations.VisibleForTesting; |
| 8 import com.google.common.io.CharStreams; | 8 import com.google.common.io.CharStreams; |
| 9 import com.google.dart.compiler.DartCompilationError; | 9 import com.google.dart.compiler.DartCompilationError; |
| 10 import com.google.dart.compiler.DartCompilerListener; | 10 import com.google.dart.compiler.DartCompilerListener; |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 } finally { | 214 } finally { |
| 215 reader.close(); | 215 reader.close(); |
| 216 } | 216 } |
| 217 } | 217 } |
| 218 | 218 |
| 219 /** | 219 /** |
| 220 * A flag indicating whether function expressions are allowed. See | 220 * A flag indicating whether function expressions are allowed. See |
| 221 * {@link #setAllowFunctionExpression(boolean)}. | 221 * {@link #setAllowFunctionExpression(boolean)}. |
| 222 */ | 222 */ |
| 223 private boolean allowFunctionExpression = true; | 223 private boolean allowFunctionExpression = true; |
| 224 |
| 225 /** |
| 226 * 'break' (with no labels) and 'continue' stmts are not valid |
| 227 * just anywhere, they must be inside a loop or a case stmt. |
| 228 * |
| 229 * A break with a label may be valid and is allowed through and |
| 230 * checked in the resolver. |
| 231 */ |
| 232 private boolean inLoopOrCaseStatement = false; |
| 224 | 233 |
| 225 /** | 234 /** |
| 226 * Set the {@link #allowFunctionExpression} flag indicating whether function e
xpressions are | 235 * Set the {@link #allowFunctionExpression} flag indicating whether function e
xpressions are |
| 227 * allowed, returning the old value. This is required to avoid ambiguity in a
few places in the | 236 * allowed, returning the old value. This is required to avoid ambiguity in a
few places in the |
| 228 * grammar. | 237 * grammar. |
| 229 * | 238 * |
| 230 * @param allow true if function expressions are allowed, false if not | 239 * @param allow true if function expressions are allowed, false if not |
| 231 * @return previous value of the flag, which should be restored | 240 * @return previous value of the flag, which should be restored |
| 232 */ | 241 */ |
| 233 private boolean setAllowFunctionExpression(boolean allow) { | 242 private boolean setAllowFunctionExpression(boolean allow) { |
| (...skipping 2831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3065 * <pre> | 3074 * <pre> |
| 3066 * functionStatementBody | 3075 * functionStatementBody |
| 3067 * : '=>' expression ';' | 3076 * : '=>' expression ';' |
| 3068 * | block | 3077 * | block |
| 3069 * </pre> | 3078 * </pre> |
| 3070 * | 3079 * |
| 3071 * @param requireSemicolonForArrow true if a semicolon is required after an ar
row expression | 3080 * @param requireSemicolonForArrow true if a semicolon is required after an ar
row expression |
| 3072 * @return {@link DartBlock} instance containing function body | 3081 * @return {@link DartBlock} instance containing function body |
| 3073 */ | 3082 */ |
| 3074 private DartBlock parseFunctionStatementBody(boolean requireSemicolonForArrow)
{ | 3083 private DartBlock parseFunctionStatementBody(boolean requireSemicolonForArrow)
{ |
| 3084 // A break inside a function body should have nothing to do with a loop in |
| 3085 // the code surrounding the definition. |
| 3086 boolean oldInLoopOrCaseStatement = inLoopOrCaseStatement; |
| 3087 inLoopOrCaseStatement = false; |
| 3088 DartBlock result; |
| 3075 if (isDietParse) { | 3089 if (isDietParse) { |
| 3076 DartBlock emptyBlock = new DartBlock(new ArrayList<DartStatement>()); | 3090 result = dietParseFunctionStatementBody(); |
| 3077 if (optional(Token.ARROW)) { | |
| 3078 while (true) { | |
| 3079 Token token = next(); | |
| 3080 if (token == Token.SEMICOLON) { | |
| 3081 break; | |
| 3082 } | |
| 3083 } | |
| 3084 } else { | |
| 3085 if (!peek(0).equals(Token.LBRACE) && looksLikeTopLevelKeyword()) { | |
| 3086 // Allow recovery back to the top level. | |
| 3087 reportErrorWithoutAdvancing(ParserErrorCode.UNEXPECTED_TOKEN); | |
| 3088 return done(emptyBlock); | |
| 3089 } | |
| 3090 expect(Token.LBRACE); | |
| 3091 int nesting = 1; | |
| 3092 while (nesting > 0) { | |
| 3093 Token token = next(); | |
| 3094 switch (token) { | |
| 3095 case LBRACE: | |
| 3096 ++nesting; | |
| 3097 break; | |
| 3098 case RBRACE: | |
| 3099 --nesting; | |
| 3100 break; | |
| 3101 case EOS: | |
| 3102 return emptyBlock; | |
| 3103 } | |
| 3104 } | |
| 3105 } | |
| 3106 // Return an empty block so we don't generate unparseable code. | |
| 3107 return emptyBlock; | |
| 3108 } else { | 3091 } else { |
| 3109 beginFunctionStatementBody(); | 3092 beginFunctionStatementBody(); |
| 3110 if (optional(Token.ARROW)) { | 3093 if (optional(Token.ARROW)) { |
| 3111 DartExpression expr = parseExpression(); | 3094 DartExpression expr = parseExpression(); |
| 3112 if (expr == null) { | 3095 if (expr == null) { |
| 3113 expr = new DartSyntheticErrorExpression(); | 3096 expr = new DartSyntheticErrorExpression(); |
| 3114 } | 3097 } |
| 3115 if (requireSemicolonForArrow) { | 3098 if (requireSemicolonForArrow) { |
| 3116 expect(Token.SEMICOLON); | 3099 expect(Token.SEMICOLON); |
| 3117 } | 3100 } |
| 3118 return done(makeReturnBlock(expr)); | 3101 result = done(makeReturnBlock(expr)); |
| 3119 } else { | 3102 } else { |
| 3120 return done(parseBlock()); | 3103 result = done(parseBlock()); |
| 3121 } | 3104 } |
| 3122 } | 3105 } |
| 3106 inLoopOrCaseStatement = oldInLoopOrCaseStatement; |
| 3107 return result; |
| 3108 } |
| 3109 |
| 3110 private DartBlock dietParseFunctionStatementBody() { |
| 3111 DartBlock emptyBlock = new DartBlock(new ArrayList<DartStatement>()); |
| 3112 if (optional(Token.ARROW)) { |
| 3113 while (true) { |
| 3114 Token token = next(); |
| 3115 if (token == Token.SEMICOLON) { |
| 3116 break; |
| 3117 } |
| 3118 } |
| 3119 } else { |
| 3120 if (!peek(0).equals(Token.LBRACE) && looksLikeTopLevelKeyword()) { |
| 3121 // Allow recovery back to the top level. |
| 3122 reportErrorWithoutAdvancing(ParserErrorCode.UNEXPECTED_TOKEN); |
| 3123 return done(emptyBlock); |
| 3124 } |
| 3125 expect(Token.LBRACE); |
| 3126 int nesting = 1; |
| 3127 while (nesting > 0) { |
| 3128 Token token = next(); |
| 3129 switch (token) { |
| 3130 case LBRACE: |
| 3131 ++nesting; |
| 3132 break; |
| 3133 case RBRACE: |
| 3134 --nesting; |
| 3135 break; |
| 3136 case EOS: |
| 3137 return emptyBlock; |
| 3138 } |
| 3139 } |
| 3140 } |
| 3141 // Return an empty block so we don't generate unparseable code. |
| 3142 return emptyBlock; |
| 3123 } | 3143 } |
| 3124 | 3144 |
| 3125 /** | 3145 /** |
| 3126 * Create a block containing a single return statement. | 3146 * Create a block containing a single return statement. |
| 3127 * | 3147 * |
| 3128 * @param returnVal return value expression | 3148 * @param returnVal return value expression |
| 3129 * @return block containing a single return statement | 3149 * @return block containing a single return statement |
| 3130 */ | 3150 */ |
| 3131 private DartBlock makeReturnBlock(DartExpression returnVal) { | 3151 private DartBlock makeReturnBlock(DartExpression returnVal) { |
| 3132 return new DartReturnBlock(returnVal); | 3152 return new DartReturnBlock(returnVal); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3174 * | THROW expression? ';' | 3194 * | THROW expression? ';' |
| 3175 * ; | 3195 * ; |
| 3176 * </pre> | 3196 * </pre> |
| 3177 */ | 3197 */ |
| 3178 private DartBreakStatement parseBreakStatement() { | 3198 private DartBreakStatement parseBreakStatement() { |
| 3179 beginBreakStatement(); | 3199 beginBreakStatement(); |
| 3180 expect(Token.BREAK); | 3200 expect(Token.BREAK); |
| 3181 DartIdentifier label = null; | 3201 DartIdentifier label = null; |
| 3182 if (match(Token.IDENTIFIER)) { | 3202 if (match(Token.IDENTIFIER)) { |
| 3183 label = parseIdentifier(); | 3203 label = parseIdentifier(); |
| 3204 } else if (!inLoopOrCaseStatement) { |
| 3205 // The validation of matching of labels to break statements is done later. |
| 3206 reportErrorWithoutAdvancing(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP); |
| 3184 } | 3207 } |
| 3185 expectStatmentTerminator(); | 3208 expectStatmentTerminator(); |
| 3186 return done(new DartBreakStatement(label)); | 3209 return done(new DartBreakStatement(label)); |
| 3187 } | 3210 } |
| 3188 | 3211 |
| 3189 private DartContinueStatement parseContinueStatement() { | 3212 private DartContinueStatement parseContinueStatement() { |
| 3190 beginContinueStatement(); | 3213 beginContinueStatement(); |
| 3191 expect(Token.CONTINUE); | 3214 expect(Token.CONTINUE); |
| 3192 DartIdentifier label = null; | 3215 DartIdentifier label = null; |
| 3216 if (!inLoopOrCaseStatement) { |
| 3217 reportErrorWithoutAdvancing(ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP);
|
| 3218 } |
| 3193 if (peek(0) == Token.IDENTIFIER) { | 3219 if (peek(0) == Token.IDENTIFIER) { |
| 3194 label = parseIdentifier(); | 3220 label = parseIdentifier(); |
| 3195 } | 3221 } |
| 3196 expectStatmentTerminator(); | 3222 expectStatmentTerminator(); |
| 3197 return done(new DartContinueStatement(label)); | 3223 return done(new DartContinueStatement(label)); |
| 3198 } | 3224 } |
| 3199 | 3225 |
| 3200 private DartReturnStatement parseReturnStatement() { | 3226 private DartReturnStatement parseReturnStatement() { |
| 3201 beginReturnStatement(); | 3227 beginReturnStatement(); |
| 3202 expect(Token.RETURN); | 3228 expect(Token.RETURN); |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3646 * | FOR '(' forLoopParts ')' statement | 3672 * | FOR '(' forLoopParts ')' statement |
| 3647 * ; | 3673 * ; |
| 3648 * </pre> | 3674 * </pre> |
| 3649 */ | 3675 */ |
| 3650 private DartWhileStatement parseWhileStatement() { | 3676 private DartWhileStatement parseWhileStatement() { |
| 3651 beginWhileStatement(); | 3677 beginWhileStatement(); |
| 3652 expect(Token.WHILE); | 3678 expect(Token.WHILE); |
| 3653 expect(Token.LPAREN); | 3679 expect(Token.LPAREN); |
| 3654 DartExpression condition = parseExpression(); | 3680 DartExpression condition = parseExpression(); |
| 3655 expectCloseParen(); | 3681 expectCloseParen(); |
| 3656 DartStatement body = parseStatement(); | 3682 DartStatement body = parseLoopOrCaseStatement(); |
| 3657 return done(new DartWhileStatement(condition, body)); | 3683 return done(new DartWhileStatement(condition, body)); |
| 3658 } | 3684 } |
| 3659 | 3685 |
| 3660 /** | 3686 /** |
| 3661 * <pre> | 3687 * <pre> |
| 3662 * iterationStatement | 3688 * iterationStatement |
| 3663 * : WHILE '(' expression ')' statement | 3689 * : WHILE '(' expression ')' statement |
| 3664 * | DO statement WHILE '(' expression ')' ';' | 3690 * | DO statement WHILE '(' expression ')' ';' |
| 3665 * | FOR '(' forLoopParts ')' statement | 3691 * | FOR '(' forLoopParts ')' statement |
| 3666 * ; | 3692 * ; |
| 3667 * </pre> | 3693 * </pre> |
| 3668 */ | 3694 */ |
| 3669 private DartDoWhileStatement parseDoWhileStatement() { | 3695 private DartDoWhileStatement parseDoWhileStatement() { |
| 3670 beginDoStatement(); | 3696 beginDoStatement(); |
| 3671 expect(Token.DO); | 3697 expect(Token.DO); |
| 3672 DartStatement body = parseStatement(); | 3698 DartStatement body = parseLoopOrCaseStatement(); |
| 3673 expect(Token.WHILE); | 3699 expect(Token.WHILE); |
| 3674 expect(Token.LPAREN); | 3700 expect(Token.LPAREN); |
| 3675 DartExpression condition = parseExpression(); | 3701 DartExpression condition = parseExpression(); |
| 3676 expectCloseParen(); | 3702 expectCloseParen(); |
| 3677 expectStatmentTerminator(); | 3703 expectStatmentTerminator(); |
| 3678 return done(new DartDoWhileStatement(condition, body)); | 3704 return done(new DartDoWhileStatement(condition, body)); |
| 3679 } | 3705 } |
| 3680 | 3706 |
| 3681 /** | 3707 /** |
| 3708 * Use this wrapper to parse the body of a loop or case statement. |
| 3709 * |
| 3710 * Sets up flag variables to make sure continue and break are properly |
| 3711 * marked as errors when in wrong context. |
| 3712 */ |
| 3713 private DartStatement parseLoopOrCaseStatement() { |
| 3714 boolean oldInBreakable = inLoopOrCaseStatement; |
| 3715 inLoopOrCaseStatement = true; |
| 3716 DartStatement stmt = parseStatement(); |
| 3717 inLoopOrCaseStatement = oldInBreakable; |
| 3718 return stmt; |
| 3719 } |
| 3720 |
| 3721 /** |
| 3682 * <pre> | 3722 * <pre> |
| 3683 * iterationStatement | 3723 * iterationStatement |
| 3684 * : WHILE '(' expression ')' statement | 3724 * : WHILE '(' expression ')' statement |
| 3685 * | DO statement WHILE '(' expression ')' ';' | 3725 * | DO statement WHILE '(' expression ')' ';' |
| 3686 * | FOR '(' forLoopParts ')' statement | 3726 * | FOR '(' forLoopParts ')' statement |
| 3687 * ; | 3727 * ; |
| 3688 * | 3728 * |
| 3689 * forLoopParts | 3729 * forLoopParts |
| 3690 * : forInitializerStatement expression? ';' expressionList? | 3730 * : forInitializerStatement expression? ';' expressionList? |
| 3691 * | constVarOrType? identifier IN expression | 3731 * | constVarOrType? identifier IN expression |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3738 } else { | 3778 } else { |
| 3739 DartExpression expression = ((DartExprStmt) setup).getExpression(); | 3779 DartExpression expression = ((DartExprStmt) setup).getExpression(); |
| 3740 if (!(expression instanceof DartIdentifier)) { | 3780 if (!(expression instanceof DartIdentifier)) { |
| 3741 reportError(setup, ParserErrorCode.FOR_IN_WITH_COMPLEX_VARIABLE); | 3781 reportError(setup, ParserErrorCode.FOR_IN_WITH_COMPLEX_VARIABLE); |
| 3742 } | 3782 } |
| 3743 } | 3783 } |
| 3744 | 3784 |
| 3745 DartExpression iterable = parseExpression(); | 3785 DartExpression iterable = parseExpression(); |
| 3746 expectCloseParen(); | 3786 expectCloseParen(); |
| 3747 | 3787 |
| 3748 DartStatement body = parseStatement(); | 3788 DartStatement body = parseLoopOrCaseStatement(); |
| 3749 return done(new DartForInStatement(setup, iterable, body)); | 3789 return done(new DartForInStatement(setup, iterable, body)); |
| 3750 | 3790 |
| 3751 } else if (optional(Token.SEMICOLON)) { | 3791 } else if (optional(Token.SEMICOLON)) { |
| 3752 | 3792 |
| 3753 // Condition | 3793 // Condition |
| 3754 DartExpression condition = null; | 3794 DartExpression condition = null; |
| 3755 if (peek(0) != Token.SEMICOLON) { | 3795 if (peek(0) != Token.SEMICOLON) { |
| 3756 condition = parseExpression(); | 3796 condition = parseExpression(); |
| 3757 } | 3797 } |
| 3758 expect(Token.SEMICOLON); | 3798 expect(Token.SEMICOLON); |
| 3759 | 3799 |
| 3760 // Next | 3800 // Next |
| 3761 DartExpression next = null; | 3801 DartExpression next = null; |
| 3762 if (peek(0) != Token.RPAREN) { | 3802 if (peek(0) != Token.RPAREN) { |
| 3763 next = parseExpressionList(); | 3803 next = parseExpressionList(); |
| 3764 } | 3804 } |
| 3765 expectCloseParen(); | 3805 expectCloseParen(); |
| 3766 | 3806 |
| 3767 DartStatement body = parseStatement(); | 3807 DartStatement body = parseLoopOrCaseStatement(); |
| 3768 return done(new DartForStatement(setup, condition, next, body)); | 3808 return done(new DartForStatement(setup, condition, next, body)); |
| 3769 } else { | 3809 } else { |
| 3770 reportUnexpectedToken(position(), null, peek(0)); | 3810 reportUnexpectedToken(position(), null, peek(0)); |
| 3771 return done(parseErrorStatement()); | 3811 return done(parseErrorStatement()); |
| 3772 } | 3812 } |
| 3773 } | 3813 } |
| 3774 | 3814 |
| 3775 /** | 3815 /** |
| 3776 * <pre> | 3816 * <pre> |
| 3777 * selectionStatement | 3817 * selectionStatement |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3805 List<DartStatement> statements = new ArrayList<DartStatement>(); | 3845 List<DartStatement> statements = new ArrayList<DartStatement>(); |
| 3806 DartStatement statement = null; | 3846 DartStatement statement = null; |
| 3807 while (true) { | 3847 while (true) { |
| 3808 switch (peek(0)) { | 3848 switch (peek(0)) { |
| 3809 case CASE: | 3849 case CASE: |
| 3810 case DEFAULT: | 3850 case DEFAULT: |
| 3811 case RBRACE: | 3851 case RBRACE: |
| 3812 case EOS: | 3852 case EOS: |
| 3813 return statements; | 3853 return statements; |
| 3814 default: | 3854 default: |
| 3815 if ((statement = parseStatement()) == null) { | 3855 if ((statement = parseLoopOrCaseStatement()) == null) { |
| 3816 return statements; | 3856 return statements; |
| 3817 } | 3857 } |
| 3818 statements.add(statement); | 3858 statements.add(statement); |
| 3819 if (statement.isAbruptCompletingStatement()) { | 3859 if (statement.isAbruptCompletingStatement()) { |
| 3820 /* | 3860 /* |
| 3821 * TODO(jat): is this correct? It seems like we would get better | 3861 * TODO(jat): is this correct? It seems like we would get better |
| 3822 * error messages if we parsed dead code as part of this case block | 3862 * error messages if we parsed dead code as part of this case block |
| 3823 * and gave an error for unreachable code | 3863 * and gave an error for unreachable code |
| 3824 */ | 3864 */ |
| 3825 return statements; | 3865 return statements; |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4202 } | 4242 } |
| 4203 | 4243 |
| 4204 private void reportError(DartNode node, ErrorCode errorCode, Object... argumen
ts) { | 4244 private void reportError(DartNode node, ErrorCode errorCode, Object... argumen
ts) { |
| 4205 reportError(new DartCompilationError(node, errorCode, arguments)); | 4245 reportError(new DartCompilationError(node, errorCode, arguments)); |
| 4206 } | 4246 } |
| 4207 | 4247 |
| 4208 private boolean currentlyParsingToplevel() { | 4248 private boolean currentlyParsingToplevel() { |
| 4209 return !(isParsingInterface || isTopLevelAbstract || isParsingClass); | 4249 return !(isParsingInterface || isTopLevelAbstract || isParsingClass); |
| 4210 } | 4250 } |
| 4211 } | 4251 } |
| OLD | NEW |