Skip to content

Commit 29d69c3

Browse files
author
Zefram
committed
parse yada-yada only as a statement
Commit f5727a1 tried to make yada-yada be parsed consistently as a term expression, but actually things are more complicated than that. The tokeniser didn't accept yada-yada in the right contexts to make it usable as an expression, and changing that would require decisions on resolving ambiguities between yada-yada and flip-flop. It's also documented as being a statement rather than an expression, though with some incorrect information about ambiguities. Overall it looks more like the intent was for yada-yada to be a statement. This commit makes it grammatically treated as such, and also fixes up the dubious parts of the documentation. [perl #132150]
1 parent c6fbd35 commit 29d69c3

File tree

8 files changed

+1121
-1109
lines changed

8 files changed

+1121
-1109
lines changed

perly.act

+325-325
Large diffs are not rendered by default.

perly.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,6 @@ int yyparse (void);
181181

182182

183183
/* Generated from:
184-
* 68a62998f7c607d7a1fa0fdf2d16ec19074c256dde18dfc475daff70d378e025 perly.y
184+
* 4667736d3c31a5169bab73c89d70a27dbce5ea4fe7e3c332a236f8a210aafdc2 perly.y
185185
* 153cba5d215c1a083a0459c43f4d55c45fd0a7093c197d7247a456dcde21ea53 regen_perly.pl
186186
* ex: set ro: */

perly.tab

+741-739
Large diffs are not rendered by default.

perly.y

+6-6
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
%left <ival> ','
9191
%right <ival> ASSIGNOP
9292
%right <ival> '?' ':'
93-
%nonassoc DOTDOT YADAYADA
93+
%nonassoc DOTDOT
9494
%left <ival> OROR DORDOR
9595
%left <ival> ANDAND
9696
%left <ival> BITOROP
@@ -481,6 +481,11 @@ barestmt: PLUGSTMT
481481
{
482482
$$ = $1;
483483
}
484+
| YADAYADA ';'
485+
{
486+
$$ = newLISTOP(OP_DIE, 0, newOP(OP_PUSHMARK, 0),
487+
newSVOP(OP_CONST, 0, newSVpvs("Unimplemented")));
488+
}
484489
| ';'
485490
{
486491
$$ = NULL;
@@ -1210,11 +1215,6 @@ term : termbinop
12101215
{ $$ = pmruntime($1, $4, $5, 1, $<ival>2); }
12111216
| BAREWORD
12121217
| listop
1213-
| YADAYADA
1214-
{
1215-
$$ = newLISTOP(OP_DIE, 0, newOP(OP_PUSHMARK, 0),
1216-
newSVOP(OP_CONST, 0, newSVpvs("Unimplemented")));
1217-
}
12181218
| PLUGEXPR
12191219
;
12201220

pod/perldelta.pod

+16
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,22 @@ XXX For a release on a stable branch, this section aspires to be:
5151

5252
[ List each incompatible change as a =head2 entry ]
5353

54+
=head2 Yada-yada is now strictly a statement
55+
56+
By the time of its initial stable release in Perl 5.12, the C<...>
57+
(yada-yada) operator was explicitly intended to serve as a statement,
58+
not an expression. However, the original implementation was confused
59+
on this point, leading to inconsistent parsing. The operator was
60+
accidentally accepted in a few situations where it did not serve as a
61+
complete statement, such as
62+
63+
... . "foo";
64+
... if $a < $b;
65+
66+
The parsing has now been made consistent, permitting yada-yada only as
67+
a statement. Affected code can use C<do{...}> to put a yada-yada into
68+
an arbitrary expression context.
69+
5470
=head1 Deprecations
5571

5672
XXX Any deprecated features, syntax, modules etc. should be listed here.

pod/perlsyn.pod

+12-21
Original file line numberDiff line numberDiff line change
@@ -754,12 +754,7 @@ X<whatever operator>
754754
X<triple-dot operator>
755755

756756
Beginning in Perl 5.12, Perl accepts an ellipsis, "C<...>", as a
757-
placeholder for code that you haven't implemented yet. This form of
758-
ellipsis, the unimplemented statement, should not be confused with the
759-
binary flip-flop C<...> operator. One is a statement and the other an
760-
operator. (Perl doesn't usually confuse them because usually Perl can tell
761-
whether it wants an operator or a statement, but see below for exceptions.)
762-
757+
placeholder for code that you haven't implemented yet.
763758
When Perl 5.12 or later encounters an ellipsis statement, it parses this
764759
without error, but if and when you should actually try to execute it, Perl
765760
throws an exception with the text C<Unimplemented>:
@@ -771,8 +766,11 @@ throws an exception with the text C<Unimplemented>:
771766
say "I found an ellipsis!";
772767
}
773768

774-
You can only use the elliptical statement to stand in for a
775-
complete statement. These examples of how the ellipsis works:
769+
You can only use the elliptical statement to stand in for a complete
770+
statement. Syntactically, "C<...;>" is a complete statement, but,
771+
as with other kinds of semicolon-terminated statement, the semicolon
772+
may be omitted if "C<...>" appears immediately before a closing brace.
773+
These examples show how the ellipsis works:
776774

777775
use v5.12;
778776
{ ... }
@@ -791,32 +789,25 @@ complete statement. These examples of how the ellipsis works:
791789
};
792790

793791
The elliptical statement cannot stand in for an expression that
794-
is part of a larger statement, since the C<...> is also the three-dot
795-
version of the flip-flop operator (see L<perlop/"Range Operators">).
796-
792+
is part of a larger statement.
797793
These examples of attempts to use an ellipsis are syntax errors:
798794

799795
use v5.12;
800796

801797
print ...;
802798
open(my $fh, ">", "/dev/passwd") or ...;
803799
if ($condition && ... ) { say "Howdy" };
800+
... if $a > $b;
801+
say "Cromulent" if ...;
802+
$flub = 5 + ...;
804803

805804
There are some cases where Perl can't immediately tell the difference
806805
between an expression and a statement. For instance, the syntax for a
807806
block and an anonymous hash reference constructor look the same unless
808807
there's something in the braces to give Perl a hint. The ellipsis is a
809-
syntax error if Perl doesn't guess that the C<{ ... }> is a block. In that
810-
case, it doesn't think the C<...> is an ellipsis because it's expecting an
811-
expression instead of a statement:
812-
813-
@transformed = map { ... } @input; # syntax error
814-
808+
syntax error if Perl doesn't guess that the C<{ ... }> is a block.
815809
Inside your block, you can use a C<;> before the ellipsis to denote that the
816-
C<{ ... }> is a block and not a hash reference constructor. Now the ellipsis
817-
works:
818-
819-
@transformed = map {; ... } @input; # ';' disambiguates
810+
C<{ ... }> is a block and not a hash reference constructor.
820811

821812
Note: Some folks colloquially refer to this bit of punctuation as a
822813
"yada-yada" or "triple-dot", but its true name

t/op/yadayada.t

+19-16
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ BEGIN {
88

99
use strict;
1010

11-
plan 12;
11+
plan 34;
1212

1313
my $err;
1414
my $err1 = "Unimplemented at $0 line ";
@@ -19,6 +19,11 @@ eval { ... };
1919
is $@, $err, "Execution of ellipsis statement reported 'Unimplemented' code";
2020
$@ = '';
2121

22+
my $i = 0;
23+
is eval { $i++; ...; $i+=10; 123 }, undef;
24+
like $@, qr/\AUnimplemented /;
25+
is $i, 1;
26+
2227
note("RT #122661: Semicolon before ellipsis statement disambiguates to indicate block rather than hash reference");
2328
my @input = (3..5);
2429
my @transformed;
@@ -42,21 +47,19 @@ eval { @transformed = map {;... } @input; };
4247
is $@, $err, "Disambiguation case 4";
4348
$@ = '';
4449

45-
note("RT #132150: ... is a term, not an operator");
46-
$err = $err1 . ( __LINE__ + 1 ) . $err2;
47-
eval { ... + 0 };
48-
is $@, $err, "... + 0 parses";
49-
$@ = '';
50-
51-
$err = $err1 . ( __LINE__ + 1 ) . $err2;
52-
eval { ... % 1 };
53-
is $@, $err, "... % 1 parses";
54-
$@ = '';
55-
56-
$err = $err1 . ( __LINE__ + 1 ) . $err2;
57-
eval { ... / 1 };
58-
is $@, $err, "... / 1 parses";
59-
$@ = '';
50+
note("RT #132150: ... in other contexts is a syntax error");
51+
foreach(
52+
"... + 0", "0 + ...",
53+
"... . 0", "0 . ...",
54+
"... or 1", "1 or ...",
55+
"... if 1", "1 if ...",
56+
'[...]',
57+
'my $a = ...',
58+
'... sub quux {}',
59+
) {
60+
is eval($_), undef;
61+
like $@, qr/\Asyntax error /;
62+
}
6063

6164
#
6265
# Regression tests, making sure ... is still parsable as an operator.

toke.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -6887,7 +6887,7 @@ Perl_yylex(pTHX)
68876887
}
68886888
if (PL_expect == XSTATE && s[1] == '.' && s[2] == '.') {
68896889
s += 3;
6890-
TERM(YADAYADA);
6890+
OPERATOR(YADAYADA);
68916891
}
68926892
if (PL_expect == XOPERATOR || !isDIGIT(s[1])) {
68936893
char tmp = *s++;

0 commit comments

Comments
 (0)