Don't try to export fd_refcnt symbols when building without USE_PERLIO
[p5sagit/p5-mst-13.2.git] / perly.y
diff --git a/perly.y b/perly.y
index 308176f..77caeb6 100644 (file)
--- a/perly.y
+++ b/perly.y
@@ -30,6 +30,9 @@
 %union {
     I32        ival;
     char *pval;
+#ifdef PERL_MAD
+    TOKEN* tkval;
+#endif
     OP *opval;
     GV *gvval;
 }
 %token <pval> LABEL
 %token <ival> FORMAT SUB ANONSUB PACKAGE USE
 %token <ival> WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE FOR
+%token <ival> GIVEN WHEN DEFAULT
 %token <ival> LOOPEX DOTDOT
 %token <ival> FUNC0 FUNC1 FUNC UNIOP LSTOP
 %token <ival> RELOP EQOP MULOP ADDOP
 %token <ival> DOLSHARP DO HASHBRACK NOAMP
-%token <ival> LOCAL MY MYSUB
+%token <ival> LOCAL MY MYSUB REQUIRE
 %token COLONATTR
 
 %type <ival> prog decl format startsub startanonsub startformsub mintro
-%type <ival> progstart remember mremember '&' savescope
+%type <ival> progstart remember mremember '&' savescope mydefsv
 %type <opval> block mblock lineseq line loop cond else
 %type <opval> expr term subscripted scalar ary hsh arylen star amper sideff
 %type <opval> argexpr nexpr texpr iexpr mexpr mnexpr miexpr
@@ -57,6 +61,7 @@
 %type <opval> formname subname proto subbody cont my_scalar
 %type <opval> subattrlist myattrlist mysubrout myattrterm myterm
 %type <opval> termbinop termunop anonymous termdo
+%type <opval> switch case
 %type <pval> label
 
 %nonassoc PREC_LOW
@@ -77,6 +82,7 @@
 %nonassoc EQOP
 %nonassoc RELOP
 %nonassoc UNIOP UNIOPSUB
+%nonassoc REQUIRE
 %left <ival> SHIFTOP
 %left ADDOP
 %left MULOP
@@ -89,6 +95,8 @@
 %left '('
 %left '[' '{'
 
+%token PEG
+
 %% /* RULES */
 
 /* The whole program */
@@ -108,6 +116,10 @@ remember:  /* NULL */      /* start a full lexical scope */
                        { $$ = block_start(TRUE); }
        ;
 
+mydefsv:       /* NULL */      /* lexicalize $_ */
+                       { $$ = (I32) allocmy("$_"); }
+       ;
+
 progstart:
                {
                    PL_expect = XSTATE; $$ = block_start(TRUE);
@@ -145,6 +157,10 @@ lineseq    :       /* NULL */
 line   :       label cond
                        { $$ = newSTATEOP(0, $1, $2); }
        |       loop    /* loops add their own labels */
+       |       switch  /* ... and so do switches */
+                       { $$ = $1; }
+       |       label case
+                       { $$ = newSTATEOP(0, $1, $2); }
        |       label ';'
                        { if ($1 != Nullch) {
                              $$ = newSTATEOP(0, $1, newOP(OP_NULL, 0));
@@ -199,6 +215,14 @@ cond       :       IF '(' remember mexpr ')' mblock else
                                   newCONDOP(0, $4, scope($6), $7)); }
        ;
 
+/* Cases for a switch statement */
+case   :       WHEN '(' remember mexpr ')' mblock
+       { $$ = block_end($3,
+               newWHENOP($4, scope($6))); }
+       |       DEFAULT block
+       { $$ = newWHENOP(0, scope($2)); }
+       ;
+
 /* Continue blocks */
 cont   :       /* NULL */
                        { $$ = Nullop; }
@@ -252,6 +276,15 @@ loop       :       label WHILE '(' remember texpr ')' mintro mblock cont
                                            NOLINE, Nullop, $2, $3, 0)); }
        ;
 
+/* Switch blocks */
+switch :       label GIVEN '(' remember mydefsv mexpr ')' mblock
+                       { PL_copline = (line_t) $2;
+                           $$ = block_end($4,
+                               newSTATEOP(0, $1,
+                                   newGIVENOP($6, scope($8),
+                                       (PADOFFSET) $5) )); }
+       ;
+
 /* determine whether there are any new my declarations */
 mintro :       /* NULL */
                        { $$ = (PL_min_intro_pending &&
@@ -308,7 +341,8 @@ decl        :       format
        ;
 
 format :       FORMAT startformsub formname block
-                       { newFORM($2, $3, $4); }
+                       { SvREFCNT_inc(PL_compcv);
+                         newFORM($2, $3, $4); }
        ;
 
 formname:      WORD            { $$ = $1; }
@@ -317,30 +351,36 @@ formname: WORD            { $$ = $1; }
 
 /* Unimplemented "my sub foo { }" */
 mysubrout:     MYSUB startsub subname proto subattrlist subbody
-                       { newMYSUB($2, $3, $4, $5, $6); }
+                       { SvREFCNT_inc(PL_compcv);
+                         newMYSUB($2, $3, $4, $5, $6); }
        ;
 
 /* Subroutine definition */
 subrout        :       SUB startsub subname proto subattrlist subbody
-                       { newATTRSUB($2, $3, $4, $5, $6); }
+                       { SvREFCNT_inc(PL_compcv);
+                         newATTRSUB($2, $3, $4, $5, $6); }
        ;
 
 startsub:      /* NULL */      /* start a regular subroutine scope */
-                       { $$ = start_subparse(FALSE, 0); }
+                       { $$ = start_subparse(FALSE, 0);
+                           SAVEFREESV(PL_compcv); }
        ;
 
 startanonsub:  /* NULL */      /* start an anonymous subroutine scope */
-                       { $$ = start_subparse(FALSE, CVf_ANON); }
+                       { $$ = start_subparse(FALSE, CVf_ANON);
+                           SAVEFREESV(PL_compcv); }
        ;
 
 startformsub:  /* NULL */      /* start a format subroutine scope */
-                       { $$ = start_subparse(TRUE, 0); }
+                       { $$ = start_subparse(TRUE, 0);
+                           SAVEFREESV(PL_compcv); }
        ;
 
 /* Name of a subroutine - must be a bareword, could be special */
-subname        :       WORD    { STRLEN n_a; char *name = SvPV(((SVOP*)$1)->op_sv,n_a);
+subname        :       WORD    { const char *const name = SvPV_nolen_const(((SVOP*)$1)->op_sv);
                          if (strEQ(name, "BEGIN") || strEQ(name, "END")
-                             || strEQ(name, "INIT") || strEQ(name, "CHECK"))
+                             || strEQ(name, "INIT") || strEQ(name, "CHECK")
+                             || strEQ(name, "UNITCHECK"))
                              CvSPECIAL_on(PL_compcv);
                          $$ = $1; }
        ;
@@ -379,7 +419,8 @@ package :   PACKAGE WORD ';'
 use    :       USE startsub
                        { CvSPECIAL_on(PL_compcv); /* It's a BEGIN {} */ }
                    WORD WORD listexpr ';'
-                       { utilize($1, $2, $4, $5, $6); }
+                        { SvREFCNT_inc(PL_compcv);
+                          utilize($1, $2, $4, $5, $6); }
        ;
 
 /* Ordinary expressions; logical combinations */
@@ -431,7 +472,8 @@ listop      :       LSTOP indirob argexpr /* map {...} @args or print $fh @args */
        |       FUNC '(' listexprcom ')'             /* print (@args) */
                        { $$ = convert($1, 0, $3); }
        |       LSTOPSUB startanonsub block /* sub f(&@);   f { foo } ... */
-                       { $3 = newANONATTRSUB($2, 0, Nullop, $3); }
+                       { SvREFCNT_inc(PL_compcv);
+                         $3 = newANONATTRSUB($2, 0, Nullop, $3); }
                    listexpr            %prec LSTOP  /* ... @bar */
                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                 append_elem(OP_LIST,
@@ -487,6 +529,10 @@ subscripted:    star '{' expr ';' '}'        /* *main::{something} */
        |       subscripted '(' ')'        /* $foo->{bar}->() */
                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                   newCVREF(0, scalar($1))); }
+       |       '(' expr ')' '[' expr ']'            /* list slice */
+                       { $$ = newSLICEOP(0, $5, $2); }
+       |       '(' ')' '[' expr ']'                 /* empty list slice! */
+                       { $$ = newSLICEOP(0, $4, Nullop); }
     ;
 
 /* Binary operators between terms */
@@ -556,13 +602,14 @@ anonymous:        '[' expr ']'
        |       HASHBRACK ';' '}'       %prec '(' /* { } (';' by tokener) */
                        { $$ = newANONHASH(Nullop); }
        |       ANONSUB startanonsub proto subattrlist block    %prec '('
-                       { $$ = newANONATTRSUB($2, $3, $4, $5); }
+                       { SvREFCNT_inc(PL_compcv);
+                         $$ = newANONATTRSUB($2, $3, $4, $5); }
 
     ;
 
 /* Things called with "do" */
 termdo :       DO term %prec UNIOP                     /* do $filename */
-                       { $$ = dofile($2); }
+                       { $$ = dofile($2, $1); }
        |       DO block        %prec '('               /* do { code */
                        { $$ = newUNOP(OP_NULL, OPf_SPECIAL, scope($2)); }
        |       DO WORD '(' ')'                         /* do somesub() */
@@ -622,10 +669,6 @@ term       :       termbinop
                        { $$ = newUNOP(OP_AV2ARYLEN, 0, ref($1, OP_AV2ARYLEN));}
        |       subscripted
                        { $$ = $1; }
-       |       '(' expr ')' '[' expr ']'            /* list slice */
-                       { $$ = newSLICEOP(0, $5, $2); }
-       |       '(' ')' '[' expr ']'                 /* empty list slice! */
-                       { $$ = newSLICEOP(0, $4, Nullop); }
        |       ary '[' expr ']'                     /* array slice */
                        { $$ = prepend_elem(OP_ASLICE,
                                newOP(OP_PUSHMARK, 0),
@@ -664,6 +707,12 @@ term       :       termbinop
                        { $$ = newUNOP($1, 0, $2); }
        |       UNIOP term                           /* Unary op */
                        { $$ = newUNOP($1, 0, $2); }
+       |       REQUIRE                              /* require, $_ implied */
+                       { $$ = newOP(OP_REQUIRE, $1 ? OPf_SPECIAL : 0); }
+       |       REQUIRE term                         /* require Foo */
+                       { $$ = newUNOP(OP_REQUIRE, $1 ? OPf_SPECIAL : 0, $2); }
+       |       UNIOPSUB
+                       { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar($1)); }
        |       UNIOPSUB term                        /* Sub treated as unop */
                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
                            append_elem(OP_LIST, $2, scalar($1))); }