Refactor logical expressions and implement equality expressions

This commit is contained in:
Matt Sherman 2023-10-03 19:04:46 -04:00
parent a5fec1fa6e
commit 6237c8caea
2 changed files with 98 additions and 12 deletions

View File

@ -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 );

View File

@ -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: {