From 6237c8caea12238e4b8723d179bd8598b8ac8188 Mon Sep 17 00:00:00 2001 From: Matt Sherman Date: Tue, 3 Oct 2023 19:04:46 -0400 Subject: [PATCH] Refactor logical expressions and implement equality expressions --- .../js/expression-evaluation/src/parser.ts | 70 +++++++++++++++---- .../src/test/parser.test.ts | 40 +++++++++++ 2 files changed, 98 insertions(+), 12 deletions(-) diff --git a/packages/js/expression-evaluation/src/parser.ts b/packages/js/expression-evaluation/src/parser.ts index 1ec0e77e16f..f53fb416045 100644 --- a/packages/js/expression-evaluation/src/parser.ts +++ b/packages/js/expression-evaluation/src/parser.ts @@ -4,8 +4,41 @@ import * as peggy from 'peggy'; const grammar = ` +{{ + function evaluateBinaryExpression( head, tail ) { + return tail.reduce( ( leftOperand, tailElement ) => { + const operator = tailElement[ 1 ]; + const rightOperand = tailElement[ 3 ]; + + switch ( operator ) { + case '&&': + return leftOperand && rightOperand; + break; + case '||': + return leftOperand || rightOperand; + break; + case '===': + return leftOperand === rightOperand; + break; + case '!==': + return leftOperand !== rightOperand; + break; + case '==': + return leftOperand == rightOperand; + break; + case '!=': + return leftOperand != rightOperand; + break; + default: + return undefined; + break; + } + }, head ); + } +}} + Start - = LogicalOrExpression + = Expression SourceCharacter = . @@ -225,24 +258,28 @@ FalseToken PrimaryExpression = IdentifierPath / Literal - / "(" WhiteSpace* expression:LogicalOrExpression WhiteSpace* ")" { + / "(" WhiteSpace* expression:Expression WhiteSpace* ")" { return expression; } -LogicalOrExpression - = left:LogicalAndExpression WhiteSpace+ LogicalOrOperator WhiteSpace+ right:LogicalOrExpression { - return left || right; - } - / LogicalAndExpression +RelationalExpression + = PrimaryExpression -LogicalOrOperator - = "||" +EqualityExpression + = head:RelationalExpression tail:( WhiteSpace* EqualityOperator WhiteSpace* RelationalExpression)* { + return evaluateBinaryExpression( head, tail ); + } + +EqualityOperator + = "===" + / "!==" + / "==" + / "!=" LogicalAndExpression - = left:PrimaryExpression WhiteSpace+ LogicalAndOperator WhiteSpace+ right:LogicalAndExpression { - return left && right; + = head:EqualityExpression tail:(WhiteSpace+ LogicalAndOperator WhiteSpace+ EqualityExpression)* { + return evaluateBinaryExpression( head, tail ); } - / Factor LogicalAndOperator = "&&" @@ -253,7 +290,16 @@ Factor } / PrimaryExpression +LogicalOrExpression + = head:LogicalAndExpression tail:(WhiteSpace+ LogicalOrOperator WhiteSpace+ LogicalAndExpression)* { + return evaluateBinaryExpression( head, tail ); + } +LogicalOrOperator + = "||" + +Expression + = LogicalOrExpression `; export const parser = peggy.generate( grammar ); diff --git a/packages/js/expression-evaluation/src/test/parser.test.ts b/packages/js/expression-evaluation/src/test/parser.test.ts index ffe3738ad2a..1e91e4434b0 100644 --- a/packages/js/expression-evaluation/src/test/parser.test.ts +++ b/packages/js/expression-evaluation/src/test/parser.test.ts @@ -114,6 +114,46 @@ describe( 'parser', () => { expect( result ).toEqual( 'baz' ); } ); + it( 'should parse an strict equality expression', () => { + const result = parser.parse( 'foo === "bar"', { + context: { + foo: 'bar', + }, + } ); + + expect( result ).toEqual( true ); + } ); + + it( 'should parse an strict inequality expression', () => { + const result = parser.parse( 'foo !== "bar"', { + context: { + foo: 'bar', + }, + } ); + + expect( result ).toEqual( false ); + } ); + + it( 'should parse an equality expression', () => { + const result = parser.parse( 'foo == "bar"', { + context: { + foo: 'bar', + }, + } ); + + expect( result ).toEqual( true ); + } ); + + it( 'should parse an inequality expression', () => { + const result = parser.parse( 'foo != "bar"', { + context: { + foo: 'bar', + }, + } ); + + expect( result ).toEqual( false ); + } ); + it( 'should parse a logical OR expression', () => { const result = parser.parse( 'foo || bar', { context: {