This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
fix icmp ping tests on cygwin
[perl5.git] / perly.y
diff --git a/perly.y b/perly.y
index a8adefb..b4bdb48 100644 (file)
--- a/perly.y
+++ b/perly.y
@@ -1,7 +1,7 @@
 /*    perly.y
  *
  *    Copyright (c) 1991-2002, 2003, 2004, 2005, 2006 Larry Wall
- *    Copyright (c) 2007, 2008 by Larry Wall and others
+ *    Copyright (c) 2007, 2008, 2009, 2010, 2011 by Larry Wall and others
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -74,7 +74,7 @@
 %token <i_tkval> '{' '}' '[' ']' '-' '+' '$' '@' '%' '*' '&' ';'
 
 %token <opval> WORD METHOD FUNCMETH THING PMFUNC PRIVATEREF QWLIST
-%token <opval> FUNC0SUB UNIOPSUB LSTOPSUB
+%token <opval> FUNC0OP FUNC0SUB UNIOPSUB LSTOPSUB
 %token <opval> PLUGEXPR PLUGSTMT
 %token <p_tkval> LABEL
 %token <i_tkval> FORMAT SUB ANONSUB PACKAGE USE
@@ -87,8 +87,6 @@
 %token <i_tkval> LOCAL MY MYSUB REQUIRE
 %token <i_tkval> COLONATTR
 
-%type <i_tkval> lpar_or_qw
-
 %type <ival> grammar remember mremember
 %type <ival>  startsub startanonsub startformsub
 /* FIXME for MAD - are these two ival? */
@@ -260,13 +258,15 @@ fullstmt: barestmt
 
 labfullstmt:   LABEL barestmt
                        {
-                         $$ = newSTATEOP(0, PVAL($1), $2);
+                         $$ = newSTATEOP(SvUTF8(((SVOP*)$1)->op_sv),
+                                        savepv(SvPVX(((SVOP*)$1)->op_sv)), $2);
                          TOKEN_GETMAD($1,
                              $2 ? cLISTOPx($$)->op_first : $$, 'L');
                        }
        |       LABEL labfullstmt
                        {
-                         $$ = newSTATEOP(0, PVAL($1), $2);
+                         $$ = newSTATEOP(SvUTF8(((SVOP*)$1)->op_sv),
+                                        savepv(SvPVX(((SVOP*)$1)->op_sv)), $2);
                          TOKEN_GETMAD($1, cLISTOPx($$)->op_first, 'L');
                        }
        ;
@@ -292,9 +292,9 @@ barestmt:   PLUGSTMT
                          newFORM($2, $3, $4);
                          $$ = (OP*)NULL;
 #endif
-                         if (CvOUTSIDE(fmtcv) && !CvUNIQUE(CvOUTSIDE(fmtcv))) {
+                         if (CvOUTSIDE(fmtcv) && !CvEVAL(CvOUTSIDE(fmtcv))) {
                              SvREFCNT_inc_simple_void(fmtcv);
-                             pad_add_anon((SV*)fmtcv, OP_NULL);
+                             pad_add_anon(fmtcv, OP_NULL);
                          }
                        }
        |       SUB startsub subname proto subattrlist subbody
@@ -362,7 +362,7 @@ barestmt:   PLUGSTMT
                          $$ = (OP*)NULL;
 #endif
                        }
-       |       IF lpar_or_qw remember mexpr ')' mblock else
+       |       IF '(' remember mexpr ')' mblock else
                        {
                          $$ = block_end($3,
                              newCONDOP(0, $4, op_scope($6), $7));
@@ -371,7 +371,7 @@ barestmt:   PLUGSTMT
                          TOKEN_GETMAD($5,$$,')');
                          PL_parser->copline = (line_t)IVAL($1);
                        }
-       |       UNLESS lpar_or_qw remember miexpr ')' mblock else
+       |       UNLESS '(' remember miexpr ')' mblock else
                        {
                          $$ = block_end($3,
                              newCONDOP(0, $4, op_scope($6), $7));
@@ -380,17 +380,17 @@ barestmt: PLUGSTMT
                          TOKEN_GETMAD($5,$$,')');
                          PL_parser->copline = (line_t)IVAL($1);
                        }
-       |       GIVEN lpar_or_qw remember mydefsv mexpr ')' mblock
+       |       GIVEN '(' remember mydefsv mexpr ')' mblock
                        {
                          $$ = block_end($3,
                                  newGIVENOP($5, op_scope($7), (PADOFFSET)$4));
                          PL_parser->copline = (line_t)IVAL($1);
                        }
-       |       WHEN lpar_or_qw remember mexpr ')' mblock
+       |       WHEN '(' remember mexpr ')' mblock
                        { $$ = block_end($3, newWHENOP($4, op_scope($6))); }
        |       DEFAULT block
                        { $$ = newWHENOP(0, op_scope($2)); }
-       |       WHILE lpar_or_qw remember texpr ')' mintro mblock cont
+       |       WHILE '(' remember texpr ')' mintro mblock cont
                        {
                          $$ = block_end($3,
                                  newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
@@ -400,7 +400,7 @@ barestmt:   PLUGSTMT
                          TOKEN_GETMAD($5,$$,')');
                          PL_parser->copline = (line_t)IVAL($1);
                        }
-       |       UNTIL lpar_or_qw remember iexpr ')' mintro mblock cont
+       |       UNTIL '(' remember iexpr ')' mintro mblock cont
                        {
                          $$ = block_end($3,
                                  newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
@@ -410,7 +410,7 @@ barestmt:   PLUGSTMT
                          TOKEN_GETMAD($5,$$,')');
                          PL_parser->copline = (line_t)IVAL($1);
                        }
-       |       FOR lpar_or_qw remember mnexpr ';' texpr ';' mintro mnexpr ')'
+       |       FOR '(' remember mnexpr ';' texpr ';' mintro mnexpr ')'
                mblock
                        {
                          OP *initop = IF_MAD($4 ? $4 : newOP(OP_NULL, 0), $4);
@@ -431,7 +431,7 @@ barestmt:   PLUGSTMT
                          TOKEN_GETMAD($10,$$,')');
                          PL_parser->copline = (line_t)IVAL($1);
                        }
-       |       FOR MY remember my_scalar lpar_or_qw mexpr ')' mblock cont
+       |       FOR MY remember my_scalar '(' mexpr ')' mblock cont
                        {
                          $$ = block_end($3, newFOROP(0, $4, $6, $8, $9));
                          TOKEN_GETMAD($1,$$,'W');
@@ -440,7 +440,7 @@ barestmt:   PLUGSTMT
                          TOKEN_GETMAD($7,$$,')');
                          PL_parser->copline = (line_t)IVAL($1);
                        }
-       |       FOR scalar lpar_or_qw remember mexpr ')' mblock cont
+       |       FOR scalar '(' remember mexpr ')' mblock cont
                        {
                          $$ = block_end($4, newFOROP(0,
                                      op_lvalue($2, OP_ENTERLOOP), $5, $7, $8));
@@ -449,7 +449,7 @@ barestmt:   PLUGSTMT
                          TOKEN_GETMAD($6,$$,')');
                          PL_parser->copline = (line_t)IVAL($1);
                        }
-       |       FOR lpar_or_qw remember mexpr ')' mblock cont
+       |       FOR '(' remember mexpr ')' mblock cont
                        {
                          $$ = block_end($3,
                                  newFOROP(0, (OP*)NULL, $4, $6, $7));
@@ -466,15 +466,9 @@ barestmt:  PLUGSTMT
                        }
        |       PACKAGE WORD WORD '{' remember
                        {
-                         int save_3_latefree = $3->op_latefree;
-                         $3->op_latefree = 1;
                          package($3);
-                         $3->op_latefree = save_3_latefree;
                          if ($2) {
-                             int save_2_latefree = $2->op_latefree;
-                             $2->op_latefree = 1;
                              package_version($2);
-                             $2->op_latefree = save_2_latefree;
                          }
                        }
                stmtseq '}'
@@ -482,9 +476,6 @@ barestmt:   PLUGSTMT
                          /* a block is a loop that happens once */
                          $$ = newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
                                  (OP*)NULL, block_end($5, $7), (OP*)NULL, 0);
-                         op_free($3);
-                         if ($2)
-                             op_free($2);
                          TOKEN_GETMAD($4,$$,'{');
                          TOKEN_GETMAD($8,$$,'}');
                          if (PL_parser->copline > (line_t)IVAL($4))
@@ -544,7 +535,7 @@ else        :       /* NULL */
                          $$ = op_scope($2);
                          TOKEN_GETMAD($1,$$,'o');
                        }
-       |       ELSIF lpar_or_qw mexpr ')' mblock else
+       |       ELSIF '(' mexpr ')' mblock else
                        { PL_parser->copline = (line_t)IVAL($1);
                            $$ = newCONDOP(0,
                                newSTATEOP(OPf_SPECIAL,NULL,$3),
@@ -732,7 +723,7 @@ listop      :       LSTOP indirob listexpr /* map {...} @args or print $fh @args */
                          TOKEN_GETMAD($2,$$,'(');
                          TOKEN_GETMAD($5,$$,')');
                        }
-       |       term ARROW method lpar_or_qw optexpr ')' /* $foo->bar(list) */
+       |       term ARROW method '(' optexpr ')' /* $foo->bar(list) */
                        { $$ = convert(OP_ENTERSUB, OPf_STACKED,
                                op_append_elem(OP_LIST,
                                    op_prepend_elem(OP_LIST, scalar($1), $5),
@@ -858,14 +849,14 @@ subscripted:    star '{' expr ';' '}'        /* *main::{something} */
                          TOKEN_GETMAD($5,$$,')');
                        }
 
-       |       subscripted lpar_or_qw expr ')'   /* $foo->{bar}->(@args) */
+       |       subscripted '(' expr ')'   /* $foo->{bar}->(@args) */
                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                   op_append_elem(OP_LIST, $3,
                                               newCVREF(0, scalar($1))));
                          TOKEN_GETMAD($2,$$,'(');
                          TOKEN_GETMAD($4,$$,')');
                        }
-       |       subscripted lpar_or_qw ')'        /* $foo->{bar}->() */
+       |       subscripted '(' ')'        /* $foo->{bar}->() */
                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                   newCVREF(0, scalar($1)));
                          TOKEN_GETMAD($2,$$,'(');
@@ -1049,7 +1040,7 @@ termdo    :       DO term %prec UNIOP                     /* do $filename */
                        { $$ = newUNOP(OP_NULL, OPf_SPECIAL, op_scope($2));
                          TOKEN_GETMAD($1,$$,'D');
                        }
-       |       DO WORD lpar_or_qw ')'                  /* do somesub() */
+       |       DO WORD '(' ')'                  /* do somesub() */
                        { $$ = newUNOP(OP_ENTERSUB,
                            OPf_SPECIAL|OPf_STACKED,
                            op_prepend_elem(OP_LIST,
@@ -1061,7 +1052,7 @@ termdo    :       DO term %prec UNIOP                     /* do $filename */
                          TOKEN_GETMAD($3,$$,'(');
                          TOKEN_GETMAD($4,$$,')');
                        }
-       |       DO WORD lpar_or_qw expr ')'             /* do somesub(@args) */
+       |       DO WORD '(' expr ')'             /* do somesub(@args) */
                        { $$ = newUNOP(OP_ENTERSUB,
                            OPf_SPECIAL|OPf_STACKED,
                            op_append_elem(OP_LIST,
@@ -1074,7 +1065,7 @@ termdo    :       DO term %prec UNIOP                     /* do $filename */
                          TOKEN_GETMAD($3,$$,'(');
                          TOKEN_GETMAD($5,$$,')');
                        }
-       |       DO scalar lpar_or_qw ')'                /* do $subref () */
+       |       DO scalar '(' ')'                /* do $subref () */
                        { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
                            op_prepend_elem(OP_LIST,
                                scalar(newCVREF(0,scalar($2))), (OP*)NULL)); dep();
@@ -1082,7 +1073,7 @@ termdo    :       DO term %prec UNIOP                     /* do $filename */
                          TOKEN_GETMAD($3,$$,'(');
                          TOKEN_GETMAD($4,$$,')');
                        }
-       |       DO scalar lpar_or_qw expr ')'           /* do $subref (@args) */
+       |       DO scalar '(' expr ')'           /* do $subref (@args) */
                        { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
                            op_prepend_elem(OP_LIST,
                                $4,
@@ -1161,12 +1152,12 @@ term    :       termbinop
                        { $$ = $1; }
        |       amper                                /* &foo; */
                        { $$ = newUNOP(OP_ENTERSUB, 0, scalar($1)); }
-       |       amper lpar_or_qw ')'                 /* &foo() */
+       |       amper '(' ')'                 /* &foo() */
                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar($1));
                          TOKEN_GETMAD($2,$$,'(');
                          TOKEN_GETMAD($3,$$,')');
                        }
-       |       amper lpar_or_qw expr ')'            /* &foo(@args) */
+       |       amper '(' expr ')'            /* &foo(@args) */
                        {
                          $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                op_append_elem(OP_LIST, $3, scalar($1)));
@@ -1232,6 +1223,13 @@ term     :       termbinop
                          TOKEN_GETMAD($2,$$,'(');
                          TOKEN_GETMAD($3,$$,')');
                        }
+       |       FUNC0OP       /* Same as above, but op created in toke.c */
+                       { $$ = $1; }
+       |       FUNC0OP '(' ')'
+                       { $$ = $1;
+                         TOKEN_GETMAD($2,$$,'(');
+                         TOKEN_GETMAD($3,$$,')');
+                       }
        |       FUNC0SUB                             /* Sub treated as nullop */
                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                scalar($1)); }
@@ -1250,10 +1248,21 @@ term    :       termbinop
                          TOKEN_GETMAD($2,$$,'(');
                          TOKEN_GETMAD($4,$$,')');
                        }
-       |       PMFUNC '(' listexpr ')'         /* m//, s///, tr/// */
-                       { $$ = pmruntime($1, $3, 1);
-                         TOKEN_GETMAD($2,$$,'(');
-                         TOKEN_GETMAD($4,$$,')');
+       |       PMFUNC /* m//, s///, qr//, tr/// */
+                       {
+                           if (   $1->op_type != OP_TRANS
+                               && $1->op_type != OP_TRANSR
+                               && (((PMOP*)$1)->op_pmflags & PMf_HAS_CV))
+                           {
+                               $<ival>$ = start_subparse(FALSE, CVf_ANON);
+                               SAVEFREESV(PL_compcv);
+                           } else
+                               $<ival>$ = 0;
+                       }
+                   '(' listexpr ')'
+                       { $$ = pmruntime($1, $4, 1, $<ival>2);
+                         TOKEN_GETMAD($3,$$,'(');
+                         TOKEN_GETMAD($5,$$,')');
                        }
        |       WORD
        |       listop
@@ -1313,14 +1322,6 @@ optexpr: /* NULL */
                        { $$ = $1; }
        ;
 
-lpar_or_qw:    '('
-                       { $$ = $1; }
-       |       QWLIST
-                       { munge_qwlist_to_paren_list($1); }
-               '('
-                       { $$ = $3; }
-       ;
-
 /* A little bit of trickery to make "for my $foo (@bar)" actually be
    lexical */
 my_scalar:     scalar