| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 polymer_expressions.parser; | 5 library polymer_expressions.parser; |
| 6 | 6 |
| 7 import 'tokenizer.dart'; | 7 import 'tokenizer.dart'; |
| 8 import 'expression.dart'; | 8 import 'expression.dart'; |
| 9 | 9 |
| 10 const _UNARY_OPERATORS = const ['+', '-', '!']; | 10 const _UNARY_OPERATORS = const ['+', '-', '!']; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 left = _astFactory.index(left, indexExpr); | 59 left = _astFactory.index(left, indexExpr); |
| 60 } else { | 60 } else { |
| 61 break; | 61 break; |
| 62 } | 62 } |
| 63 } else if (_token.kind == DOT_TOKEN) { | 63 } else if (_token.kind == DOT_TOKEN) { |
| 64 _advance(); | 64 _advance(); |
| 65 var right = _parseUnary(); | 65 var right = _parseUnary(); |
| 66 left = _makeInvokeOrGetter(left, right); | 66 left = _makeInvokeOrGetter(left, right); |
| 67 } else if (_token.kind == KEYWORD_TOKEN && _token.value == 'in') { | 67 } else if (_token.kind == KEYWORD_TOKEN && _token.value == 'in') { |
| 68 left = _parseComprehension(left); | 68 left = _parseComprehension(left); |
| 69 } else if (_token.kind == OPERATOR_TOKEN && _token.value == '?') { |
| 70 left = _parseTernary(left); |
| 69 } else if (_token.kind == OPERATOR_TOKEN | 71 } else if (_token.kind == OPERATOR_TOKEN |
| 70 && _token.precedence >= precedence) { | 72 && _token.precedence >= precedence) { |
| 71 left = _parseBinary(left); | 73 left = _parseBinary(left); |
| 72 } else { | 74 } else { |
| 73 break; | 75 break; |
| 74 } | 76 } |
| 75 } | 77 } |
| 76 return left; | 78 return left; |
| 77 } | 79 } |
| 78 | 80 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 } | 119 } |
| 118 } else if (value == '!') { | 120 } else if (value == '!') { |
| 119 _advance(); | 121 _advance(); |
| 120 var expr = _parsePrecedence(_parsePrimary(), POSTFIX_PRECEDENCE); | 122 var expr = _parsePrecedence(_parsePrimary(), POSTFIX_PRECEDENCE); |
| 121 return _astFactory.unary(value, expr); | 123 return _astFactory.unary(value, expr); |
| 122 } | 124 } |
| 123 } | 125 } |
| 124 return _parsePrimary(); | 126 return _parsePrimary(); |
| 125 } | 127 } |
| 126 | 128 |
| 129 Expression _parseTernary(condition) { |
| 130 _advance(OPERATOR_TOKEN, '?'); |
| 131 var trueExpr = _parseExpression(); |
| 132 _advance(COLON_TOKEN); |
| 133 var falseExpr = _parseExpression(); |
| 134 return _astFactory.ternary(condition, trueExpr, falseExpr); |
| 135 } |
| 136 |
| 127 Expression _parsePrimary() { | 137 Expression _parsePrimary() { |
| 128 var kind = _token.kind; | 138 var kind = _token.kind; |
| 129 switch (kind) { | 139 switch (kind) { |
| 130 case KEYWORD_TOKEN: | 140 case KEYWORD_TOKEN: |
| 131 var keyword = _token.value; | 141 var keyword = _token.value; |
| 132 if (keyword == 'this') { | 142 if (keyword == 'this') { |
| 133 _advance(); | 143 _advance(); |
| 134 // TODO(justin): return keyword node | 144 // TODO(justin): return keyword node |
| 135 return _astFactory.identifier('this'); | 145 return _astFactory.identifier('this'); |
| 136 } else if (keyword == 'in') { | 146 } else if (keyword == 'in') { |
| 137 return null; | 147 return null; |
| 138 } | 148 } |
| 139 throw new ArgumentError('unrecognized keyword: $keyword'); | 149 throw new ArgumentError('unrecognized keyword: $keyword'); |
| 140 case IDENTIFIER_TOKEN: | 150 case IDENTIFIER_TOKEN: |
| 141 return _parseInvokeOrIdentifier(); | 151 return _parseInvokeOrIdentifier(); |
| 142 case STRING_TOKEN: | 152 case STRING_TOKEN: |
| 143 return _parseString(); | 153 return _parseString(); |
| 144 case INTEGER_TOKEN: | 154 case INTEGER_TOKEN: |
| 145 return _parseInteger(); | 155 return _parseInteger(); |
| 146 case DECIMAL_TOKEN: | 156 case DECIMAL_TOKEN: |
| 147 return _parseDecimal(); | 157 return _parseDecimal(); |
| 148 case GROUPER_TOKEN: | 158 case GROUPER_TOKEN: |
| 149 if (_token.value == '(') { | 159 if (_token.value == '(') { |
| 150 return _parseParenthesized(); | 160 return _parseParenthesized(); |
| 151 } else if (_token.value == '{') { | 161 } else if (_token.value == '{') { |
| 152 return _parseMapLiteral(); | 162 return _parseMapLiteral(); |
| 153 } | 163 } |
| 154 return null; | 164 return null; |
| 165 case COLON_TOKEN: |
| 166 // TODO(justinfagnani): We need better errors throughout the parser, and |
| 167 // we should be throwing ParseErrors to be caught by the caller |
| 168 throw new ArgumentError('unexpected token ":"'); |
| 155 default: | 169 default: |
| 156 return null; | 170 return null; |
| 157 } | 171 } |
| 158 } | 172 } |
| 159 | 173 |
| 160 MapLiteral _parseMapLiteral() { | 174 MapLiteral _parseMapLiteral() { |
| 161 var entries = []; | 175 var entries = []; |
| 162 do { | 176 do { |
| 163 _advance(); | 177 _advance(); |
| 164 if (_token.kind == GROUPER_TOKEN && _token.value == '}') { | 178 if (_token.kind == GROUPER_TOKEN && _token.value == '}') { |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 return value; | 279 return value; |
| 266 } | 280 } |
| 267 | 281 |
| 268 Literal<double> _parseDecimal([String prefix = '']) { | 282 Literal<double> _parseDecimal([String prefix = '']) { |
| 269 var value = _astFactory.literal(double.parse('$prefix${_token.value}')); | 283 var value = _astFactory.literal(double.parse('$prefix${_token.value}')); |
| 270 _advance(); | 284 _advance(); |
| 271 return value; | 285 return value; |
| 272 } | 286 } |
| 273 | 287 |
| 274 } | 288 } |
| OLD | NEW |