perl/perly.y
<<
>>
Prefs
   1/*    perly.y
   2 *
   3 *    Copyright (c) 1991-2002, 2003, 2004, 2005, 2006 Larry Wall
   4 *    Copyright (c) 2007, 2008 by Larry Wall and others
   5 *
   6 *    You may distribute under the terms of either the GNU General Public
   7 *    License or the Artistic License, as specified in the README file.
   8 *
   9 */
  10
  11/*
  12 * 'I see,' laughed Strider.  'I look foul and feel fair.  Is that it?
  13 *  All that is gold does not glitter, not all those who wander are lost.'
  14 *
  15 *     [p.171 of _The Lord of the Rings_, I/x: "Strider"]
  16 */
  17
  18/*
  19 * This file holds the grammar for the Perl language. If edited, you need
  20 * to run regen_perly.pl, which re-creates the files perly.h, perly.tab
  21 * and perly.act which are derived from this.
  22 *
  23 * Note that these derived files are included and compiled twice; once
  24 * from perly.c, and once from madly.c. The second time, a number of MAD
  25 * macros are defined, which compile in extra code that allows the parse
  26 * tree to be accurately dumped. In particular:
  27 *
  28 * MAD            defined if compiling madly.c
  29 * DO_MAD(A)      expands to A  under madly.c, to null otherwise
  30 * IF_MAD(a,b)    expands to A under madly.c, to B otherwise
  31 * TOKEN_GETMAD() expands to token_getmad() under madly.c, to null otherwise
  32 * TOKEN_FREE()   similarly
  33 * OP_GETMAD()    similarly
  34 * IVAL(i)        expands to (i)->tk_lval.ival or (i)
  35 * PVAL(p)        expands to (p)->tk_lval.pval or (p)
  36 *
  37 * The main job of of this grammar is to call the various newFOO()
  38 * functions in op.c to build a syntax tree of OP structs.
  39 * It relies on the lexer in toke.c to do the tokenizing.
  40 *
  41 * Note: due to the way that the cleanup code works WRT to freeing ops on
  42 * the parse stack, it is dangerous to assign to the $n variables within
  43 * an action.
  44 */
  45
  46/*  Make the parser re-entrant. */
  47
  48%pure_parser
  49
  50/* FIXME for MAD - is the new mintro on while and until important?  */
  51
  52%start prog
  53
  54%union {
  55    I32 ival; /* __DEFAULT__ (marker for regen_perly.pl;
  56                                must always be 1st union member) */
  57    char *pval;
  58    OP *opval;
  59    GV *gvval;
  60#ifdef PERL_IN_MADLY_C
  61    TOKEN* p_tkval;
  62    TOKEN* i_tkval;
  63#else
  64    char *p_tkval;
  65    I32 i_tkval;
  66#endif
  67#ifdef PERL_MAD
  68    TOKEN* tkval;
  69#endif
  70}
  71
  72%token <i_tkval> '{' '}' '[' ']' '-' '+' '$' '@' '%' '*' '&' ';'
  73
  74%token <opval> WORD METHOD FUNCMETH THING PMFUNC PRIVATEREF
  75%token <opval> FUNC0SUB UNIOPSUB LSTOPSUB
  76%token <p_tkval> LABEL
  77%token <i_tkval> FORMAT SUB ANONSUB PACKAGE USE
  78%token <i_tkval> WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE FOR
  79%token <i_tkval> GIVEN WHEN DEFAULT
  80%token <i_tkval> LOOPEX DOTDOT
  81%token <i_tkval> FUNC0 FUNC1 FUNC UNIOP LSTOP
  82%token <i_tkval> RELOP EQOP MULOP ADDOP
  83%token <i_tkval> DOLSHARP DO HASHBRACK NOAMP
  84%token <i_tkval> LOCAL MY MYSUB REQUIRE
  85%token <i_tkval> COLONATTR
  86
  87%type <ival> prog progstart remember mremember
  88%type <ival>  startsub startanonsub startformsub
  89/* FIXME for MAD - are these two ival? */
  90%type <ival> mydefsv mintro
  91
  92%type <opval> decl format subrout mysubrout package use peg
  93
  94%type <opval> block mblock lineseq line loop cond else
  95%type <opval> expr term subscripted scalar ary hsh arylen star amper sideff
  96%type <opval> argexpr nexpr texpr iexpr mexpr mnexpr miexpr
  97%type <opval> listexpr listexprcom indirob listop method
  98%type <opval> formname subname proto subbody cont my_scalar
  99%type <opval> subattrlist myattrlist myattrterm myterm
 100%type <opval> termbinop termunop anonymous termdo
 101%type <opval> switch case
 102%type <p_tkval> label
 103
 104%nonassoc <i_tkval> PREC_LOW
 105%nonassoc LOOPEX
 106
 107%left <i_tkval> OROP DOROP
 108%left <i_tkval> ANDOP
 109%right <i_tkval> NOTOP
 110%nonassoc LSTOP LSTOPSUB
 111%left <i_tkval> ','
 112%right <i_tkval> ASSIGNOP
 113%right <i_tkval> '?' ':'
 114%nonassoc DOTDOT
 115%left <i_tkval> OROR DORDOR
 116%left <i_tkval> ANDAND
 117%left <i_tkval> BITOROP
 118%left <i_tkval> BITANDOP
 119%nonassoc EQOP
 120%nonassoc RELOP
 121%nonassoc UNIOP UNIOPSUB
 122%nonassoc REQUIRE
 123%left <i_tkval> SHIFTOP
 124%left ADDOP
 125%left MULOP
 126%left <i_tkval> MATCHOP
 127%right <i_tkval> '!' '~' UMINUS REFGEN
 128%right <i_tkval> POWOP
 129%nonassoc <i_tkval> PREINC PREDEC POSTINC POSTDEC
 130%left <i_tkval> ARROW
 131%nonassoc <i_tkval> ')'
 132%left <i_tkval> '('
 133%left '[' '{'
 134
 135%token <i_tkval> PEG
 136
 137%% /* RULES */
 138
 139/* The whole program */
 140prog    :       progstart
 141        /*CONTINUED*/   lineseq
 142                        { $$ = $1; newPROG(block_end($1,$2)); }
 143        ;
 144
 145/* An ordinary block */
 146block   :       '{' remember lineseq '}'
 147                        { if (PL_parser->copline > (line_t)IVAL($1))
 148                              PL_parser->copline = (line_t)IVAL($1);
 149                          $$ = block_end($2, $3);
 150                          TOKEN_GETMAD($1,$$,'{');
 151                          TOKEN_GETMAD($4,$$,'}');
 152                        }
 153        ;
 154
 155remember:       /* NULL */      /* start a full lexical scope */
 156                        { $$ = block_start(TRUE); }
 157        ;
 158
 159mydefsv:        /* NULL */      /* lexicalize $_ */
 160                        { $$ = (I32) allocmy("$_"); }
 161        ;
 162
 163progstart:
 164                {
 165                    PL_parser->expect = XSTATE; $$ = block_start(TRUE);
 166                }
 167        ;
 168
 169
 170mblock  :       '{' mremember lineseq '}'
 171                        { if (PL_parser->copline > (line_t)IVAL($1))
 172                              PL_parser->copline = (line_t)IVAL($1);
 173                          $$ = block_end($2, $3);
 174                          TOKEN_GETMAD($1,$$,'{');
 175                          TOKEN_GETMAD($4,$$,'}');
 176                        }
 177        ;
 178
 179mremember:      /* NULL */      /* start a partial lexical scope */
 180                        { $$ = block_start(FALSE); }
 181        ;
 182
 183/* A collection of "lines" in the program */
 184lineseq :       /* NULL */
 185                        { $$ = (OP*)NULL; }
 186        |       lineseq decl
 187                        {
 188                        $$ = IF_MAD(
 189                                append_list(OP_LINESEQ,
 190                                    (LISTOP*)$1, (LISTOP*)$2),
 191                                $1);
 192                        }
 193        |       lineseq line
 194                        {   $$ = append_list(OP_LINESEQ,
 195                                (LISTOP*)$1, (LISTOP*)$2);
 196                            PL_pad_reset_pending = TRUE;
 197                            if ($1 && $2)
 198                                PL_hints |= HINT_BLOCK_SCOPE;
 199                        }
 200        ;
 201
 202/* A "line" in the program */
 203line    :       label cond
 204                        { $$ = newSTATEOP(0, PVAL($1), $2);
 205                          TOKEN_GETMAD($1,((LISTOP*)$$)->op_first,'L'); }
 206        |       loop    /* loops add their own labels */
 207        |       switch  /* ... and so do switches */
 208                        { $$ = $1; }
 209        |       label case
 210                        { $$ = newSTATEOP(0, PVAL($1), $2); }
 211        |       label ';'
 212                        {
 213                          if (PVAL($1)) {
 214                              $$ = newSTATEOP(0, PVAL($1), newOP(OP_NULL, 0));
 215                              TOKEN_GETMAD($1,$$,'L');
 216                              TOKEN_GETMAD($2,((LISTOP*)$$)->op_first,';');
 217                          }
 218                          else {
 219                              $$ = IF_MAD(
 220                                        newOP(OP_NULL, 0),
 221                                        (OP*)NULL);
 222                              PL_parser->copline = NOLINE;
 223                              TOKEN_FREE($1);
 224                              TOKEN_GETMAD($2,$$,';');
 225                          }
 226                          PL_parser->expect = XSTATE;
 227                        }
 228        |       label sideff ';'
 229                        {
 230                          $$ = newSTATEOP(0, PVAL($1), $2);
 231                          PL_parser->expect = XSTATE;
 232                          DO_MAD({
 233                              /* sideff might already have a nexstate */
 234                              OP* op = ((LISTOP*)$$)->op_first;
 235                              if (op) {
 236                                  while (op->op_sibling &&
 237                                     op->op_sibling->op_type == OP_NEXTSTATE)
 238                                        op = op->op_sibling;
 239                                  token_getmad($1,op,'L');
 240                                  token_getmad($3,op,';');
 241                              }
 242                          })
 243                        }
 244        ;
 245
 246/* An expression which may have a side-effect */
 247sideff  :       error
 248                        { $$ = (OP*)NULL; }
 249        |       expr
 250                        { $$ = $1; }
 251        |       expr IF expr
 252                        { $$ = newLOGOP(OP_AND, 0, $3, $1);
 253                          TOKEN_GETMAD($2,$$,'i');
 254                        }
 255        |       expr UNLESS expr
 256                        { $$ = newLOGOP(OP_OR, 0, $3, $1);
 257                          TOKEN_GETMAD($2,$$,'i');
 258                        }
 259        |       expr WHILE expr
 260                        { $$ = newLOOPOP(OPf_PARENS, 1, scalar($3), $1);
 261                          TOKEN_GETMAD($2,$$,'w');
 262                        }
 263        |       expr UNTIL iexpr
 264                        { $$ = newLOOPOP(OPf_PARENS, 1, $3, $1);
 265                          TOKEN_GETMAD($2,$$,'w');
 266                        }
 267        |       expr FOR expr
 268                        { $$ = newFOROP(0, NULL, (line_t)IVAL($2),
 269                                        (OP*)NULL, $3, $1, (OP*)NULL);
 270                          TOKEN_GETMAD($2,((LISTOP*)$$)->op_first->op_sibling,'w');
 271                        }
 272        ;
 273
 274/* else and elsif blocks */
 275else    :       /* NULL */
 276                        { $$ = (OP*)NULL; }
 277        |       ELSE mblock
 278                        { ($2)->op_flags |= OPf_PARENS; $$ = scope($2);
 279                          TOKEN_GETMAD($1,$$,'o');
 280                        }
 281        |       ELSIF '(' mexpr ')' mblock else
 282                        { PL_parser->copline = (line_t)IVAL($1);
 283                            $$ = newCONDOP(0, newSTATEOP(OPf_SPECIAL,NULL,$3), scope($5), $6);
 284                            PL_hints |= HINT_BLOCK_SCOPE;
 285                          TOKEN_GETMAD($1,$$,'I');
 286                          TOKEN_GETMAD($2,$$,'(');
 287                          TOKEN_GETMAD($4,$$,')');
 288                        }
 289        ;
 290
 291/* Real conditional expressions */
 292cond    :       IF '(' remember mexpr ')' mblock else
 293                        { PL_parser->copline = (line_t)IVAL($1);
 294                            $$ = block_end($3,
 295                                   newCONDOP(0, $4, scope($6), $7));
 296                          TOKEN_GETMAD($1,$$,'I');
 297                          TOKEN_GETMAD($2,$$,'(');
 298                          TOKEN_GETMAD($5,$$,')');
 299                        }
 300        |       UNLESS '(' remember miexpr ')' mblock else
 301                        { PL_parser->copline = (line_t)IVAL($1);
 302                            $$ = block_end($3,
 303                                   newCONDOP(0, $4, scope($6), $7));
 304                          TOKEN_GETMAD($1,$$,'I');
 305                          TOKEN_GETMAD($2,$$,'(');
 306                          TOKEN_GETMAD($5,$$,')');
 307                        }
 308        ;
 309
 310/* Cases for a switch statement */
 311case    :       WHEN '(' remember mexpr ')' mblock
 312        { $$ = block_end($3,
 313                newWHENOP($4, scope($6))); }
 314        |       DEFAULT block
 315        { $$ = newWHENOP(0, scope($2)); }
 316        ;
 317
 318/* Continue blocks */
 319cont    :       /* NULL */
 320                        { $$ = (OP*)NULL; }
 321        |       CONTINUE block
 322                        { $$ = scope($2);
 323                          TOKEN_GETMAD($1,$$,'o');
 324                        }
 325        ;
 326
 327/* Loops: while, until, for, and a bare block */
 328loop    :       label WHILE '(' remember texpr ')' mintro mblock cont
 329                        { OP *innerop;
 330                          PL_parser->copline = (line_t)$2;
 331                            $$ = block_end($4,
 332                                   newSTATEOP(0, PVAL($1),
 333                                     innerop = newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
 334                                                IVAL($2), $5, $8, $9, $7)));
 335                          TOKEN_GETMAD($1,innerop,'L');
 336                          TOKEN_GETMAD($2,innerop,'W');
 337                          TOKEN_GETMAD($3,innerop,'(');
 338                          TOKEN_GETMAD($6,innerop,')');
 339                        }
 340
 341        |       label UNTIL '(' remember iexpr ')' mintro mblock cont
 342                        { OP *innerop;
 343                          PL_parser->copline = (line_t)$2;
 344                            $$ = block_end($4,
 345                                   newSTATEOP(0, PVAL($1),
 346                                     innerop = newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
 347                                                IVAL($2), $5, $8, $9, $7)));
 348                          TOKEN_GETMAD($1,innerop,'L');
 349                          TOKEN_GETMAD($2,innerop,'W');
 350                          TOKEN_GETMAD($3,innerop,'(');
 351                          TOKEN_GETMAD($6,innerop,')');
 352                        }
 353        |       label FOR MY remember my_scalar '(' mexpr ')' mblock cont
 354                        { OP *innerop;
 355                          $$ = block_end($4,
 356                             innerop = newFOROP(0, PVAL($1), (line_t)IVAL($2),
 357                                            $5, $7, $9, $10));
 358                          TOKEN_GETMAD($1,((LISTOP*)innerop)->op_first,'L');
 359                          TOKEN_GETMAD($2,((LISTOP*)innerop)->op_first->op_sibling,'W');
 360                          TOKEN_GETMAD($3,((LISTOP*)innerop)->op_first->op_sibling,'d');
 361                          TOKEN_GETMAD($6,((LISTOP*)innerop)->op_first->op_sibling,'(');
 362                          TOKEN_GETMAD($8,((LISTOP*)innerop)->op_first->op_sibling,')');
 363                        }
 364        |       label FOR scalar '(' remember mexpr ')' mblock cont
 365                        { OP *innerop;
 366                          $$ = block_end($5,
 367                             innerop = newFOROP(0, PVAL($1), (line_t)IVAL($2),
 368                                    mod($3, OP_ENTERLOOP), $6, $8, $9));
 369                          TOKEN_GETMAD($1,((LISTOP*)innerop)->op_first,'L');
 370                          TOKEN_GETMAD($2,((LISTOP*)innerop)->op_first->op_sibling,'W');
 371                          TOKEN_GETMAD($4,((LISTOP*)innerop)->op_first->op_sibling,'(');
 372                          TOKEN_GETMAD($7,((LISTOP*)innerop)->op_first->op_sibling,')');
 373                        }
 374        |       label FOR '(' remember mexpr ')' mblock cont
 375                        { OP *innerop;
 376                          $$ = block_end($4,
 377                             innerop = newFOROP(0, PVAL($1), (line_t)IVAL($2),
 378                                                    (OP*)NULL, $5, $7, $8));
 379                          TOKEN_GETMAD($1,((LISTOP*)innerop)->op_first,'L');
 380                          TOKEN_GETMAD($2,((LISTOP*)innerop)->op_first->op_sibling,'W');
 381                          TOKEN_GETMAD($3,((LISTOP*)innerop)->op_first->op_sibling,'(');
 382                          TOKEN_GETMAD($6,((LISTOP*)innerop)->op_first->op_sibling,')');
 383                        }
 384        |       label FOR '(' remember mnexpr ';' texpr ';' mintro mnexpr ')'
 385                    mblock
 386                        /* basically fake up an initialize-while lineseq */
 387                        { OP *forop;
 388                          PL_parser->copline = (line_t)IVAL($2);
 389                          forop = newSTATEOP(0, PVAL($1),
 390                                            newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
 391                                                IVAL($2), scalar($7),
 392                                                $12, $10, $9));
 393#ifdef MAD
 394                          forop = newUNOP(OP_NULL, 0, append_elem(OP_LINESEQ,
 395                                newSTATEOP(0,
 396                                           CopLABEL_alloc(($1)->tk_lval.pval),
 397                                           ($5 ? $5 : newOP(OP_NULL, 0)) ),
 398                                forop));
 399
 400                          token_getmad($2,forop,'3');
 401                          token_getmad($3,forop,'(');
 402                          token_getmad($6,forop,'1');
 403                          token_getmad($8,forop,'2');
 404                          token_getmad($11,forop,')');
 405                          token_getmad($1,forop,'L');
 406#else
 407                          if ($5) {
 408                                forop = append_elem(OP_LINESEQ,
 409                                        newSTATEOP(0, CopLABEL_alloc($1), $5),
 410                                        forop);
 411                          }
 412
 413
 414#endif
 415                          $$ = block_end($4, forop); }
 416        |       label block cont  /* a block is a loop that happens once */
 417                        { $$ = newSTATEOP(0, PVAL($1),
 418                                 newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
 419                                            NOLINE, (OP*)NULL, $2, $3, 0));
 420                          TOKEN_GETMAD($1,((LISTOP*)$$)->op_first,'L'); }
 421        ;
 422
 423/* Switch blocks */
 424switch  :       label GIVEN '(' remember mydefsv mexpr ')' mblock
 425                        { PL_parser->copline = (line_t) $2;
 426                            $$ = block_end($4,
 427                                newSTATEOP(0, PVAL($1),
 428                                    newGIVENOP($6, scope($8),
 429                                        (PADOFFSET) $5) )); }
 430        ;
 431
 432/* determine whether there are any new my declarations */
 433mintro  :       /* NULL */
 434                        { $$ = (PL_min_intro_pending &&
 435                            PL_max_intro_pending >=  PL_min_intro_pending);
 436                          intro_my(); }
 437
 438/* Normal expression */
 439nexpr   :       /* NULL */
 440                        { $$ = (OP*)NULL; }
 441        |       sideff
 442        ;
 443
 444/* Boolean expression */
 445texpr   :       /* NULL means true */
 446                        { YYSTYPE tmplval;
 447                          (void)scan_num("1", &tmplval);
 448                          $$ = tmplval.opval; }
 449        |       expr
 450        ;
 451
 452/* Inverted boolean expression */
 453iexpr   :       expr
 454                        { $$ = invert(scalar($1)); }
 455        ;
 456
 457/* Expression with its own lexical scope */
 458mexpr   :       expr
 459                        { $$ = $1; intro_my(); }
 460        ;
 461
 462mnexpr  :       nexpr
 463                        { $$ = $1; intro_my(); }
 464        ;
 465
 466miexpr  :       iexpr
 467                        { $$ = $1; intro_my(); }
 468        ;
 469
 470/* Optional "MAIN:"-style loop labels */
 471label   :       /* empty */
 472                        {
 473#ifdef MAD
 474                          YYSTYPE tmplval;
 475                          tmplval.pval = NULL;
 476                          $$ = newTOKEN(OP_NULL, tmplval, 0);
 477#else
 478                          $$ = NULL;
 479#endif
 480                        }
 481        |       LABEL
 482        ;
 483
 484/* Some kind of declaration - just hang on peg in the parse tree */
 485decl    :       format
 486                        { $$ = $1; }
 487        |       subrout
 488                        { $$ = $1; }
 489        |       mysubrout
 490                        { $$ = $1; }
 491        |       package
 492                        { $$ = $1; }
 493        |       use
 494                        { $$ = $1; }
 495
 496    /* these two are only used by MAD */
 497
 498        |       peg
 499                        { $$ = $1; }
 500        ;
 501
 502peg     :       PEG
 503                        { $$ = newOP(OP_NULL,0);
 504                          TOKEN_GETMAD($1,$$,'p');
 505                        }
 506        ;
 507
 508format  :       FORMAT startformsub formname block
 509                        { SvREFCNT_inc_simple_void(PL_compcv);
 510#ifdef MAD
 511                          $$ = newFORM($2, $3, $4);
 512                          prepend_madprops($1->tk_mad, $$, 'F');
 513                          $1->tk_mad = 0;
 514                          token_free($1);
 515#else
 516                          newFORM($2, $3, $4);
 517                          $$ = (OP*)NULL;
 518#endif
 519                        }
 520        ;
 521
 522formname:       WORD            { $$ = $1; }
 523        |       /* NULL */      { $$ = (OP*)NULL; }
 524        ;
 525
 526/* Unimplemented "my sub foo { }" */
 527mysubrout:      MYSUB startsub subname proto subattrlist subbody
 528                        { SvREFCNT_inc_simple_void(PL_compcv);
 529#ifdef MAD
 530                          $$ = newMYSUB($2, $3, $4, $5, $6);
 531                          token_getmad($1,$$,'d');
 532#else
 533                          newMYSUB($2, $3, $4, $5, $6);
 534                          $$ = (OP*)NULL;
 535#endif
 536                        }
 537        ;
 538
 539/* Subroutine definition */
 540subrout :       SUB startsub subname proto subattrlist subbody
 541                        { SvREFCNT_inc_simple_void(PL_compcv);
 542#ifdef MAD
 543                          {
 544                              OP* o = newSVOP(OP_ANONCODE, 0,
 545                                (SV*)newATTRSUB($2, $3, $4, $5, $6));
 546                              $$ = newOP(OP_NULL,0);
 547                              op_getmad(o,$$,'&');
 548                              op_getmad($3,$$,'n');
 549                              op_getmad($4,$$,'s');
 550                              op_getmad($5,$$,'a');
 551                              token_getmad($1,$$,'d');
 552                              append_madprops($6->op_madprop, $$, 0);
 553                              $6->op_madprop = 0;
 554                            }
 555#else
 556                          newATTRSUB($2, $3, $4, $5, $6);
 557                          $$ = (OP*)NULL;
 558#endif
 559                        }
 560        ;
 561
 562startsub:       /* NULL */      /* start a regular subroutine scope */
 563                        { $$ = start_subparse(FALSE, 0);
 564                            SAVEFREESV(PL_compcv); }
 565
 566        ;
 567
 568startanonsub:   /* NULL */      /* start an anonymous subroutine scope */
 569                        { $$ = start_subparse(FALSE, CVf_ANON);
 570                            SAVEFREESV(PL_compcv); }
 571        ;
 572
 573startformsub:   /* NULL */      /* start a format subroutine scope */
 574                        { $$ = start_subparse(TRUE, 0);
 575                            SAVEFREESV(PL_compcv); }
 576        ;
 577
 578/* Name of a subroutine - must be a bareword, could be special */
 579subname :       WORD    { const char *const name = SvPV_nolen_const(((SVOP*)$1)->op_sv);
 580                          if (strEQ(name, "BEGIN") || strEQ(name, "END")
 581                              || strEQ(name, "INIT") || strEQ(name, "CHECK")
 582                              || strEQ(name, "UNITCHECK"))
 583                              CvSPECIAL_on(PL_compcv);
 584                          $$ = $1; }
 585        ;
 586
 587/* Subroutine prototype */
 588proto   :       /* NULL */
 589                        { $$ = (OP*)NULL; }
 590        |       THING
 591        ;
 592
 593/* Optional list of subroutine attributes */
 594subattrlist:    /* NULL */
 595                        { $$ = (OP*)NULL; }
 596        |       COLONATTR THING
 597                        { $$ = $2;
 598                          TOKEN_GETMAD($1,$$,':');
 599                        }
 600        |       COLONATTR
 601                        { $$ = IF_MAD(
 602                                    newOP(OP_NULL, 0),
 603                                    (OP*)NULL
 604                                );
 605                          TOKEN_GETMAD($1,$$,':');
 606                        }
 607        ;
 608
 609/* List of attributes for a "my" variable declaration */
 610myattrlist:     COLONATTR THING
 611                        { $$ = $2;
 612                          TOKEN_GETMAD($1,$$,':');
 613                        }
 614        |       COLONATTR
 615                        { $$ = IF_MAD(
 616                                    newOP(OP_NULL, 0),
 617                                    (OP*)NULL
 618                                );
 619                          TOKEN_GETMAD($1,$$,':');
 620                        }
 621        ;
 622
 623/* Subroutine body - either null or a block */
 624subbody :       block   { $$ = $1; }
 625        |       ';'     { $$ = IF_MAD(
 626                                    newOP(OP_NULL,0),
 627                                    (OP*)NULL
 628                                );
 629                          PL_parser->expect = XSTATE;
 630                          TOKEN_GETMAD($1,$$,';');
 631                        }
 632        ;
 633
 634package :       PACKAGE WORD ';'
 635                        {
 636#ifdef MAD
 637                          $$ = package($2);
 638                          token_getmad($1,$$,'o');
 639                          token_getmad($3,$$,';');
 640#else
 641                          package($2);
 642                          $$ = (OP*)NULL;
 643#endif
 644                        }
 645        ;
 646
 647use     :       USE startsub
 648                        { CvSPECIAL_on(PL_compcv); /* It's a BEGIN {} */ }
 649                    WORD WORD listexpr ';'
 650                        { SvREFCNT_inc_simple_void(PL_compcv);
 651#ifdef MAD
 652                          $$ = utilize(IVAL($1), $2, $4, $5, $6);
 653                          token_getmad($1,$$,'o');
 654                          token_getmad($7,$$,';');
 655                          if (PL_parser->rsfp_filters &&
 656                                      AvFILLp(PL_parser->rsfp_filters) >= 0)
 657                              append_madprops(newMADPROP('!', MAD_PV, "", 0), $$, 0);
 658#else
 659                          utilize(IVAL($1), $2, $4, $5, $6);
 660                          $$ = (OP*)NULL;
 661#endif
 662                        }
 663        ;
 664
 665/* Ordinary expressions; logical combinations */
 666expr    :       expr ANDOP expr
 667                        { $$ = newLOGOP(OP_AND, 0, $1, $3);
 668                          TOKEN_GETMAD($2,$$,'o');
 669                        }
 670        |       expr OROP expr
 671                        { $$ = newLOGOP(IVAL($2), 0, $1, $3);
 672                          TOKEN_GETMAD($2,$$,'o');
 673                        }
 674        |       expr DOROP expr
 675                        { $$ = newLOGOP(OP_DOR, 0, $1, $3);
 676                          TOKEN_GETMAD($2,$$,'o');
 677                        }
 678        |       argexpr %prec PREC_LOW
 679        ;
 680
 681/* Expressions are a list of terms joined by commas */
 682argexpr :       argexpr ','
 683                        {
 684#ifdef MAD
 685                          OP* op = newNULLLIST();
 686                          token_getmad($2,op,',');
 687                          $$ = append_elem(OP_LIST, $1, op);
 688#else
 689                          $$ = $1;
 690#endif
 691                        }
 692        |       argexpr ',' term
 693                        { 
 694                          OP* term = $3;
 695                          DO_MAD(
 696                              term = newUNOP(OP_NULL, 0, term);
 697                              token_getmad($2,term,',');
 698                          )
 699                          $$ = append_elem(OP_LIST, $1, term);
 700                        }
 701        |       term %prec PREC_LOW
 702        ;
 703
 704/* List operators */
 705listop  :       LSTOP indirob argexpr /* map {...} @args or print $fh @args */
 706                        { $$ = convert(IVAL($1), OPf_STACKED,
 707                                prepend_elem(OP_LIST, newGVREF(IVAL($1),$2), $3) );
 708                          TOKEN_GETMAD($1,$$,'o');
 709                        }
 710        |       FUNC '(' indirob expr ')'      /* print ($fh @args */
 711                        { $$ = convert(IVAL($1), OPf_STACKED,
 712                                prepend_elem(OP_LIST, newGVREF(IVAL($1),$3), $4) );
 713                          TOKEN_GETMAD($1,$$,'o');
 714                          TOKEN_GETMAD($2,$$,'(');
 715                          TOKEN_GETMAD($5,$$,')');
 716                        }
 717        |       term ARROW method '(' listexprcom ')' /* $foo->bar(list) */
 718                        { $$ = convert(OP_ENTERSUB, OPf_STACKED,
 719                                append_elem(OP_LIST,
 720                                    prepend_elem(OP_LIST, scalar($1), $5),
 721                                    newUNOP(OP_METHOD, 0, $3)));
 722                          TOKEN_GETMAD($2,$$,'A');
 723                          TOKEN_GETMAD($4,$$,'(');
 724                          TOKEN_GETMAD($6,$$,')');
 725                        }
 726        |       term ARROW method                     /* $foo->bar */
 727                        { $$ = convert(OP_ENTERSUB, OPf_STACKED,
 728                                append_elem(OP_LIST, scalar($1),
 729                                    newUNOP(OP_METHOD, 0, $3)));
 730                          TOKEN_GETMAD($2,$$,'A');
 731                        }
 732        |       METHOD indirob listexpr              /* new Class @args */
 733                        { $$ = convert(OP_ENTERSUB, OPf_STACKED,
 734                                append_elem(OP_LIST,
 735                                    prepend_elem(OP_LIST, $2, $3),
 736                                    newUNOP(OP_METHOD, 0, $1)));
 737                        }
 738        |       FUNCMETH indirob '(' listexprcom ')' /* method $object (@args) */
 739                        { $$ = convert(OP_ENTERSUB, OPf_STACKED,
 740                                append_elem(OP_LIST,
 741                                    prepend_elem(OP_LIST, $2, $4),
 742                                    newUNOP(OP_METHOD, 0, $1)));
 743                          TOKEN_GETMAD($3,$$,'(');
 744                          TOKEN_GETMAD($5,$$,')');
 745                        }
 746        |       LSTOP listexpr                       /* print @args */
 747                        { $$ = convert(IVAL($1), 0, $2);
 748                          TOKEN_GETMAD($1,$$,'o');
 749                        }
 750        |       FUNC '(' listexprcom ')'             /* print (@args) */
 751                        { $$ = convert(IVAL($1), 0, $3);
 752                          TOKEN_GETMAD($1,$$,'o');
 753                          TOKEN_GETMAD($2,$$,'(');
 754                          TOKEN_GETMAD($4,$$,')');
 755                        }
 756        |       LSTOPSUB startanonsub block /* sub f(&@);   f { foo } ... */
 757                        { SvREFCNT_inc_simple_void(PL_compcv);
 758                          $<opval>$ = newANONATTRSUB($2, 0, (OP*)NULL, $3); }
 759                    listexpr            %prec LSTOP  /* ... @bar */
 760                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
 761                                 append_elem(OP_LIST,
 762                                   prepend_elem(OP_LIST, $<opval>4, $5), $1));
 763                        }
 764        ;
 765
 766/* Names of methods. May use $object->$methodname */
 767method  :       METHOD
 768        |       scalar
 769        ;
 770
 771/* Some kind of subscripted expression */
 772subscripted:    star '{' expr ';' '}'        /* *main::{something} */
 773                        /* In this and all the hash accessors, ';' is
 774                         * provided by the tokeniser */
 775                        { $$ = newBINOP(OP_GELEM, 0, $1, scalar($3));
 776                            PL_parser->expect = XOPERATOR;
 777                          TOKEN_GETMAD($2,$$,'{');
 778                          TOKEN_GETMAD($4,$$,';');
 779                          TOKEN_GETMAD($5,$$,'}');
 780                        }
 781        |       scalar '[' expr ']'          /* $array[$element] */
 782                        { $$ = newBINOP(OP_AELEM, 0, oopsAV($1), scalar($3));
 783                          TOKEN_GETMAD($2,$$,'[');
 784                          TOKEN_GETMAD($4,$$,']');
 785                        }
 786        |       term ARROW '[' expr ']'      /* somearef->[$element] */
 787                        { $$ = newBINOP(OP_AELEM, 0,
 788                                        ref(newAVREF($1),OP_RV2AV),
 789                                        scalar($4));
 790                          TOKEN_GETMAD($2,$$,'a');
 791                          TOKEN_GETMAD($3,$$,'[');
 792                          TOKEN_GETMAD($5,$$,']');
 793                        }
 794        |       subscripted '[' expr ']'    /* $foo->[$bar]->[$baz] */
 795                        { $$ = newBINOP(OP_AELEM, 0,
 796                                        ref(newAVREF($1),OP_RV2AV),
 797                                        scalar($3));
 798                          TOKEN_GETMAD($2,$$,'[');
 799                          TOKEN_GETMAD($4,$$,']');
 800                        }
 801        |       scalar '{' expr ';' '}'    /* $foo->{bar();} */
 802                        { $$ = newBINOP(OP_HELEM, 0, oopsHV($1), jmaybe($3));
 803                            PL_parser->expect = XOPERATOR;
 804                          TOKEN_GETMAD($2,$$,'{');
 805                          TOKEN_GETMAD($4,$$,';');
 806                          TOKEN_GETMAD($5,$$,'}');
 807                        }
 808        |       term ARROW '{' expr ';' '}' /* somehref->{bar();} */
 809                        { $$ = newBINOP(OP_HELEM, 0,
 810                                        ref(newHVREF($1),OP_RV2HV),
 811                                        jmaybe($4));
 812                            PL_parser->expect = XOPERATOR;
 813                          TOKEN_GETMAD($2,$$,'a');
 814                          TOKEN_GETMAD($3,$$,'{');
 815                          TOKEN_GETMAD($5,$$,';');
 816                          TOKEN_GETMAD($6,$$,'}');
 817                        }
 818        |       subscripted '{' expr ';' '}' /* $foo->[bar]->{baz;} */
 819                        { $$ = newBINOP(OP_HELEM, 0,
 820                                        ref(newHVREF($1),OP_RV2HV),
 821                                        jmaybe($3));
 822                            PL_parser->expect = XOPERATOR;
 823                          TOKEN_GETMAD($2,$$,'{');
 824                          TOKEN_GETMAD($4,$$,';');
 825                          TOKEN_GETMAD($5,$$,'}');
 826                        }
 827        |       term ARROW '(' ')'          /* $subref->() */
 828                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
 829                                   newCVREF(0, scalar($1)));
 830                          TOKEN_GETMAD($2,$$,'a');
 831                          TOKEN_GETMAD($3,$$,'(');
 832                          TOKEN_GETMAD($4,$$,')');
 833                        }
 834        |       term ARROW '(' expr ')'     /* $subref->(@args) */
 835                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
 836                                   append_elem(OP_LIST, $4,
 837                                       newCVREF(0, scalar($1))));
 838                          TOKEN_GETMAD($2,$$,'a');
 839                          TOKEN_GETMAD($3,$$,'(');
 840                          TOKEN_GETMAD($5,$$,')');
 841                        }
 842
 843        |       subscripted '(' expr ')'   /* $foo->{bar}->(@args) */
 844                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
 845                                   append_elem(OP_LIST, $3,
 846                                               newCVREF(0, scalar($1))));
 847                          TOKEN_GETMAD($2,$$,'(');
 848                          TOKEN_GETMAD($4,$$,')');
 849                        }
 850        |       subscripted '(' ')'        /* $foo->{bar}->() */
 851                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
 852                                   newCVREF(0, scalar($1)));
 853                          TOKEN_GETMAD($2,$$,'(');
 854                          TOKEN_GETMAD($3,$$,')');
 855                        }
 856        |       '(' expr ')' '[' expr ']'            /* list slice */
 857                        { $$ = newSLICEOP(0, $5, $2);
 858                          TOKEN_GETMAD($1,$$,'(');
 859                          TOKEN_GETMAD($3,$$,')');
 860                          TOKEN_GETMAD($4,$$,'[');
 861                          TOKEN_GETMAD($6,$$,']');
 862                        }
 863        |       '(' ')' '[' expr ']'                 /* empty list slice! */
 864                        { $$ = newSLICEOP(0, $4, (OP*)NULL);
 865                          TOKEN_GETMAD($1,$$,'(');
 866                          TOKEN_GETMAD($2,$$,')');
 867                          TOKEN_GETMAD($3,$$,'[');
 868                          TOKEN_GETMAD($5,$$,']');
 869                        }
 870    ;
 871
 872/* Binary operators between terms */
 873termbinop:      term ASSIGNOP term                     /* $x = $y */
 874                        { $$ = newASSIGNOP(OPf_STACKED, $1, IVAL($2), $3);
 875                          TOKEN_GETMAD($2,$$,'o');
 876                        }
 877        |       term POWOP term                        /* $x ** $y */
 878                        { $$ = newBINOP(IVAL($2), 0, scalar($1), scalar($3));
 879                          TOKEN_GETMAD($2,$$,'o');
 880                        }
 881        |       term MULOP term                        /* $x * $y, $x x $y */
 882                        {   if (IVAL($2) != OP_REPEAT)
 883                                scalar($1);
 884                            $$ = newBINOP(IVAL($2), 0, $1, scalar($3));
 885                          TOKEN_GETMAD($2,$$,'o');
 886                        }
 887        |       term ADDOP term                        /* $x + $y */
 888                        { $$ = newBINOP(IVAL($2), 0, scalar($1), scalar($3));
 889                          TOKEN_GETMAD($2,$$,'o');
 890                        }
 891        |       term SHIFTOP term                      /* $x >> $y, $x << $y */
 892                        { $$ = newBINOP(IVAL($2), 0, scalar($1), scalar($3));
 893                          TOKEN_GETMAD($2,$$,'o');
 894                        }
 895        |       term RELOP term                        /* $x > $y, etc. */
 896                        { $$ = newBINOP(IVAL($2), 0, scalar($1), scalar($3));
 897                          TOKEN_GETMAD($2,$$,'o');
 898                        }
 899        |       term EQOP term                         /* $x == $y, $x eq $y */
 900                        { $$ = newBINOP(IVAL($2), 0, scalar($1), scalar($3));
 901                          TOKEN_GETMAD($2,$$,'o');
 902                        }
 903        |       term BITANDOP term                     /* $x & $y */
 904                        { $$ = newBINOP(IVAL($2), 0, scalar($1), scalar($3));
 905                          TOKEN_GETMAD($2,$$,'o');
 906                        }
 907        |       term BITOROP term                      /* $x | $y */
 908                        { $$ = newBINOP(IVAL($2), 0, scalar($1), scalar($3));
 909                          TOKEN_GETMAD($2,$$,'o');
 910                        }
 911        |       term DOTDOT term                       /* $x..$y, $x...$y */
 912                        {
 913                          $$ = newRANGE(IVAL($2), scalar($1), scalar($3));
 914                          DO_MAD({
 915                              UNOP *op;
 916                              op = (UNOP*)$$;
 917                              op = (UNOP*)op->op_first; /* get to flop */
 918                              op = (UNOP*)op->op_first; /* get to flip */
 919                              op = (UNOP*)op->op_first; /* get to range */
 920                              token_getmad($2,(OP*)op,'o');
 921                            })
 922                        }
 923        |       term ANDAND term                       /* $x && $y */
 924                        { $$ = newLOGOP(OP_AND, 0, $1, $3);
 925                          TOKEN_GETMAD($2,$$,'o');
 926                        }
 927        |       term OROR term                         /* $x || $y */
 928                        { $$ = newLOGOP(OP_OR, 0, $1, $3);
 929                          TOKEN_GETMAD($2,$$,'o');
 930                        }
 931        |       term DORDOR term                       /* $x // $y */
 932                        { $$ = newLOGOP(OP_DOR, 0, $1, $3);
 933                          TOKEN_GETMAD($2,$$,'o');
 934                        }
 935        |       term MATCHOP term                      /* $x =~ /$y/ */
 936                        { $$ = bind_match(IVAL($2), $1, $3);
 937                          TOKEN_GETMAD($2,
 938                                ($$->op_type == OP_NOT
 939                                    ? ((UNOP*)$$)->op_first : $$),
 940                                '~');
 941                        }
 942    ;
 943
 944/* Unary operators and terms */
 945termunop : '-' term %prec UMINUS                       /* -$x */
 946                        { $$ = newUNOP(OP_NEGATE, 0, scalar($2));
 947                          TOKEN_GETMAD($1,$$,'o');
 948                        }
 949        |       '+' term %prec UMINUS                  /* +$x */
 950                        { $$ = IF_MAD(
 951                                    newUNOP(OP_NULL, 0, $2),
 952                                    $2
 953                                );
 954                          TOKEN_GETMAD($1,$$,'+');
 955                        }
 956        |       '!' term                               /* !$x */
 957                        { $$ = newUNOP(OP_NOT, 0, scalar($2));
 958                          TOKEN_GETMAD($1,$$,'o');
 959                        }
 960        |       '~' term                               /* ~$x */
 961                        { $$ = newUNOP(OP_COMPLEMENT, 0, scalar($2));
 962                          TOKEN_GETMAD($1,$$,'o');
 963                        }
 964        |       term POSTINC                           /* $x++ */
 965                        { $$ = newUNOP(OP_POSTINC, 0,
 966                                        mod(scalar($1), OP_POSTINC));
 967                          TOKEN_GETMAD($2,$$,'o');
 968                        }
 969        |       term POSTDEC                           /* $x-- */
 970                        { $$ = newUNOP(OP_POSTDEC, 0,
 971                                        mod(scalar($1), OP_POSTDEC));
 972                          TOKEN_GETMAD($2,$$,'o');
 973                        }
 974        |       PREINC term                            /* ++$x */
 975                        { $$ = newUNOP(OP_PREINC, 0,
 976                                        mod(scalar($2), OP_PREINC));
 977                          TOKEN_GETMAD($1,$$,'o');
 978                        }
 979        |       PREDEC term                            /* --$x */
 980                        { $$ = newUNOP(OP_PREDEC, 0,
 981                                        mod(scalar($2), OP_PREDEC));
 982                          TOKEN_GETMAD($1,$$,'o');
 983                        }
 984
 985    ;
 986
 987/* Constructors for anonymous data */
 988anonymous:      '[' expr ']'
 989                        { $$ = newANONLIST($2);
 990                          TOKEN_GETMAD($1,$$,'[');
 991                          TOKEN_GETMAD($3,$$,']');
 992                        }
 993        |       '[' ']'
 994                        { $$ = newANONLIST((OP*)NULL);
 995                          TOKEN_GETMAD($1,$$,'[');
 996                          TOKEN_GETMAD($2,$$,']');
 997                        }
 998        |       HASHBRACK expr ';' '}'  %prec '(' /* { foo => "Bar" } */
 999                        { $$ = newANONHASH($2);
1000                          TOKEN_GETMAD($1,$$,'{');
1001                          TOKEN_GETMAD($3,$$,';');
1002                          TOKEN_GETMAD($4,$$,'}');
1003                        }
1004        |       HASHBRACK ';' '}'       %prec '(' /* { } (';' by tokener) */
1005                        { $$ = newANONHASH((OP*)NULL);
1006                          TOKEN_GETMAD($1,$$,'{');
1007                          TOKEN_GETMAD($2,$$,';');
1008                          TOKEN_GETMAD($3,$$,'}');
1009                        }
1010        |       ANONSUB startanonsub proto subattrlist block    %prec '('
1011                        { SvREFCNT_inc_simple_void(PL_compcv);
1012                          $$ = newANONATTRSUB($2, $3, $4, $5);
1013                          TOKEN_GETMAD($1,$$,'o');
1014                          OP_GETMAD($3,$$,'s');
1015                          OP_GETMAD($4,$$,'a');
1016                        }
1017
1018    ;
1019
1020/* Things called with "do" */
1021termdo  :       DO term %prec UNIOP                     /* do $filename */
1022                        { $$ = dofile($2, IVAL($1));
1023                          TOKEN_GETMAD($1,$$,'o');
1024                        }
1025        |       DO block        %prec '('               /* do { code */
1026                        { $$ = newUNOP(OP_NULL, OPf_SPECIAL, scope($2));
1027                          TOKEN_GETMAD($1,$$,'D');
1028                        }
1029        |       DO WORD '(' ')'                         /* do somesub() */
1030                        { $$ = newUNOP(OP_ENTERSUB,
1031                            OPf_SPECIAL|OPf_STACKED,
1032                            prepend_elem(OP_LIST,
1033                                scalar(newCVREF(
1034                                    (OPpENTERSUB_AMPER<<8),
1035                                    scalar($2)
1036                                )),(OP*)NULL)); dep();
1037                          TOKEN_GETMAD($1,$$,'o');
1038                          TOKEN_GETMAD($3,$$,'(');
1039                          TOKEN_GETMAD($4,$$,')');
1040                        }
1041        |       DO WORD '(' expr ')'                    /* do somesub(@args) */
1042                        { $$ = newUNOP(OP_ENTERSUB,
1043                            OPf_SPECIAL|OPf_STACKED,
1044                            append_elem(OP_LIST,
1045                                $4,
1046                                scalar(newCVREF(
1047                                    (OPpENTERSUB_AMPER<<8),
1048                                    scalar($2)
1049                                )))); dep();
1050                          TOKEN_GETMAD($1,$$,'o');
1051                          TOKEN_GETMAD($3,$$,'(');
1052                          TOKEN_GETMAD($5,$$,')');
1053                        }
1054        |       DO scalar '(' ')'                      /* do $subref () */
1055                        { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
1056                            prepend_elem(OP_LIST,
1057                                scalar(newCVREF(0,scalar($2))), (OP*)NULL)); dep();
1058                          TOKEN_GETMAD($1,$$,'o');
1059                          TOKEN_GETMAD($3,$$,'(');
1060                          TOKEN_GETMAD($4,$$,')');
1061                        }
1062        |       DO scalar '(' expr ')'                 /* do $subref (@args) */
1063                        { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
1064                            prepend_elem(OP_LIST,
1065                                $4,
1066                                scalar(newCVREF(0,scalar($2))))); dep();
1067                          TOKEN_GETMAD($1,$$,'o');
1068                          TOKEN_GETMAD($3,$$,'(');
1069                          TOKEN_GETMAD($5,$$,')');
1070                        }
1071
1072        ;
1073
1074term    :       termbinop
1075        |       termunop
1076        |       anonymous
1077        |       termdo
1078        |       term '?' term ':' term
1079                        { $$ = newCONDOP(0, $1, $3, $5);
1080                          TOKEN_GETMAD($2,$$,'?');
1081                          TOKEN_GETMAD($4,$$,':');
1082                        }
1083        |       REFGEN term                          /* \$x, \@y, \%z */
1084                        { $$ = newUNOP(OP_REFGEN, 0, mod($2,OP_REFGEN));
1085                          TOKEN_GETMAD($1,$$,'o');
1086                        }
1087        |       myattrterm      %prec UNIOP
1088                        { $$ = $1; }
1089        |       LOCAL term      %prec UNIOP
1090                        { $$ = localize($2,IVAL($1));
1091                          TOKEN_GETMAD($1,$$,'k');
1092                        }
1093        |       '(' expr ')'
1094                        { $$ = sawparens(IF_MAD(newUNOP(OP_NULL,0,$2), $2));
1095                          TOKEN_GETMAD($1,$$,'(');
1096                          TOKEN_GETMAD($3,$$,')');
1097                        }
1098        |       '(' ')'
1099                        { $$ = sawparens(newNULLLIST());
1100                          TOKEN_GETMAD($1,$$,'(');
1101                          TOKEN_GETMAD($2,$$,')');
1102                        }
1103        |       scalar  %prec '('
1104                        { $$ = $1; }
1105        |       star    %prec '('
1106                        { $$ = $1; }
1107        |       hsh     %prec '('
1108                        { $$ = $1; }
1109        |       ary     %prec '('
1110                        { $$ = $1; }
1111        |       arylen  %prec '('                    /* $#x, $#{ something } */
1112                        { $$ = newUNOP(OP_AV2ARYLEN, 0, ref($1, OP_AV2ARYLEN));}
1113        |       subscripted
1114                        { $$ = $1; }
1115        |       ary '[' expr ']'                     /* array slice */
1116                        { $$ = prepend_elem(OP_ASLICE,
1117                                newOP(OP_PUSHMARK, 0),
1118                                    newLISTOP(OP_ASLICE, 0,
1119                                        list($3),
1120                                        ref($1, OP_ASLICE)));
1121                          TOKEN_GETMAD($2,$$,'[');
1122                          TOKEN_GETMAD($4,$$,']');
1123                        }
1124        |       ary '{' expr ';' '}'                 /* @hash{@keys} */
1125                        { $$ = prepend_elem(OP_HSLICE,
1126                                newOP(OP_PUSHMARK, 0),
1127                                    newLISTOP(OP_HSLICE, 0,
1128                                        list($3),
1129                                        ref(oopsHV($1), OP_HSLICE)));
1130                            PL_parser->expect = XOPERATOR;
1131                          TOKEN_GETMAD($2,$$,'{');
1132                          TOKEN_GETMAD($4,$$,';');
1133                          TOKEN_GETMAD($5,$$,'}');
1134                        }
1135        |       THING   %prec '('
1136                        { $$ = $1; }
1137        |       amper                                /* &foo; */
1138                        { $$ = newUNOP(OP_ENTERSUB, 0, scalar($1)); }
1139        |       amper '(' ')'                        /* &foo() */
1140                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar($1));
1141                          TOKEN_GETMAD($2,$$,'(');
1142                          TOKEN_GETMAD($3,$$,')');
1143                        }
1144        |       amper '(' expr ')'                   /* &foo(@args) */
1145                        {
1146                          $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
1147                                append_elem(OP_LIST, $3, scalar($1)));
1148                          DO_MAD({
1149                              OP* op = $$;
1150                              if (op->op_type == OP_CONST) { /* defeat const fold */
1151                                op = (OP*)op->op_madprop->mad_val;
1152                              }
1153                              token_getmad($2,op,'(');
1154                              token_getmad($4,op,')');
1155                          })
1156                        }
1157        |       NOAMP WORD listexpr                  /* foo(@args) */
1158                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
1159                            append_elem(OP_LIST, $3, scalar($2)));
1160                          TOKEN_GETMAD($1,$$,'o');
1161                        }
1162        |       LOOPEX  /* loop exiting command (goto, last, dump, etc) */
1163                        { $$ = newOP(IVAL($1), OPf_SPECIAL);
1164                            PL_hints |= HINT_BLOCK_SCOPE;
1165                          TOKEN_GETMAD($1,$$,'o');
1166                        }
1167        |       LOOPEX term
1168                        { $$ = newLOOPEX(IVAL($1),$2);
1169                          TOKEN_GETMAD($1,$$,'o');
1170                        }
1171        |       NOTOP argexpr                        /* not $foo */
1172                        { $$ = newUNOP(OP_NOT, 0, scalar($2));
1173                          TOKEN_GETMAD($1,$$,'o');
1174                        }
1175        |       UNIOP                                /* Unary op, $_ implied */
1176                        { $$ = newOP(IVAL($1), 0);
1177                          TOKEN_GETMAD($1,$$,'o');
1178                        }
1179        |       UNIOP block                          /* eval { foo }* */
1180                        { $$ = newUNOP(IVAL($1), 0, $2);
1181                          TOKEN_GETMAD($1,$$,'o');
1182                        }
1183        |       UNIOP term                           /* Unary op */
1184                        { $$ = newUNOP(IVAL($1), 0, $2);
1185                          TOKEN_GETMAD($1,$$,'o');
1186                        }
1187        |       REQUIRE                              /* require, $_ implied */
1188                        { $$ = newOP(OP_REQUIRE, $1 ? OPf_SPECIAL : 0);
1189                          TOKEN_GETMAD($1,$$,'o');
1190                        }
1191        |       REQUIRE term                         /* require Foo */
1192                        { $$ = newUNOP(OP_REQUIRE, $1 ? OPf_SPECIAL : 0, $2);
1193                          TOKEN_GETMAD($1,$$,'o');
1194                        }
1195        |       UNIOPSUB
1196                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar($1)); }
1197        |       UNIOPSUB term                        /* Sub treated as unop */
1198                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
1199                            append_elem(OP_LIST, $2, scalar($1))); }
1200        |       FUNC0                                /* Nullary operator */
1201                        { $$ = newOP(IVAL($1), 0);
1202                          TOKEN_GETMAD($1,$$,'o');
1203                        }
1204        |       FUNC0 '(' ')'
1205                        { $$ = newOP(IVAL($1), 0);
1206                          TOKEN_GETMAD($1,$$,'o');
1207                          TOKEN_GETMAD($2,$$,'(');
1208                          TOKEN_GETMAD($3,$$,')');
1209                        }
1210        |       FUNC0SUB                             /* Sub treated as nullop */
1211                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
1212                                scalar($1)); }
1213        |       FUNC1 '(' ')'                        /* not () */
1214                        { $$ = (IVAL($1) == OP_NOT)
1215                            ? newUNOP(IVAL($1), 0, newSVOP(OP_CONST, 0, newSViv(0)))
1216                            : newOP(IVAL($1), OPf_SPECIAL);
1217
1218                          TOKEN_GETMAD($1,$$,'o');
1219                          TOKEN_GETMAD($2,$$,'(');
1220                          TOKEN_GETMAD($3,$$,')');
1221                        }
1222        |       FUNC1 '(' expr ')'                   /* not($foo) */
1223                        { $$ = newUNOP(IVAL($1), 0, $3);
1224                          TOKEN_GETMAD($1,$$,'o');
1225                          TOKEN_GETMAD($2,$$,'(');
1226                          TOKEN_GETMAD($4,$$,')');
1227                        }
1228        |       PMFUNC '(' argexpr ')'          /* m//, s///, tr/// */
1229                        { $$ = pmruntime($1, $3, 1);
1230                          TOKEN_GETMAD($2,$$,'(');
1231                          TOKEN_GETMAD($4,$$,')');
1232                        }
1233        |       WORD
1234        |       listop
1235        ;
1236
1237/* "my" declarations, with optional attributes */
1238myattrterm:     MY myterm myattrlist
1239                        { $$ = my_attrs($2,$3);
1240                          DO_MAD(
1241                              token_getmad($1,$$,'d');
1242                              append_madprops($3->op_madprop, $$, 'a');
1243                              $3->op_madprop = 0;
1244                          )
1245                        }
1246        |       MY myterm
1247                        { $$ = localize($2,IVAL($1));
1248                          TOKEN_GETMAD($1,$$,'d');
1249                        }
1250        ;
1251
1252/* Things that can be "my"'d */
1253myterm  :       '(' expr ')'
1254                        { $$ = sawparens($2);
1255                          TOKEN_GETMAD($1,$$,'(');
1256                          TOKEN_GETMAD($3,$$,')');
1257                        }
1258        |       '(' ')'
1259                        { $$ = sawparens(newNULLLIST());
1260                          TOKEN_GETMAD($1,$$,'(');
1261                          TOKEN_GETMAD($2,$$,')');
1262                        }
1263        |       scalar  %prec '('
1264                        { $$ = $1; }
1265        |       hsh     %prec '('
1266                        { $$ = $1; }
1267        |       ary     %prec '('
1268                        { $$ = $1; }
1269        ;
1270
1271/* Basic list expressions */
1272listexpr:       /* NULL */ %prec PREC_LOW
1273                        { $$ = (OP*)NULL; }
1274        |       argexpr    %prec PREC_LOW
1275                        { $$ = $1; }
1276        ;
1277
1278listexprcom:    /* NULL */
1279                        { $$ = (OP*)NULL; }
1280        |       expr
1281                        { $$ = $1; }
1282        |       expr ','
1283                        {
1284#ifdef MAD
1285                          OP* op = newNULLLIST();
1286                          token_getmad($2,op,',');
1287                          $$ = append_elem(OP_LIST, $1, op);
1288#else
1289                          $$ = $1;
1290#endif
1291
1292                        }
1293        ;
1294
1295/* A little bit of trickery to make "for my $foo (@bar)" actually be
1296   lexical */
1297my_scalar:      scalar
1298                        { PL_parser->in_my = 0; $$ = my($1); }
1299        ;
1300
1301amper   :       '&' indirob
1302                        { $$ = newCVREF(IVAL($1),$2);
1303                          TOKEN_GETMAD($1,$$,'&');
1304                        }
1305        ;
1306
1307scalar  :       '$' indirob
1308                        { $$ = newSVREF($2);
1309                          TOKEN_GETMAD($1,$$,'$');
1310                        }
1311        ;
1312
1313ary     :       '@' indirob
1314                        { $$ = newAVREF($2);
1315                          TOKEN_GETMAD($1,$$,'@');
1316                        }
1317        ;
1318
1319hsh     :       '%' indirob
1320                        { $$ = newHVREF($2);
1321                          TOKEN_GETMAD($1,$$,'%');
1322                        }
1323        ;
1324
1325arylen  :       DOLSHARP indirob
1326                        { $$ = newAVREF($2);
1327                          TOKEN_GETMAD($1,$$,'l');
1328                        }
1329        ;
1330
1331star    :       '*' indirob
1332                        { $$ = newGVREF(0,$2);
1333                          TOKEN_GETMAD($1,$$,'*');
1334                        }
1335        ;
1336
1337/* Indirect objects */
1338indirob :       WORD
1339                        { $$ = scalar($1); }
1340        |       scalar %prec PREC_LOW
1341                        { $$ = scalar($1); }
1342        |       block
1343                        { $$ = scope($1); }
1344
1345        |       PRIVATEREF
1346                        { $$ = $1; }
1347        ;
1348
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.