Skip to content

Commit a6cecd8

Browse files
committed
[ExpressionLanguage] add XOR operator
1 parent e1ac6e1 commit a6cecd8

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