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 /* This file holds the grammar for the Perl language. If edited, you need
16 * to run regen_perly.pl, which re-creates the files perly.h, perly.tab
17 * and perly.act which are derived from this.
19 * The main job of of this grammar is to call the various newFOO()
20 * functions in op.c to build a syntax tree of OP structs.
21 * It relies on the lexer in toke.c to do the tokenizing.
24 /* Make the parser re-entrant. */
39 %token <opval> WORD METHOD FUNCMETH THING PMFUNC PRIVATEREF
40 %token <opval> FUNC0SUB UNIOPSUB LSTOPSUB
42 %token <ival> FORMAT SUB ANONSUB PACKAGE USE
43 %token <ival> WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE FOR
44 %token <ival> LOOPEX DOTDOT
45 %token <ival> FUNC0 FUNC1 FUNC UNIOP LSTOP
46 %token <ival> RELOP EQOP MULOP ADDOP
47 %token <ival> DOLSHARP DO HASHBRACK NOAMP
48 %token <ival> LOCAL MY MYSUB REQUIRE
51 %type <ival> prog decl format startsub startanonsub startformsub mintro
52 %type <ival> progstart remember mremember '&' savescope
53 %type <opval> block mblock lineseq line loop cond else
54 %type <opval> expr term subscripted scalar ary hsh arylen star amper sideff
55 %type <opval> argexpr nexpr texpr iexpr mexpr mnexpr miexpr
56 %type <opval> listexpr listexprcom indirob listop method
57 %type <opval> formname subname proto subbody cont my_scalar
58 %type <opval> subattrlist myattrlist mysubrout myattrterm myterm
59 %type <opval> termbinop termunop anonymous termdo
65 %left <ival> OROP DOROP
68 %nonassoc LSTOP LSTOPSUB
70 %right <ival> ASSIGNOP
79 %nonassoc UNIOP UNIOPSUB
85 %right '!' '~' UMINUS REFGEN
87 %nonassoc PREINC PREDEC POSTINC POSTDEC
95 /* The whole program */
98 { $$ = $1; newPROG(block_end($1,$2)); }
101 /* An ordinary block */
102 block : '{' remember lineseq '}'
103 { if (PL_copline > (line_t)$1)
104 PL_copline = (line_t)$1;
105 $$ = block_end($2, $3); }
108 remember: /* NULL */ /* start a full lexical scope */
109 { $$ = block_start(TRUE); }
114 PL_expect = XSTATE; $$ = block_start(TRUE);
119 mblock : '{' mremember lineseq '}'
120 { if (PL_copline > (line_t)$1)
121 PL_copline = (line_t)$1;
122 $$ = block_end($2, $3); }
125 mremember: /* NULL */ /* start a partial lexical scope */
126 { $$ = block_start(FALSE); }
129 savescope: /* NULL */ /* remember stack pos in case of error */
130 { $$ = PL_savestack_ix; }
132 /* A collection of "lines" in the program */
137 | lineseq savescope line
139 $$ = append_list(OP_LINESEQ,
140 (LISTOP*)$1, (LISTOP*)$3);
141 PL_pad_reset_pending = TRUE;
142 if ($1 && $3) PL_hints |= HINT_BLOCK_SCOPE; }
145 /* A "line" in the program */
147 { $$ = newSTATEOP(0, $1, $2); }
148 | loop /* loops add their own labels */
150 { if ($1 != Nullch) {
151 $$ = newSTATEOP(0, $1, newOP(OP_NULL, 0));
157 PL_expect = XSTATE; }
159 { $$ = newSTATEOP(0, $1, $2);
160 PL_expect = XSTATE; }
163 /* An expression which may have a side-effect */
169 { $$ = newLOGOP(OP_AND, 0, $3, $1); }
171 { $$ = newLOGOP(OP_OR, 0, $3, $1); }
173 { $$ = newLOOPOP(OPf_PARENS, 1, scalar($3), $1); }
175 { $$ = newLOOPOP(OPf_PARENS, 1, $3, $1);}
177 { $$ = newFOROP(0, Nullch, (line_t)$2,
178 Nullop, $3, $1, Nullop); }
181 /* else and elsif blocks */
185 { ($2)->op_flags |= OPf_PARENS; $$ = scope($2); }
186 | ELSIF '(' mexpr ')' mblock else
187 { PL_copline = (line_t)$1;
188 $$ = newCONDOP(0, $3, scope($5), $6);
189 PL_hints |= HINT_BLOCK_SCOPE; }
192 /* Real conditional expressions */
193 cond : IF '(' remember mexpr ')' mblock else
194 { PL_copline = (line_t)$1;
196 newCONDOP(0, $4, scope($6), $7)); }
197 | UNLESS '(' remember miexpr ')' mblock else
198 { PL_copline = (line_t)$1;
200 newCONDOP(0, $4, scope($6), $7)); }
203 /* Continue blocks */
210 /* Loops: while, until, for, and a bare block */
211 loop : label WHILE '(' remember texpr ')' mintro mblock cont
212 { PL_copline = (line_t)$2;
215 newWHILEOP(0, 1, (LOOP*)Nullop,
216 $2, $5, $8, $9, $7))); }
217 | label UNTIL '(' remember iexpr ')' mintro mblock cont
218 { PL_copline = (line_t)$2;
221 newWHILEOP(0, 1, (LOOP*)Nullop,
222 $2, $5, $8, $9, $7))); }
223 | label FOR MY remember my_scalar '(' mexpr ')' mblock cont
225 newFOROP(0, $1, (line_t)$2, $5, $7, $9, $10)); }
226 | label FOR scalar '(' remember mexpr ')' mblock cont
228 newFOROP(0, $1, (line_t)$2, mod($3, OP_ENTERLOOP),
230 | label FOR '(' remember mexpr ')' mblock cont
232 newFOROP(0, $1, (line_t)$2, Nullop, $5, $7, $8)); }
233 | label FOR '(' remember mnexpr ';' texpr ';' mintro mnexpr ')'
235 /* basically fake up an initialize-while lineseq */
237 PL_copline = (line_t)$2;
238 forop = newSTATEOP(0, $1,
239 newWHILEOP(0, 1, (LOOP*)Nullop,
243 forop = append_elem(OP_LINESEQ,
244 newSTATEOP(0, ($1?savepv($1):Nullch),
249 $$ = block_end($4, forop); }
250 | label block cont /* a block is a loop that happens once */
251 { $$ = newSTATEOP(0, $1,
252 newWHILEOP(0, 1, (LOOP*)Nullop,
253 NOLINE, Nullop, $2, $3, 0)); }
256 /* determine whether there are any new my declarations */
258 { $$ = (PL_min_intro_pending &&
259 PL_max_intro_pending >= PL_min_intro_pending);
262 /* Normal expression */
268 /* Boolean expression */
269 texpr : /* NULL means true */
270 { (void)scan_num("1", &yylval); $$ = yylval.opval; }
274 /* Inverted boolean expression */
276 { $$ = invert(scalar($1)); }
279 /* Expression with its own lexical scope */
281 { $$ = $1; intro_my(); }
285 { $$ = $1; intro_my(); }
289 { $$ = $1; intro_my(); }
292 /* Optional "MAIN:"-style loop labels */
298 /* Some kind of declaration - does not take part in the parse tree */
311 format : FORMAT startformsub formname block
312 { newFORM($2, $3, $4); }
315 formname: WORD { $$ = $1; }
316 | /* NULL */ { $$ = Nullop; }
319 /* Unimplemented "my sub foo { }" */
320 mysubrout: MYSUB startsub subname proto subattrlist subbody
321 { newMYSUB($2, $3, $4, $5, $6); }
324 /* Subroutine definition */
325 subrout : SUB startsub subname proto subattrlist subbody
326 { newATTRSUB($2, $3, $4, $5, $6); }
329 startsub: /* NULL */ /* start a regular subroutine scope */
330 { $$ = start_subparse(FALSE, 0); }
333 startanonsub: /* NULL */ /* start an anonymous subroutine scope */
334 { $$ = start_subparse(FALSE, CVf_ANON); }
337 startformsub: /* NULL */ /* start a format subroutine scope */
338 { $$ = start_subparse(TRUE, 0); }
341 /* Name of a subroutine - must be a bareword, could be special */
342 subname : WORD { const char *const name = SvPV_nolen_const(((SVOP*)$1)->op_sv);
343 if (strEQ(name, "BEGIN") || strEQ(name, "END")
344 || strEQ(name, "INIT") || strEQ(name, "CHECK"))
345 CvSPECIAL_on(PL_compcv);
349 /* Subroutine prototype */
355 /* Optional list of subroutine attributes */
356 subattrlist: /* NULL */
364 /* List of attributes for a "my" variable declaration */
365 myattrlist: COLONATTR THING
371 /* Subroutine body - either null or a block */
372 subbody : block { $$ = $1; }
373 | ';' { $$ = Nullop; PL_expect = XSTATE; }
376 package : PACKAGE WORD ';'
381 { CvSPECIAL_on(PL_compcv); /* It's a BEGIN {} */ }
382 WORD WORD listexpr ';'
383 { utilize($1, $2, $4, $5, $6); }
386 /* Ordinary expressions; logical combinations */
387 expr : expr ANDOP expr
388 { $$ = newLOGOP(OP_AND, 0, $1, $3); }
390 { $$ = newLOGOP($2, 0, $1, $3); }
392 { $$ = newLOGOP(OP_DOR, 0, $1, $3); }
393 | argexpr %prec PREC_LOW
396 /* Expressions are a list of terms joined by commas */
397 argexpr : argexpr ','
400 { $$ = append_elem(OP_LIST, $1, $3); }
401 | term %prec PREC_LOW
405 listop : LSTOP indirob argexpr /* map {...} @args or print $fh @args */
406 { $$ = convert($1, OPf_STACKED,
407 prepend_elem(OP_LIST, newGVREF($1,$2), $3) ); }
408 | FUNC '(' indirob expr ')' /* print ($fh @args */
409 { $$ = convert($1, OPf_STACKED,
410 prepend_elem(OP_LIST, newGVREF($1,$3), $4) ); }
411 | term ARROW method '(' listexprcom ')' /* $foo->bar(list) */
412 { $$ = convert(OP_ENTERSUB, OPf_STACKED,
414 prepend_elem(OP_LIST, scalar($1), $5),
415 newUNOP(OP_METHOD, 0, $3))); }
416 | term ARROW method /* $foo->bar */
417 { $$ = convert(OP_ENTERSUB, OPf_STACKED,
418 append_elem(OP_LIST, scalar($1),
419 newUNOP(OP_METHOD, 0, $3))); }
420 | METHOD indirob listexpr /* new Class @args */
421 { $$ = convert(OP_ENTERSUB, OPf_STACKED,
423 prepend_elem(OP_LIST, $2, $3),
424 newUNOP(OP_METHOD, 0, $1))); }
425 | FUNCMETH indirob '(' listexprcom ')' /* method $object (@args) */
426 { $$ = convert(OP_ENTERSUB, OPf_STACKED,
428 prepend_elem(OP_LIST, $2, $4),
429 newUNOP(OP_METHOD, 0, $1))); }
430 | LSTOP listexpr /* print @args */
431 { $$ = convert($1, 0, $2); }
432 | FUNC '(' listexprcom ')' /* print (@args) */
433 { $$ = convert($1, 0, $3); }
434 | LSTOPSUB startanonsub block /* sub f(&@); f { foo } ... */
435 { $3 = newANONATTRSUB($2, 0, Nullop, $3); }
436 listexpr %prec LSTOP /* ... @bar */
437 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
439 prepend_elem(OP_LIST, $3, $5), $1)); }
442 /* Names of methods. May use $object->$methodname */
447 /* Some kind of subscripted expression */
448 subscripted: star '{' expr ';' '}' /* *main::{something} */
449 /* In this and all the hash accessors, ';' is
450 * provided by the tokeniser */
451 { $$ = newBINOP(OP_GELEM, 0, $1, scalar($3));
452 PL_expect = XOPERATOR; }
453 | scalar '[' expr ']' /* $array[$element] */
454 { $$ = newBINOP(OP_AELEM, 0, oopsAV($1), scalar($3)); }
455 | term ARROW '[' expr ']' /* somearef->[$element] */
456 { $$ = newBINOP(OP_AELEM, 0,
457 ref(newAVREF($1),OP_RV2AV),
459 | subscripted '[' expr ']' /* $foo->[$bar]->[$baz] */
460 { $$ = newBINOP(OP_AELEM, 0,
461 ref(newAVREF($1),OP_RV2AV),
463 | scalar '{' expr ';' '}' /* $foo->{bar();} */
464 { $$ = newBINOP(OP_HELEM, 0, oopsHV($1), jmaybe($3));
465 PL_expect = XOPERATOR; }
466 | term ARROW '{' expr ';' '}' /* somehref->{bar();} */
467 { $$ = newBINOP(OP_HELEM, 0,
468 ref(newHVREF($1),OP_RV2HV),
470 PL_expect = XOPERATOR; }
471 | subscripted '{' expr ';' '}' /* $foo->[bar]->{baz;} */
472 { $$ = newBINOP(OP_HELEM, 0,
473 ref(newHVREF($1),OP_RV2HV),
475 PL_expect = XOPERATOR; }
476 | term ARROW '(' ')' /* $subref->() */
477 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
478 newCVREF(0, scalar($1))); }
479 | term ARROW '(' expr ')' /* $subref->(@args) */
480 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
481 append_elem(OP_LIST, $4,
482 newCVREF(0, scalar($1)))); }
484 | subscripted '(' expr ')' /* $foo->{bar}->(@args) */
485 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
486 append_elem(OP_LIST, $3,
487 newCVREF(0, scalar($1)))); }
488 | subscripted '(' ')' /* $foo->{bar}->() */
489 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
490 newCVREF(0, scalar($1))); }
491 | '(' expr ')' '[' expr ']' /* list slice */
492 { $$ = newSLICEOP(0, $5, $2); }
493 | '(' ')' '[' expr ']' /* empty list slice! */
494 { $$ = newSLICEOP(0, $4, Nullop); }
497 /* Binary operators between terms */
498 termbinop : term ASSIGNOP term /* $x = $y */
499 { $$ = newASSIGNOP(OPf_STACKED, $1, $2, $3); }
500 | term POWOP term /* $x ** $y */
501 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
502 | term MULOP term /* $x * $y, $x x $y */
503 { if ($2 != OP_REPEAT)
505 $$ = newBINOP($2, 0, $1, scalar($3)); }
506 | term ADDOP term /* $x + $y */
507 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
508 | term SHIFTOP term /* $x >> $y, $x << $y */
509 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
510 | term RELOP term /* $x > $y, etc. */
511 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
512 | term EQOP term /* $x == $y, $x eq $y */
513 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
514 | term BITANDOP term /* $x & $y */
515 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
516 | term BITOROP term /* $x | $y */
517 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
518 | term DOTDOT term /* $x..$y, $x...$y */
519 { $$ = newRANGE($2, scalar($1), scalar($3));}
520 | term ANDAND term /* $x && $y */
521 { $$ = newLOGOP(OP_AND, 0, $1, $3); }
522 | term OROR term /* $x || $y */
523 { $$ = newLOGOP(OP_OR, 0, $1, $3); }
524 | term DORDOR term /* $x // $y */
525 { $$ = newLOGOP(OP_DOR, 0, $1, $3); }
526 | term MATCHOP term /* $x =~ /$y/ */
527 { $$ = bind_match($2, $1, $3); }
530 /* Unary operators and terms */
531 termunop : '-' term %prec UMINUS /* -$x */
532 { $$ = newUNOP(OP_NEGATE, 0, scalar($2)); }
533 | '+' term %prec UMINUS /* +$x */
536 { $$ = newUNOP(OP_NOT, 0, scalar($2)); }
538 { $$ = newUNOP(OP_COMPLEMENT, 0, scalar($2));}
539 | term POSTINC /* $x++ */
540 { $$ = newUNOP(OP_POSTINC, 0,
541 mod(scalar($1), OP_POSTINC)); }
542 | term POSTDEC /* $x-- */
543 { $$ = newUNOP(OP_POSTDEC, 0,
544 mod(scalar($1), OP_POSTDEC)); }
545 | PREINC term /* ++$x */
546 { $$ = newUNOP(OP_PREINC, 0,
547 mod(scalar($2), OP_PREINC)); }
548 | PREDEC term /* --$x */
549 { $$ = newUNOP(OP_PREDEC, 0,
550 mod(scalar($2), OP_PREDEC)); }
554 /* Constructors for anonymous data */
555 anonymous: '[' expr ']'
556 { $$ = newANONLIST($2); }
558 { $$ = newANONLIST(Nullop); }
559 | HASHBRACK expr ';' '}' %prec '(' /* { foo => "Bar" } */
560 { $$ = newANONHASH($2); }
561 | HASHBRACK ';' '}' %prec '(' /* { } (';' by tokener) */
562 { $$ = newANONHASH(Nullop); }
563 | ANONSUB startanonsub proto subattrlist block %prec '('
564 { $$ = newANONATTRSUB($2, $3, $4, $5); }
568 /* Things called with "do" */
569 termdo : DO term %prec UNIOP /* do $filename */
570 { $$ = dofile($2, $1); }
571 | DO block %prec '(' /* do { code */
572 { $$ = newUNOP(OP_NULL, OPf_SPECIAL, scope($2)); }
573 | DO WORD '(' ')' /* do somesub() */
574 { $$ = newUNOP(OP_ENTERSUB,
575 OPf_SPECIAL|OPf_STACKED,
576 prepend_elem(OP_LIST,
578 (OPpENTERSUB_AMPER<<8),
581 | DO WORD '(' expr ')' /* do somesub(@args) */
582 { $$ = newUNOP(OP_ENTERSUB,
583 OPf_SPECIAL|OPf_STACKED,
587 (OPpENTERSUB_AMPER<<8),
590 | DO scalar '(' ')' /* do $subref () */
591 { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
592 prepend_elem(OP_LIST,
593 scalar(newCVREF(0,scalar($2))), Nullop)); dep();}
594 | DO scalar '(' expr ')' /* do $subref (@args) */
595 { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
596 prepend_elem(OP_LIST,
598 scalar(newCVREF(0,scalar($2))))); dep();}
606 | term '?' term ':' term
607 { $$ = newCONDOP(0, $1, $3, $5); }
608 | REFGEN term /* \$x, \@y, \%z */
609 { $$ = newUNOP(OP_REFGEN, 0, mod($2,OP_REFGEN)); }
610 | myattrterm %prec UNIOP
612 | LOCAL term %prec UNIOP
613 { $$ = localize($2,$1); }
615 { $$ = sawparens($2); }
617 { $$ = sawparens(newNULLLIST()); }
626 | arylen %prec '(' /* $#x, $#{ something } */
627 { $$ = newUNOP(OP_AV2ARYLEN, 0, ref($1, OP_AV2ARYLEN));}
630 | ary '[' expr ']' /* array slice */
631 { $$ = prepend_elem(OP_ASLICE,
632 newOP(OP_PUSHMARK, 0),
633 newLISTOP(OP_ASLICE, 0,
635 ref($1, OP_ASLICE))); }
636 | ary '{' expr ';' '}' /* @hash{@keys} */
637 { $$ = prepend_elem(OP_HSLICE,
638 newOP(OP_PUSHMARK, 0),
639 newLISTOP(OP_HSLICE, 0,
641 ref(oopsHV($1), OP_HSLICE)));
642 PL_expect = XOPERATOR; }
646 { $$ = newUNOP(OP_ENTERSUB, 0, scalar($1)); }
647 | amper '(' ')' /* &foo() */
648 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar($1)); }
649 | amper '(' expr ')' /* &foo(@args) */
650 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
651 append_elem(OP_LIST, $3, scalar($1))); }
652 | NOAMP WORD listexpr /* foo(@args) */
653 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
654 append_elem(OP_LIST, $3, scalar($2))); }
655 | LOOPEX /* loop exiting command (goto, last, dump, etc) */
656 { $$ = newOP($1, OPf_SPECIAL);
657 PL_hints |= HINT_BLOCK_SCOPE; }
659 { $$ = newLOOPEX($1,$2); }
660 | NOTOP argexpr /* not $foo */
661 { $$ = newUNOP(OP_NOT, 0, scalar($2)); }
662 | UNIOP /* Unary op, $_ implied */
663 { $$ = newOP($1, 0); }
664 | UNIOP block /* eval { foo } */
665 { $$ = newUNOP($1, 0, $2); }
666 | UNIOP term /* Unary op */
667 { $$ = newUNOP($1, 0, $2); }
668 | REQUIRE /* require, $_ implied */
669 { $$ = newOP(OP_REQUIRE, $1 ? OPf_SPECIAL : 0); }
670 | REQUIRE term /* require Foo */
671 { $$ = newUNOP(OP_REQUIRE, $1 ? OPf_SPECIAL : 0, $2); }
672 | UNIOPSUB term /* Sub treated as unop */
673 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
674 append_elem(OP_LIST, $2, scalar($1))); }
675 | FUNC0 /* Nullary operator */
676 { $$ = newOP($1, 0); }
678 { $$ = newOP($1, 0); }
679 | FUNC0SUB /* Sub treated as nullop */
680 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
682 | FUNC1 '(' ')' /* not () */
683 { $$ = $1 == OP_NOT ? newUNOP($1, 0, newSVOP(OP_CONST, 0, newSViv(0)))
684 : newOP($1, OPf_SPECIAL); }
685 | FUNC1 '(' expr ')' /* not($foo) */
686 { $$ = newUNOP($1, 0, $3); }
687 | PMFUNC '(' argexpr ')' /* m//, s///, tr/// */
688 { $$ = pmruntime($1, $3, 1); }
693 /* "my" declarations, with optional attributes */
694 myattrterm: MY myterm myattrlist
695 { $$ = my_attrs($2,$3); }
697 { $$ = localize($2,$1); }
700 /* Things that can be "my"'d */
701 myterm : '(' expr ')'
702 { $$ = sawparens($2); }
704 { $$ = sawparens(newNULLLIST()); }
713 /* Basic list expressions */
714 listexpr: /* NULL */ %prec PREC_LOW
716 | argexpr %prec PREC_LOW
720 listexprcom: /* NULL */
728 /* A little bit of trickery to make "for my $foo (@bar)" actually be
731 { PL_in_my = 0; $$ = my($1); }
735 { $$ = newCVREF($1,$2); }
739 { $$ = newSVREF($2); }
743 { $$ = newAVREF($2); }
747 { $$ = newHVREF($2); }
750 arylen : DOLSHARP indirob
751 { $$ = newAVREF($2); }
755 { $$ = newGVREF(0,$2); }
758 /* Indirect objects */
761 | scalar %prec PREC_LOW