From 46fe91781d195cab857878860ee6722497306947 Mon Sep 17 00:00:00 2001 From: Dimitri Gritsajuk Date: Tue, 12 Nov 2019 13:06:46 +0100 Subject: [PATCH] [ExpressionLanguage] add XOR operator --- .../Component/ExpressionLanguage/CHANGELOG.md | 5 +++ .../Component/ExpressionLanguage/Lexer.php | 2 +- .../ExpressionLanguage/Node/BinaryNode.php | 2 ++ .../Component/ExpressionLanguage/Parser.php | 1 + .../Tests/ExpressionLanguageTest.php | 31 +++++++++++++++++++ .../ExpressionLanguage/Tests/LexerTest.php | 8 +++++ .../ExpressionLanguage/Tests/ParserTest.php | 5 +++ 7 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md b/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md index 6c50b2ea424df..f3d48fae7afee 100644 --- a/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md +++ b/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.4.0 +----- + + * add `xor` operator + 4.0.0 ----- diff --git a/src/Symfony/Component/ExpressionLanguage/Lexer.php b/src/Symfony/Component/ExpressionLanguage/Lexer.php index 95b90705dd32f..8a7790af6fc79 100644 --- a/src/Symfony/Component/ExpressionLanguage/Lexer.php +++ b/src/Symfony/Component/ExpressionLanguage/Lexer.php @@ -73,7 +73,7 @@ public function tokenize($expression) // strings $tokens[] = new Token(Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1)), $cursor + 1); $cursor += \strlen($match[0]); - } elseif (preg_match('/not in(?=[\s(])|\!\=\=|not(?=[\s(])|and(?=[\s(])|\=\=\=|\>\=|or(?=[\s(])|\<\=|\*\*|\.\.|in(?=[\s(])|&&|\|\||matches|\=\=|\!\=|\*|~|%|\/|\>|\||\!|\^|&|\+|\<|\-/A', $expression, $match, 0, $cursor)) { + } elseif (preg_match('/not in(?=[\s(])|\!\=\=|not(?=[\s(])|and(?=[\s(])|\=\=\=|\>\=|or(?=[\s(])|xor(?=[\s(])|\<\=|\*\*|\.\.|in(?=[\s(])|&&|\|\||matches|\=\=|\!\=|\*|~|%|\/|\>|\||\!|\^|&|\+|\<|\-/A', $expression, $match, 0, $cursor)) { // operators $tokens[] = new Token(Token::OPERATOR_TYPE, $match[0], $cursor + 1); $cursor += \strlen($match[0]); diff --git a/src/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php b/src/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php index 0af4f16623e0c..3e81994239087 100644 --- a/src/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php +++ b/src/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php @@ -104,6 +104,8 @@ public function evaluate($functions, $values) case 'or': case '||': return $left || $this->nodes['right']->evaluate($functions, $values); + case 'xor': + return $left xor $this->nodes['right']->evaluate($functions, $values); case 'and': case '&&': return $left && $this->nodes['right']->evaluate($functions, $values); diff --git a/src/Symfony/Component/ExpressionLanguage/Parser.php b/src/Symfony/Component/ExpressionLanguage/Parser.php index 59c4d67d781c6..89c2dd775f499 100644 --- a/src/Symfony/Component/ExpressionLanguage/Parser.php +++ b/src/Symfony/Component/ExpressionLanguage/Parser.php @@ -45,6 +45,7 @@ public function __construct(array $functions) $this->binaryOperators = [ 'or' => ['precedence' => 10, 'associativity' => self::OPERATOR_LEFT], '||' => ['precedence' => 10, 'associativity' => self::OPERATOR_LEFT], + 'xor' => ['precedence' => 13, 'associativity' => self::OPERATOR_LEFT], 'and' => ['precedence' => 15, 'associativity' => self::OPERATOR_LEFT], '&&' => ['precedence' => 15, 'associativity' => self::OPERATOR_LEFT], '|' => ['precedence' => 16, 'associativity' => self::OPERATOR_LEFT], diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php index 6e01b250caca5..d8ecaeff932a2 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php @@ -256,4 +256,35 @@ function (ExpressionLanguage $el) { ], ]; } + + /** + * @dataProvider getLogicalOperators + */ + public function testLogicalOperators($expression, $expected) + { + $this->assertSame($expected, (new ExpressionLanguage())->evaluate($expression)); + } + + public function getLogicalOperators() + { + return [ + // AND + ['true and true', true], + ['true and false', false], + ['false and true', false], + ['false and false', false], + + // OR + ['true or true', true], + ['true or false', true], + ['false or true', true], + ['false or false', false], + + // XOR + ['true xor true', false], + ['true xor false', true], + ['false xor true', true], + ['false xor false', false], + ]; + } } diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php index 2674752aa25c5..c16d91c7093ba 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php @@ -114,6 +114,14 @@ public function getTokenizeData() [new Token('string', '#foo', 1)], '"#foo"', ], + [ + [ + new Token('name', 'a', 1), + new Token('operator', 'xor', 3), + new Token('name', 'b', 7), + ], + 'a xor b', + ], ]; } } diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php index 84b30dc151cf4..56d08b0af79a4 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php @@ -151,6 +151,11 @@ public function getParseData() 'bar', ['foo' => 'bar'], ], + + [ + new Node\BinaryNode('xor', new Node\ConstantNode(true), new Node\ConstantNode(false)), + 'true xor false', + ], ]; } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy