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

Side by Side Diff: third_party/pkg/angular/lib/core/parser/parser.dart

Issue 148453003: Updating Angular version (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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 part of angular.core.parser; 1 library angular.core.parser;
2 2
3 typedef ParsedGetter(self); 3 export 'package:angular/core/parser/syntax.dart'
4 typedef ParsedSetter(self, value); 4 show Visitor, Expression, BoundExpression;
5 export 'package:angular/core/parser/dynamic_parser.dart'
6 show DynamicParser, DynamicParserBackend, ClosureMap;
7 export 'package:angular/core/parser/static_parser.dart'
8 show StaticParser, StaticParserFunctions;
5 9
6 typedef Getter([locals]); 10 typedef LocalsWrapper(context, locals);
7 typedef Setter(value, [locals]); 11 typedef Getter(self);
12 typedef Setter(self, value);
8 13
9 abstract class ParserAST { 14 /// Placeholder for DI. The parser you are looking for is [DynamicParser].
10 bool get assignable; 15 abstract class Parser<T> {
11 } 16 T call(String input);
12
13 class Token {
14 final int index;
15 final String text;
16
17 var value;
18 // Tokens should have one of these set.
19 String opKey;
20 String key;
21
22 Token(this.index, this.text);
23
24 withOp(op) {
25 this.opKey = op;
26 }
27
28 withGetterSetter(key) {
29 this.key = key;
30 }
31
32 withValue(value) { this.value = value; }
33
34 toString() => "Token($text)";
35 }
36
37 typedef Operator(dynamic self, ParserAST a, ParserAST b);
38
39 Operator NULL_OP = (_, _0, _1) => null;
40 Operator NOT_IMPL_OP = (_, _0, _1) { throw "Op not implemented"; };
41
42 // FUNCTIONS USED AT RUNTIME.
43
44 parserEvalError(String s, String text, stack) =>
45 ['Eval Error: $s while evaling [$text]' +
46 (stack != null ? '\n\nFROM:\n$stack' : '')];
47
48 // Automatic type conversion.
49 autoConvertAdd(a, b) {
50 if (a != null && b != null) {
51 // TODO(deboer): Support others.
52 if (a is String && b is! String) {
53 return a + b.toString();
54 }
55 if (a is! String && b is String) {
56 return a.toString() + b;
57 }
58 return a + b;
59 }
60 if (a != null) return a;
61 if (b != null) return b;
62 return null;
63 }
64
65 objectIndexGetField(o, i, evalError) {
66 if (o == null) throw evalError('Accessing null object');
67
68 if (o is List) {
69 return o[i.toInt()];
70 } else if (o is Map) {
71 return o[i.toString()]; // toString dangerous?
72 }
73 throw evalError("Attempted field access on a non-list, non-map");
74 }
75
76 objectIndexSetField(o, i, v, evalError) {
77 if (o is List) {
78 int arrayIndex = i.toInt();
79 if (o.length <= arrayIndex) { o.length = arrayIndex + 1; }
80 o[arrayIndex] = v;
81 } else if (o is Map) {
82 o[i.toString()] = v; // toString dangerous?
83 } else {
84 throw evalError("Attempting to set a field on a non-list, non-map");
85 }
86 return v;
87 }
88
89 safeFunctionCall(userFn, fnName, evalError) {
90 if (userFn == null) {
91 throw evalError("Undefined function $fnName");
92 }
93 if (userFn is! Function) {
94 throw evalError("$fnName is not a function");
95 }
96 return userFn;
97 } 17 }
98 18
99 19
100 Map<String, Operator> OPERATORS = { 20 abstract class ParserBackend<T> {
101 'undefined': NULL_OP, 21 bool isAssignable(T expression);
102 'null': NULL_OP,
103 'true': (self, a, b) => true,
104 'false': (self, a, b) => false,
105 '+': (self, aFn, bFn) {
106 var a = aFn.eval(self);
107 var b = bFn.eval(self);
108 return autoConvertAdd(a, b);
109 },
110 '-': (self, a, b) {
111 assert(a != null || b != null);
112 var aResult = a != null ? a.eval(self) : null;
113 var bResult = b != null ? b.eval(self) : null;
114 return (aResult == null ? 0 : aResult) - (bResult == null ? 0 : bResult);
115 },
116 '*': (s, a, b) => a.eval(s) * b.eval(s),
117 '/': (s, a, b) => a.eval(s) / b.eval(s),
118 '~/': (s, a, b) => a.eval(s) ~/ b.eval(s),
119 '%': (s, a, b) => a.eval(s) % b.eval(s),
120 '^': (s, a, b) => a.eval(s) ^ b.eval(s),
121 '=': NULL_OP,
122 '==': (s, a, b) => a.eval(s) == b.eval(s),
123 '!=': (s, a, b) => a.eval(s) != b.eval(s),
124 '<': (s, a, b) => a.eval(s) < b.eval(s),
125 '>': (s, a, b) => a.eval(s) > b.eval(s),
126 '<=': (s, a, b) => a.eval(s) <= b.eval(s),
127 '>=': (s, a, b) => a.eval(s) >= b.eval(s),
128 '&&': (s, a, b) => toBool(a.eval(s)) && toBool(b.eval(s)),
129 '||': (s, a, b) => toBool(a.eval(s)) || toBool(b.eval(s)),
130 '&': (s, a, b) => a.eval(s) & b.eval(s),
131 '|': NOT_IMPL_OP, //b()(a())
132 '!': (s, a, b) => !toBool(a.eval(s)),
133 '?': (s, c, t, f) => toBool(c.eval(s)) ? t.eval(s) : f.eval(s),
134 };
135 22
136 @NgInjectableService() 23 T newChain(List expressions)
137 class DynamicParser implements Parser { 24 => null;
138 final Lexer _lexer; 25 T newFilter(T expression, String name, List arguments)
139 final ParserBackend _b; 26 => null;
140 27
141 DynamicParser(this._lexer, this._b); 28 T newAssign(T target, T value)
29 => null;
30 T newConditional(T condition, T yes, T no)
31 => null;
142 32
143 List<Token> _tokens; 33 T newAccessScope(String name)
144 String _text; 34 => null;
145 var _evalError; 35 T newAccessMember(T object, String name)
36 => null;
37 T newAccessKeyed(T object, T key)
38 => null;
146 39
147 Map<String, ParserAST> _cache = {}; 40 T newCallScope(String name, List arguments)
41 => null;
42 T newCallFunction(T function, List arguments)
43 => null;
44 T newCallMember(T object, String name, List arguments)
45 => null;
148 46
149 ParserAST call(String text) { 47 T newPrefix(String operation, T expression)
150 var value = _cache[text]; 48 => null;
151 if (value != null) { 49 T newPrefixPlus(T expression)
152 return value; 50 => expression;
153 } 51 T newPrefixMinus(T expression)
154 return _cache[text] = _call(text); 52 => newBinaryMinus(newLiteralZero(), expression);
155 } 53 T newPrefixNot(T expression)
54 => newPrefix('!', expression);
156 55
157 ParserAST _call(String text) { 56 T newBinary(String operation, T left, T right)
158 try { 57 => null;
159 if (text == null) text = ''; 58 T newBinaryPlus(T left, T right)
160 _tokenSavers = []; 59 => newBinary('+', left, right);
161 _text = text; 60 T newBinaryMinus(T left, T right)
162 _tokens = _lexer.call(text); 61 => newBinary('-', left, right);
163 _evalError = (String s, [stack]) => parserEvalError(s, text, stack); 62 T newBinaryMultiply(T left, T right)
63 => newBinary('*', left, right);
64 T newBinaryDivide(T left, T right)
65 => newBinary('/', left, right);
66 T newBinaryModulo(T left, T right)
67 => newBinary('%', left, right);
68 T newBinaryTruncatingDivide(T left, T right)
69 => newBinary('~/', left, right);
70 T newBinaryLogicalAnd(T left, T right)
71 => newBinary('&&', left, right);
72 T newBinaryLogicalOr(T left, T right)
73 => newBinary('||', left, right);
74 T newBinaryEqual(T left, T right)
75 => newBinary('==', left, right);
76 T newBinaryNotEqual(T left, T right)
77 => newBinary('!=', left, right);
78 T newBinaryLessThan(T left, T right)
79 => newBinary('<', left, right);
80 T newBinaryGreaterThan(T left, T right)
81 => newBinary('>', left, right);
82 T newBinaryLessThanEqual(T left, T right)
83 => newBinary('<=', left, right);
84 T newBinaryGreaterThanEqual(T left, T right)
85 => newBinary('>=', left, right);
164 86
165 ParserAST value = _statements(); 87 T newLiteralPrimitive(value)
166 88 => null;
167 if (_tokens.length != 0) { 89 T newLiteralArray(List elements)
168 throw _parserError("Unconsumed token ${_tokens[0].text}"); 90 => null;
169 } 91 T newLiteralObject(List<String> keys, List values)
170 return value; 92 => null;
171 } finally { 93 T newLiteralNull()
172 _tokens = null; 94 => newLiteralPrimitive(null);
173 _text = null; 95 T newLiteralZero()
174 _evalError = null; 96 => newLiteralNumber(0);
175 _tokenSavers = null; 97 T newLiteralBoolean(bool value)
176 } 98 => newLiteralPrimitive(value);
177 } 99 T newLiteralNumber(num value)
178 100 => newLiteralPrimitive(value);
179 primaryFromToken(Token token, parserError) { 101 T newLiteralString(String value)
180 if (token.key != null) { 102 => null;
181 return _b.getterSetter(token.key);
182 }
183 if (token.opKey != null) {
184 return _b.fromOperator(token.opKey);
185 }
186 if (token.value != null) {
187 return _b.value(token.value);
188 }
189 if (token.text != null) {
190 return _b.value(token.text);
191 }
192 throw parserError("Internal Angular Error: Tokens should have keys, text or fns");
193 }
194
195 _parserError(String s, [Token t]) {
196 if (t == null && !_tokens.isEmpty) t = _tokens[0];
197 String location = t == null ?
198 'the end of the expression' :
199 'at column ${t.index + 1} in';
200 return 'Parser Error: $s $location [$_text]';
201 }
202
203
204 Token _peekToken() {
205 if (_tokens.length == 0)
206 throw "Unexpected end of expression: " + _text;
207 return _tokens[0];
208 }
209
210 Token _peek([String e1, String e2, String e3, String e4]) {
211 if (_tokens.length > 0) {
212 Token token = _tokens[0];
213 String t = token.text;
214 if (t==e1 || t==e2 || t==e3 || t==e4 ||
215 (e1 == null && e2 == null && e3 == null && e4 == null)) {
216 return token;
217 }
218 }
219 return null;
220 }
221
222 /**
223 * Token savers are synchronous lists that allows Parser functions to
224 * access the tokens parsed during some amount of time. They are useful
225 * for printing helpful debugging messages.
226 */
227 List<List<Token>> _tokenSavers;
228 List<Token> _saveTokens() { var n = []; _tokenSavers.add(n); return n; }
229 _stopSavingTokens(x) { if (!_tokenSavers.remove(x)) { throw 'bad token saver'; } return x; }
230 _tokensText(List x) => x.map((x) => x.text).join();
231
232
233 Token _expect([String e1, String e2, String e3, String e4]){
234 Token token = _peek(e1, e2, e3, e4);
235 if (token != null) {
236 var consumed = _tokens.removeAt(0);
237 _tokenSavers.forEach((ts) => ts.add(consumed));
238 return token;
239 }
240 return null;
241 }
242
243 ParserAST _consume(e1){
244 if (_expect(e1) == null) {
245 throw _parserError("Missing expected $e1");
246 }
247 }
248
249 ParserAST _primary() {
250 var primary;
251 var ts = _saveTokens();
252 if (_expect('(') != null) {
253 primary = _filterChain();
254 _consume(')');
255 } else if (_expect('[') != null) {
256 primary = _arrayDeclaration();
257 } else if (_expect('{') != null) {
258 primary = _object();
259 } else {
260 Token token = _expect();
261 primary = primaryFromToken(token, _parserError);
262 if (primary == null) {
263 throw _parserError("Internal Angular Error: Unreachable code A.");
264 }
265 }
266
267 var next;
268 while ((next = _expect('(', '[', '.')) != null) {
269 if (next.text == '(') {
270 primary = _functionCall(primary, _tokensText(ts.sublist(0, ts.length - 1 )));
271 } else if (next.text == '[') {
272 primary = _objectIndex(primary);
273 } else if (next.text == '.') {
274 primary = _fieldAccess(primary);
275 } else {
276 throw _parserError("Internal Angular Error: Unreachable code B.");
277 }
278 }
279 _stopSavingTokens(ts);
280 return primary;
281 }
282
283 ParserAST _binaryFn(ParserAST left, String op, ParserAST right) =>
284 _b.binaryFn(left, op, right);
285
286 ParserAST _unaryFn(String op, ParserAST right) =>
287 _b.unaryFn(op, right);
288
289 ParserAST _unary() {
290 var token;
291 if (_expect('+') != null) {
292 return _primary();
293 } else if ((token = _expect('-')) != null) {
294 return _binaryFn(_b.zero(), token.opKey, _unary());
295 } else if ((token = _expect('!')) != null) {
296 return _unaryFn(token.opKey, _unary());
297 } else {
298 return _primary();
299 }
300 }
301
302 ParserAST _multiplicative() {
303 var left = _unary();
304 var token;
305 while ((token = _expect('*','%','/','~/')) != null) {
306 left = _binaryFn(left, token.opKey, _unary());
307 }
308 return left;
309 }
310
311 ParserAST _additive() {
312 var left = _multiplicative();
313 var token;
314 while ((token = _expect('+','-')) != null) {
315 left = _binaryFn(left, token.opKey, _multiplicative());
316 }
317 return left;
318 }
319
320 ParserAST _relational() {
321 var left = _additive();
322 var token;
323 if ((token = _expect('<', '>', '<=', '>=')) != null) {
324 left = _binaryFn(left, token.opKey, _relational());
325 }
326 return left;
327 }
328
329 ParserAST _equality() {
330 var left = _relational();
331 var token;
332 if ((token = _expect('==','!=')) != null) {
333 left = _binaryFn(left, token.opKey, _equality());
334 }
335 return left;
336 }
337
338 ParserAST _logicalAND() {
339 var left = _equality();
340 var token;
341 if ((token = _expect('&&')) != null) {
342 left = _binaryFn(left, token.opKey, _logicalAND());
343 }
344 return left;
345 }
346
347 ParserAST _logicalOR() {
348 var left = _logicalAND();
349 var token;
350 while(true) {
351 if ((token = _expect('||')) != null) {
352 left = _binaryFn(left, token.opKey, _logicalAND());
353 } else {
354 return left;
355 }
356 }
357 }
358
359 ParserAST _ternary() {
360 var ts = _saveTokens();
361 var cond = _logicalOR();
362 var token = _expect('?');
363 if (token != null) {
364 var _true = _expression();
365 if ((token = _expect(':')) != null) {
366 cond = _b.ternaryFn(cond, _true, _expression());
367 } else {
368 throw _parserError('Conditional expression ${_tokensText(ts)} requires '
369 'all 3 expressions');
370 }
371 }
372 _stopSavingTokens(ts);
373 return cond;
374 }
375
376 ParserAST _assignment() {
377 var ts = _saveTokens();
378 var left = _ternary();
379 _stopSavingTokens(ts);
380 var right;
381 var token;
382 if ((token = _expect('=')) != null) {
383 if (!left.assignable) {
384 throw _parserError('Expression ${_tokensText(ts)} is not assignable', to ken);
385 }
386 right = _ternary();
387 return _b.assignment(left, right, _evalError);
388 } else {
389 return left;
390 }
391 }
392
393 ParserAST _expression() {
394 return _assignment();
395 }
396
397 _filterChain() {
398 var left = _expression();
399 var token;
400 while(true) {
401 if ((token = _expect('|')) != null) {
402 left = _filter(left);
403 } else {
404 return left;
405 }
406 }
407 }
408
409 ParserAST _filter(ParserAST left) {
410 var token = _expect();
411 var filterName = token.text;
412 var argsFn = [];
413 while(true) {
414 if ((token = _expect(':')) != null) {
415 argsFn.add(_expression());
416 } else {
417 return _b.filter(filterName, left, argsFn, _evalError);
418 }
419 }
420 }
421
422 _statements() {
423 List<ParserAST> statements = [];
424 while (true) {
425 if (_tokens.length > 0 && _peek('}', ')', ';', ']') == null)
426 statements.add(_filterChain());
427 if (_expect(';') == null) {
428 return statements.length == 1
429 ? statements[0]
430 : _b.multipleStatements(statements);
431 }
432 }
433 }
434
435 _functionCall(fn, fnName) {
436 var argsFn = [];
437 if (_peekToken().text != ')') {
438 do {
439 argsFn.add(_expression());
440 } while (_expect(',') != null);
441 }
442 _consume(')');
443 return _b.functionCall(fn, fnName, argsFn, _evalError);
444 }
445
446 // This is used with json array declaration
447 _arrayDeclaration() {
448 var elementFns = [];
449 if (_peekToken().text != ']') {
450 do {
451 elementFns.add(_expression());
452 } while (_expect(',') != null);
453 }
454 _consume(']');
455 return _b.arrayDeclaration(elementFns);
456 }
457
458 _objectIndex(obj) {
459 var indexFn = _expression();
460 _consume(']');
461 return _b.objectIndex(obj, indexFn, _evalError);
462 }
463
464 _fieldAccess(object) {
465 var field = _expect().text;
466 //var getter = getter(field);
467 return _b.fieldAccess(object, field);
468 }
469
470 _object() {
471 var keyValues = [];
472 if (_peekToken().text != '}') {
473 do {
474 var token = _expect(),
475 key = token.value != null && token.value is String ? token.value : token .text;
476 _consume(":");
477 var value = _expression();
478 keyValues.add({"key":key, "value":value});
479 } while (_expect(',') != null);
480 }
481 _consume('}');
482 return _b.object(keyValues);
483 }
484
485 } 103 }
OLDNEW
« no previous file with comments | « third_party/pkg/angular/lib/core/parser/lexer.dart ('k') | third_party/pkg/angular/lib/core/parser/parser_library.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698