3 * Copyright (c) 1991-2002, 2003, 2004 Larry Wall
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.
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.'
15 /* Make the parser re-entrant. */
29 %token <tkval> '{' '}' '[' ']' '-' '+' '$' '@' '%' '*'
31 %token <opval> WORD METHOD FUNCMETH THING PMFUNC PRIVATEREF
32 %token <opval> FUNC0SUB UNIOPSUB LSTOPSUB
34 %token <tkval> FORMAT SUB ANONSUB PACKAGE USE
35 %token <tkval> WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE FOR
36 %token <tkval> LOOPEX DOTDOT
37 %token <tkval> FUNC0 FUNC1 FUNC UNIOP LSTOP
38 %token <tkval> RELOP EQOP MULOP ADDOP
39 %token <tkval> DOLSHARP DO HASHBRACK NOAMP
40 %token <tkval> LOCAL MY MYSUB
41 %token <tkval> COLONATTR
43 %type <ival> prog progstart remember mremember savescope
44 %type <ival> startsub startanonsub startformsub mintro
48 %type <opval> decl format subrout mysubrout package use peg
50 %type <opval> block mblock lineseq line loop cond else
51 %type <opval> expr term subscripted scalar ary hsh arylen star amper sideff
52 %type <opval> argexpr nexpr texpr iexpr mexpr mnexpr miexpr
53 %type <opval> listexpr listexprcom indirob listop method
54 %type <opval> formname subname proto subbody cont my_scalar
55 %type <opval> subattrlist myattrlist myattrterm myterm
56 %type <opval> termbinop termunop anonymous termdo
59 %nonassoc <tkval> PREC_LOW
62 %left <tkval> OROP DOROP
65 %nonassoc LSTOP LSTOPSUB
67 %right <tkval> ASSIGNOP
68 %right <tkval> '?' ':'
70 %left <tkval> OROR DORDOR
73 %left <tkval> BITANDOP
76 %nonassoc UNIOP UNIOPSUB
81 %right <tkval> '!' '~' UMINUS REFGEN
83 %nonassoc <tkval> PREINC PREDEC POSTINC POSTDEC
93 /* The whole program */
96 { $$ = $1; newPROG(block_end($1,$2)); }
99 /* An ordinary block */
100 block : '{' remember lineseq '}'
101 { if (PL_copline > (line_t)($1)->tk_lval.ival)
102 PL_copline = (line_t)($1)->tk_lval.ival;
103 $$ = block_end($2, $3);
104 token_getmad($1,$$,'{');
105 token_getmad($4,$$,'}');
109 remember: /* NULL */ /* start a full lexical scope */
110 { $$ = block_start(TRUE); }
115 PL_expect = XSTATE; $$ = block_start(TRUE);
120 mblock : '{' mremember lineseq '}'
121 { if (PL_copline > (line_t)($1)->tk_lval.ival)
122 PL_copline = (line_t)($1)->tk_lval.ival;
123 $$ = block_end($2, $3);
124 token_getmad($1,$$,'{');
125 token_getmad($4,$$,'}');
129 mremember: /* NULL */ /* start a partial lexical scope */
130 { $$ = block_start(FALSE); }
133 savescope: /* NULL */ /* remember stack pos in case of error */
134 { $$ = PL_savestack_ix; }
136 /* A collection of "lines" in the program */
141 { $$ = append_list(OP_LINESEQ,
142 (LISTOP*)$1, (LISTOP*)$2); }
143 | lineseq savescope line
145 $$ = append_list(OP_LINESEQ,
146 (LISTOP*)$1, (LISTOP*)$3);
147 PL_pad_reset_pending = TRUE;
148 if ($1 && $3) PL_hints |= HINT_BLOCK_SCOPE; }
151 /* A "line" in the program */
153 { $$ = newSTATEOP(0, ($1)->tk_lval.pval, $2);
154 token_getmad($1,((LISTOP*)$$)->op_first,'L'); }
155 | loop /* loops add their own labels */
158 if (($1)->tk_lval.pval) {
159 $$ = newSTATEOP(0, ($1)->tk_lval.pval, newOP(OP_NULL, 0));
160 token_getmad($1,$$,'L');
161 token_getmad($2,((LISTOP*)$$)->op_first,';');
164 $$ = newOP(OP_NULL, 0);
167 token_getmad($2,$$,';');
173 $$ = newSTATEOP(0, ($1)->tk_lval.pval, $2);
175 /* sideff might already have a nexstate */
176 op = ((LISTOP*)$$)->op_first;
178 while (op->op_sibling &&
179 op->op_sibling->op_type == OP_NEXTSTATE)
181 token_getmad($1,op,'L');
182 token_getmad($3,op,';');
187 /* An expression which may have a side-effect */
193 { $$ = newLOGOP(OP_AND, 0, $3, $1);
194 token_getmad($2,$$,'i');
197 { $$ = newLOGOP(OP_OR, 0, $3, $1);
198 token_getmad($2,$$,'i');
201 { $$ = newLOOPOP(OPf_PARENS, 1, scalar($3), $1);
202 token_getmad($2,$$,'w');
205 { $$ = newLOOPOP(OPf_PARENS, 1, $3, $1);
206 token_getmad($2,$$,'w');
209 { $$ = newFOROP(0, Nullch, (line_t)($2)->tk_lval.ival,
210 Nullop, $3, $1, Nullop);
211 token_getmad($2,((LISTOP*)$$)->op_first->op_sibling,'w');
215 /* else and elsif blocks */
219 { ($2)->op_flags |= OPf_PARENS; $$ = scope($2);
220 token_getmad($1,$$,'o');
222 | ELSIF '(' mexpr ')' mblock else
223 { PL_copline = (line_t)($1)->tk_lval.ival;
224 $$ = newCONDOP(0, $3, scope($5), $6);
225 PL_hints |= HINT_BLOCK_SCOPE;
226 token_getmad($1,$$,'I');
227 token_getmad($2,$$,'(');
228 token_getmad($4,$$,')');
232 /* Real conditional expressions */
233 cond : IF '(' remember mexpr ')' mblock else
234 { PL_copline = (line_t)($1)->tk_lval.ival;
236 newCONDOP(0, $4, scope($6), $7));
237 token_getmad($1,$$,'I');
238 token_getmad($2,$$,'(');
239 token_getmad($5,$$,')');
241 | UNLESS '(' remember miexpr ')' mblock else
242 { PL_copline = (line_t)($1)->tk_lval.ival;
244 newCONDOP(0, $4, scope($6), $7));
245 token_getmad($1,$$,'I');
246 token_getmad($2,$$,'(');
247 token_getmad($5,$$,')');
251 /* Continue blocks */
256 token_getmad($1,$$,'o');
260 /* Loops: while, until, for, and a bare block */
261 loop : label WHILE '(' remember texpr ')' mintro mblock cont
263 PL_copline = (line_t)$2;
265 newSTATEOP(0, ($1)->tk_lval.pval,
266 innerop = newWHILEOP(0, 1, (LOOP*)Nullop,
267 ($2)->tk_lval.ival, $5, $8, $9, $7)));
268 token_getmad($1,innerop,'L');
269 token_getmad($2,innerop,'W');
270 token_getmad($3,innerop,'(');
271 token_getmad($6,innerop,')');
273 | label UNTIL '(' remember iexpr ')' mintro mblock cont
275 PL_copline = (line_t)$2;
277 newSTATEOP(0, ($1)->tk_lval.pval,
278 innerop = newWHILEOP(0, 1, (LOOP*)Nullop,
279 ($2)->tk_lval.ival, $5, $8, $9, $7)));
280 token_getmad($1,innerop,'L');
281 token_getmad($2,innerop,'W');
282 token_getmad($3,innerop,'(');
283 token_getmad($6,innerop,')');
285 | label FOR MY remember my_scalar '(' mexpr ')' mblock cont
288 innerop = newFOROP(0, ($1)->tk_lval.pval, (line_t)($2)->tk_lval.ival, $5, $7, $9, $10));
289 token_getmad($1,((LISTOP*)innerop)->op_first,'L');
290 token_getmad($2,((LISTOP*)innerop)->op_first->op_sibling,'W');
291 token_getmad($3,((LISTOP*)innerop)->op_first->op_sibling,'d');
292 token_getmad($6,((LISTOP*)innerop)->op_first->op_sibling,'(');
293 token_getmad($8,((LISTOP*)innerop)->op_first->op_sibling,')');
295 | label FOR scalar '(' remember mexpr ')' mblock cont
298 innerop = newFOROP(0, ($1)->tk_lval.pval, (line_t)($2)->tk_lval.ival, mod($3, OP_ENTERLOOP),
300 token_getmad($1,((LISTOP*)innerop)->op_first,'L');
301 token_getmad($2,((LISTOP*)innerop)->op_first->op_sibling,'W');
302 token_getmad($4,((LISTOP*)innerop)->op_first->op_sibling,'(');
303 token_getmad($7,((LISTOP*)innerop)->op_first->op_sibling,')');
305 | label FOR '(' remember mexpr ')' mblock cont
308 innerop = newFOROP(0, ($1)->tk_lval.pval, (line_t)($2)->tk_lval.ival, Nullop, $5, $7, $8));
309 token_getmad($1,((LISTOP*)innerop)->op_first,'L');
310 token_getmad($2,((LISTOP*)innerop)->op_first->op_sibling,'W');
311 token_getmad($3,((LISTOP*)innerop)->op_first->op_sibling,'(');
312 token_getmad($6,((LISTOP*)innerop)->op_first->op_sibling,')');
314 | label FOR '(' remember mnexpr ';' texpr ';' mintro mnexpr ')' mblock
315 /* basically fake up an initialize-while lineseq */
317 PL_copline = (line_t)($2)->tk_lval.ival;
318 forop = newSTATEOP(0, ($1)->tk_lval.pval,
319 newWHILEOP(0, 1, (LOOP*)Nullop,
320 ($2)->tk_lval.ival, scalar($7),
323 $5 = newOP(OP_NULL, 0);
324 forop = newUNOP(OP_NULL, 0, append_elem(OP_LINESEQ,
327 ?savepv(($1)->tk_lval.pval):Nullch),
331 token_getmad($2,forop,'3');
332 token_getmad($3,forop,'(');
333 token_getmad($6,forop,'1');
334 token_getmad($8,forop,'2');
335 token_getmad($11,forop,')');
336 token_getmad($1,forop,'L');
337 $$ = block_end($4, forop);
339 | label block cont /* a block is a loop that happens once */
340 { $$ = newSTATEOP(0, ($1)->tk_lval.pval,
341 newWHILEOP(0, 1, (LOOP*)Nullop,
342 NOLINE, Nullop, $2, $3, 0));
343 token_getmad($1,((LISTOP*)$$)->op_first,'L'); }
346 /* determine whether there are any new my declarations */
348 { $$ = (PL_min_intro_pending &&
349 PL_max_intro_pending >= PL_min_intro_pending);
353 /* Normal expression */
359 /* Boolean expression */
360 texpr : /* NULL means true */
362 (void)scan_num("1", &tmplval);
363 $$ = tmplval.opval; }
367 /* Inverted boolean expression */
369 { $$ = invert(scalar($1)); }
372 /* Expression with its own lexical scope */
374 { $$ = $1; intro_my(); }
378 { $$ = $1; intro_my(); }
382 { $$ = $1; intro_my(); }
385 /* Optional "MAIN:"-style loop labels */
388 tmplval.pval = Nullch;
389 $$ = newTOKEN(OP_NULL, tmplval, 0); }
393 /* Some kind of declaration - just hang on peg in the parse tree */
409 { $$ = newOP(OP_NULL,0);
410 token_getmad($1,$$,'p');
414 format : FORMAT startformsub formname block
415 { $$ = newFORM($2, $3, $4);
416 prepend_madprops($1->tk_mad, $$, 'F');
422 formname: WORD { $$ = $1; }
423 | /* NULL */ { $$ = Nullop; }
426 /* Unimplemented "my sub foo { }" */
427 mysubrout: MYSUB startsub subname proto subattrlist subbody
428 { $$ = newMYSUB($2, $3, $4, $5, $6);
429 token_getmad($1,$$,'d');
433 /* Subroutine definition */
434 subrout : SUB startsub subname proto subattrlist subbody
435 { OP* o = newSVOP(OP_ANONCODE, 0,
436 (SV*)newATTRSUB($2, $3, $4, $5, $6));
437 $$ = newOP(OP_NULL,0);
439 op_getmad($3,$$,'n');
440 op_getmad($4,$$,'s');
441 op_getmad($5,$$,'a');
442 token_getmad($1,$$,'d');
443 append_madprops($6->op_madprop, $$, 0);
448 startsub: /* NULL */ /* start a regular subroutine scope */
449 { $$ = start_subparse(FALSE, 0); }
452 startanonsub: /* NULL */ /* start an anonymous subroutine scope */
453 { $$ = start_subparse(FALSE, CVf_ANON); }
456 startformsub: /* NULL */ /* start a format subroutine scope */
457 { $$ = start_subparse(TRUE, 0); }
460 /* Name of a subroutine - must be a bareword, could be special */
461 subname : WORD { STRLEN n_a; char *name = SvPV(((SVOP*)$1)->op_sv,n_a);
462 if (strEQ(name, "BEGIN") || strEQ(name, "END")
463 || strEQ(name, "INIT") || strEQ(name, "CHECK"))
464 CvSPECIAL_on(PL_compcv);
468 /* Subroutine prototype */
474 /* Optional list of subroutine attributes */
475 subattrlist: /* NULL */
479 token_getmad($1,$$,':');
482 { $$ = newOP(OP_NULL, 0);
483 token_getmad($1,$$,':');
487 /* List of attributes for a "my" variable declaration */
488 myattrlist: COLONATTR THING
490 token_getmad($1,$$,':');
493 { $$ = newOP(OP_NULL, 0);
494 token_getmad($1,$$,':');
498 /* Subroutine body - either null or a block */
499 subbody : block { $$ = $1; }
500 | ';' { $$ = newOP(OP_NULL,0); PL_expect = XSTATE;
501 token_getmad($1,$$,';');
505 package : PACKAGE WORD ';'
507 token_getmad($1,$$,'o');
508 token_getmad($3,$$,';');
513 { CvSPECIAL_on(PL_compcv); /* It's a BEGIN {} */ }
514 WORD WORD listexpr ';'
515 { $$ = utilize(($1)->tk_lval.ival, $2, $4, $5, $6);
516 token_getmad($1,$$,'o');
517 token_getmad($7,$$,';');
518 if (PL_rsfp_filters && AvFILLp(PL_rsfp_filters) >= 0)
519 append_madprops(newMADPROP('!', MAD_PV, "", 0), $$, 0);
523 /* Ordinary expressions; logical combinations */
524 expr : expr ANDOP expr
525 { $$ = newLOGOP(OP_AND, 0, $1, $3);
526 token_getmad($2,$$,'o');
529 { $$ = newLOGOP(($2)->tk_lval.ival, 0, $1, $3);
530 token_getmad($2,$$,'o');
533 { $$ = newLOGOP(OP_DOR, 0, $1, $3);
534 token_getmad($2,$$,'o');
536 | argexpr %prec PREC_LOW
539 /* Expressions are a list of terms joined by commas */
540 argexpr : argexpr ','
541 { OP* op = newNULLLIST();
542 token_getmad($2,op,',');
543 $$ = append_elem(OP_LIST, $1, op);
547 $3 = newUNOP(OP_NULL, 0, $3);
548 token_getmad($2,$3,',');
549 $$ = append_elem(OP_LIST, $1, $3);
551 | term %prec PREC_LOW
555 listop : LSTOP indirob argexpr /* print $fh @args */
556 { $$ = convert(($1)->tk_lval.ival, OPf_STACKED,
557 prepend_elem(OP_LIST, newGVREF(($1)->tk_lval.ival,$2), $3) );
558 token_getmad($1,$$,'o');
560 | FUNC '(' indirob expr ')' /* print ($fh @args */
561 { $$ = convert(($1)->tk_lval.ival, OPf_STACKED,
562 prepend_elem(OP_LIST, newGVREF(($1)->tk_lval.ival,$3), $4) );
563 token_getmad($1,$$,'o');
564 token_getmad($2,$$,'(');
565 token_getmad($5,$$,')');
567 | term ARROW method '(' listexprcom ')' /* $foo->bar(list) */
568 { $$ = convert(OP_ENTERSUB, OPf_STACKED,
570 prepend_elem(OP_LIST, scalar($1), $5),
571 newUNOP(OP_METHOD, 0, $3)));
572 token_getmad($2,$$,'A');
573 token_getmad($4,$$,'(');
574 token_getmad($6,$$,')');
576 | term ARROW method /* $foo->bar */
577 { $$ = convert(OP_ENTERSUB, OPf_STACKED,
578 append_elem(OP_LIST, scalar($1),
579 newUNOP(OP_METHOD, 0, $3)));
580 token_getmad($2,$$,'A');
582 | METHOD indirob listexpr /* new Class @args */
583 { $$ = convert(OP_ENTERSUB, OPf_STACKED,
585 prepend_elem(OP_LIST, $2, $3),
586 newUNOP(OP_METHOD, 0, $1)));
588 | FUNCMETH indirob '(' listexprcom ')' /* method $object (@args) */
589 { $$ = convert(OP_ENTERSUB, OPf_STACKED,
591 prepend_elem(OP_LIST, $2, $4),
592 newUNOP(OP_METHOD, 0, $1)));
593 token_getmad($3,$$,'(');
594 token_getmad($5,$$,')');
596 | LSTOP listexpr /* print @args */
597 { $$ = convert(($1)->tk_lval.ival, 0, $2);
598 token_getmad($1,$$,'o');
600 | FUNC '(' listexprcom ')' /* print (@args) */
601 { $$ = convert(($1)->tk_lval.ival, 0, $3);
602 token_getmad($1,$$,'o');
603 token_getmad($2,$$,'(');
604 token_getmad($4,$$,')');
606 | LSTOPSUB startanonsub block /* map { foo } ... */
607 { $3 = newANONATTRSUB($2, 0, Nullop, $3); }
608 listexpr %prec LSTOP /* ... @bar */
609 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
611 prepend_elem(OP_LIST, $3, $5), $1));
615 /* Names of methods. May use $object->$methodname */
620 /* Some kind of subscripted expression */
621 subscripted: star '{' expr ';' '}' /* *main::{something} */
622 /* In this and all the hash accessors, ';' is
623 * provided by the tokeniser */
624 { $$ = newBINOP(OP_GELEM, 0, $1, scalar($3));
625 PL_expect = XOPERATOR;
626 token_getmad($2,$$,'{');
627 token_getmad($4,$$,';');
628 token_getmad($5,$$,'}');
630 | scalar '[' expr ']' /* $array[$element] */
631 { $$ = newBINOP(OP_AELEM, 0, oopsAV($1), scalar($3));
632 token_getmad($2,$$,'[');
633 token_getmad($4,$$,']');
635 | term ARROW '[' expr ']' /* somearef->[$element] */
636 { $$ = newBINOP(OP_AELEM, 0,
637 ref(newAVREF($1),OP_RV2AV),
639 token_getmad($2,$$,'a');
640 token_getmad($3,$$,'[');
641 token_getmad($5,$$,']');
643 | subscripted '[' expr ']' /* $foo->[$bar]->[$baz] */
644 { $$ = newBINOP(OP_AELEM, 0,
645 ref(newAVREF($1),OP_RV2AV),
647 token_getmad($2,$$,'[');
648 token_getmad($4,$$,']');
650 | scalar '{' expr ';' '}' /* $foo->{bar();} */
651 { $$ = newBINOP(OP_HELEM, 0, oopsHV($1), jmaybe($3));
652 PL_expect = XOPERATOR;
653 token_getmad($2,$$,'{');
654 token_getmad($4,$$,';');
655 token_getmad($5,$$,'}');
657 | term ARROW '{' expr ';' '}' /* somehref->{bar();} */
658 { $$ = newBINOP(OP_HELEM, 0,
659 ref(newHVREF($1),OP_RV2HV),
661 PL_expect = XOPERATOR;
662 token_getmad($2,$$,'a');
663 token_getmad($3,$$,'{');
664 token_getmad($5,$$,';');
665 token_getmad($6,$$,'}');
667 | subscripted '{' expr ';' '}' /* $foo->[bar]->{baz;} */
668 { $$ = newBINOP(OP_HELEM, 0,
669 ref(newHVREF($1),OP_RV2HV),
671 PL_expect = XOPERATOR;
672 token_getmad($2,$$,'{');
673 token_getmad($4,$$,';');
674 token_getmad($5,$$,'}');
676 | term ARROW '(' ')' /* $subref->() */
677 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
678 newCVREF(0, scalar($1)));
679 token_getmad($2,$$,'a');
680 token_getmad($3,$$,'(');
681 token_getmad($4,$$,')');
683 | term ARROW '(' expr ')' /* $subref->(@args) */
684 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
685 append_elem(OP_LIST, $4,
686 newCVREF(0, scalar($1))));
687 token_getmad($2,$$,'a');
688 token_getmad($3,$$,'(');
689 token_getmad($5,$$,')');
692 | subscripted '(' expr ')' /* $foo->{bar}->(@args) */
693 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
694 append_elem(OP_LIST, $3,
695 newCVREF(0, scalar($1))));
696 token_getmad($2,$$,'(');
697 token_getmad($4,$$,')');
699 | subscripted '(' ')' /* $foo->{bar}->() */
700 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
701 newCVREF(0, scalar($1)));
702 token_getmad($2,$$,'(');
703 token_getmad($3,$$,')');
707 /* Binary operators between terms */
708 termbinop: term ASSIGNOP term /* $x = $y */
709 { $$ = newASSIGNOP(OPf_STACKED, $1, ($2)->tk_lval.ival, $3);
710 token_getmad($2,$$,'o');
712 | term POWOP term /* $x ** $y */
713 { $$ = newBINOP(($2)->tk_lval.ival, 0, scalar($1), scalar($3));
714 token_getmad($2,$$,'o');
716 | term MULOP term /* $x * $y, $x x $y */
717 { if (($2)->tk_lval.ival != OP_REPEAT)
719 $$ = newBINOP(($2)->tk_lval.ival, 0, $1, scalar($3));
720 token_getmad($2,$$,'o');
722 | term ADDOP term /* $x + $y */
723 { $$ = newBINOP(($2)->tk_lval.ival, 0, scalar($1), scalar($3));
724 token_getmad($2,$$,'o');
726 | term SHIFTOP term /* $x >> $y, $x << $y */
727 { $$ = newBINOP(($2)->tk_lval.ival, 0, scalar($1), scalar($3));
728 token_getmad($2,$$,'o');
730 | term RELOP term /* $x > $y, etc. */
731 { $$ = newBINOP(($2)->tk_lval.ival, 0, scalar($1), scalar($3));
732 token_getmad($2,$$,'o');
734 | term EQOP term /* $x == $y, $x eq $y */
735 { $$ = newBINOP(($2)->tk_lval.ival, 0, scalar($1), scalar($3));
736 token_getmad($2,$$,'o');
738 | term BITANDOP term /* $x & $y */
739 { $$ = newBINOP(($2)->tk_lval.ival, 0, scalar($1), scalar($3));
740 token_getmad($2,$$,'o');
742 | term BITOROP term /* $x | $y */
743 { $$ = newBINOP(($2)->tk_lval.ival, 0, scalar($1), scalar($3));
744 token_getmad($2,$$,'o');
746 | term DOTDOT term /* $x..$y, $x...$y */
748 $$ = newRANGE(($2)->tk_lval.ival, scalar($1), scalar($3));
750 op = (UNOP*)op->op_first; /* get to flop */
751 op = (UNOP*)op->op_first; /* get to flip */
752 op = (UNOP*)op->op_first; /* get to range */
753 token_getmad($2,(OP*)op,'o');
755 | term ANDAND term /* $x && $y */
756 { $$ = newLOGOP(OP_AND, 0, $1, $3);
757 token_getmad($2,$$,'o');
759 | term OROR term /* $x || $y */
760 { $$ = newLOGOP(OP_OR, 0, $1, $3);
761 token_getmad($2,$$,'o');
763 | term DORDOR term /* $x // $y */
764 { $$ = newLOGOP(OP_DOR, 0, $1, $3);
765 token_getmad($2,$$,'o');
767 | term MATCHOP term /* $x =~ /$y/ */
768 { $$ = bind_match(($2)->tk_lval.ival, $1, $3);
769 if ($$->op_type == OP_NOT)
770 token_getmad($2,((UNOP*)$$)->op_first,'~');
772 token_getmad($2,$$,'~');
776 /* Unary operators and terms */
777 termunop : '-' term %prec UMINUS /* -$x */
778 { $$ = newUNOP(OP_NEGATE, 0, scalar($2));
779 token_getmad($1,$$,'o');
781 | '+' term %prec UMINUS /* +$x */
782 { $$ = newUNOP(OP_NULL, 0, $2);
783 token_getmad($1,$$,'+');
786 { $$ = newUNOP(OP_NOT, 0, scalar($2));
787 token_getmad($1,$$,'o');
790 { $$ = newUNOP(OP_COMPLEMENT, 0, scalar($2));
791 token_getmad($1,$$,'o');
793 | term POSTINC /* $x++ */
794 { $$ = newUNOP(OP_POSTINC, 0,
795 mod(scalar($1), OP_POSTINC));
796 token_getmad($2,$$,'o');
798 | term POSTDEC /* $x-- */
799 { $$ = newUNOP(OP_POSTDEC, 0,
800 mod(scalar($1), OP_POSTDEC));
801 token_getmad($2,$$,'o');
803 | PREINC term /* ++$x */
804 { $$ = newUNOP(OP_PREINC, 0,
805 mod(scalar($2), OP_PREINC));
806 token_getmad($1,$$,'o');
808 | PREDEC term /* --$x */
809 { $$ = newUNOP(OP_PREDEC, 0,
810 mod(scalar($2), OP_PREDEC));
811 token_getmad($1,$$,'o');
816 /* Constructors for anonymous data */
817 anonymous: '[' expr ']'
818 { $$ = newANONLIST($2);
819 token_getmad($1,$$,'[');
820 token_getmad($3,$$,']');
823 { $$ = newANONLIST(Nullop);
824 token_getmad($1,$$,'[');
825 token_getmad($2,$$,']');
827 | HASHBRACK expr ';' '}' %prec '(' /* { foo => "Bar" } */
828 { $$ = newANONHASH($2);
829 token_getmad($1,$$,'{');
830 token_getmad($3,$$,';');
831 token_getmad($4,$$,'}');
833 | HASHBRACK ';' '}' %prec '(' /* { } (';' by tokener) */
834 { $$ = newANONHASH(Nullop);
835 token_getmad($1,$$,'{');
836 token_getmad($2,$$,';');
837 token_getmad($3,$$,'}');
839 | ANONSUB startanonsub proto subattrlist block %prec '('
840 { $$ = newANONATTRSUB($2, $3, $4, $5);
841 token_getmad($1,$$,'o');
842 op_getmad($3,$$,'s');
843 op_getmad($4,$$,'a');
848 /* Things called with "do" */
849 termdo : DO term %prec UNIOP /* do $filename */
850 { $$ = dofile($2, $1);
851 token_getmad($1,$$,'o');
853 | DO block %prec '(' /* do { code */
854 { $$ = newUNOP(OP_NULL, OPf_SPECIAL, scope($2));
855 token_getmad($1,$$,'D');
857 | DO WORD '(' ')' /* do somesub() */
858 { $$ = newUNOP(OP_ENTERSUB,
859 OPf_SPECIAL|OPf_STACKED,
860 prepend_elem(OP_LIST,
862 (OPpENTERSUB_AMPER<<8),
865 token_getmad($1,$$,'o');
866 token_getmad($3,$$,'(');
867 token_getmad($4,$$,')');
869 | DO WORD '(' expr ')' /* do somesub(@args) */
870 { $$ = newUNOP(OP_ENTERSUB,
871 OPf_SPECIAL|OPf_STACKED,
875 (OPpENTERSUB_AMPER<<8),
878 token_getmad($1,$$,'o');
879 token_getmad($3,$$,'(');
880 token_getmad($5,$$,')');
882 | DO scalar '(' ')' /* do $subref () */
883 { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
884 prepend_elem(OP_LIST,
885 scalar(newCVREF(0,scalar($2))), Nullop)); dep();
886 token_getmad($1,$$,'o');
887 token_getmad($3,$$,'(');
888 token_getmad($4,$$,')');
890 | DO scalar '(' expr ')' /* do $subref (@args) */
891 { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
892 prepend_elem(OP_LIST,
894 scalar(newCVREF(0,scalar($2))))); dep();
895 token_getmad($1,$$,'o');
896 token_getmad($3,$$,'(');
897 token_getmad($5,$$,')');
906 | term '?' term ':' term
907 { $$ = newCONDOP(0, $1, $3, $5);
908 token_getmad($2,$$,'?');
909 token_getmad($4,$$,':');
911 | REFGEN term /* \$x, \@y, \%z */
912 { $$ = newUNOP(OP_REFGEN, 0, mod($2,OP_REFGEN));
913 token_getmad($1,$$,'o');
915 | myattrterm %prec UNIOP
917 | LOCAL term %prec UNIOP
918 { $$ = localize($2,($1)->tk_lval.ival);
919 token_getmad($1,$$,'d');
922 { $$ = sawparens(newUNOP(OP_NULL,0,$2));
923 token_getmad($1,$$,'(');
924 token_getmad($3,$$,')');
927 { $$ = sawparens(newNULLLIST());
928 token_getmad($1,$$,'(');
929 token_getmad($2,$$,')');
939 | arylen %prec '(' /* $#x, $#{ something } */
940 { $$ = newUNOP(OP_AV2ARYLEN, 0, ref($1, OP_AV2ARYLEN));}
943 | '(' expr ')' '[' expr ']' /* list slice */
944 { $$ = newSLICEOP(0, $5, $2);
945 token_getmad($1,$$,'(');
946 token_getmad($3,$$,')');
947 token_getmad($4,$$,'[');
948 token_getmad($6,$$,']');
950 | '(' ')' '[' expr ']' /* empty list slice! */
951 { $$ = newSLICEOP(0, $4, Nullop);
952 token_getmad($1,$$,'(');
953 token_getmad($2,$$,')');
954 token_getmad($3,$$,'[');
955 token_getmad($5,$$,']');
957 | ary '[' expr ']' /* array slice */
958 { $$ = prepend_elem(OP_ASLICE,
959 newOP(OP_PUSHMARK, 0),
960 newLISTOP(OP_ASLICE, 0,
962 ref($1, OP_ASLICE)));
963 token_getmad($2,$$,'[');
964 token_getmad($4,$$,']');
966 | ary '{' expr ';' '}' /* @hash{@keys} */
967 { $$ = prepend_elem(OP_HSLICE,
968 newOP(OP_PUSHMARK, 0),
969 newLISTOP(OP_HSLICE, 0,
971 ref(oopsHV($1), OP_HSLICE)));
972 PL_expect = XOPERATOR;
973 token_getmad($2,$$,'{');
974 token_getmad($4,$$,';');
975 token_getmad($5,$$,'}');
980 { $$ = newUNOP(OP_ENTERSUB, 0, scalar($1)); }
981 | amper '(' ')' /* &foo() */
982 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar($1));
983 token_getmad($2,$$,'(');
984 token_getmad($3,$$,')');
986 | amper '(' expr ')' /* &foo(@args) */
988 $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
989 append_elem(OP_LIST, $3, scalar($1)));
991 if (op->op_type == OP_CONST) { /* defeat const fold */
992 op = (OP*)op->op_madprop->mad_val;
994 token_getmad($2,op,'(');
995 token_getmad($4,op,')');
997 | NOAMP WORD listexpr /* foo(@args) */
998 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
999 append_elem(OP_LIST, $3, scalar($2)));
1000 token_getmad($1,$$,'o');
1002 | LOOPEX /* loop exiting command (goto, last, dump, etc) */
1003 { $$ = newOP(($1)->tk_lval.ival, OPf_SPECIAL);
1004 PL_hints |= HINT_BLOCK_SCOPE;
1005 token_getmad($1,$$,'o');
1008 { $$ = newLOOPEX(($1)->tk_lval.ival,$2);
1009 token_getmad($1,$$,'o');
1011 | NOTOP argexpr /* not $foo */
1012 { $$ = newUNOP(OP_NOT, 0, scalar($2));
1013 token_getmad($1,$$,'o');
1015 | UNIOP /* Unary op, $_ implied */
1016 { $$ = newOP(($1)->tk_lval.ival, 0);
1017 token_getmad($1,$$,'o');
1019 | UNIOP block /* eval { foo }, I *think* */
1020 { $$ = newUNOP(($1)->tk_lval.ival, 0, $2);
1021 token_getmad($1,$$,'o');
1023 | UNIOP term /* Unary op */
1024 { $$ = newUNOP(($1)->tk_lval.ival, 0, $2);
1025 token_getmad($1,$$,'o');
1027 | UNIOPSUB term /* Sub treated as unop */
1028 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
1029 append_elem(OP_LIST, $2, scalar($1)));
1031 | FUNC0 /* Nullary operator */
1032 { $$ = newOP(($1)->tk_lval.ival, 0);
1033 token_getmad($1,$$,'o');
1036 { $$ = newOP(($1)->tk_lval.ival, 0);
1037 token_getmad($1,$$,'o');
1038 token_getmad($2,$$,'(');
1039 token_getmad($3,$$,')');
1041 | FUNC0SUB /* Sub treated as nullop */
1042 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
1044 | FUNC1 '(' ')' /* not () */
1045 { $$ = newOP(($1)->tk_lval.ival, OPf_SPECIAL);
1046 token_getmad($1,$$,'o');
1047 token_getmad($2,$$,'(');
1048 token_getmad($3,$$,')');
1050 | FUNC1 '(' expr ')' /* not($foo) */
1051 { $$ = newUNOP(($1)->tk_lval.ival, 0, $3);
1052 token_getmad($1,$$,'o');
1053 token_getmad($2,$$,'(');
1054 token_getmad($4,$$,')');
1056 | PMFUNC '(' argexpr ')' /* m//, s///, tr/// */
1057 { $$ = pmruntime($1, $3, 1);
1058 token_getmad($2,$$,'(');
1059 token_getmad($4,$$,')');
1065 /* "my" declarations, with optional attributes */
1066 myattrterm: MY myterm myattrlist
1067 { $$ = my_attrs($2,$3);
1068 token_getmad($1,$$,'d');
1069 append_madprops($3->op_madprop, $$, 'a');
1073 { $$ = localize($2,($1)->tk_lval.ival);
1074 token_getmad($1,$$,'d');
1078 /* Things that can be "my"'d */
1079 myterm : '(' expr ')'
1080 { $$ = sawparens($2);
1081 token_getmad($1,$$,'(');
1082 token_getmad($3,$$,')');
1085 { $$ = sawparens(newNULLLIST());
1086 token_getmad($1,$$,'(');
1087 token_getmad($2,$$,')');
1097 /* Basic list expressions */
1098 listexpr: /* NULL */ %prec PREC_LOW
1100 | argexpr %prec PREC_LOW
1104 listexprcom: /* NULL */
1109 { OP* op = newNULLLIST();
1110 token_getmad($2,op,',');
1111 $$ = append_elem(OP_LIST, $1, op);
1115 /* A little bit of trickery to make "for my $foo (@bar)" actually be
1118 { PL_in_my = 0; $$ = my($1); }
1122 { $$ = newCVREF(($1)->tk_lval.ival,$2);
1123 token_getmad($1,$$,'&');
1127 scalar : '$' indirob
1128 { $$ = newSVREF($2);
1129 token_getmad($1,$$,'$');
1134 { $$ = newAVREF($2);
1135 token_getmad($1,$$,'@');
1140 { $$ = newHVREF($2);
1141 token_getmad($1,$$,'%');
1145 arylen : DOLSHARP indirob
1146 { $$ = newAVREF($2);
1147 token_getmad($1,$$,'l');
1152 { $$ = newGVREF(0,$2);
1153 token_getmad($1,$$,'*');
1157 /* Indirect objects */
1159 { $$ = scalar($1); }
1160 | scalar %prec PREC_LOW
1161 { $$ = scalar($1); }