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