Skip to content

Commit cbf94f0

Browse files
committed
fix(parser/eval): fix for '"s" + ("m"|filter) + "e"'
closes dart-archive#755
1 parent 613030a commit cbf94f0

File tree

6 files changed

+52
-63
lines changed

6 files changed

+52
-63
lines changed

bin/parser_generator_for_spec.dart

+1
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ main(arguments) {
175175
'add(a,b)',
176176
'notAProperty',
177177
"'Foo'|uppercase",
178+
"'f' + ('o'|uppercase) + 'o'",
178179
"1|increment:2",
179180
"'abcd'|substring:1:offset",
180181
"'abcd'|substring:1:3|uppercase",

lib/core/parser/dynamic_parser.dart

+16-29
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,7 @@ class DynamicParserBackend extends ParserBackend {
6868
final ClosureMap _closures;
6969
DynamicParserBackend(this._closures);
7070

71-
bool isAssignable(Expression expression)
72-
=> expression.isAssignable;
71+
bool isAssignable(Expression expression) => expression.isAssignable;
7372

7473
Expression newFilter(expression, name, arguments) {
7574
List allArguments = new List(arguments.length + 1);
@@ -78,58 +77,46 @@ class DynamicParserBackend extends ParserBackend {
7877
return new Filter(expression, name, arguments, allArguments);
7978
}
8079

81-
Expression newChain(expressions)
82-
=> new Chain(expressions);
83-
Expression newAssign(target, value)
84-
=> new Assign(target, value);
80+
Expression newChain(expressions) => new Chain(expressions);
81+
Expression newAssign(target, value) => new Assign(target, value);
8582
Expression newConditional(condition, yes, no)
8683
=> new Conditional(condition, yes, no);
8784

88-
Expression newAccessKeyed(object, key)
89-
=> new AccessKeyed(object, key);
85+
Expression newAccessKeyed(object, key) => new AccessKeyed(object, key);
9086
Expression newCallFunction(function, arguments)
9187
=> new CallFunction(function, arguments);
9288

93-
Expression newPrefixNot(expression)
94-
=> new PrefixNot(expression);
89+
Expression newPrefixNot(expression) => new PrefixNot(expression);
9590

9691
Expression newBinary(operation, left, right)
9792
=> new Binary(operation, left, right);
9893

99-
Expression newLiteralPrimitive(value)
100-
=> new LiteralPrimitive(value);
101-
Expression newLiteralArray(elements)
102-
=> new LiteralArray(elements);
103-
Expression newLiteralObject(keys, values)
104-
=> new LiteralObject(keys, values);
105-
Expression newLiteralString(value)
106-
=> new LiteralString(value);
94+
Expression newLiteralPrimitive(value) => new LiteralPrimitive(value);
95+
Expression newLiteralArray(elements) => new LiteralArray(elements);
96+
Expression newLiteralObject(keys, values) => new LiteralObject(keys, values);
97+
Expression newLiteralString(value) => new LiteralString(value);
10798

10899

109100
Expression newAccessScope(name) {
110101
Getter getter = _closures.lookupGetter(name);
111102
Setter setter = _closures.lookupSetter(name);
112-
if (getter != null && setter != null) {
113-
return new AccessScopeFast(name, getter, setter);
114-
} else {
115-
return new AccessScope(name);
116-
}
103+
return (getter != null && setter != null)
104+
? new AccessScopeFast(name, getter, setter)
105+
: new AccessScope(name);
117106
}
118107

119108
Expression newAccessMember(object, name) {
120109
Getter getter = _closures.lookupGetter(name);
121110
Setter setter = _closures.lookupSetter(name);
122-
if (getter != null && setter != null) {
123-
return new AccessMemberFast(object, name, getter, setter);
124-
} else {
125-
return new AccessMember(object, name);
126-
}
111+
return (getter != null && setter != null)
112+
? new AccessMemberFast(object, name, getter, setter)
113+
: new AccessMember(object, name);
127114
}
128115

129116
Expression newCallScope(name, arguments) {
130117
Function constructor = _computeCallConstructor(
131118
_callScopeConstructors, name, arguments.length);
132-
return (constructor != null)
119+
return constructor != null
133120
? constructor(name, arguments, _closures)
134121
: new CallScope(name, arguments);
135122
}

lib/core/parser/eval.dart

+27-27
Original file line numberDiff line numberDiff line change
@@ -39,57 +39,57 @@ class Conditional extends syntax.Conditional {
3939
Conditional(syntax.Expression condition,
4040
syntax.Expression yes, syntax.Expression no)
4141
: super(condition, yes, no);
42-
eval(scope, [FilterMap filters]) => toBool(condition.eval(scope))
43-
? yes.eval(scope)
44-
: no.eval(scope);
42+
eval(scope, [FilterMap filters]) => toBool(condition.eval(scope, filters))
43+
? yes.eval(scope, filters)
44+
: no.eval(scope, filters);
4545
}
4646

4747
class PrefixNot extends syntax.Prefix {
4848
PrefixNot(syntax.Expression expression) : super('!', expression);
49-
eval(scope, [FilterMap filters]) => !toBool(expression.eval(scope));
49+
eval(scope, [FilterMap filters]) => !toBool(expression.eval(scope, filters));
5050
}
5151

5252
class Binary extends syntax.Binary {
5353
Binary(String operation, syntax.Expression left, syntax.Expression right):
5454
super(operation, left, right);
5555
eval(scope, [FilterMap filters]) {
56-
var left = this.left.eval(scope);
56+
var lValue = left.eval(scope, filters);
5757
switch (operation) {
58-
case '&&': return toBool(left) && toBool(this.right.eval(scope));
59-
case '||': return toBool(left) || toBool(this.right.eval(scope));
58+
case '&&': return toBool(lValue) && toBool(this.right.eval(scope, filters));
59+
case '||': return toBool(lValue) || toBool(this.right.eval(scope, filters));
6060
}
61-
var right = this.right.eval(scope);
61+
var rValue = right.eval(scope, filters);
6262

6363
// Null check for the operations.
64-
if (left == null || right == null) {
64+
if (lValue == null || rValue == null) {
6565
switch (operation) {
6666
case '+':
67-
if (left != null) return left;
68-
if (right != null) return right;
67+
if (lValue != null) return lValue;
68+
if (rValue != null) return rValue;
6969
return 0;
7070
case '-':
71-
if (left != null) return left;
72-
if (right != null) return 0 - right;
71+
if (lValue != null) return lValue;
72+
if (rValue != null) return 0 - rValue;
7373
return 0;
7474
}
7575
return null;
7676
}
7777

7878
switch (operation) {
79-
case '+' : return autoConvertAdd(left, right);
80-
case '-' : return left - right;
81-
case '*' : return left * right;
82-
case '/' : return left / right;
83-
case '~/' : return left ~/ right;
84-
case '%' : return left % right;
85-
case '==' : return left == right;
86-
case '!=' : return left != right;
87-
case '<' : return left < right;
88-
case '>' : return left > right;
89-
case '<=' : return left <= right;
90-
case '>=' : return left >= right;
91-
case '^' : return left ^ right;
92-
case '&' : return left & right;
79+
case '+' : return autoConvertAdd(lValue, rValue);
80+
case '-' : return lValue - rValue;
81+
case '*' : return lValue * rValue;
82+
case '/' : return lValue / rValue;
83+
case '~/' : return lValue ~/ rValue;
84+
case '%' : return lValue % rValue;
85+
case '==' : return lValue == rValue;
86+
case '!=' : return lValue != rValue;
87+
case '<' : return lValue < rValue;
88+
case '>' : return lValue > rValue;
89+
case '<=' : return lValue <= rValue;
90+
case '>=' : return lValue >= rValue;
91+
case '^' : return lValue ^ rValue;
92+
case '&' : return lValue & rValue;
9393
}
9494
throw new EvalError('Internal error [$operation] not handled');
9595
}

lib/core/parser/static_parser.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class StaticParserFunctions {
1515
class StaticParser implements Parser<Expression> {
1616
final StaticParserFunctions _functions;
1717
final DynamicParser _fallbackParser;
18-
final Map<String, Expression> _cache = {};
18+
final _cache = <String, Expression>{};
1919
StaticParser(this._functions, this._fallbackParser);
2020

2121
Expression call(String input) {

lib/core/parser/syntax.dart

+6-6
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ abstract class Expression {
3939
bool get isAssignable => false;
4040
bool get isChain => false;
4141

42-
eval(scope, [FilterMap filters = defaultFilterMap])
43-
=> throw new EvalError("Cannot evaluate $this");
44-
assign(scope, value)
45-
=> throw new EvalError("Cannot assign to $this");
46-
bind(context, [LocalsWrapper wrapper])
47-
=> new BoundExpression(this, context, wrapper);
42+
eval(scope, [FilterMap filters = defaultFilterMap]) =>
43+
throw new EvalError("Cannot evaluate $this");
44+
assign(scope, value) =>
45+
throw new EvalError("Cannot assign to $this");
46+
bind(context, [LocalsWrapper wrapper]) =>
47+
new BoundExpression(this, context, wrapper);
4848

4949
accept(Visitor visitor);
5050
String toString() => Unparser.unparse(this);

test/core/parser/parser_spec.dart

+1
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,7 @@ main() {
980980
describe('filters', () {
981981
it('should call a filter', () {
982982
expect(eval("'Foo'|uppercase", filters)).toEqual("FOO");
983+
expect(eval("'f' + ('o'|uppercase) + 'o'", filters)).toEqual("fOo");
983984
expect(eval("'fOo'|uppercase|lowercase", filters)).toEqual("foo");
984985
});
985986

0 commit comments

Comments
 (0)