Skip to content

Commit 52b3838

Browse files
committed
feat(parser): split parse into parseBinding and parseAction
1 parent 00bc9e5 commit 52b3838

File tree

3 files changed

+121
-143
lines changed

3 files changed

+121
-143
lines changed

modules/change_detection/src/parser/ast.js

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ import {FIELD, toBool, autoConvertAdd, isBlank, FunctionWrapper, BaseException}
22
import {List, ListWrapper} from "facade/collection";
33

44
export class AST {
5-
eval(context, formatters) {
5+
eval(context) {
6+
throw new BaseException("Not supported");
67
}
78

89
visit(visitor) {
910
}
1011
}
1112

1213
export class ImplicitReceiver extends AST {
13-
eval(context, formatters) {
14+
eval(context) {
1415
return context;
1516
}
1617

@@ -20,17 +21,17 @@ export class ImplicitReceiver extends AST {
2021
}
2122

2223
export class Conditional extends AST {
23-
constructor(condition:AST, yes:AST, no:AST){
24+
constructor(condition:AST, trueExp:AST, falseExp:AST){
2425
this.condition = condition;
25-
this.yes = yes;
26-
this.no = no;
26+
this.trueExp = trueExp;
27+
this.falseExp = falseExp;
2728
}
2829

29-
eval(context, formatters) {
30-
if(this.condition.eval(context, formatters)) {
31-
return this.yes.eval(context, formatters);
30+
eval(context) {
31+
if(this.condition.eval(context)) {
32+
return this.trueExp.eval(context);
3233
} else {
33-
return this.no.eval(context, formatters);
34+
return this.falseExp.eval(context);
3435
}
3536
}
3637
}
@@ -42,8 +43,8 @@ export class FieldRead extends AST {
4243
this.getter = getter;
4344
}
4445

45-
eval(context, formatters) {
46-
return this.getter(this.receiver.eval(context, formatters));
46+
eval(context) {
47+
return this.getter(this.receiver.eval(context));
4748
}
4849

4950
visit(visitor) {
@@ -59,15 +60,6 @@ export class Formatter extends AST {
5960
this.allArgs = ListWrapper.concat([exp], args);
6061
}
6162

62-
eval(context, formatters) {
63-
var formatter = formatters[this.name];
64-
if (isBlank(formatter)) {
65-
throw new BaseException(`No formatter '${this.name}' found!`);
66-
}
67-
var evaledArgs = evalList(context, this.allArgs, formatters);
68-
return FunctionWrapper.apply(formatter, evaledArgs);
69-
}
70-
7163
visit(visitor) {
7264
visitor.visitFormatter(this);
7365
}
@@ -78,7 +70,7 @@ export class LiteralPrimitive extends AST {
7870
constructor(value) {
7971
this.value = value;
8072
}
81-
eval(context, formatters) {
73+
eval(context) {
8274
return this.value;
8375
}
8476
visit(visitor) {
@@ -100,16 +92,18 @@ export class Binary extends AST {
10092
visitor.visitBinary(this);
10193
}
10294

103-
eval(context, formatters) {
104-
var left = this.left.eval(context, formatters);
95+
eval(context) {
96+
var left = this.left.eval(context);
10597
switch (this.operation) {
106-
case '&&': return toBool(left) && toBool(this.right.eval(context, formatters));
107-
case '||': return toBool(left) || toBool(this.right.eval(context, formatters));
98+
case '&&': return toBool(left) && toBool(this.right.eval(context));
99+
case '||': return toBool(left) || toBool(this.right.eval(context));
108100
}
109-
var right = this.right.eval(context, formatters);
101+
var right = this.right.eval(context);
110102

111103
// Null check for the operations.
112-
if (left == null || right == null) return null;
104+
if (left == null || right == null) {
105+
throw new BaseException("One of the operands is null");
106+
}
113107

114108
switch (this.operation) {
115109
case '+' : return autoConvertAdd(left, right);
@@ -139,8 +133,8 @@ export class PrefixNot extends AST {
139133
this.expression = expression;
140134
}
141135
visit(visitor) { visitor.visitPrefixNot(this); }
142-
eval(context, formatters) {
143-
return !toBool(this.expression.eval(context, formatters));
136+
eval(context) {
137+
return !toBool(this.expression.eval(context));
144138
}
145139
}
146140

@@ -155,11 +149,11 @@ export class AstVisitor {
155149
}
156150

157151
var _evalListCache = [[],[0],[0,0],[0,0,0],[0,0,0,0],[0,0,0,0,0]];
158-
function evalList(context, exps:List, formatters){
152+
function evalList(context, exps:List){
159153
var length = exps.length;
160154
var result = _evalListCache[length];
161155
for (var i = 0; i < length; i++) {
162-
result[i] = exps[i].eval(context, formatters);
156+
result[i] = exps[i].eval(context);
163157
}
164158
return result;
165159
}

modules/change_detection/src/parser/parser.js

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,29 @@ export class Parser {
2424
this._closureMap = closureMap;
2525
}
2626

27-
parse(input:string):AST {
27+
parseAction(input:string):AST {
2828
var tokens = this._lexer.tokenize(input);
29-
return new _ParseAST(input, tokens, this._closureMap).parseChain();
29+
return new _ParseAST(input, tokens, this._closureMap, true).parseChain();
30+
}
31+
32+
parseBinding(input:string):AST {
33+
var tokens = this._lexer.tokenize(input);
34+
return new _ParseAST(input, tokens, this._closureMap, false).parseChain();
3035
}
3136
}
3237

3338
class _ParseAST {
3439
@FIELD('final input:String')
3540
@FIELD('final tokens:List<Token>')
3641
@FIELD('final closureMap:ClosureMap')
42+
@FIELD('final parseAction:boolean')
3743
@FIELD('index:int')
38-
constructor(input:string, tokens:List, closureMap:ClosureMap) {
44+
constructor(input:string, tokens:List, closureMap:ClosureMap, parseAction:boolean) {
3945
this.input = input;
4046
this.tokens = tokens;
4147
this.index = 0;
4248
this.closureMap = closureMap;
49+
this.parseAction = parseAction;
4350
}
4451

4552
peek(offset:int):Token {
@@ -79,17 +86,14 @@ class _ParseAST {
7986

8087
parseChain():AST {
8188
var exprs = [];
82-
var isChain = false;
8389
while (this.index < this.tokens.length) {
8490
var expr = this.parseFormatter();
8591
ListWrapper.push(exprs, expr);
8692

8793
while (this.optionalCharacter($SEMICOLON)) {
88-
isChain = true;
89-
}
90-
91-
if (isChain && expr instanceof Formatter) {
92-
this.error('Cannot have a formatter in a chain');
94+
if (! this.parseAction) {
95+
this.error("Binding expression cannot contain chained expression");
96+
}
9397
}
9498
}
9599
return ListWrapper.first(exprs);
@@ -98,6 +102,9 @@ class _ParseAST {
98102
parseFormatter() {
99103
var result = this.parseExpression();
100104
while (this.optionalOperator("|")) {
105+
if (this.parseAction) {
106+
this.error("Cannot have a formatter in an action expression");
107+
}
101108
var name = this.parseIdentifier();
102109
var args = ListWrapper.create();
103110
while (this.optionalCharacter($COLON)) {
@@ -299,4 +306,4 @@ class ParserError extends Error {
299306
toString() {
300307
return this.message;
301308
}
302-
}
309+
}

0 commit comments

Comments
 (0)