This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Expand on cookbook todo
[perl5.git] / perly.y
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 YADAYADA
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 YADAYADA
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 */
140 prog    :       progstart
141         /*CONTINUED*/   lineseq
142                         { $$ = $1; newPROG(block_end($1,$2)); }
143         ;
144
145 /* An ordinary block */
146 block   :       '{' 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
155 remember:       /* NULL */      /* start a full lexical scope */
156                         { $$ = block_start(TRUE); }
157         ;
158
159 mydefsv:        /* NULL */      /* lexicalize $_ */
160                         { $$ = (I32) allocmy("$_"); }
161         ;
162
163 progstart:
164                 {
165                     PL_parser->expect = XSTATE; $$ = block_start(TRUE);
166                 }
167         ;
168
169
170 mblock  :       '{' 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
179 mremember:      /* NULL */      /* start a partial lexical scope */
180                         { $$ = block_start(FALSE); }
181         ;
182
183 /* A collection of "lines" in the program */
184 lineseq :       /* 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 */
203 line    :       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 */
247 sideff  :       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         |       expr WHEN expr
273                         { $$ = newWHENOP($3, scope($1)); }
274         ;
275
276 /* else and elsif blocks */
277 else    :       /* NULL */
278                         { $$ = (OP*)NULL; }
279         |       ELSE mblock
280                         { ($2)->op_flags |= OPf_PARENS; $$ = scope($2);
281                           TOKEN_GETMAD($1,$$,'o');
282                         }
283         |       ELSIF '(' mexpr ')' mblock else
284                         { PL_parser->copline = (line_t)IVAL($1);
285                             $$ = newCONDOP(0, newSTATEOP(OPf_SPECIAL,NULL,$3), scope($5), $6);
286                             PL_hints |= HINT_BLOCK_SCOPE;
287                           TOKEN_GETMAD($1,$$,'I');
288                           TOKEN_GETMAD($2,$$,'(');
289                           TOKEN_GETMAD($4,$$,')');
290                         }
291         ;
292
293 /* Real conditional expressions */
294 cond    :       IF '(' remember mexpr ')' mblock else
295                         { PL_parser->copline = (line_t)IVAL($1);
296                             $$ = block_end($3,
297                                    newCONDOP(0, $4, scope($6), $7));
298                           TOKEN_GETMAD($1,$$,'I');
299                           TOKEN_GETMAD($2,$$,'(');
300                           TOKEN_GETMAD($5,$$,')');
301                         }
302         |       UNLESS '(' remember miexpr ')' mblock else
303                         { PL_parser->copline = (line_t)IVAL($1);
304                             $$ = block_end($3,
305                                    newCONDOP(0, $4, scope($6), $7));
306                           TOKEN_GETMAD($1,$$,'I');
307                           TOKEN_GETMAD($2,$$,'(');
308                           TOKEN_GETMAD($5,$$,')');
309                         }
310         ;
311
312 /* Cases for a switch statement */
313 case    :       WHEN '(' remember mexpr ')' mblock
314         { $$ = block_end($3,
315                 newWHENOP($4, scope($6))); }
316         |       DEFAULT block
317         { $$ = newWHENOP(0, scope($2)); }
318         ;
319
320 /* Continue blocks */
321 cont    :       /* NULL */
322                         { $$ = (OP*)NULL; }
323         |       CONTINUE block
324                         { $$ = scope($2);
325                           TOKEN_GETMAD($1,$$,'o');
326                         }
327         ;
328
329 /* Loops: while, until, for, and a bare block */
330 loop    :       label WHILE '(' remember texpr ')' mintro mblock cont
331                         { OP *innerop;
332                           PL_parser->copline = (line_t)$2;
333                             $$ = block_end($4,
334                                    newSTATEOP(0, PVAL($1),
335                                      innerop = newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
336                                                 IVAL($2), $5, $8, $9, $7)));
337                           TOKEN_GETMAD($1,innerop,'L');
338                           TOKEN_GETMAD($2,innerop,'W');
339                           TOKEN_GETMAD($3,innerop,'(');
340                           TOKEN_GETMAD($6,innerop,')');
341                         }
342
343         |       label UNTIL '(' remember iexpr ')' mintro mblock cont
344                         { OP *innerop;
345                           PL_parser->copline = (line_t)$2;
346                             $$ = block_end($4,
347                                    newSTATEOP(0, PVAL($1),
348                                      innerop = newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
349                                                 IVAL($2), $5, $8, $9, $7)));
350                           TOKEN_GETMAD($1,innerop,'L');
351                           TOKEN_GETMAD($2,innerop,'W');
352                           TOKEN_GETMAD($3,innerop,'(');
353                           TOKEN_GETMAD($6,innerop,')');
354                         }
355         |       label FOR MY remember my_scalar '(' mexpr ')' mblock cont
356                         { OP *innerop;
357                           $$ = block_end($4,
358                              innerop = newFOROP(0, PVAL($1), (line_t)IVAL($2),
359                                             $5, $7, $9, $10));
360                           TOKEN_GETMAD($1,((LISTOP*)innerop)->op_first,'L');
361                           TOKEN_GETMAD($2,((LISTOP*)innerop)->op_first->op_sibling,'W');
362                           TOKEN_GETMAD($3,((LISTOP*)innerop)->op_first->op_sibling,'d');
363                           TOKEN_GETMAD($6,((LISTOP*)innerop)->op_first->op_sibling,'(');
364                           TOKEN_GETMAD($8,((LISTOP*)innerop)->op_first->op_sibling,')');
365                         }
366         |       label FOR scalar '(' remember mexpr ')' mblock cont
367                         { OP *innerop;
368                           $$ = block_end($5,
369                              innerop = newFOROP(0, PVAL($1), (line_t)IVAL($2),
370                                     mod($3, OP_ENTERLOOP), $6, $8, $9));
371                           TOKEN_GETMAD($1,((LISTOP*)innerop)->op_first,'L');
372                           TOKEN_GETMAD($2,((LISTOP*)innerop)->op_first->op_sibling,'W');
373                           TOKEN_GETMAD($4,((LISTOP*)innerop)->op_first->op_sibling,'(');
374                           TOKEN_GETMAD($7,((LISTOP*)innerop)->op_first->op_sibling,')');
375                         }
376         |       label FOR '(' remember mexpr ')' mblock cont
377                         { OP *innerop;
378                           $$ = block_end($4,
379                              innerop = newFOROP(0, PVAL($1), (line_t)IVAL($2),
380                                                     (OP*)NULL, $5, $7, $8));
381                           TOKEN_GETMAD($1,((LISTOP*)innerop)->op_first,'L');
382                           TOKEN_GETMAD($2,((LISTOP*)innerop)->op_first->op_sibling,'W');
383                           TOKEN_GETMAD($3,((LISTOP*)innerop)->op_first->op_sibling,'(');
384                           TOKEN_GETMAD($6,((LISTOP*)innerop)->op_first->op_sibling,')');
385                         }
386         |       label FOR '(' remember mnexpr ';' texpr ';' mintro mnexpr ')'
387                     mblock
388                         /* basically fake up an initialize-while lineseq */
389                         { OP *forop;
390                           PL_parser->copline = (line_t)IVAL($2);
391                           forop = newSTATEOP(0, PVAL($1),
392                                             newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
393                                                 IVAL($2), scalar($7),
394                                                 $12, $10, $9));
395 #ifdef MAD
396                           forop = newUNOP(OP_NULL, 0, append_elem(OP_LINESEQ,
397                                 newSTATEOP(0,
398                                            CopLABEL_alloc(($1)->tk_lval.pval),
399                                            ($5 ? $5 : newOP(OP_NULL, 0)) ),
400                                 forop));
401
402                           token_getmad($2,forop,'3');
403                           token_getmad($3,forop,'(');
404                           token_getmad($6,forop,'1');
405                           token_getmad($8,forop,'2');
406                           token_getmad($11,forop,')');
407                           token_getmad($1,forop,'L');
408 #else
409                           if ($5) {
410                                 forop = append_elem(OP_LINESEQ,
411                                         newSTATEOP(0, CopLABEL_alloc($1), $5),
412                                         forop);
413                           }
414
415
416 #endif
417                           $$ = block_end($4, forop); }
418         |       label block cont  /* a block is a loop that happens once */
419                         { $$ = newSTATEOP(0, PVAL($1),
420                                  newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
421                                             NOLINE, (OP*)NULL, $2, $3, 0));
422                           TOKEN_GETMAD($1,((LISTOP*)$$)->op_first,'L'); }
423         ;
424
425 /* Switch blocks */
426 switch  :       label GIVEN '(' remember mydefsv mexpr ')' mblock
427                         { PL_parser->copline = (line_t) $2;
428                             $$ = block_end($4,
429                                 newSTATEOP(0, PVAL($1),
430                                     newGIVENOP($6, scope($8),
431                                         (PADOFFSET) $5) )); }
432         ;
433
434 /* determine whether there are any new my declarations */
435 mintro  :       /* NULL */
436                         { $$ = (PL_min_intro_pending &&
437                             PL_max_intro_pending >=  PL_min_intro_pending);
438                           intro_my(); }
439
440 /* Normal expression */
441 nexpr   :       /* NULL */
442                         { $$ = (OP*)NULL; }
443         |       sideff
444         ;
445
446 /* Boolean expression */
447 texpr   :       /* NULL means true */
448                         { YYSTYPE tmplval;
449                           (void)scan_num("1", &tmplval);
450                           $$ = tmplval.opval; }
451         |       expr
452         ;
453
454 /* Inverted boolean expression */
455 iexpr   :       expr
456                         { $$ = invert(scalar($1)); }
457         ;
458
459 /* Expression with its own lexical scope */
460 mexpr   :       expr
461                         { $$ = $1; intro_my(); }
462         ;
463
464 mnexpr  :       nexpr
465                         { $$ = $1; intro_my(); }
466         ;
467
468 miexpr  :       iexpr
469                         { $$ = $1; intro_my(); }
470         ;
471
472 /* Optional "MAIN:"-style loop labels */
473 label   :       /* empty */
474                         {
475 #ifdef MAD
476                           YYSTYPE tmplval;
477                           tmplval.pval = NULL;
478                           $$ = newTOKEN(OP_NULL, tmplval, 0);
479 #else
480                           $$ = NULL;
481 #endif
482                         }
483         |       LABEL
484         ;
485
486 /* Some kind of declaration - just hang on peg in the parse tree */
487 decl    :       format
488                         { $$ = $1; }
489         |       subrout
490                         { $$ = $1; }
491         |       mysubrout
492                         { $$ = $1; }
493         |       package
494                         { $$ = $1; }
495         |       use
496                         { $$ = $1; }
497
498     /* these two are only used by MAD */
499
500         |       peg
501                         { $$ = $1; }
502         ;
503
504 peg     :       PEG
505                         { $$ = newOP(OP_NULL,0);
506                           TOKEN_GETMAD($1,$$,'p');
507                         }
508         ;
509
510 format  :       FORMAT startformsub formname block
511                         { SvREFCNT_inc_simple_void(PL_compcv);
512 #ifdef MAD
513                           $$ = newFORM($2, $3, $4);
514                           prepend_madprops($1->tk_mad, $$, 'F');
515                           $1->tk_mad = 0;
516                           token_free($1);
517 #else
518                           newFORM($2, $3, $4);
519                           $$ = (OP*)NULL;
520 #endif
521                         }
522         ;
523
524 formname:       WORD            { $$ = $1; }
525         |       /* NULL */      { $$ = (OP*)NULL; }
526         ;
527
528 /* Unimplemented "my sub foo { }" */
529 mysubrout:      MYSUB startsub subname proto subattrlist subbody
530                         { SvREFCNT_inc_simple_void(PL_compcv);
531 #ifdef MAD
532                           $$ = newMYSUB($2, $3, $4, $5, $6);
533                           token_getmad($1,$$,'d');
534 #else
535                           newMYSUB($2, $3, $4, $5, $6);
536                           $$ = (OP*)NULL;
537 #endif
538                         }
539         ;
540
541 /* Subroutine definition */
542 subrout :       SUB startsub subname proto subattrlist subbody
543                         { SvREFCNT_inc_simple_void(PL_compcv);
544 #ifdef MAD
545                           {
546                               OP* o = newSVOP(OP_ANONCODE, 0,
547                                 (SV*)newATTRSUB($2, $3, $4, $5, $6));
548                               $$ = newOP(OP_NULL,0);
549                               op_getmad(o,$$,'&');
550                               op_getmad($3,$$,'n');
551                               op_getmad($4,$$,'s');
552                               op_getmad($5,$$,'a');
553                               token_getmad($1,$$,'d');
554                               append_madprops($6->op_madprop, $$, 0);
555                               $6->op_madprop = 0;
556                             }
557 #else
558                           newATTRSUB($2, $3, $4, $5, $6);
559                           $$ = (OP*)NULL;
560 #endif
561                         }
562         ;
563
564 startsub:       /* NULL */      /* start a regular subroutine scope */
565                         { $$ = start_subparse(FALSE, 0);
566                             SAVEFREESV(PL_compcv); }
567
568         ;
569
570 startanonsub:   /* NULL */      /* start an anonymous subroutine scope */
571                         { $$ = start_subparse(FALSE, CVf_ANON);
572                             SAVEFREESV(PL_compcv); }
573         ;
574
575 startformsub:   /* NULL */      /* start a format subroutine scope */
576                         { $$ = start_subparse(TRUE, 0);
577                             SAVEFREESV(PL_compcv); }
578         ;
579
580 /* Name of a subroutine - must be a bareword, could be special */
581 subname :       WORD    { const char *const name = SvPV_nolen_const(((SVOP*)$1)->op_sv);
582                           if (strEQ(name, "BEGIN") || strEQ(name, "END")
583                               || strEQ(name, "INIT") || strEQ(name, "CHECK")
584                               || strEQ(name, "UNITCHECK"))
585                               CvSPECIAL_on(PL_compcv);
586                           $$ = $1; }
587         ;
588
589 /* Subroutine prototype */
590 proto   :       /* NULL */
591                         { $$ = (OP*)NULL; }
592         |       THING
593         ;
594
595 /* Optional list of subroutine attributes */
596 subattrlist:    /* NULL */
597                         { $$ = (OP*)NULL; }
598         |       COLONATTR THING
599                         { $$ = $2;
600                           TOKEN_GETMAD($1,$$,':');
601                         }
602         |       COLONATTR
603                         { $$ = IF_MAD(
604                                     newOP(OP_NULL, 0),
605                                     (OP*)NULL
606                                 );
607                           TOKEN_GETMAD($1,$$,':');
608                         }
609         ;
610
611 /* List of attributes for a "my" variable declaration */
612 myattrlist:     COLONATTR THING
613                         { $$ = $2;
614                           TOKEN_GETMAD($1,$$,':');
615                         }
616         |       COLONATTR
617                         { $$ = IF_MAD(
618                                     newOP(OP_NULL, 0),
619                                     (OP*)NULL
620                                 );
621                           TOKEN_GETMAD($1,$$,':');
622                         }
623         ;
624
625 /* Subroutine body - either null or a block */
626 subbody :       block   { $$ = $1; }
627         |       ';'     { $$ = IF_MAD(
628                                     newOP(OP_NULL,0),
629                                     (OP*)NULL
630                                 );
631                           PL_parser->expect = XSTATE;
632                           TOKEN_GETMAD($1,$$,';');
633                         }
634         ;
635
636 package :       PACKAGE WORD ';'
637                         {
638 #ifdef MAD
639                           $$ = package($2);
640                           token_getmad($1,$$,'o');
641                           token_getmad($3,$$,';');
642 #else
643                           package($2);
644                           $$ = (OP*)NULL;
645 #endif
646                         }
647         ;
648
649 use     :       USE startsub
650                         { CvSPECIAL_on(PL_compcv); /* It's a BEGIN {} */ }
651                     WORD WORD listexpr ';'
652                         { SvREFCNT_inc_simple_void(PL_compcv);
653 #ifdef MAD
654                           $$ = utilize(IVAL($1), $2, $4, $5, $6);
655                           token_getmad($1,$$,'o');
656                           token_getmad($7,$$,';');
657                           if (PL_parser->rsfp_filters &&
658                                       AvFILLp(PL_parser->rsfp_filters) >= 0)
659                               append_madprops(newMADPROP('!', MAD_NULL, NULL, 0), $$, 0);
660 #else
661                           utilize(IVAL($1), $2, $4, $5, $6);
662                           $$ = (OP*)NULL;
663 #endif
664                         }
665         ;
666
667 /* Ordinary expressions; logical combinations */
668 expr    :       expr ANDOP expr
669                         { $$ = newLOGOP(OP_AND, 0, $1, $3);
670                           TOKEN_GETMAD($2,$$,'o');
671                         }
672         |       expr OROP expr
673                         { $$ = newLOGOP(IVAL($2), 0, $1, $3);
674                           TOKEN_GETMAD($2,$$,'o');
675                         }
676         |       expr DOROP expr
677                         { $$ = newLOGOP(OP_DOR, 0, $1, $3);
678                           TOKEN_GETMAD($2,$$,'o');
679                         }
680         |       argexpr %prec PREC_LOW
681         ;
682
683 /* Expressions are a list of terms joined by commas */
684 argexpr :       argexpr ','
685                         {
686 #ifdef MAD
687                           OP* op = newNULLLIST();
688                           token_getmad($2,op,',');
689                           $$ = append_elem(OP_LIST, $1, op);
690 #else
691                           $$ = $1;
692 #endif
693                         }
694         |       argexpr ',' term
695                         { 
696                           OP* term = $3;
697                           DO_MAD(
698                               term = newUNOP(OP_NULL, 0, term);
699                               token_getmad($2,term,',');
700                           )
701                           $$ = append_elem(OP_LIST, $1, term);
702                         }
703         |       term %prec PREC_LOW
704         ;
705
706 /* List operators */
707 listop  :       LSTOP indirob argexpr /* map {...} @args or print $fh @args */
708                         { $$ = convert(IVAL($1), OPf_STACKED,
709                                 prepend_elem(OP_LIST, newGVREF(IVAL($1),$2), $3) );
710                           TOKEN_GETMAD($1,$$,'o');
711                         }
712         |       FUNC '(' indirob expr ')'      /* print ($fh @args */
713                         { $$ = convert(IVAL($1), OPf_STACKED,
714                                 prepend_elem(OP_LIST, newGVREF(IVAL($1),$3), $4) );
715                           TOKEN_GETMAD($1,$$,'o');
716                           TOKEN_GETMAD($2,$$,'(');
717                           TOKEN_GETMAD($5,$$,')');
718                         }
719         |       term ARROW method '(' listexprcom ')' /* $foo->bar(list) */
720                         { $$ = convert(OP_ENTERSUB, OPf_STACKED,
721                                 append_elem(OP_LIST,
722                                     prepend_elem(OP_LIST, scalar($1), $5),
723                                     newUNOP(OP_METHOD, 0, $3)));
724                           TOKEN_GETMAD($2,$$,'A');
725                           TOKEN_GETMAD($4,$$,'(');
726                           TOKEN_GETMAD($6,$$,')');
727                         }
728         |       term ARROW method                     /* $foo->bar */
729                         { $$ = convert(OP_ENTERSUB, OPf_STACKED,
730                                 append_elem(OP_LIST, scalar($1),
731                                     newUNOP(OP_METHOD, 0, $3)));
732                           TOKEN_GETMAD($2,$$,'A');
733                         }
734         |       METHOD indirob listexpr              /* new Class @args */
735                         { $$ = convert(OP_ENTERSUB, OPf_STACKED,
736                                 append_elem(OP_LIST,
737                                     prepend_elem(OP_LIST, $2, $3),
738                                     newUNOP(OP_METHOD, 0, $1)));
739                         }
740         |       FUNCMETH indirob '(' listexprcom ')' /* method $object (@args) */
741                         { $$ = convert(OP_ENTERSUB, OPf_STACKED,
742                                 append_elem(OP_LIST,
743                                     prepend_elem(OP_LIST, $2, $4),
744                                     newUNOP(OP_METHOD, 0, $1)));
745                           TOKEN_GETMAD($3,$$,'(');
746                           TOKEN_GETMAD($5,$$,')');
747                         }
748         |       LSTOP listexpr                       /* print @args */
749                         { $$ = convert(IVAL($1), 0, $2);
750                           TOKEN_GETMAD($1,$$,'o');
751                         }
752         |       FUNC '(' listexprcom ')'             /* print (@args) */
753                         { $$ = convert(IVAL($1), 0, $3);
754                           TOKEN_GETMAD($1,$$,'o');
755                           TOKEN_GETMAD($2,$$,'(');
756                           TOKEN_GETMAD($4,$$,')');
757                         }
758         |       LSTOPSUB startanonsub block /* sub f(&@);   f { foo } ... */
759                         { SvREFCNT_inc_simple_void(PL_compcv);
760                           $<opval>$ = newANONATTRSUB($2, 0, (OP*)NULL, $3); }
761                     listexpr            %prec LSTOP  /* ... @bar */
762                         { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
763                                  append_elem(OP_LIST,
764                                    prepend_elem(OP_LIST, $<opval>4, $5), $1));
765                         }
766         ;
767
768 /* Names of methods. May use $object->$methodname */
769 method  :       METHOD
770         |       scalar
771         ;
772
773 /* Some kind of subscripted expression */
774 subscripted:    star '{' expr ';' '}'        /* *main::{something} */
775                         /* In this and all the hash accessors, ';' is
776                          * provided by the tokeniser */
777                         { $$ = newBINOP(OP_GELEM, 0, $1, scalar($3));
778                             PL_parser->expect = XOPERATOR;
779                           TOKEN_GETMAD($2,$$,'{');
780                           TOKEN_GETMAD($4,$$,';');
781                           TOKEN_GETMAD($5,$$,'}');
782                         }
783         |       scalar '[' expr ']'          /* $array[$element] */
784                         { $$ = newBINOP(OP_AELEM, 0, oopsAV($1), scalar($3));
785                           TOKEN_GETMAD($2,$$,'[');
786                           TOKEN_GETMAD($4,$$,']');
787                         }
788         |       term ARROW '[' expr ']'      /* somearef->[$element] */
789                         { $$ = newBINOP(OP_AELEM, 0,
790                                         ref(newAVREF($1),OP_RV2AV),
791                                         scalar($4));
792                           TOKEN_GETMAD($2,$$,'a');
793                           TOKEN_GETMAD($3,$$,'[');
794                           TOKEN_GETMAD($5,$$,']');
795                         }
796         |       subscripted '[' expr ']'    /* $foo->[$bar]->[$baz] */
797                         { $$ = newBINOP(OP_AELEM, 0,
798                                         ref(newAVREF($1),OP_RV2AV),
799                                         scalar($3));
800                           TOKEN_GETMAD($2,$$,'[');
801                           TOKEN_GETMAD($4,$$,']');
802                         }
803         |       scalar '{' expr ';' '}'    /* $foo->{bar();} */
804                         { $$ = newBINOP(OP_HELEM, 0, oopsHV($1), jmaybe($3));
805                             PL_parser->expect = XOPERATOR;
806                           TOKEN_GETMAD($2,$$,'{');
807                           TOKEN_GETMAD($4,$$,';');
808                           TOKEN_GETMAD($5,$$,'}');
809                         }
810         |       term ARROW '{' expr ';' '}' /* somehref->{bar();} */
811                         { $$ = newBINOP(OP_HELEM, 0,
812                                         ref(newHVREF($1),OP_RV2HV),
813                                         jmaybe($4));
814                             PL_parser->expect = XOPERATOR;
815                           TOKEN_GETMAD($2,$$,'a');
816                           TOKEN_GETMAD($3,$$,'{');
817                           TOKEN_GETMAD($5,$$,';');
818                           TOKEN_GETMAD($6,$$,'}');
819                         }
820         |       subscripted '{' expr ';' '}' /* $foo->[bar]->{baz;} */
821                         { $$ = newBINOP(OP_HELEM, 0,
822                                         ref(newHVREF($1),OP_RV2HV),
823                                         jmaybe($3));
824                             PL_parser->expect = XOPERATOR;
825                           TOKEN_GETMAD($2,$$,'{');
826                           TOKEN_GETMAD($4,$$,';');
827                           TOKEN_GETMAD($5,$$,'}');
828                         }
829         |       term ARROW '(' ')'          /* $subref->() */
830                         { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
831                                    newCVREF(0, scalar($1)));
832                           TOKEN_GETMAD($2,$$,'a');
833                           TOKEN_GETMAD($3,$$,'(');
834                           TOKEN_GETMAD($4,$$,')');
835                         }
836         |       term ARROW '(' expr ')'     /* $subref->(@args) */
837                         { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
838                                    append_elem(OP_LIST, $4,
839                                        newCVREF(0, scalar($1))));
840                           TOKEN_GETMAD($2,$$,'a');
841                           TOKEN_GETMAD($3,$$,'(');
842                           TOKEN_GETMAD($5,$$,')');
843                         }
844
845         |       subscripted '(' expr ')'   /* $foo->{bar}->(@args) */
846                         { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
847                                    append_elem(OP_LIST, $3,
848                                                newCVREF(0, scalar($1))));
849                           TOKEN_GETMAD($2,$$,'(');
850                           TOKEN_GETMAD($4,$$,')');
851                         }
852         |       subscripted '(' ')'        /* $foo->{bar}->() */
853                         { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
854                                    newCVREF(0, scalar($1)));
855                           TOKEN_GETMAD($2,$$,'(');
856                           TOKEN_GETMAD($3,$$,')');
857                         }
858         |       '(' expr ')' '[' expr ']'            /* list slice */
859                         { $$ = newSLICEOP(0, $5, $2);
860                           TOKEN_GETMAD($1,$$,'(');
861                           TOKEN_GETMAD($3,$$,')');
862                           TOKEN_GETMAD($4,$$,'[');
863                           TOKEN_GETMAD($6,$$,']');
864                         }
865         |       '(' ')' '[' expr ']'                 /* empty list slice! */
866                         { $$ = newSLICEOP(0, $4, (OP*)NULL);
867                           TOKEN_GETMAD($1,$$,'(');
868                           TOKEN_GETMAD($2,$$,')');
869                           TOKEN_GETMAD($3,$$,'[');
870                           TOKEN_GETMAD($5,$$,']');
871                         }
872     ;
873
874 /* Binary operators between terms */
875 termbinop:      term ASSIGNOP term                     /* $x = $y */
876                         { $$ = newASSIGNOP(OPf_STACKED, $1, IVAL($2), $3);
877                           TOKEN_GETMAD($2,$$,'o');
878                         }
879         |       term POWOP term                        /* $x ** $y */
880                         { $$ = newBINOP(IVAL($2), 0, scalar($1), scalar($3));
881                           TOKEN_GETMAD($2,$$,'o');
882                         }
883         |       term MULOP term                        /* $x * $y, $x x $y */
884                         {   if (IVAL($2) != OP_REPEAT)
885                                 scalar($1);
886                             $$ = newBINOP(IVAL($2), 0, $1, scalar($3));
887                           TOKEN_GETMAD($2,$$,'o');
888                         }
889         |       term ADDOP term                        /* $x + $y */
890                         { $$ = newBINOP(IVAL($2), 0, scalar($1), scalar($3));
891                           TOKEN_GETMAD($2,$$,'o');
892                         }
893         |       term SHIFTOP term                      /* $x >> $y, $x << $y */
894                         { $$ = newBINOP(IVAL($2), 0, scalar($1), scalar($3));
895                           TOKEN_GETMAD($2,$$,'o');
896                         }
897         |       term RELOP term                        /* $x > $y, etc. */
898                         { $$ = newBINOP(IVAL($2), 0, scalar($1), scalar($3));
899                           TOKEN_GETMAD($2,$$,'o');
900                         }
901         |       term EQOP term                         /* $x == $y, $x eq $y */
902                         { $$ = newBINOP(IVAL($2), 0, scalar($1), scalar($3));
903                           TOKEN_GETMAD($2,$$,'o');
904                         }
905         |       term BITANDOP term                     /* $x & $y */
906                         { $$ = newBINOP(IVAL($2), 0, scalar($1), scalar($3));
907                           TOKEN_GETMAD($2,$$,'o');
908                         }
909         |       term BITOROP term                      /* $x | $y */
910                         { $$ = newBINOP(IVAL($2), 0, scalar($1), scalar($3));
911                           TOKEN_GETMAD($2,$$,'o');
912                         }
913         |       term DOTDOT term                       /* $x..$y, $x...$y */
914                         {
915                           $$ = newRANGE(IVAL($2), scalar($1), scalar($3));
916                           DO_MAD({
917                               UNOP *op;
918                               op = (UNOP*)$$;
919                               op = (UNOP*)op->op_first; /* get to flop */
920                               op = (UNOP*)op->op_first; /* get to flip */
921                               op = (UNOP*)op->op_first; /* get to range */
922                               token_getmad($2,(OP*)op,'o');
923                             })
924                         }
925         |       term ANDAND term                       /* $x && $y */
926                         { $$ = newLOGOP(OP_AND, 0, $1, $3);
927                           TOKEN_GETMAD($2,$$,'o');
928                         }
929         |       term OROR term                         /* $x || $y */
930                         { $$ = newLOGOP(OP_OR, 0, $1, $3);
931                           TOKEN_GETMAD($2,$$,'o');
932                         }
933         |       term DORDOR term                       /* $x // $y */
934                         { $$ = newLOGOP(OP_DOR, 0, $1, $3);
935                           TOKEN_GETMAD($2,$$,'o');
936                         }
937         |       term MATCHOP term                      /* $x =~ /$y/ */
938                         { $$ = bind_match(IVAL($2), $1, $3);
939                           TOKEN_GETMAD($2,
940                                 ($$->op_type == OP_NOT
941                                     ? ((UNOP*)$$)->op_first : $$),
942                                 '~');
943                         }
944     ;
945
946 /* Unary operators and terms */
947 termunop : '-' term %prec UMINUS                       /* -$x */
948                         { $$ = newUNOP(OP_NEGATE, 0, scalar($2));
949                           TOKEN_GETMAD($1,$$,'o');
950                         }
951         |       '+' term %prec UMINUS                  /* +$x */
952                         { $$ = IF_MAD(
953                                     newUNOP(OP_NULL, 0, $2),
954                                     $2
955                                 );
956                           TOKEN_GETMAD($1,$$,'+');
957                         }
958         |       '!' term                               /* !$x */
959                         { $$ = newUNOP(OP_NOT, 0, scalar($2));
960                           TOKEN_GETMAD($1,$$,'o');
961                         }
962         |       '~' term                               /* ~$x */
963                         { $$ = newUNOP(OP_COMPLEMENT, 0, scalar($2));
964                           TOKEN_GETMAD($1,$$,'o');
965                         }
966         |       term POSTINC                           /* $x++ */
967                         { $$ = newUNOP(OP_POSTINC, 0,
968                                         mod(scalar($1), OP_POSTINC));
969                           TOKEN_GETMAD($2,$$,'o');
970                         }
971         |       term POSTDEC                           /* $x-- */
972                         { $$ = newUNOP(OP_POSTDEC, 0,
973                                         mod(scalar($1), OP_POSTDEC));
974                           TOKEN_GETMAD($2,$$,'o');
975                         }
976         |       PREINC term                            /* ++$x */
977                         { $$ = newUNOP(OP_PREINC, 0,
978                                         mod(scalar($2), OP_PREINC));
979                           TOKEN_GETMAD($1,$$,'o');
980                         }
981         |       PREDEC term                            /* --$x */
982                         { $$ = newUNOP(OP_PREDEC, 0,
983                                         mod(scalar($2), OP_PREDEC));
984                           TOKEN_GETMAD($1,$$,'o');
985                         }
986
987     ;
988
989 /* Constructors for anonymous data */
990 anonymous:      '[' expr ']'
991                         { $$ = newANONLIST($2);
992                           TOKEN_GETMAD($1,$$,'[');
993                           TOKEN_GETMAD($3,$$,']');
994                         }
995         |       '[' ']'
996                         { $$ = newANONLIST((OP*)NULL);
997                           TOKEN_GETMAD($1,$$,'[');
998                           TOKEN_GETMAD($2,$$,']');
999                         }
1000         |       HASHBRACK expr ';' '}'  %prec '(' /* { foo => "Bar" } */
1001                         { $$ = newANONHASH($2);
1002                           TOKEN_GETMAD($1,$$,'{');
1003                           TOKEN_GETMAD($3,$$,';');
1004                           TOKEN_GETMAD($4,$$,'}');
1005                         }
1006         |       HASHBRACK ';' '}'       %prec '(' /* { } (';' by tokener) */
1007                         { $$ = newANONHASH((OP*)NULL);
1008                           TOKEN_GETMAD($1,$$,'{');
1009                           TOKEN_GETMAD($2,$$,';');
1010                           TOKEN_GETMAD($3,$$,'}');
1011                         }
1012         |       ANONSUB startanonsub proto subattrlist block    %prec '('
1013                         { SvREFCNT_inc_simple_void(PL_compcv);
1014                           $$ = newANONATTRSUB($2, $3, $4, $5);
1015                           TOKEN_GETMAD($1,$$,'o');
1016                           OP_GETMAD($3,$$,'s');
1017                           OP_GETMAD($4,$$,'a');
1018                         }
1019
1020     ;
1021
1022 /* Things called with "do" */
1023 termdo  :       DO term %prec UNIOP                     /* do $filename */
1024                         { $$ = dofile($2, IVAL($1));
1025                           TOKEN_GETMAD($1,$$,'o');
1026                         }
1027         |       DO block        %prec '('               /* do { code */
1028                         { $$ = newUNOP(OP_NULL, OPf_SPECIAL, scope($2));
1029                           TOKEN_GETMAD($1,$$,'D');
1030                         }
1031         |       DO WORD '(' ')'                         /* do somesub() */
1032                         { $$ = newUNOP(OP_ENTERSUB,
1033                             OPf_SPECIAL|OPf_STACKED,
1034                             prepend_elem(OP_LIST,
1035                                 scalar(newCVREF(
1036                                     (OPpENTERSUB_AMPER<<8),
1037                                     scalar($2)
1038                                 )),(OP*)NULL)); dep();
1039                           TOKEN_GETMAD($1,$$,'o');
1040                           TOKEN_GETMAD($3,$$,'(');
1041                           TOKEN_GETMAD($4,$$,')');
1042                         }
1043         |       DO WORD '(' expr ')'                    /* do somesub(@args) */
1044                         { $$ = newUNOP(OP_ENTERSUB,
1045                             OPf_SPECIAL|OPf_STACKED,
1046                             append_elem(OP_LIST,
1047                                 $4,
1048                                 scalar(newCVREF(
1049                                     (OPpENTERSUB_AMPER<<8),
1050                                     scalar($2)
1051                                 )))); dep();
1052                           TOKEN_GETMAD($1,$$,'o');
1053                           TOKEN_GETMAD($3,$$,'(');
1054                           TOKEN_GETMAD($5,$$,')');
1055                         }
1056         |       DO scalar '(' ')'                      /* do $subref () */
1057                         { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
1058                             prepend_elem(OP_LIST,
1059                                 scalar(newCVREF(0,scalar($2))), (OP*)NULL)); dep();
1060                           TOKEN_GETMAD($1,$$,'o');
1061                           TOKEN_GETMAD($3,$$,'(');
1062                           TOKEN_GETMAD($4,$$,')');
1063                         }
1064         |       DO scalar '(' expr ')'                 /* do $subref (@args) */
1065                         { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
1066                             prepend_elem(OP_LIST,
1067                                 $4,
1068                                 scalar(newCVREF(0,scalar($2))))); dep();
1069                           TOKEN_GETMAD($1,$$,'o');
1070                           TOKEN_GETMAD($3,$$,'(');
1071                           TOKEN_GETMAD($5,$$,')');
1072                         }
1073
1074         ;
1075
1076 term    :       termbinop
1077         |       termunop
1078         |       anonymous
1079         |       termdo
1080         |       term '?' term ':' term
1081                         { $$ = newCONDOP(0, $1, $3, $5);
1082                           TOKEN_GETMAD($2,$$,'?');
1083                           TOKEN_GETMAD($4,$$,':');
1084                         }
1085         |       REFGEN term                          /* \$x, \@y, \%z */
1086                         { $$ = newUNOP(OP_REFGEN, 0, mod($2,OP_REFGEN));
1087                           TOKEN_GETMAD($1,$$,'o');
1088                         }
1089         |       myattrterm      %prec UNIOP
1090                         { $$ = $1; }
1091         |       LOCAL term      %prec UNIOP
1092                         { $$ = localize($2,IVAL($1));
1093                           TOKEN_GETMAD($1,$$,'k');
1094                         }
1095         |       '(' expr ')'
1096                         { $$ = sawparens(IF_MAD(newUNOP(OP_NULL,0,$2), $2));
1097                           TOKEN_GETMAD($1,$$,'(');
1098                           TOKEN_GETMAD($3,$$,')');
1099                         }
1100         |       '(' ')'
1101                         { $$ = sawparens(newNULLLIST());
1102                           TOKEN_GETMAD($1,$$,'(');
1103                           TOKEN_GETMAD($2,$$,')');
1104                         }
1105         |       scalar  %prec '('
1106                         { $$ = $1; }
1107         |       star    %prec '('
1108                         { $$ = $1; }
1109         |       hsh     %prec '('
1110                         { $$ = $1; }
1111         |       ary     %prec '('
1112                         { $$ = $1; }
1113         |       arylen  %prec '('                    /* $#x, $#{ something } */
1114                         { $$ = newUNOP(OP_AV2ARYLEN, 0, ref($1, OP_AV2ARYLEN));}
1115         |       subscripted
1116                         { $$ = $1; }
1117         |       ary '[' expr ']'                     /* array slice */
1118                         { $$ = prepend_elem(OP_ASLICE,
1119                                 newOP(OP_PUSHMARK, 0),
1120                                     newLISTOP(OP_ASLICE, 0,
1121                                         list($3),
1122                                         ref($1, OP_ASLICE)));
1123                           TOKEN_GETMAD($2,$$,'[');
1124                           TOKEN_GETMAD($4,$$,']');
1125                         }
1126         |       ary '{' expr ';' '}'                 /* @hash{@keys} */
1127                         { $$ = prepend_elem(OP_HSLICE,
1128                                 newOP(OP_PUSHMARK, 0),
1129                                     newLISTOP(OP_HSLICE, 0,
1130                                         list($3),
1131                                         ref(oopsHV($1), OP_HSLICE)));
1132                             PL_parser->expect = XOPERATOR;
1133                           TOKEN_GETMAD($2,$$,'{');
1134                           TOKEN_GETMAD($4,$$,';');
1135                           TOKEN_GETMAD($5,$$,'}');
1136                         }
1137         |       THING   %prec '('
1138                         { $$ = $1; }
1139         |       amper                                /* &foo; */
1140                         { $$ = newUNOP(OP_ENTERSUB, 0, scalar($1)); }
1141         |       amper '(' ')'                        /* &foo() */
1142                         { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar($1));
1143                           TOKEN_GETMAD($2,$$,'(');
1144                           TOKEN_GETMAD($3,$$,')');
1145                         }
1146         |       amper '(' expr ')'                   /* &foo(@args) */
1147                         {
1148                           $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
1149                                 append_elem(OP_LIST, $3, scalar($1)));
1150                           DO_MAD({
1151                               OP* op = $$;
1152                               if (op->op_type == OP_CONST) { /* defeat const fold */
1153                                 op = (OP*)op->op_madprop->mad_val;
1154                               }
1155                               token_getmad($2,op,'(');
1156                               token_getmad($4,op,')');
1157                           })
1158                         }
1159         |       NOAMP WORD listexpr                  /* foo(@args) */
1160                         { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
1161                             append_elem(OP_LIST, $3, scalar($2)));
1162                           TOKEN_GETMAD($1,$$,'o');
1163                         }
1164         |       LOOPEX  /* loop exiting command (goto, last, dump, etc) */
1165                         { $$ = newOP(IVAL($1), OPf_SPECIAL);
1166                             PL_hints |= HINT_BLOCK_SCOPE;
1167                           TOKEN_GETMAD($1,$$,'o');
1168                         }
1169         |       LOOPEX term
1170                         { $$ = newLOOPEX(IVAL($1),$2);
1171                           TOKEN_GETMAD($1,$$,'o');
1172                         }
1173         |       NOTOP argexpr                        /* not $foo */
1174                         { $$ = newUNOP(OP_NOT, 0, scalar($2));
1175                           TOKEN_GETMAD($1,$$,'o');
1176                         }
1177         |       UNIOP                                /* Unary op, $_ implied */
1178                         { $$ = newOP(IVAL($1), 0);
1179                           TOKEN_GETMAD($1,$$,'o');
1180                         }
1181         |       UNIOP block                          /* eval { foo }* */
1182                         { $$ = newUNOP(IVAL($1), 0, $2);
1183                           TOKEN_GETMAD($1,$$,'o');
1184                         }
1185         |       UNIOP term                           /* Unary op */
1186                         { $$ = newUNOP(IVAL($1), 0, $2);
1187                           TOKEN_GETMAD($1,$$,'o');
1188                         }
1189         |       REQUIRE                              /* require, $_ implied */
1190                         { $$ = newOP(OP_REQUIRE, $1 ? OPf_SPECIAL : 0);
1191                           TOKEN_GETMAD($1,$$,'o');
1192                         }
1193         |       REQUIRE term                         /* require Foo */
1194                         { $$ = newUNOP(OP_REQUIRE, $1 ? OPf_SPECIAL : 0, $2);
1195                           TOKEN_GETMAD($1,$$,'o');
1196                         }
1197         |       UNIOPSUB
1198                         { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar($1)); }
1199         |       UNIOPSUB term                        /* Sub treated as unop */
1200                         { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
1201                             append_elem(OP_LIST, $2, scalar($1))); }
1202         |       FUNC0                                /* Nullary operator */
1203                         { $$ = newOP(IVAL($1), 0);
1204                           TOKEN_GETMAD($1,$$,'o');
1205                         }
1206         |       FUNC0 '(' ')'
1207                         { $$ = newOP(IVAL($1), 0);
1208                           TOKEN_GETMAD($1,$$,'o');
1209                           TOKEN_GETMAD($2,$$,'(');
1210                           TOKEN_GETMAD($3,$$,')');
1211                         }
1212         |       FUNC0SUB                             /* Sub treated as nullop */
1213                         { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
1214                                 scalar($1)); }
1215         |       FUNC1 '(' ')'                        /* not () */
1216                         { $$ = (IVAL($1) == OP_NOT)
1217                             ? newUNOP(IVAL($1), 0, newSVOP(OP_CONST, 0, newSViv(0)))
1218                             : newOP(IVAL($1), OPf_SPECIAL);
1219
1220                           TOKEN_GETMAD($1,$$,'o');
1221                           TOKEN_GETMAD($2,$$,'(');
1222                           TOKEN_GETMAD($3,$$,')');
1223                         }
1224         |       FUNC1 '(' expr ')'                   /* not($foo) */
1225                         { $$ = newUNOP(IVAL($1), 0, $3);
1226                           TOKEN_GETMAD($1,$$,'o');
1227                           TOKEN_GETMAD($2,$$,'(');
1228                           TOKEN_GETMAD($4,$$,')');
1229                         }
1230         |       PMFUNC '(' argexpr ')'          /* m//, s///, tr/// */
1231                         { $$ = pmruntime($1, $3, 1);
1232                           TOKEN_GETMAD($2,$$,'(');
1233                           TOKEN_GETMAD($4,$$,')');
1234                         }
1235         |       WORD
1236         |       listop
1237         |       YADAYADA
1238                         {
1239                           $$ = newLISTOP(OP_DIE, 0, newOP(OP_PUSHMARK, 0),
1240                                 newSVOP(OP_CONST, 0, newSVpvs("Unimplemented")));
1241                           TOKEN_GETMAD($1,$$,'X');
1242                         }
1243         ;
1244
1245 /* "my" declarations, with optional attributes */
1246 myattrterm:     MY myterm myattrlist
1247                         { $$ = my_attrs($2,$3);
1248                           DO_MAD(
1249                               token_getmad($1,$$,'d');
1250                               append_madprops($3->op_madprop, $$, 'a');
1251                               $3->op_madprop = 0;
1252                           )
1253                         }
1254         |       MY myterm
1255                         { $$ = localize($2,IVAL($1));
1256                           TOKEN_GETMAD($1,$$,'d');
1257                         }
1258         ;
1259
1260 /* Things that can be "my"'d */
1261 myterm  :       '(' expr ')'
1262                         { $$ = sawparens($2);
1263                           TOKEN_GETMAD($1,$$,'(');
1264                           TOKEN_GETMAD($3,$$,')');
1265                         }
1266         |       '(' ')'
1267                         { $$ = sawparens(newNULLLIST());
1268                           TOKEN_GETMAD($1,$$,'(');
1269                           TOKEN_GETMAD($2,$$,')');
1270                         }
1271         |       scalar  %prec '('
1272                         { $$ = $1; }
1273         |       hsh     %prec '('
1274                         { $$ = $1; }
1275         |       ary     %prec '('
1276                         { $$ = $1; }
1277         ;
1278
1279 /* Basic list expressions */
1280 listexpr:       /* NULL */ %prec PREC_LOW
1281                         { $$ = (OP*)NULL; }
1282         |       argexpr    %prec PREC_LOW
1283                         { $$ = $1; }
1284         ;
1285
1286 listexprcom:    /* NULL */
1287                         { $$ = (OP*)NULL; }
1288         |       expr
1289                         { $$ = $1; }
1290         |       expr ','
1291                         {
1292 #ifdef MAD
1293                           OP* op = newNULLLIST();
1294                           token_getmad($2,op,',');
1295                           $$ = append_elem(OP_LIST, $1, op);
1296 #else
1297                           $$ = $1;
1298 #endif
1299
1300                         }
1301         ;
1302
1303 /* A little bit of trickery to make "for my $foo (@bar)" actually be
1304    lexical */
1305 my_scalar:      scalar
1306                         { PL_parser->in_my = 0; $$ = my($1); }
1307         ;
1308
1309 amper   :       '&' indirob
1310                         { $$ = newCVREF(IVAL($1),$2);
1311                           TOKEN_GETMAD($1,$$,'&');
1312                         }
1313         ;
1314
1315 scalar  :       '$' indirob
1316                         { $$ = newSVREF($2);
1317                           TOKEN_GETMAD($1,$$,'$');
1318                         }
1319         ;
1320
1321 ary     :       '@' indirob
1322                         { $$ = newAVREF($2);
1323                           TOKEN_GETMAD($1,$$,'@');
1324                         }
1325         ;
1326
1327 hsh     :       '%' indirob
1328                         { $$ = newHVREF($2);
1329                           TOKEN_GETMAD($1,$$,'%');
1330                         }
1331         ;
1332
1333 arylen  :       DOLSHARP indirob
1334                         { $$ = newAVREF($2);
1335                           TOKEN_GETMAD($1,$$,'l');
1336                         }
1337         ;
1338
1339 star    :       '*' indirob
1340                         { $$ = newGVREF(0,$2);
1341                           TOKEN_GETMAD($1,$$,'*');
1342                         }
1343         ;
1344
1345 /* Indirect objects */
1346 indirob :       WORD
1347                         { $$ = scalar($1); }
1348         |       scalar %prec PREC_LOW
1349                         { $$ = scalar($1); }
1350         |       block
1351                         { $$ = scope($1); }
1352
1353         |       PRIVATEREF
1354                         { $$ = $1; }
1355         ;