Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(956)

Side by Side Diff: dart/pkg/polymer_expressions/lib/parser.dart

Issue 336013003: Version 1.5.0-dev.4.14 (Closed) Base URL: http://dart.googlecode.com/svn/trunk/
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 export 'tokenizer.dart' show ParseException;
8 import 'expression.dart'; 9 import 'expression.dart';
9 10
10 const _UNARY_OPERATORS = const ['+', '-', '!']; 11 const _UNARY_OPERATORS = const <String>['+', '-', '!'];
12 const _BINARY_OPERATORS = const <String>['+', '-', '*', '/', '%', '^', '==',
13 '!=', '>', '<', '>=', '<=', '||', '&&', '&', '===', '!==', '|'];
11 14
12 Expression parse(String expr) => new Parser(expr).parse(); 15 Expression parse(String expr) => new Parser(expr).parse();
13 16
14 class Parser { 17 class Parser {
15 final AstFactory _astFactory; 18 final AstFactory _astFactory;
16 final Tokenizer _tokenizer; 19 final Tokenizer _tokenizer;
17 List<Token> _tokens; 20 List<Token> _tokens;
18 Iterator _iterator; 21 Iterator _iterator;
19 Token get _token => _iterator.current; 22 Token get _token => _iterator.current;
20 23
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 } else if (right is Invoke && right.receiver is Identifier) { 92 } else if (right is Invoke && right.receiver is Identifier) {
90 Identifier method = right.receiver; 93 Identifier method = right.receiver;
91 return _astFactory.invoke(left, method.value, right.arguments); 94 return _astFactory.invoke(left, method.value, right.arguments);
92 } else { 95 } else {
93 throw new ParseException("expected identifier: $right"); 96 throw new ParseException("expected identifier: $right");
94 } 97 }
95 } 98 }
96 99
97 Expression _parseBinary(left) { 100 Expression _parseBinary(left) {
98 var op = _token; 101 var op = _token;
102 if (!_BINARY_OPERATORS.contains(op.value)) {
103 throw new ParseException("unknown operator: ${op.value}");
104 }
99 _advance(); 105 _advance();
100 var right = _parseUnary(); 106 var right = _parseUnary();
101 while (_token != null 107 while (_token != null
102 && (_token.kind == OPERATOR_TOKEN 108 && (_token.kind == OPERATOR_TOKEN
103 || _token.kind == DOT_TOKEN 109 || _token.kind == DOT_TOKEN
104 || _token.kind == GROUPER_TOKEN) 110 || _token.kind == GROUPER_TOKEN)
105 && _token.precedence > op.precedence) { 111 && _token.precedence > op.precedence) {
106 right = _parsePrecedence(right, _token.precedence); 112 right = _parsePrecedence(right, _token.precedence);
107 } 113 }
108 return _astFactory.binary(left, op.value, right); 114 return _astFactory.binary(left, op.value, right);
109 } 115 }
110 116
111 Expression _parseUnary() { 117 Expression _parseUnary() {
112 if (_token.kind == OPERATOR_TOKEN) { 118 if (_token.kind == OPERATOR_TOKEN) {
113 var value = _token.value; 119 var value = _token.value;
114 if (value == '+' || value == '-') { 120 if (value == '+' || value == '-') {
115 _advance(); 121 _advance();
116 if (_token.kind == INTEGER_TOKEN) { 122 if (_token.kind == INTEGER_TOKEN) {
117 return _parseInteger(value); 123 return _parseInteger(value);
118 } else if (_token.kind == DECIMAL_TOKEN) { 124 } else if (_token.kind == DECIMAL_TOKEN) {
119 return _parseDecimal(value); 125 return _parseDecimal(value);
120 } else { 126 } else {
121 var expr = _parsePrecedence(_parsePrimary(), POSTFIX_PRECEDENCE); 127 var expr = _parsePrecedence(_parsePrimary(), POSTFIX_PRECEDENCE);
122 return _astFactory.unary(value, expr); 128 return _astFactory.unary(value, expr);
123 } 129 }
124 } else if (value == '!') { 130 } else if (value == '!') {
125 _advance(); 131 _advance();
126 var expr = _parsePrecedence(_parsePrimary(), POSTFIX_PRECEDENCE); 132 var expr = _parsePrecedence(_parsePrimary(), POSTFIX_PRECEDENCE);
127 return _astFactory.unary(value, expr); 133 return _astFactory.unary(value, expr);
134 } else {
135 throw new ParseException("unexpected token: $value");
128 } 136 }
129 } 137 }
130 return _parsePrimary(); 138 return _parsePrimary();
131 } 139 }
132 140
133 Expression _parseTernary(condition) { 141 Expression _parseTernary(condition) {
134 _advance(OPERATOR_TOKEN, '?'); 142 _advance(OPERATOR_TOKEN, '?');
135 var trueExpr = _parseExpression(); 143 var trueExpr = _parseExpression();
136 _advance(COLON_TOKEN); 144 _advance(COLON_TOKEN);
137 var falseExpr = _parseExpression(); 145 var falseExpr = _parseExpression();
138 return _astFactory.ternary(condition, trueExpr, falseExpr); 146 return _astFactory.ternary(condition, trueExpr, falseExpr);
139 } 147 }
140 148
141 Expression _parsePrimary() { 149 Expression _parsePrimary() {
142 var kind = _token.kind; 150 var kind = _token.kind;
143 switch (kind) { 151 switch (kind) {
144 case KEYWORD_TOKEN: 152 case KEYWORD_TOKEN:
145 var keyword = _token.value; 153 var keyword = _token.value;
146 if (keyword == 'this') { 154 if (keyword == 'this') {
147 _advance(); 155 _advance();
148 // TODO(justin): return keyword node 156 // TODO(justin): return keyword node
149 return _astFactory.identifier('this'); 157 return _astFactory.identifier('this');
150 } else if (KEYWORDS.contains(keyword)) { 158 } else if (KEYWORDS.contains(keyword)) {
151 throw new ParseException('invalid keyword: $keyword'); 159 throw new ParseException('unexpected keyword: $keyword');
152 } 160 }
153 throw new ArgumentError('unrecognized keyword: $keyword'); 161 throw new ParseException('unrecognized keyword: $keyword');
154 case IDENTIFIER_TOKEN: 162 case IDENTIFIER_TOKEN:
155 return _parseInvokeOrIdentifier(); 163 return _parseInvokeOrIdentifier();
156 case STRING_TOKEN: 164 case STRING_TOKEN:
157 return _parseString(); 165 return _parseString();
158 case INTEGER_TOKEN: 166 case INTEGER_TOKEN:
159 return _parseInteger(); 167 return _parseInteger();
160 case DECIMAL_TOKEN: 168 case DECIMAL_TOKEN:
161 return _parseDecimal(); 169 return _parseDecimal();
162 case GROUPER_TOKEN: 170 case GROUPER_TOKEN:
163 if (_token.value == '(') { 171 if (_token.value == '(') {
164 return _parseParenthesized(); 172 return _parseParenthesized();
165 } else if (_token.value == '{') { 173 } else if (_token.value == '{') {
166 return _parseMapLiteral(); 174 return _parseMapLiteral();
167 } else if (_token.value == '[') { 175 } else if (_token.value == '[') {
168 return _parseListLiteral(); 176 return _parseListLiteral();
169 } 177 }
170 return null; 178 return null;
171 case COLON_TOKEN: 179 case COLON_TOKEN:
172 // TODO(justinfagnani): We need better errors throughout the parser, and 180 throw new ParseException('unexpected token ":"');
173 // we should be throwing ParseErrors to be caught by the caller
174 throw new ArgumentError('unexpected token ":"');
175 default: 181 default:
176 return null; 182 return null;
177 } 183 }
178 } 184 }
179 185
180 ListLiteral _parseListLiteral() { 186 ListLiteral _parseListLiteral() {
181 var items = []; 187 var items = [];
182 do { 188 do {
183 _advance(); 189 _advance();
184 if (_token.kind == GROUPER_TOKEN && _token.value == ']') { 190 if (_token.kind == GROUPER_TOKEN && _token.value == ']') {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 var right = _parseExpression(); 226 var right = _parseExpression();
221 return _astFactory.inExpr(left, right); 227 return _astFactory.inExpr(left, right);
222 } 228 }
223 229
224 AsExpression _parseAsExpression(Expression left) { 230 AsExpression _parseAsExpression(Expression left) {
225 assert(_token.value == 'as'); 231 assert(_token.value == 'as');
226 _advance(); 232 _advance();
227 var right = _parseExpression(); 233 var right = _parseExpression();
228 if (right is! Identifier) { 234 if (right is! Identifier) {
229 throw new ParseException( 235 throw new ParseException(
230 "as... statements must end with an identifier"); 236 "'as' statements must end with an identifier");
231 } 237 }
232 return _astFactory.asExpr(left, right); 238 return _astFactory.asExpr(left, right);
233 } 239 }
234 240
235 Expression _parseInvokeOrIdentifier() { 241 Expression _parseInvokeOrIdentifier() {
236 if (_token.value == 'true') { 242 if (_token.value == 'true') {
237 _advance(); 243 _advance();
238 return _astFactory.literal(true); 244 return _astFactory.literal(true);
239 } 245 }
240 if (_token.value == 'false') { 246 if (_token.value == 'false') {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 return value; 315 return value;
310 } 316 }
311 317
312 Literal<double> _parseDecimal([String prefix = '']) { 318 Literal<double> _parseDecimal([String prefix = '']) {
313 var value = _astFactory.literal(double.parse('$prefix${_token.value}')); 319 var value = _astFactory.literal(double.parse('$prefix${_token.value}'));
314 _advance(); 320 _advance();
315 return value; 321 return value;
316 } 322 }
317 323
318 } 324 }
OLDNEW
« no previous file with comments | « dart/pkg/polymer_expressions/lib/eval.dart ('k') | dart/pkg/polymer_expressions/lib/polymer_expressions.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698