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
51 %type <ival> prog decl format startsub startanonsub startformsub
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 mtexpr 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
84 %right '!' '~' UMINUS REFGEN
86 %nonassoc PREINC PREDEC POSTINC POSTDEC
94 /* The whole program */
97 { $$ = $1; newPROG(block_end($1,$2)); }
100 /* An ordinary block */
101 block : '{' remember lineseq '}'
102 { if (PL_copline > (line_t)$1)
103 PL_copline = (line_t)$1;
104 $$ = block_end($2, $3); }
107 remember: /* NULL */ /* start a full lexical scope */
108 { $$ = block_start(TRUE); }
113 PL_expect = XSTATE; $$ = block_start(TRUE);
118 mblock : '{' mremember lineseq '}'
119 { if (PL_copline > (line_t)$1)
120 PL_copline = (line_t)$1;
121 $$ = block_end($2, $3); }
124 mremember: /* NULL */ /* start a partial lexical scope */
125 { $$ = block_start(FALSE); }
128 savescope: /* NULL */ /* remember stack pos in case of error */
129 { $$ = PL_savestack_ix; }
131 /* A collection of "lines" in the program */
136 | lineseq savescope line
138 $$ = append_list(OP_LINESEQ,
139 (LISTOP*)$1, (LISTOP*)$3);
140 PL_pad_reset_pending = TRUE;
141 if ($1 && $3) PL_hints |= HINT_BLOCK_SCOPE; }
144 /* A "line" in the program */
146 { $$ = newSTATEOP(0, $1, $2); }
147 | loop /* loops add their own labels */
149 { if ($1 != Nullch) {
150 $$ = newSTATEOP(0, $1, newOP(OP_NULL, 0));
156 PL_expect = XSTATE; }
158 { $$ = newSTATEOP(0, $1, $2);
159 PL_expect = XSTATE; }
162 /* An expression which may have a side-effect */
168 { $$ = newLOGOP(OP_AND, 0, $3, $1); }
170 { $$ = newLOGOP(OP_OR, 0, $3, $1); }
172 { $$ = newLOOPOP(OPf_PARENS, 1, scalar($3), $1); }
174 { $$ = newLOOPOP(OPf_PARENS, 1, $3, $1);}
176 { $$ = newFOROP(0, Nullch, (line_t)$2,
177 Nullop, $3, $1, Nullop); }
180 /* else and elsif blocks */
184 { ($2)->op_flags |= OPf_PARENS; $$ = scope($2); }
185 | ELSIF '(' mexpr ')' mblock else
186 { PL_copline = (line_t)$1;
187 $$ = newCONDOP(0, $3, scope($5), $6);
188 PL_hints |= HINT_BLOCK_SCOPE; }
191 /* Real conditional expressions */
192 cond : IF '(' remember mexpr ')' mblock else
193 { PL_copline = (line_t)$1;
195 newCONDOP(0, $4, scope($6), $7)); }
196 | UNLESS '(' remember miexpr ')' mblock else
197 { PL_copline = (line_t)$1;
199 newCONDOP(0, $4, scope($6), $7)); }
202 /* Continue blocks */
209 /* Loops: while, until, for, and a bare block */
210 loop : label WHILE '(' remember mtexpr ')' mblock cont
211 { PL_copline = (line_t)$2;
214 newWHILEOP(0, 1, (LOOP*)Nullop,
216 | label UNTIL '(' remember miexpr ')' mblock cont
217 { PL_copline = (line_t)$2;
220 newWHILEOP(0, 1, (LOOP*)Nullop,
222 | label FOR MY remember my_scalar '(' mexpr ')' mblock cont
224 newFOROP(0, $1, (line_t)$2, $5, $7, $9, $10)); }
225 | label FOR scalar '(' remember mexpr ')' mblock cont
227 newFOROP(0, $1, (line_t)$2, mod($3, OP_ENTERLOOP),
229 | label FOR '(' remember mexpr ')' mblock cont
231 newFOROP(0, $1, (line_t)$2, Nullop, $5, $7, $8)); }
232 | label FOR '(' remember mnexpr ';' mtexpr ';' mnexpr ')' mblock
233 /* basically fake up an initialize-while lineseq */
235 PL_copline = (line_t)$2;
236 forop = newSTATEOP(0, $1,
237 newWHILEOP(0, 1, (LOOP*)Nullop,
241 forop = append_elem(OP_LINESEQ,
242 newSTATEOP(0, ($1?savepv($1):Nullch),
247 $$ = block_end($4, forop); }
248 | label block cont /* a block is a loop that happens once */
249 { $$ = newSTATEOP(0, $1,
250 newWHILEOP(0, 1, (LOOP*)Nullop,
251 NOLINE, Nullop, $2, $3)); }
254 /* Normal expression */
260 /* Boolean expression */
261 texpr : /* NULL means true */
262 { (void)scan_num("1", &yylval); $$ = yylval.opval; }
266 /* Inverted boolean expression */
268 { $$ = invert(scalar($1)); }
271 /* Expression with its own lexical scope */
273 { $$ = $1; intro_my(); }
277 { $$ = $1; intro_my(); }
281 { $$ = $1; intro_my(); }
285 { $$ = $1; intro_my(); }
288 /* Optional "MAIN:"-style loop labels */
294 /* Some kind of declaration - does not take part in the parse tree */
307 format : FORMAT startformsub formname block
308 { newFORM($2, $3, $4); }
311 formname: WORD { $$ = $1; }
312 | /* NULL */ { $$ = Nullop; }
315 /* Unimplemented "my sub foo { }" */
316 mysubrout: MYSUB startsub subname proto subattrlist subbody
317 { newMYSUB($2, $3, $4, $5, $6); }
320 /* Subroutine definition */
321 subrout : SUB startsub subname proto subattrlist subbody
322 { newATTRSUB($2, $3, $4, $5, $6); }
325 startsub: /* NULL */ /* start a regular subroutine scope */
326 { $$ = start_subparse(FALSE, 0); }
329 startanonsub: /* NULL */ /* start an anonymous subroutine scope */
330 { $$ = start_subparse(FALSE, CVf_ANON); }
333 startformsub: /* NULL */ /* start a format subroutine scope */
334 { $$ = start_subparse(TRUE, 0); }
337 /* Name of a subroutine - must be a bareword, could be special */
338 subname : WORD { STRLEN n_a; char *name = SvPV(((SVOP*)$1)->op_sv,n_a);
339 if (strEQ(name, "BEGIN") || strEQ(name, "END")
340 || strEQ(name, "INIT") || strEQ(name, "CHECK"))
341 CvSPECIAL_on(PL_compcv);
345 /* Subroutine prototype */
351 /* Optional list of subroutine attributes */
352 subattrlist: /* NULL */
360 /* List of attributes for a "my" variable declaration */
361 myattrlist: COLONATTR THING
367 /* Subroutine body - either null or a block */
368 subbody : block { $$ = $1; }
369 | ';' { $$ = Nullop; PL_expect = XSTATE; }
372 package : PACKAGE WORD ';'
377 { CvSPECIAL_on(PL_compcv); /* It's a BEGIN {} */ }
378 WORD WORD listexpr ';'
379 { utilize($1, $2, $4, $5, $6); }
382 /* Ordinary expressions; logical combinations */
383 expr : expr ANDOP expr
384 { $$ = newLOGOP(OP_AND, 0, $1, $3); }
386 { $$ = newLOGOP($2, 0, $1, $3); }
388 { $$ = newLOGOP(OP_DOR, 0, $1, $3); }
389 | argexpr %prec PREC_LOW
392 /* Expressions are a list of terms joined by commas */
393 argexpr : argexpr ','
396 { $$ = append_elem(OP_LIST, $1, $3); }
397 | term %prec PREC_LOW
401 listop : LSTOP indirob argexpr /* map {...} @args or print $fh @args */
402 { $$ = convert($1, OPf_STACKED,
403 prepend_elem(OP_LIST, newGVREF($1,$2), $3) ); }
404 | FUNC '(' indirob expr ')' /* print ($fh @args */
405 { $$ = convert($1, OPf_STACKED,
406 prepend_elem(OP_LIST, newGVREF($1,$3), $4) ); }
407 | term ARROW method '(' listexprcom ')' /* $foo->bar(list) */
408 { $$ = convert(OP_ENTERSUB, OPf_STACKED,
410 prepend_elem(OP_LIST, scalar($1), $5),
411 newUNOP(OP_METHOD, 0, $3))); }
412 | term ARROW method /* $foo->bar */
413 { $$ = convert(OP_ENTERSUB, OPf_STACKED,
414 append_elem(OP_LIST, scalar($1),
415 newUNOP(OP_METHOD, 0, $3))); }
416 | METHOD indirob listexpr /* new Class @args */
417 { $$ = convert(OP_ENTERSUB, OPf_STACKED,
419 prepend_elem(OP_LIST, $2, $3),
420 newUNOP(OP_METHOD, 0, $1))); }
421 | FUNCMETH indirob '(' listexprcom ')' /* method $object (@args) */
422 { $$ = convert(OP_ENTERSUB, OPf_STACKED,
424 prepend_elem(OP_LIST, $2, $4),
425 newUNOP(OP_METHOD, 0, $1))); }
426 | LSTOP listexpr /* print @args */
427 { $$ = convert($1, 0, $2); }
428 | FUNC '(' listexprcom ')' /* print (@args) */
429 { $$ = convert($1, 0, $3); }
430 | LSTOPSUB startanonsub block /* sub f(&@); f { foo } ... */
431 { $3 = newANONATTRSUB($2, 0, Nullop, $3); }
432 listexpr %prec LSTOP /* ... @bar */
433 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
435 prepend_elem(OP_LIST, $3, $5), $1)); }
438 /* Names of methods. May use $object->$methodname */
443 /* Some kind of subscripted expression */
444 subscripted: star '{' expr ';' '}' /* *main::{something} */
445 /* In this and all the hash accessors, ';' is
446 * provided by the tokeniser */
447 { $$ = newBINOP(OP_GELEM, 0, $1, scalar($3));
448 PL_expect = XOPERATOR; }
449 | scalar '[' expr ']' /* $array[$element] */
450 { $$ = newBINOP(OP_AELEM, 0, oopsAV($1), scalar($3)); }
451 | term ARROW '[' expr ']' /* somearef->[$element] */
452 { $$ = newBINOP(OP_AELEM, 0,
453 ref(newAVREF($1),OP_RV2AV),
455 | subscripted '[' expr ']' /* $foo->[$bar]->[$baz] */
456 { $$ = newBINOP(OP_AELEM, 0,
457 ref(newAVREF($1),OP_RV2AV),
459 | scalar '{' expr ';' '}' /* $foo->{bar();} */
460 { $$ = newBINOP(OP_HELEM, 0, oopsHV($1), jmaybe($3));
461 PL_expect = XOPERATOR; }
462 | term ARROW '{' expr ';' '}' /* somehref->{bar();} */
463 { $$ = newBINOP(OP_HELEM, 0,
464 ref(newHVREF($1),OP_RV2HV),
466 PL_expect = XOPERATOR; }
467 | subscripted '{' expr ';' '}' /* $foo->[bar]->{baz;} */
468 { $$ = newBINOP(OP_HELEM, 0,
469 ref(newHVREF($1),OP_RV2HV),
471 PL_expect = XOPERATOR; }
472 | term ARROW '(' ')' /* $subref->() */
473 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
474 newCVREF(0, scalar($1))); }
475 | term ARROW '(' expr ')' /* $subref->(@args) */
476 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
477 append_elem(OP_LIST, $4,
478 newCVREF(0, scalar($1)))); }
480 | subscripted '(' expr ')' /* $foo->{bar}->(@args) */
481 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
482 append_elem(OP_LIST, $3,
483 newCVREF(0, scalar($1)))); }
484 | subscripted '(' ')' /* $foo->{bar}->() */
485 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
486 newCVREF(0, scalar($1))); }
489 /* Binary operators between terms */
490 termbinop : term ASSIGNOP term /* $x = $y */
491 { $$ = newASSIGNOP(OPf_STACKED, $1, $2, $3); }
492 | term POWOP term /* $x ** $y */
493 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
494 | term MULOP term /* $x * $y, $x x $y */
495 { if ($2 != OP_REPEAT)
497 $$ = newBINOP($2, 0, $1, scalar($3)); }
498 | term ADDOP term /* $x + $y */
499 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
500 | term SHIFTOP term /* $x >> $y, $x << $y */
501 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
502 | term RELOP term /* $x > $y, etc. */
503 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
504 | term EQOP term /* $x == $y, $x eq $y */
505 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
506 | term BITANDOP term /* $x & $y */
507 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
508 | term BITOROP term /* $x | $y */
509 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
510 | term DOTDOT term /* $x..$y, $x...$y */
511 { $$ = newRANGE($2, scalar($1), scalar($3));}
512 | term ANDAND term /* $x && $y */
513 { $$ = newLOGOP(OP_AND, 0, $1, $3); }
514 | term OROR term /* $x || $y */
515 { $$ = newLOGOP(OP_OR, 0, $1, $3); }
516 | term DORDOR term /* $x // $y */
517 { $$ = newLOGOP(OP_DOR, 0, $1, $3); }
518 | term MATCHOP term /* $x =~ /$y/ */
519 { $$ = bind_match($2, $1, $3); }
522 /* Unary operators and terms */
523 termunop : '-' term %prec UMINUS /* -$x */
524 { $$ = newUNOP(OP_NEGATE, 0, scalar($2)); }
525 | '+' term %prec UMINUS /* +$x */
528 { $$ = newUNOP(OP_NOT, 0, scalar($2)); }
530 { $$ = newUNOP(OP_COMPLEMENT, 0, scalar($2));}
531 | term POSTINC /* $x++ */
532 { $$ = newUNOP(OP_POSTINC, 0,
533 mod(scalar($1), OP_POSTINC)); }
534 | term POSTDEC /* $x-- */
535 { $$ = newUNOP(OP_POSTDEC, 0,
536 mod(scalar($1), OP_POSTDEC)); }
537 | PREINC term /* ++$x */
538 { $$ = newUNOP(OP_PREINC, 0,
539 mod(scalar($2), OP_PREINC)); }
540 | PREDEC term /* --$x */
541 { $$ = newUNOP(OP_PREDEC, 0,
542 mod(scalar($2), OP_PREDEC)); }
546 /* Constructors for anonymous data */
547 anonymous: '[' expr ']'
548 { $$ = newANONLIST($2); }
550 { $$ = newANONLIST(Nullop); }
551 | HASHBRACK expr ';' '}' %prec '(' /* { foo => "Bar" } */
552 { $$ = newANONHASH($2); }
553 | HASHBRACK ';' '}' %prec '(' /* { } (';' by tokener) */
554 { $$ = newANONHASH(Nullop); }
555 | ANONSUB startanonsub proto subattrlist block %prec '('
556 { $$ = newANONATTRSUB($2, $3, $4, $5); }
560 /* Things called with "do" */
561 termdo : DO term %prec UNIOP /* do $filename */
563 | DO block %prec '(' /* do { code */
564 { $$ = newUNOP(OP_NULL, OPf_SPECIAL, scope($2)); }
565 | DO WORD '(' ')' /* do somesub() */
566 { $$ = newUNOP(OP_ENTERSUB,
567 OPf_SPECIAL|OPf_STACKED,
568 prepend_elem(OP_LIST,
570 (OPpENTERSUB_AMPER<<8),
573 | DO WORD '(' expr ')' /* do somesub(@args) */
574 { $$ = newUNOP(OP_ENTERSUB,
575 OPf_SPECIAL|OPf_STACKED,
579 (OPpENTERSUB_AMPER<<8),
582 | DO scalar '(' ')' /* do $subref () */
583 { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
584 prepend_elem(OP_LIST,
585 scalar(newCVREF(0,scalar($2))), Nullop)); dep();}
586 | DO scalar '(' expr ')' /* do $subref (@args) */
587 { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
588 prepend_elem(OP_LIST,
590 scalar(newCVREF(0,scalar($2))))); dep();}
598 | term '?' term ':' term
599 { $$ = newCONDOP(0, $1, $3, $5); }
600 | REFGEN term /* \$x, \@y, \%z */
601 { $$ = newUNOP(OP_REFGEN, 0, mod($2,OP_REFGEN)); }
602 | myattrterm %prec UNIOP
604 | LOCAL term %prec UNIOP
605 { $$ = localize($2,$1); }
607 { $$ = sawparens($2); }
609 { $$ = sawparens(newNULLLIST()); }
618 | arylen %prec '(' /* $#x, $#{ something } */
619 { $$ = newUNOP(OP_AV2ARYLEN, 0, ref($1, OP_AV2ARYLEN));}
622 | '(' expr ')' '[' expr ']' /* list slice */
623 { $$ = newSLICEOP(0, $5, $2); }
624 | '(' ')' '[' expr ']' /* empty list slice! */
625 { $$ = newSLICEOP(0, $4, Nullop); }
626 | ary '[' expr ']' /* array slice */
627 { $$ = prepend_elem(OP_ASLICE,
628 newOP(OP_PUSHMARK, 0),
629 newLISTOP(OP_ASLICE, 0,
631 ref($1, OP_ASLICE))); }
632 | ary '{' expr ';' '}' /* @hash{@keys} */
633 { $$ = prepend_elem(OP_HSLICE,
634 newOP(OP_PUSHMARK, 0),
635 newLISTOP(OP_HSLICE, 0,
637 ref(oopsHV($1), OP_HSLICE)));
638 PL_expect = XOPERATOR; }
642 { $$ = newUNOP(OP_ENTERSUB, 0, scalar($1)); }
643 | amper '(' ')' /* &foo() */
644 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar($1)); }
645 | amper '(' expr ')' /* &foo(@args) */
646 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
647 append_elem(OP_LIST, $3, scalar($1))); }
648 | NOAMP WORD listexpr /* foo(@args) */
649 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
650 append_elem(OP_LIST, $3, scalar($2))); }
651 | LOOPEX /* loop exiting command (goto, last, dump, etc) */
652 { $$ = newOP($1, OPf_SPECIAL);
653 PL_hints |= HINT_BLOCK_SCOPE; }
655 { $$ = newLOOPEX($1,$2); }
656 | NOTOP argexpr /* not $foo */
657 { $$ = newUNOP(OP_NOT, 0, scalar($2)); }
658 | UNIOP /* Unary op, $_ implied */
659 { $$ = newOP($1, 0); }
660 | UNIOP block /* eval { foo } */
661 { $$ = newUNOP($1, 0, $2); }
662 | UNIOP term /* Unary op */
663 { $$ = newUNOP($1, 0, $2); }
664 | UNIOPSUB term /* Sub treated as unop */
665 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
666 append_elem(OP_LIST, $2, scalar($1))); }
667 | FUNC0 /* Nullary operator */
668 { $$ = newOP($1, 0); }
670 { $$ = newOP($1, 0); }
671 | FUNC0SUB /* Sub treated as nullop */
672 { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
674 | FUNC1 '(' ')' /* not () */
675 { $$ = $1 == OP_NOT ? newUNOP($1, 0, newSVOP(OP_CONST, 0, newSViv(0)))
676 : newOP($1, OPf_SPECIAL); }
677 | FUNC1 '(' expr ')' /* not($foo) */
678 { $$ = newUNOP($1, 0, $3); }
679 | PMFUNC '(' argexpr ')' /* m//, s///, tr/// */
680 { $$ = pmruntime($1, $3, 1); }
685 /* "my" declarations, with optional attributes */
686 myattrterm: MY myterm myattrlist
687 { $$ = my_attrs($2,$3); }
689 { $$ = localize($2,$1); }
692 /* Things that can be "my"'d */
693 myterm : '(' expr ')'
694 { $$ = sawparens($2); }
696 { $$ = sawparens(newNULLLIST()); }
705 /* Basic list expressions */
706 listexpr: /* NULL */ %prec PREC_LOW
708 | argexpr %prec PREC_LOW
712 listexprcom: /* NULL */
720 /* A little bit of trickery to make "for my $foo (@bar)" actually be
723 { PL_in_my = 0; $$ = my($1); }
727 { $$ = newCVREF($1,$2); }
731 { $$ = newSVREF($2); }
735 { $$ = newAVREF($2); }
739 { $$ = newHVREF($2); }
742 arylen : DOLSHARP indirob
743 { $$ = newAVREF($2); }
747 { $$ = newGVREF(0,$2); }
750 /* Indirect objects */
753 | scalar %prec PREC_LOW