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