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