| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 // TODO(jimhug): Error recovery needs major work! | 5 // TODO(jimhug): Error recovery needs major work! |
| 6 /** | 6 /** |
| 7 * A simple recursive descent parser for the dart language. | 7 * A simple recursive descent parser for the dart language. |
| 8 * | 8 * |
| 9 * This parser is designed to be more permissive than the official | 9 * This parser is designed to be more permissive than the official |
| 10 * Dart grammar. It is expected that many grammar errors would be | 10 * Dart grammar. It is expected that many grammar errors would be |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 /** Allow semicolons to be omitted at the end of lines. */ | 27 /** Allow semicolons to be omitted at the end of lines. */ |
| 28 // TODO(nweiz): make this work for more than just end-of-file | 28 // TODO(nweiz): make this work for more than just end-of-file |
| 29 final bool optionalSemicolons; | 29 final bool optionalSemicolons; |
| 30 | 30 |
| 31 /** | 31 /** |
| 32 * Allow the await keyword, when the await transformation is available (see | 32 * Allow the await keyword, when the await transformation is available (see |
| 33 * await/awaitc.dart). | 33 * await/awaitc.dart). |
| 34 */ | 34 */ |
| 35 bool get enableAwait() => experimentalAwaitPhase != null; | 35 bool get enableAwait() => experimentalAwaitPhase != null; |
| 36 | 36 |
| 37 /** To prevent conflicts in initializers */ | 37 /** |
| 38 bool _inInitializers; | 38 * To resolve ambiguity in initializers between constructor body and lambda |
| 39 * expression. |
| 40 */ |
| 41 bool _inhibitLambda; |
| 39 | 42 |
| 40 Token _previousToken; | 43 Token _previousToken; |
| 41 Token _peekToken; | 44 Token _peekToken; |
| 42 | 45 |
| 43 // When we encounter '(' in a method body we need to find the ')' to know it | 46 // When we encounter '(' in a method body we need to find the ')' to know it |
| 44 // we're parsing a lambda, paren-expr, or argument list. Closure formals are | 47 // we're parsing a lambda, paren-expr, or argument list. Closure formals are |
| 45 // followed by '=>' or '{'. This list is used to cache the tokens after any | 48 // followed by '=>' or '{'. This list is used to cache the tokens after any |
| 46 // nested parenthesis we find while peeking. | 49 // nested parenthesis we find while peeking. |
| 47 // TODO(jmesserly): it's simpler and faster to cache this on the Token itself, | 50 // TODO(jmesserly): it's simpler and faster to cache this on the Token itself, |
| 48 // but that might add too much complexity for tools that need to invalidate. | 51 // but that might add too much complexity for tools that need to invalidate. |
| 49 List<Token> _afterParens; | 52 List<Token> _afterParens; |
| 50 int _afterParensIndex = 0; | 53 int _afterParensIndex = 0; |
| 51 | 54 |
| 52 Parser(this.source, [this.diet = false, this.throwOnIncomplete = false, | 55 Parser(this.source, [this.diet = false, this.throwOnIncomplete = false, |
| 53 this.optionalSemicolons = false, int startOffset = 0]) { | 56 this.optionalSemicolons = false, int startOffset = 0]) { |
| 54 tokenizer = new Tokenizer(source, true, startOffset); | 57 tokenizer = new Tokenizer(source, true, startOffset); |
| 55 _peekToken = tokenizer.next(); | 58 _peekToken = tokenizer.next(); |
| 56 _previousToken = null; | 59 _previousToken = null; |
| 57 _inInitializers = false; | 60 _inhibitLambda = false; |
| 58 _afterParens = <Token>[]; | 61 _afterParens = <Token>[]; |
| 59 } | 62 } |
| 60 | 63 |
| 61 /** Generate an error if [source] has not been completely consumed. */ | 64 /** Generate an error if [source] has not been completely consumed. */ |
| 62 void checkEndOfFile() { | 65 void checkEndOfFile() { |
| 63 _eat(TokenKind.END_OF_FILE); | 66 _eat(TokenKind.END_OF_FILE); |
| 64 } | 67 } |
| 65 | 68 |
| 66 /** Guard to break out of parser when an unexpected end of file is found. */ | 69 /** Guard to break out of parser when an unexpected end of file is found. */ |
| 67 // TODO(jimhug): Failure to call this method can lead to inifinite parser | 70 // TODO(jimhug): Failure to call this method can lead to inifinite parser |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 var formals = formalParameterList(); | 280 var formals = formalParameterList(); |
| 278 _eatSemicolon(); | 281 _eatSemicolon(); |
| 279 | 282 |
| 280 var func = new FunctionDefinition(null, di.type, di.name, formals, | 283 var func = new FunctionDefinition(null, di.type, di.name, formals, |
| 281 null, null, null, null, _makeSpan(start)); | 284 null, null, null, null, _makeSpan(start)); |
| 282 | 285 |
| 283 return new FunctionTypeDefinition(func, typeParams, _makeSpan(start)); | 286 return new FunctionTypeDefinition(func, typeParams, _makeSpan(start)); |
| 284 } | 287 } |
| 285 | 288 |
| 286 initializers() { | 289 initializers() { |
| 287 _inInitializers = true; | 290 _inhibitLambda = true; |
| 288 var ret = []; | 291 var ret = []; |
| 289 do { | 292 do { |
| 290 ret.add(expression()); | 293 ret.add(expression()); |
| 291 } while (_maybeEat(TokenKind.COMMA)); | 294 } while (_maybeEat(TokenKind.COMMA)); |
| 292 _inInitializers = false; | 295 _inhibitLambda = false; |
| 293 return ret; | 296 return ret; |
| 294 } | 297 } |
| 295 | 298 |
| 296 functionBody(bool inExpression) { | 299 functionBody(bool inExpression) { |
| 297 int start = _peekToken.start; | 300 int start = _peekToken.start; |
| 298 if (_maybeEat(TokenKind.ARROW)) { | 301 if (_maybeEat(TokenKind.ARROW)) { |
| 299 var expr = expression(); | 302 var expr = expression(); |
| 300 if (!inExpression) { | 303 if (!inExpression) { |
| 301 _eatSemicolon(); | 304 _eatSemicolon(); |
| 302 } | 305 } |
| (...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 922 if (label === null && _maybeEat(TokenKind.COLON)) { | 925 if (label === null && _maybeEat(TokenKind.COLON)) { |
| 923 label = _makeLabel(expr); | 926 label = _makeLabel(expr); |
| 924 expr = expression(); | 927 expr = expression(); |
| 925 } | 928 } |
| 926 return new ArgumentNode(label, expr, _makeSpan(start)); | 929 return new ArgumentNode(label, expr, _makeSpan(start)); |
| 927 } | 930 } |
| 928 | 931 |
| 929 arguments() { | 932 arguments() { |
| 930 var args = []; | 933 var args = []; |
| 931 _eatLeftParen(); | 934 _eatLeftParen(); |
| 935 var saved = _inhibitLambda; |
| 936 _inhibitLambda = false; |
| 932 if (!_maybeEat(TokenKind.RPAREN)) { | 937 if (!_maybeEat(TokenKind.RPAREN)) { |
| 933 do { | 938 do { |
| 934 args.add(argument()); | 939 args.add(argument()); |
| 935 } while (_maybeEat(TokenKind.COMMA)); | 940 } while (_maybeEat(TokenKind.COMMA)); |
| 936 _eat(TokenKind.RPAREN); | 941 _eat(TokenKind.RPAREN); |
| 937 } | 942 } |
| 943 _inhibitLambda = saved; |
| 938 return args; | 944 return args; |
| 939 } | 945 } |
| 940 | 946 |
| 941 finishPostfixExpression(expr) { | 947 finishPostfixExpression(expr) { |
| 942 switch(_peek()) { | 948 switch(_peek()) { |
| 943 case TokenKind.LPAREN: | 949 case TokenKind.LPAREN: |
| 944 return finishCallOrLambdaExpression(expr); | 950 return finishCallOrLambdaExpression(expr); |
| 945 case TokenKind.LBRACK: | 951 case TokenKind.LBRACK: |
| 946 _eat(TokenKind.LBRACK); | 952 _eat(TokenKind.LBRACK); |
| 947 var index = expression(); | 953 var index = expression(); |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1172 | 1178 |
| 1173 _parenOrLambda() { | 1179 _parenOrLambda() { |
| 1174 int start = _peekToken.start; | 1180 int start = _peekToken.start; |
| 1175 if (_atClosureParameters()) { | 1181 if (_atClosureParameters()) { |
| 1176 var formals = formalParameterList(); | 1182 var formals = formalParameterList(); |
| 1177 var body = functionBody(true); | 1183 var body = functionBody(true); |
| 1178 var func = new FunctionDefinition(null, null, null, formals, null, null, | 1184 var func = new FunctionDefinition(null, null, null, formals, null, null, |
| 1179 null, body, _makeSpan(start)); | 1185 null, body, _makeSpan(start)); |
| 1180 return new LambdaExpression(func, func.span); | 1186 return new LambdaExpression(func, func.span); |
| 1181 } else { | 1187 } else { |
| 1182 var saved = _inInitializers; | 1188 _eatLeftParen(); |
| 1183 _inInitializers = false; | 1189 var saved = _inhibitLambda; |
| 1184 var args = arguments(); | 1190 _inhibitLambda = false; |
| 1185 _inInitializers = saved; | 1191 var expr = expression(); |
| 1186 if (args.length == 1) { | 1192 _eat(TokenKind.RPAREN); |
| 1187 return new ParenExpression(args[0].value, _makeSpan(start)); | 1193 _inhibitLambda = saved; |
| 1188 } else { | 1194 return new ParenExpression(expr, _makeSpan(start)); |
| 1189 _error('unexpected comma expression'); | |
| 1190 return args[0].value; | |
| 1191 } | |
| 1192 } | 1195 } |
| 1193 } | 1196 } |
| 1194 | 1197 |
| 1195 bool _atClosureParameters() { | 1198 bool _atClosureParameters() { |
| 1196 if (_inInitializers) return false; | 1199 if (_inhibitLambda) return false; |
| 1197 Token after = _peekAfterCloseParen(); | 1200 Token after = _peekAfterCloseParen(); |
| 1198 return after.kind == TokenKind.ARROW || after.kind == TokenKind.LBRACE; | 1201 return after.kind == TokenKind.ARROW || after.kind == TokenKind.LBRACE; |
| 1199 } | 1202 } |
| 1200 | 1203 |
| 1201 /** Eats an LPAREN, and advances our after-RPAREN lookahead. */ | 1204 /** Eats an LPAREN, and advances our after-RPAREN lookahead. */ |
| 1202 _eatLeftParen() { | 1205 _eatLeftParen() { |
| 1203 _eat(TokenKind.LPAREN); | 1206 _eat(TokenKind.LPAREN); |
| 1204 _afterParensIndex++; | 1207 _afterParensIndex++; |
| 1205 } | 1208 } |
| 1206 | 1209 |
| (...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1700 int _pos = 0; | 1703 int _pos = 0; |
| 1701 next() { | 1704 next() { |
| 1702 var token = tokens[_pos]; | 1705 var token = tokens[_pos]; |
| 1703 ++_pos; | 1706 ++_pos; |
| 1704 if (_pos == tokens.length) { | 1707 if (_pos == tokens.length) { |
| 1705 parser.tokenizer = previousTokenizer; | 1708 parser.tokenizer = previousTokenizer; |
| 1706 } | 1709 } |
| 1707 return token; | 1710 return token; |
| 1708 } | 1711 } |
| 1709 } | 1712 } |
| OLD | NEW |