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