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