8000 feature #34329 [ExpressionLanguage] add XOR operator (ottaviano) · symfony/symfony@d1d4bc8 · GitHub
[go: up one dir, main page]

Skip to content

Commit d1d4bc8

Browse files
feature #34329 [ExpressionLanguage] add XOR operator (ottaviano)
This PR was merged into the 4.4 branch. Discussion ---------- [ExpressionLanguage] add XOR operator | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | ~ | License | MIT | Doc PR | ~ 👋 little PR for adding the best logical operator: `XOR` Commits ------- 46fe917 [ExpressionLanguage] add XOR operator
2 parents f63976f + 46fe917 commit d1d4bc8

File tree

7 files changed

+53
-1
lines changed

7 files changed

+53
-1
lines changed

src/Symfony/Component/ExpressionLanguage/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
4.4.0
5+
-----
6+
7+
* add `xor` operator
8+
49
4.0.0
510
-----
611

src/Symfony/Component/ExpressionLanguage/Lexer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public function tokenize($expression)
7373
// strings
7474
$tokens[] = new Token(Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1)), $cursor + 1);
7575
$cursor += \strlen($match[0]);
76-
} elseif (preg_match('/not in(?=[\s(])|\!\=\=|not(?=[\s(])|and(?=[\s(])|\=\=\=|\>\=|or(?=[\s(])|\<\=|\*\*|\.\.|in(?=[\s(])|&&|\|\||matches|\=\=|\!\=|\*|~|%|\/|\>|\||\!|\^|&|\+|\<|\-/A', $expression, $match, 0, $cursor)) {
76+
} elseif (preg_match('/not in(?=[\s(])|\!\=\=|not(?=[\s(])|and(?=[\s(])|\=\=\=|\>\=|or(?=[\s(])|xor(?=[\s(])|\<\=|\*\*|\.\.|in(?=[\s(])|&&|\|\||matches|\=\=|\!\=|\*|~|%|\/|\>|\||\!|\^|&|\+|\<|\-/A', $expression, $match, 0, $cursor)) {
7777
// operators
7878
$tokens[] = new Token(Token::OPERATOR_TYPE, $match[0], $cursor + 1);
7979
$cursor += \strlen($match[0]);

src/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ public function evaluate($functions, $values)
104104
case 'or':
105105
case '||':
106106
return $left || $this->nodes['right']->evaluate($functions, $values);
107+
case 'xor':
108+
return $left xor $this->nodes['right']->evaluate($functions, $values);
107109
case 'and':
108110
case '&&':
109111
return $left && $this->nodes['right']->evaluate($functions, $values);

src/Symfony/Component/ExpressionLanguage/Parser.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public function __construct(array $functions)
4545
$this->binaryOperators = [
4646
'or' => ['precedence' => 10, 'associativity' => self::OPERATOR_LEFT],
4747
'||' => ['precedence' => 10, 'associativity' => self::OPERATOR_LEFT],
48+
'xor' => ['precedence' => 13, 'associativity' => self::OPERATOR_LEFT],
4849
'and' => ['precedence' => 15, 'associativity' => self::OPERATOR_LEFT],
4950
'&&' => ['precedence' => 15, 'associativity' => self::OPERATOR_LEFT],
5051
'|' => ['precedence' => 16, 'associativity' => self::OPERATOR_LEFT],

src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,4 +256,35 @@ function (ExpressionLanguage $el) {
256256
],
257257
];
258258
}
259+
260+
/**
261+
* @dataProvider getLogicalOperators
262+
*/
263+
public function testLogicalOperators($expression, $expected)
264+
{
265+
$this->assertSame($expected, (new ExpressionLanguage())->evaluate($expression));
266+
}
267+
268+
public function getLogicalOperators()
269+
{
270+
return [
271+
// AND
272+
['true and true', true],
273+
['true and false', false],
274+
['false and true', false],
275+
['false and false', false],
276+
277+
// OR
278+
['true or true', true],
279+
['true or false', true],
280+
['false or true', true],
281+
['false or false', false],
282+
283+
// XOR
284+
['true xor true', false],
285+
['true xor false', true],
286+
['false xor true', true],
287+
['false xor false', false],
288+
];
289+
}
259290
}

src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,14 @@ public function getTokenizeData()
114114
[new Token('string', '#foo', 1)],
115115
'"#foo"',
116116
],
117+
[
118+
[
119+
new Token('name', 'a', 1),
120+
new Token('operator', 'xor', 3),
121+
new Token('name', 'b', 7),
122+
],
123+
'a xor b',
124+
],
117125
];
118126
}
119127
}

src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ public function getParseData()
151151
'bar',
152152
['foo' => 'bar'],
153153
],
154+
155+
[
156+
new Node\BinaryNode('xor', new Node\ConstantNode(true), new Node\ConstantNode(false)),
157+
'true xor false',
158+
],
154159
];
155160
}
156161

0 commit comments

Comments
 (0)
0