1 /* $Header: perl.y,v 3.0.1.5 90/03/12 16:55:56 lwall Locked $
3 * Copyright (c) 1989, Larry Wall
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
9 * Revision 3.0.1.5 90/03/12 16:55:56 lwall
10 * patch13: added list slice operator (LIST)[LIST]
11 * patch13: (LIST,) now legal
13 * Revision 3.0.1.4 90/02/28 18:03:23 lwall
14 * patch9: line numbers were bogus during certain portions of foreach evaluation
16 * Revision 3.0.1.3 89/12/21 20:13:41 lwall
17 * patch7: send() didn't allow a TO argument
19 * Revision 3.0.1.2 89/11/11 04:49:04 lwall
20 * patch2: moved yydebug to where its type doesn't matter
21 * patch2: !$foo++ was unreasonably illegal
22 * patch2: local(@foo) didn't work
23 * patch2: default args to unary operators didn't work
25 * Revision 3.0.1.1 89/10/26 23:20:41 lwall
26 * patch1: grandfathered "format stdout"
27 * patch1: operator(); is now normally equivalent to operator;
29 * Revision 3.0 89/10/18 15:22:04 lwall
39 ARG *arg4; /* rarely used arguments to make_op() */
51 struct compcmd compval;
57 %token <ival> APPEND OPEN SELECT LOOPEX
58 %token <ival> USING FORMAT DO SHIFT PUSH POP LVALFUN
59 %token <ival> WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE SPLIT FLIST
60 %token <ival> FOR FILOP FILOP2 FILOP3 FILOP4 FILOP22 FILOP25
61 %token <ival> FUNC0 FUNC1 FUNC2 FUNC3 HSHFUN HSHFUN3
62 %token <ival> FLIST2 SUB FILETEST LOCAL DELETE
63 %token <ival> RELOP EQOP MULOP ADDOP PACKAGE AMPER LFUNC4
64 %token <formval> FORMLIST
65 %token <stabval> REG ARYLEN ARY HSH STAR
66 %token <arg> SUBST PATTERN
67 %token <arg> RSTRING TRANS
69 %type <ival> prog decl format remember
71 %type <cmdval> block lineseq line loop cond sideff nexpr else
72 %type <arg> expr sexpr cexpr csexpr term handle aryword hshword
73 %type <arg> texpr listop
75 %type <compval> compblock
77 %nonassoc <ival> LISTOP
88 %nonassoc <ival> UNIOP
103 #if defined(YYDEBUG) && defined(DEBUGGING)
104 yydebug = (debug & 1);
107 /*CONTINUED*/ lineseq
109 eval_root = block_head($2);
111 main_root = block_head($2); }
114 compblock: block CONTINUE block
115 { $$.comp_true = $1; $$.comp_alt = $3; }
117 { $$.comp_true = $1; $$.comp_alt = $2; }
124 | ELSIF '(' expr ')' compblock
126 $$ = make_ccmd(C_ELSIF,$3,$5); }
129 block : '{' remember lineseq '}'
130 { $$ = block_head($3);
131 if (savestack->ary_fill > $2)
135 remember: /* NULL */ /* in case they push a package name */
136 { $$ = savestack->ary_fill; }
142 { $$ = append_line($1,$2); }
148 { $$ = add_label($1,$2); }
149 | loop /* loops add their own labels */
151 { if ($1 != Nullch) {
152 $$ = add_label($1, make_acmd(C_EXPR, Nullstab,
157 { $$ = add_label($1,$2); }
163 { $$ = make_acmd(C_EXPR, Nullstab, $1, Nullarg); }
166 make_acmd(C_EXPR, Nullstab, Nullarg, $1), $3); }
168 { $$ = addcond(invert(
169 make_acmd(C_EXPR, Nullstab, Nullarg, $1)), $3); }
172 make_acmd(C_EXPR, Nullstab, Nullarg, $1), $3); }
174 { $$ = addloop(invert(
175 make_acmd(C_EXPR, Nullstab, Nullarg, $1)), $3); }
178 cond : IF '(' expr ')' compblock
180 $$ = make_icmd(C_IF,$3,$5); }
181 | UNLESS '(' expr ')' compblock
183 $$ = invert(make_icmd(C_IF,$3,$5)); }
186 $$ = make_ccmd(C_IF,cmd_to_arg($2),$3); }
187 | UNLESS block compblock
189 $$ = invert(make_ccmd(C_IF,cmd_to_arg($2),$3)); }
192 loop : label WHILE '(' texpr ')' compblock
194 $$ = wopt(add_label($1,
195 make_ccmd(C_WHILE,$4,$6) )); }
196 | label UNTIL '(' expr ')' compblock
198 $$ = wopt(add_label($1,
199 invert(make_ccmd(C_WHILE,$4,$6)) )); }
200 | label WHILE block compblock
202 $$ = wopt(add_label($1,
203 make_ccmd(C_WHILE, cmd_to_arg($3),$4) )); }
204 | label UNTIL block compblock
206 $$ = wopt(add_label($1,
207 invert(make_ccmd(C_WHILE, cmd_to_arg($3),$4)) )); }
208 | label FOR REG '(' expr ')' compblock
211 * The following gobbledygook catches EXPRs that
212 * aren't explicit array refs and translates
213 * foreach VAR (EXPR) {
216 * foreach VAR (@ary) {
217 * where @ary is a hidden array made by genstab().
218 * (Note that @ary may become a local array if
219 * it is determined that it might be called
220 * recursively. See cmd_tosave().)
222 if ($5->arg_type != O_ARRAY) {
223 scrstab = aadd(genstab());
225 make_acmd(C_EXPR, Nullstab,
226 l(make_op(O_ASSIGN,2,
227 listish(make_op(O_ARRAY, 1,
228 stab2arg(A_STAB,scrstab),
229 Nullarg,Nullarg, 1)),
230 listish(make_list($5)),
233 wopt(over($3,add_label($1,
236 stab2arg(A_STAB,scrstab),
240 $$->c_head->c_line = $2;
243 $$ = wopt(over($3,add_label($1,
244 make_ccmd(C_WHILE,$5,$7) )));
247 | label FOR '(' expr ')' compblock
249 if ($4->arg_type != O_ARRAY) {
250 scrstab = aadd(genstab());
252 make_acmd(C_EXPR, Nullstab,
253 l(make_op(O_ASSIGN,2,
254 listish(make_op(O_ARRAY, 1,
255 stab2arg(A_STAB,scrstab),
256 Nullarg,Nullarg, 1 )),
257 listish(make_list($4)),
260 wopt(over(defstab,add_label($1,
263 stab2arg(A_STAB,scrstab),
267 $$->c_head->c_line = $2;
269 else { /* lisp, anyone? */
270 $$ = wopt(over(defstab,add_label($1,
271 make_ccmd(C_WHILE,$4,$6) )));
274 | label FOR '(' nexpr ';' texpr ';' nexpr ')' block
275 /* basically fake up an initialize-while lineseq */
276 { yyval.compval.comp_true = $10;
277 yyval.compval.comp_alt = $8;
279 $$ = append_line($4,wopt(add_label($1,
280 make_ccmd(C_WHILE,$6,yyval.compval) ))); }
281 | label compblock /* a block is a loop that happens once */
282 { $$ = add_label($1,make_ccmd(C_BLOCK,Nullarg,$2)); }
290 texpr : /* NULL means true */
291 { (void)scanstr("1"); $$ = yylval.arg; }
308 format : FORMAT WORD '=' FORMLIST
309 { if (strEQ($2,"stdout"))
310 stab_form(stabent("STDOUT",TRUE)) = $4;
311 else if (strEQ($2,"stderr"))
312 stab_form(stabent("STDERR",TRUE)) = $4;
314 stab_form(stabent($2,TRUE)) = $4;
316 | FORMAT '=' FORMLIST
317 { stab_form(stabent("STDOUT",TRUE)) = $3; }
320 subrout : SUB WORD block
324 package : PACKAGE WORD ';'
329 str_set(curstname,$2);
330 sprintf(tmpbuf,"'_%s",$2);
331 curstash = stab_xhash(hadd(stabent(tmpbuf,TRUE)));
332 curstash->tbl_coeffsize = 0;
341 expr : expr ',' sexpr
342 { $$ = make_op(O_COMMA, 2, $1, $3, Nullarg); }
350 sexpr : sexpr '=' sexpr
352 if ($1->arg_type == O_ASSIGN && $1->arg_len == 1)
353 $1->arg_type = O_ITEM; /* a local() */
354 if ($1->arg_type == O_LIST)
356 $$ = l(make_op(O_ASSIGN, 2, $1, $3, Nullarg)); }
357 | sexpr POW '=' sexpr
358 { $$ = l(make_op(O_POW, 2, $1, $4, Nullarg)); }
359 | sexpr MULOP '=' sexpr
360 { $$ = l(make_op($2, 2, $1, $4, Nullarg)); }
361 | sexpr ADDOP '=' sexpr
362 { $$ = rcatmaybe(l(make_op($2, 2, $1, $4, Nullarg)));}
364 { $$ = l(make_op(O_LEFT_SHIFT, 2, $1, $4, Nullarg)); }
366 { $$ = l(make_op(O_RIGHT_SHIFT, 2, $1, $4, Nullarg)); }
367 | sexpr '&' '=' sexpr
368 { $$ = l(make_op(O_BIT_AND, 2, $1, $4, Nullarg)); }
369 | sexpr '^' '=' sexpr
370 { $$ = l(make_op(O_XOR, 2, $1, $4, Nullarg)); }
371 | sexpr '|' '=' sexpr
372 { $$ = l(make_op(O_BIT_OR, 2, $1, $4, Nullarg)); }
376 { $$ = make_op(O_POW, 2, $1, $3, Nullarg); }
378 { $$ = make_op($2, 2, $1, $3, Nullarg); }
380 { $$ = make_op($2, 2, $1, $3, Nullarg); }
382 { $$ = make_op(O_LEFT_SHIFT, 2, $1, $3, Nullarg); }
384 { $$ = make_op(O_RIGHT_SHIFT, 2, $1, $3, Nullarg); }
386 { $$ = make_op($2, 2, $1, $3, Nullarg); }
388 { $$ = make_op($2, 2, $1, $3, Nullarg); }
390 { $$ = make_op(O_BIT_AND, 2, $1, $3, Nullarg); }
392 { $$ = make_op(O_XOR, 2, $1, $3, Nullarg); }
394 { $$ = make_op(O_BIT_OR, 2, $1, $3, Nullarg); }
397 $$ = make_op(O_F_OR_R, 4, $1, $3, Nullarg); }
399 { $$ = make_op(O_AND, 2, $1, $3, Nullarg); }
401 { $$ = make_op(O_OR, 2, $1, $3, Nullarg); }
402 | sexpr '?' sexpr ':' sexpr
403 { $$ = make_op(O_COND_EXPR, 3, $1, $3, $5); }
405 { $$ = mod_match(O_MATCH, $1, $3); }
407 { $$ = mod_match(O_NMATCH, $1, $3); }
412 term : '-' term %prec UMINUS
413 { $$ = make_op(O_NEGATE, 1, $2, Nullarg, Nullarg); }
414 | '+' term %prec UMINUS
417 { $$ = make_op(O_NOT, 1, $2, Nullarg, Nullarg); }
419 { $$ = make_op(O_COMPLEMENT, 1, $2, Nullarg, Nullarg);}
421 { $$ = addflags(1, AF_POST|AF_UP,
422 l(make_op(O_ITEM,1,$1,Nullarg,Nullarg))); }
424 { $$ = addflags(1, AF_POST,
425 l(make_op(O_ITEM,1,$1,Nullarg,Nullarg))); }
427 { $$ = addflags(1, AF_PRE|AF_UP,
428 l(make_op(O_ITEM,1,$2,Nullarg,Nullarg))); }
430 { $$ = addflags(1, AF_PRE,
431 l(make_op(O_ITEM,1,$2,Nullarg,Nullarg))); }
433 { opargs[$1] = 0; /* force it special */
435 stab2arg(A_STAB,stabent($2,TRUE)),
440 $$ = make_op($1, 1, $2, Nullarg, Nullarg); }
442 { opargs[$1] = ($1 != O_FTTTY);
445 $1 == O_FTTTY?stabent("STDIN",TRUE):defstab),
448 { $$ = l(localize(make_op(O_ASSIGN, 1,
449 localize(listish(make_list($3))),
450 Nullarg,Nullarg))); }
452 { $$ = make_list(hide_ary($2)); }
454 { $$ = make_list(hide_ary($2)); }
456 { $$ = make_list(Nullarg); }
457 | DO sexpr %prec FILETEST
459 make_op(O_DOFILE,2,$2,Nullarg,Nullarg) );
462 { $$ = cmd_to_arg($2); }
464 { $$ = stab2arg(A_STAB,$1); }
466 { $$ = stab2arg(A_STAR,$1); }
467 | REG '[' expr ']' %prec '('
468 { $$ = make_op(O_AELEM, 2,
469 stab2arg(A_STAB,aadd($1)), $3, Nullarg); }
471 { $$ = make_op(O_HASH, 1,
475 { $$ = make_op(O_ARRAY, 1,
478 | REG '{' expr '}' %prec '('
479 { $$ = make_op(O_HELEM, 2,
480 stab2arg(A_STAB,hadd($1)),
483 | '(' expr ')' '[' expr ']' %prec '('
484 { $$ = make_op(O_LSLICE, 3,
486 listish(make_list($5)),
487 listish(make_list($2))); }
488 | ARY '[' expr ']' %prec '('
489 { $$ = make_op(O_ASLICE, 2,
490 stab2arg(A_STAB,aadd($1)),
491 listish(make_list($3)),
493 | ARY '{' expr '}' %prec '('
494 { $$ = make_op(O_HSLICE, 2,
495 stab2arg(A_STAB,hadd($1)),
496 listish(make_list($3)),
498 | DELETE REG '{' expr '}' %prec '('
499 { $$ = make_op(O_DELETE, 2,
500 stab2arg(A_STAB,hadd($2)),
504 { $$ = stab2arg(A_ARYLEN,$1); }
513 | DO WORD '(' expr ')'
514 { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
515 stab2arg(A_WORD,stabent($2,TRUE)),
517 Nullarg); Safefree($2); }
518 | AMPER WORD '(' expr ')'
519 { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
520 stab2arg(A_WORD,stabent($2,TRUE)),
522 Nullarg); Safefree($2); }
524 { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
525 stab2arg(A_WORD,stabent($2,TRUE)),
529 { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
530 stab2arg(A_WORD,stabent($2,TRUE)),
534 { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
535 stab2arg(A_WORD,stabent($2,TRUE)),
538 | DO REG '(' expr ')'
539 { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
543 | AMPER REG '(' expr ')'
544 { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
549 { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
554 { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
559 { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
564 { $$ = make_op($1,0,Nullarg,Nullarg,Nullarg); }
566 { $$ = make_op($1,1,cval_to_arg($2),
569 { $$ = make_op($1,0,Nullarg,Nullarg,Nullarg);
570 if ($1 == O_EVAL || $1 == O_RESET)
573 { $$ = make_op($1,1,$2,Nullarg,Nullarg);
574 if ($1 == O_EVAL || $1 == O_RESET)
577 { $$ = make_op(O_SELECT, 0, Nullarg, Nullarg, Nullarg);}
578 | SELECT '(' handle ')'
579 { $$ = make_op(O_SELECT, 1, $3, Nullarg, Nullarg); }
580 | SELECT '(' sexpr csexpr csexpr csexpr ')'
582 $$ = make_op(O_SSELECT, 4, $3, $4, $5); }
583 | OPEN WORD %prec '('
584 { $$ = make_op(O_OPEN, 2,
585 stab2arg(A_WORD,stabent($2,TRUE)),
586 stab2arg(A_STAB,stabent($2,TRUE)),
589 { $$ = make_op(O_OPEN, 2,
590 stab2arg(A_WORD,stabent($3,TRUE)),
591 stab2arg(A_STAB,stabent($3,TRUE)),
593 | OPEN '(' handle cexpr ')'
594 { $$ = make_op(O_OPEN, 2,
597 | FILOP '(' handle ')'
598 { $$ = make_op($1, 1,
602 { $$ = make_op($1, 1,
603 stab2arg(A_WORD,stabent($2,TRUE)),
607 { $$ = make_op($1, 1,
611 { $$ = make_op($1, 1,
612 stab2arg(A_WORD,Nullstab),
615 { $$ = make_op($1, 0,
616 Nullarg, Nullarg, Nullarg); }
617 | FILOP2 '(' handle cexpr ')'
618 { $$ = make_op($1, 2, $3, $4, Nullarg); }
619 | FILOP3 '(' handle csexpr cexpr ')'
620 { $$ = make_op($1, 3, $3, $4, make_list($5)); }
621 | FILOP22 '(' handle ',' handle ')'
622 { $$ = make_op($1, 2, $3, $5, Nullarg); }
623 | FILOP4 '(' handle csexpr csexpr cexpr ')'
624 { arg4 = $6; $$ = make_op($1, 4, $3, $4, $5); }
625 | FILOP25 '(' handle ',' handle csexpr csexpr cexpr ')'
626 { arg4 = $7; arg5 = $8;
627 $$ = make_op($1, 5, $3, $5, $6); }
628 | PUSH '(' aryword cexpr ')'
629 { $$ = make_op($1, 2,
633 | POP aryword %prec '('
634 { $$ = make_op(O_POP, 1, $2, Nullarg, Nullarg); }
635 | POP '(' aryword ')'
636 { $$ = make_op(O_POP, 1, $3, Nullarg, Nullarg); }
637 | SHIFT aryword %prec '('
638 { $$ = make_op(O_SHIFT, 1, $2, Nullarg, Nullarg); }
639 | SHIFT '(' aryword ')'
640 { $$ = make_op(O_SHIFT, 1, $3, Nullarg, Nullarg); }
642 { $$ = make_op(O_SHIFT, 1,
644 aadd(stabent(subline ? "_" : "ARGV", TRUE))),
647 { (void)scanpat("/\\s+/");
648 $$ = make_split(defstab,yylval.arg,Nullarg); }
649 | SPLIT '(' sexpr csexpr csexpr ')'
650 { $$ = mod_match(O_MATCH, $4,
651 make_split(defstab,$3,$5));}
652 | SPLIT '(' sexpr csexpr ')'
653 { $$ = mod_match(O_MATCH, $4,
654 make_split(defstab,$3,Nullarg) ); }
655 | SPLIT '(' sexpr ')'
656 { $$ = mod_match(O_MATCH,
657 stab2arg(A_STAB,defstab),
658 make_split(defstab,$3,Nullarg) ); }
659 | FLIST2 '(' sexpr cexpr ')'
660 { $$ = make_op($1, 2,
662 listish(make_list($4)),
665 { $$ = make_op($1, 1,
669 | LVALFUN sexpr %prec '('
670 { $$ = l(make_op($1, 1, fixl($1,$2),
671 Nullarg, Nullarg)); }
673 { $$ = l(make_op($1, 1,
674 stab2arg(A_STAB,defstab),
675 Nullarg, Nullarg)); }
677 { $$ = make_op($1, 0, Nullarg, Nullarg, Nullarg); }
679 { $$ = make_op($1, 0, Nullarg, Nullarg, Nullarg); }
681 { $$ = make_op($1, 0, Nullarg, Nullarg, Nullarg);
682 if ($1 == O_EVAL || $1 == O_RESET)
685 { $$ = make_op($1, 1, $3, Nullarg, Nullarg);
686 if ($1 == O_EVAL || $1 == O_RESET)
688 | FUNC2 '(' sexpr cexpr ')'
689 { $$ = make_op($1, 2, $3, $4, Nullarg);
690 if ($1 == O_INDEX && $$[2].arg_type == A_SINGLE)
691 fbmcompile($$[2].arg_ptr.arg_str,0); }
692 | FUNC3 '(' sexpr csexpr cexpr ')'
693 { $$ = make_op($1, 3, $3, $4, $5); }
694 | LFUNC4 '(' sexpr csexpr csexpr cexpr ')'
695 { arg4 = $6; $$ = make_op($1, 4, l($3), $4, $5); }
696 | HSHFUN '(' hshword ')'
697 { $$ = make_op($1, 1,
702 { $$ = make_op($1, 1,
706 | HSHFUN3 '(' hshword csexpr cexpr ')'
707 { $$ = make_op($1, 3, $3, $4, $5); }
713 stab2arg(A_WORD,Nullstab),
714 stab2arg(A_STAB,defstab),
718 stab2arg(A_WORD,Nullstab),
719 maybelistish($1,make_list($2)),
723 stab2arg(A_WORD,stabent($2,TRUE)),
724 stab2arg(A_STAB,defstab),
728 stab2arg(A_WORD,stabent($2,TRUE)),
729 maybelistish($1,make_list($3)),
730 Nullarg); Safefree($2); }
734 maybelistish($1,make_list($3)),
739 { $$ = stab2arg(A_WORD,stabent($1,TRUE)); Safefree($1);}
744 { $$ = stab2arg(A_WORD,aadd(stabent($1,TRUE)));
747 { $$ = stab2arg(A_STAB,$1); }
751 { $$ = stab2arg(A_WORD,hadd(stabent($1,TRUE)));
754 { $$ = stab2arg(A_STAB,$1); }