mirror of
https://github.com/Perl/perl5.git
synced 2026-01-26 16:39:36 +00:00
Create a new logical xor operator, spelled ^^
Previously, the low-precedence `xor` operator did not have a higher-precedence logical variant, as compared `or` vs `||` and `and` vs `&&`. This PR adds such an operator syntax, completing the set.
This commit is contained in:
parent
d3f42b8d38
commit
d6e802ac91
4
perly.act
generated
4
perly.act
generated
@ -1554,7 +1554,7 @@ case 2:
|
||||
|
||||
case 199:
|
||||
#line 1250 "perly.y"
|
||||
{ (yyval.opval) = newLOGOP(OP_OR, 0, (ps[-2].val.opval), (ps[0].val.opval)); }
|
||||
{ (yyval.opval) = newLOGOP((ps[-1].val.ival), 0, (ps[-2].val.opval), (ps[0].val.opval)); }
|
||||
|
||||
break;
|
||||
|
||||
@ -2354,6 +2354,6 @@ case 2:
|
||||
|
||||
|
||||
/* Generated from:
|
||||
* ae786f28e8bc303471bcc03fc82e93a348d603252cc8c164a96cc0c26af78217 perly.y
|
||||
* d200edcf6b5ba783b2b4e34928c5787fcab506e14d318042f4e46dee90ba0898 perly.y
|
||||
* acf1cbfd2545faeaaa58b1cf0cf9d7f98b5be0752eb7a54528ef904a9e2e1ca7 regen_perly.pl
|
||||
* ex: set ro ft=c: */
|
||||
|
||||
2
perly.h
generated
2
perly.h
generated
@ -236,6 +236,6 @@ int yyparse (void);
|
||||
|
||||
|
||||
/* Generated from:
|
||||
* ae786f28e8bc303471bcc03fc82e93a348d603252cc8c164a96cc0c26af78217 perly.y
|
||||
* d200edcf6b5ba783b2b4e34928c5787fcab506e14d318042f4e46dee90ba0898 perly.y
|
||||
* acf1cbfd2545faeaaa58b1cf0cf9d7f98b5be0752eb7a54528ef904a9e2e1ca7 regen_perly.pl
|
||||
* ex: set ro ft=c: */
|
||||
|
||||
2
perly.tab
generated
2
perly.tab
generated
@ -1336,6 +1336,6 @@ static const toketypes yy_type_tab[] =
|
||||
};
|
||||
|
||||
/* Generated from:
|
||||
* ae786f28e8bc303471bcc03fc82e93a348d603252cc8c164a96cc0c26af78217 perly.y
|
||||
* d200edcf6b5ba783b2b4e34928c5787fcab506e14d318042f4e46dee90ba0898 perly.y
|
||||
* acf1cbfd2545faeaaa58b1cf0cf9d7f98b5be0752eb7a54528ef904a9e2e1ca7 regen_perly.pl
|
||||
* ex: set ro ft=c: */
|
||||
|
||||
2
perly.y
2
perly.y
@ -1247,7 +1247,7 @@ termbinop: term[lhs] PLUGIN_HIGH_OP[op] term[rhs]
|
||||
| term[lhs] PLUGIN_LOGICAL_AND_OP[op] term[rhs]
|
||||
{ $$ = build_infix_plugin($lhs, $rhs, $op); }
|
||||
| term[lhs] OROR term[rhs] /* $x || $y */
|
||||
{ $$ = newLOGOP(OP_OR, 0, $lhs, $rhs); }
|
||||
{ $$ = newLOGOP($OROR, 0, $lhs, $rhs); }
|
||||
| term[lhs] PLUGIN_LOGICAL_OR_OP[op] term[rhs]
|
||||
{ $$ = build_infix_plugin($lhs, $rhs, $op); }
|
||||
| term[lhs] DORDOR term[rhs] /* $x // $y */
|
||||
|
||||
@ -140,7 +140,7 @@ values only, not array values.
|
||||
left & &.
|
||||
left | |. ^ ^.
|
||||
left &&
|
||||
left || //
|
||||
left || ^^ //
|
||||
nonassoc .. ...
|
||||
right ?:
|
||||
right = += -= *= etc. goto last next redo dump
|
||||
@ -1019,6 +1019,13 @@ if the left operand is true, the right operand is not even evaluated.
|
||||
Scalar or list context propagates down to the right operand if it
|
||||
is evaluated.
|
||||
|
||||
=head2 C-style Logical Xor
|
||||
X<^^> X<operator, logical, xor>
|
||||
|
||||
Binary C<"^^"> performs a logical XOR operation. Both operands are
|
||||
evaluated and the result is true only if exactly one of the operands is true.
|
||||
Scalar or list context propagates down to the right operand.
|
||||
|
||||
=head2 Logical Defined-Or
|
||||
X<//> X<operator, logical, defined-or>
|
||||
|
||||
|
||||
11
t/op/lop.t
11
t/op/lop.t
@ -1,7 +1,7 @@
|
||||
#!./perl
|
||||
|
||||
#
|
||||
# test the logical operators '&&', '||', '!', 'and', 'or', , 'xor', 'not'
|
||||
# test the logical operators '&&', '||', '^^', '!', 'and', 'or', , 'xor', 'not'
|
||||
#
|
||||
|
||||
BEGIN {
|
||||
@ -10,7 +10,7 @@ BEGIN {
|
||||
set_up_inc('../lib');
|
||||
}
|
||||
|
||||
plan tests => 33;
|
||||
plan tests => 47;
|
||||
|
||||
for my $i (undef, 0 .. 2, "", "0 but true") {
|
||||
my $true = 1;
|
||||
@ -104,4 +104,11 @@ for my $test (
|
||||
) {
|
||||
my ($a,$b, $exp) = @$test;
|
||||
is(($a xor $b), $exp, "($a xor $b) == '$exp'");
|
||||
is(($a ^^ $b), $exp, "($a ^^ $b) == '$exp'");
|
||||
}
|
||||
|
||||
# precedence
|
||||
is((1 xor 1 and 0), 1, '(1 xor 1 and 0) == 1');
|
||||
is((1 xor 0 or 1), 1, "(1 xor 0 or 1) == 1");
|
||||
is((1 ^^ 1 && 0), 1, '(1 ^^ 1 && 0) == 1');
|
||||
is((1 ^^ 0 || 1), 1, "(1 ^^ 0 || 1) == 1");
|
||||
|
||||
13
toke.c
13
toke.c
@ -482,7 +482,7 @@ static struct debug_tokens {
|
||||
DEBUG_TOKEN (NONE, NOAMP),
|
||||
DEBUG_TOKEN (NONE, NOTOP),
|
||||
DEBUG_TOKEN (IVAL, OROP),
|
||||
DEBUG_TOKEN (NONE, OROR),
|
||||
DEBUG_TOKEN (IVAL, OROR),
|
||||
DEBUG_TOKEN (IVAL, PERLY_AMPERSAND),
|
||||
DEBUG_TOKEN (IVAL, PERLY_BRACE_CLOSE),
|
||||
DEBUG_TOKEN (IVAL, PERLY_BRACE_OPEN),
|
||||
@ -6099,6 +6099,16 @@ yyl_caret(pTHX_ char *s)
|
||||
{
|
||||
char *d = s;
|
||||
const bool bof = cBOOL(FEATURE_BITWISE_IS_ENABLED);
|
||||
if (s[1] == '^') {
|
||||
s += 2;
|
||||
if (!PL_lex_allbrackets && PL_lex_fakeeof >=
|
||||
(*s == '=' ? LEX_FAKEEOF_ASSIGN : LEX_FAKEEOF_LOGIC)) {
|
||||
s -= 2;
|
||||
TOKEN(0);
|
||||
}
|
||||
pl_yylval.ival = OP_XOR;
|
||||
OPERATOR(OROR);
|
||||
}
|
||||
if (bof && s[1] == '.')
|
||||
s++;
|
||||
if (!PL_lex_allbrackets && PL_lex_fakeeof >=
|
||||
@ -6618,6 +6628,7 @@ yyl_verticalbar(pTHX_ char *s)
|
||||
s -= 2;
|
||||
TOKEN(0);
|
||||
}
|
||||
pl_yylval.ival = OP_OR;
|
||||
AOPERATOR(OROR);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user