From f76de45ea578f695d66ca1faab1ab0224379927c Mon Sep 17 00:00:00 2001 From: Fred Kleuver Date: Thu, 17 May 2018 04:46:05 +0200 Subject: [PATCH] fix(parser): allow $parent as an argument of binding behaviors and value converters - Closes #608 --- src/parser.js | 12 ++++++------ test/parser.spec.js | 24 ++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/parser.js b/src/parser.js index 7acaba74..c59dc8ef 100644 --- a/src/parser.js +++ b/src/parser.js @@ -105,7 +105,7 @@ export class ParserImplementation { } parseBinary(minPrecedence) { - let left = this.parseLeftHandSideExpression(); + let left = this.parseLeftHandSideExpression(0); while (this.currentToken & T$BinaryOp) { const opToken = this.currentToken; @@ -118,20 +118,20 @@ export class ParserImplementation { return left; } - parseLeftHandSideExpression(context = 0) { + parseLeftHandSideExpression(context) { let result; // Unary + Primary expression primary: switch (this.currentToken) { case T$Plus: this.nextToken(); - return this.parseLeftHandSideExpression(); + return this.parseLeftHandSideExpression(0); case T$Minus: this.nextToken(); - return new Binary('-', new LiteralPrimitive(0), this.parseLeftHandSideExpression()); + return new Binary('-', new LiteralPrimitive(0), this.parseLeftHandSideExpression(0)); case T$Bang: this.nextToken(); - return new PrefixNot('!', this.parseLeftHandSideExpression()); + return new PrefixNot('!', this.parseLeftHandSideExpression(0)); case T$ParentScope: // $parent { do { @@ -554,7 +554,7 @@ const T$MemberOrCallExpression = 1 << 24; /** ',' */ const T$Comma = 12 | T$AccessScopeTerminal; /** '[' */ const T$LBracket = 13 | T$OpeningToken | T$AccessScopeTerminal | T$MemberExpression | T$MemberOrCallExpression; /** ']' */ const T$RBracket = 14 | T$ClosingToken | T$ExpressionTerminal; -/** ':' */ const T$Colon = 15; +/** ':' */ const T$Colon = 15 | T$AccessScopeTerminal; /** '?' */ const T$Question = 16; // Operator precedence: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table diff --git a/test/parser.spec.js b/test/parser.spec.js index 159c2186..7056c207 100644 --- a/test/parser.spec.js +++ b/test/parser.spec.js @@ -276,9 +276,29 @@ describe('Parser', () => { ) }); - describe('parses BindingBehavior', () => { + const variadics = [ + { ctor: BindingBehavior, op: '&' }, + { ctor: ValueConverter, op: '|' } + ]; + + for (const variadic of variadics) { + describe(`parses ${variadic.ctor.name} with scope arguments`, () => { + const tests = [ + { expression: `foo${variadic.op}bar:$this:$this`, expected: new variadic.ctor(new AccessScope('foo', 0), 'bar', [new AccessThis(0), new AccessThis(0)]) }, + { expression: `foo${variadic.op}bar:$this:$parent`, expected: new variadic.ctor(new AccessScope('foo', 0), 'bar', [new AccessThis(0), new AccessThis(1)]) }, + { expression: `foo${variadic.op}bar:$parent:$this`, expected: new variadic.ctor(new AccessScope('foo', 0), 'bar', [new AccessThis(1), new AccessThis(0)]) }, + { expression: `foo${variadic.op}bar:$parent.$parent:$parent.$parent`, expected: new variadic.ctor(new AccessScope('foo', 0), 'bar', [new AccessThis(2), new AccessThis(2)]) } + ]; + + for (const test of tests) { + it(test.expression, () => { + let expression = parser.parse(test.expression); + verifyEqual(expression, test.expected); + }); + } + }); + } - }); it('parses binding behavior', () => { let expression = parser.parse('foo & bar');