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