1
1
library angular.core.parser;
2
2
3
+ import 'package:di/annotations.dart' ;
3
4
import 'package:angular/core/parser/syntax.dart'
4
- show CallArguments;
5
+ show defaultFormatterMap, Expression, Visitor, CallArguments;
6
+ import 'package:angular/core/parser/eval.dart' ;
7
+ import 'package:angular/core/parser/utils.dart' show EvalError;
8
+ import 'package:angular/cache/module.dart' ;
9
+ import 'package:angular/core/annotation_src.dart' hide Formatter;
10
+ import 'package:angular/core/module_internal.dart' show FormatterMap;
11
+ import 'package:angular/core/parser/lexer.dart' ;
12
+ import 'package:angular/core/parser/parse_expression.dart' ;
13
+ import 'package:angular/utils.dart' ;
14
+
5
15
export 'package:angular/core/parser/syntax.dart'
6
- show Visitor, Expression, BoundExpression, CallArguments;
7
- export 'package:angular/core/parser/dynamic_parser.dart'
8
- show DynamicParser, DynamicParserBackend, ClosureMap;
16
+ show Visitor, Expression, BoundExpression, CallArguments;
9
17
10
18
typedef LocalsWrapper (context, locals);
11
19
typedef Getter (self);
@@ -14,9 +22,11 @@ typedef BoundGetter([locals]);
14
22
typedef BoundSetter (value, [locals]);
15
23
typedef MethodClosure (obj, List posArgs, Map namedArgs);
16
24
17
- /// Placeholder for DI. The parser you are looking for is [DynamicParser] .
18
- abstract class Parser <T > {
19
- T call (String input);
25
+ abstract class ClosureMap {
26
+ Getter lookupGetter (String name);
27
+ Setter lookupSetter (String name);
28
+ Symbol lookupSymbol (String name);
29
+ MethodClosure lookupFunction (String name, CallArguments arguments);
20
30
}
21
31
22
32
abstract class ParserBackend <T > {
@@ -67,3 +77,123 @@ abstract class ParserBackend<T> {
67
77
T newLiteralNumber (num value) => newLiteralPrimitive (value);
68
78
T newLiteralString (String value) => null ;
69
79
}
80
+
81
+ @Injectable ()
82
+ class Parser {
83
+ final Lexer _lexer;
84
+ final ParserBackend _backend;
85
+ final Map <String , Expression > _cache = {};
86
+ Parser (this ._lexer, this ._backend, CacheRegister cacheRegister) {
87
+ cacheRegister.registerCache ("Parser" , _cache);
88
+ }
89
+
90
+ Expression call (String input) {
91
+ if (input == null ) input = '' ;
92
+ return _cache.putIfAbsent (input, () => _parse (input));
93
+ }
94
+
95
+ Expression _parse (String input) {
96
+ Expression expression = parseExpression (_lexer, _backend, input);
97
+ return new _UnwrapExceptionDecorator (expression);
98
+ }
99
+ }
100
+
101
+ class _UnwrapExceptionDecorator extends Expression {
102
+ final Expression _expression;
103
+ _UnwrapExceptionDecorator (this ._expression);
104
+
105
+ bool get isAssignable => _expression.isAssignable;
106
+ bool get isChain => _expression.isChain;
107
+
108
+ accept (Visitor visitor) => _expression.accept (visitor);
109
+ toString () => _expression.toString ();
110
+
111
+ eval (scope, [FormatterMap formatters = defaultFormatterMap]) {
112
+ try {
113
+ return _expression.eval (scope, formatters);
114
+ } on EvalError catch (e, s) {
115
+ throw e.unwrap ("$this " , s);
116
+ }
117
+ }
118
+
119
+ assign (scope, value) {
120
+ try {
121
+ return _expression.assign (scope, value);
122
+ } on EvalError catch (e, s) {
123
+ throw e.unwrap ("$this " , s);
124
+ }
125
+ }
126
+ }
127
+
128
+ @Injectable ()
129
+ class RuntimeParserBackend extends ParserBackend {
130
+ final ClosureMap _closures;
131
+ RuntimeParserBackend (this ._closures);
132
+
133
+ bool isAssignable (Expression expression) => expression.isAssignable;
134
+
135
+ Expression newFormatter (expression, name, arguments) {
136
+ List allArguments = new List (arguments.length + 1 );
137
+ allArguments[0 ] = expression;
138
+ allArguments.setAll (1 , arguments);
139
+ return new Formatter (expression, name, arguments, allArguments);
140
+ }
141
+
142
+ Expression newChain (expressions) => new Chain (expressions);
143
+ Expression newAssign (target, value) => new Assign (target, value);
144
+ Expression newConditional (condition, yes, no) =>
145
+ new Conditional (condition, yes, no);
146
+
147
+ Expression newAccessKeyed (object, key) => new AccessKeyed (object, key);
148
+ Expression newCallFunction (function, arguments) =>
149
+ new CallFunction (function, _closures, arguments);
150
+
151
+ Expression newPrefixNot (expression) => new PrefixNot (expression);
152
+
153
+ Expression newBinary (operation, left, right) =>
154
+ new Binary (operation, left, right);
155
+
156
+ Expression newLiteralPrimitive (value) => new LiteralPrimitive (value);
157
+ Expression newLiteralArray (elements) => new LiteralArray (elements);
158
+ Expression newLiteralObject (keys, values) => new LiteralObject (keys, values);
159
+ Expression newLiteralString (value) => new LiteralString (value);
160
+
161
+ Expression newAccessScope (name) {
162
+ Getter getter;
163
+ Setter setter;
164
+ if (name == 'this' ) {
165
+ getter = (o) => o;
166
+ } else {
167
+ _assertNotReserved (name);
168
+ getter = _closures.lookupGetter (name);
169
+ setter = _closures.lookupSetter (name);
170
+ }
171
+ return new AccessScopeFast (name, getter, setter);
172
+ }
173
+
174
+ Expression newAccessMember (object, name) {
175
+ _assertNotReserved (name);
176
+ Getter getter = _closures.lookupGetter (name);
177
+ Setter setter = _closures.lookupSetter (name);
178
+ return new AccessMemberFast (object, name, getter, setter);
179
+ }
180
+
181
+ Expression newCallScope (name, arguments) {
182
+ _assertNotReserved (name);
183
+ MethodClosure function = _closures.lookupFunction (name, arguments);
184
+ return new CallScope (name, function, arguments);
185
+ }
186
+
187
+ Expression newCallMember (object, name, arguments) {
188
+ _assertNotReserved (name);
189
+ MethodClosure function = _closures.lookupFunction (name, arguments);
190
+ return new CallMember (object, function, name, arguments);
191
+ }
192
+
193
+ _assertNotReserved (name) {
194
+ if (isReservedWord (name)) {
195
+ throw "Identifier '$name ' is a reserved word." ;
196
+ }
197
+ }
198
+ }
199
+
0 commit comments