This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl 4.0 patch 16: patch #11, continued
[perl5.git] / perly.y
1 /* $RCSfile: perly.y,v $$Revision: 4.0.1.2 $$Date: 91/11/05 18:17:38 $
2  *
3  *    Copyright (c) 1991, 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  * $Log:        perly.y,v $
9  * Revision 4.0.1.2  91/11/05  18:17:38  lwall
10  * patch11: extra comma at end of list is now allowed in more places (Hi, Felix!)
11  * patch11: once-thru blocks didn't display right in the debugger
12  * patch11: debugger got confused over nested subroutine definitions
13  * 
14  * Revision 4.0.1.1  91/06/07  11:42:34  lwall
15  * patch4: new copyright notice
16  * 
17  * Revision 4.0  91/03/20  01:38:40  lwall
18  * 4.0 baseline.
19  * 
20  */
21
22 %{
23 #include "INTERN.h"
24 #include "perl.h"
25
26 /*SUPPRESS 530*/
27 /*SUPPRESS 593*/
28 /*SUPPRESS 595*/
29
30 STAB *scrstab;
31 ARG *arg4;      /* rarely used arguments to make_op() */
32 ARG *arg5;
33
34 %}
35
36 %start prog
37
38 %union {
39     int ival;
40     char *cval;
41     ARG *arg;
42     CMD *cmdval;
43     struct compcmd compval;
44     STAB *stabval;
45     FCMD *formval;
46 }
47
48 %token <ival> '{' ')'
49
50 %token <cval> WORD
51 %token <ival> APPEND OPEN SSELECT LOOPEX
52 %token <ival> USING FORMAT DO SHIFT PUSH POP LVALFUN
53 %token <ival> WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE SPLIT FLIST
54 %token <ival> FOR FILOP FILOP2 FILOP3 FILOP4 FILOP22 FILOP25
55 %token <ival> FUNC0 FUNC1 FUNC2 FUNC2x FUNC3 FUNC4 FUNC5 HSHFUN HSHFUN3
56 %token <ival> FLIST2 SUB FILETEST LOCAL DELETE
57 %token <ival> RELOP EQOP MULOP ADDOP PACKAGE AMPER
58 %token <formval> FORMLIST
59 %token <stabval> REG ARYLEN ARY HSH STAR
60 %token <arg> SUBST PATTERN
61 %token <arg> RSTRING TRANS
62
63 %type <ival> prog decl format remember crp
64 %type <cmdval> block lineseq line loop cond sideff nexpr else
65 %type <arg> expr sexpr cexpr csexpr term handle aryword hshword
66 %type <arg> texpr listop bareword
67 %type <cval> label
68 %type <compval> compblock
69
70 %nonassoc <ival> LISTOP
71 %left ','
72 %right '='
73 %right '?' ':'
74 %nonassoc DOTDOT
75 %left OROR
76 %left ANDAND
77 %left '|' '^'
78 %left '&'
79 %nonassoc EQOP
80 %nonassoc RELOP
81 %nonassoc <ival> UNIOP
82 %nonassoc FILETEST
83 %left LS RS
84 %left ADDOP
85 %left MULOP
86 %left MATCH NMATCH 
87 %right '!' '~' UMINUS
88 %right POW
89 %nonassoc INC DEC
90 %left '('
91
92 %% /* RULES */
93
94 prog    :       /* NULL */
95                 {
96 #if defined(YYDEBUG) && defined(DEBUGGING)
97                     yydebug = (debug & 1);
98 #endif
99                 }
100         /*CONTINUED*/   lineseq
101                         { if (in_eval)
102                                 eval_root = block_head($2);
103                             else
104                                 main_root = block_head($2); }
105         ;
106
107 compblock:      block CONTINUE block
108                         { $$.comp_true = $1; $$.comp_alt = $3; }
109         |       block else
110                         { $$.comp_true = $1; $$.comp_alt = $2; }
111         ;
112
113 else    :       /* NULL */
114                         { $$ = Nullcmd; }
115         |       ELSE block
116                         { $$ = $2; }
117         |       ELSIF '(' expr ')' compblock
118                         { cmdline = $1;
119                             $$ = make_ccmd(C_ELSIF,$3,$5); }
120         ;
121
122 block   :       '{' remember lineseq '}'
123                         { $$ = block_head($3);
124                           if (cmdline > $1)
125                               cmdline = $1;
126                           if (savestack->ary_fill > $2)
127                             restorelist($2); }
128         ;
129
130 remember:       /* NULL */      /* in case they push a package name */
131                         { $$ = savestack->ary_fill; }
132         ;
133
134 lineseq :       /* NULL */
135                         { $$ = Nullcmd; }
136         |       lineseq line
137                         { $$ = append_line($1,$2); }
138         ;
139
140 line    :       decl
141                         { $$ = Nullcmd; }
142         |       label cond
143                         { $$ = add_label($1,$2); }
144         |       loop    /* loops add their own labels */
145         |       label ';'
146                         { if ($1 != Nullch) {
147                               $$ = add_label($1, make_acmd(C_EXPR, Nullstab,
148                                   Nullarg, Nullarg) );
149                             }
150                             else {
151                               $$ = Nullcmd;
152                               cmdline = NOLINE;
153                             } }
154         |       label sideff ';'
155                         { $$ = add_label($1,$2); }
156         ;
157
158 sideff  :       error
159                         { $$ = Nullcmd; }
160         |       expr
161                         { $$ = make_acmd(C_EXPR, Nullstab, $1, Nullarg); }
162         |       expr IF expr
163                         { $$ = addcond(
164                                make_acmd(C_EXPR, Nullstab, Nullarg, $1), $3); }
165         |       expr UNLESS expr
166                         { $$ = addcond(invert(
167                                make_acmd(C_EXPR, Nullstab, Nullarg, $1)), $3); }
168         |       expr WHILE expr
169                         { $$ = addloop(
170                                make_acmd(C_EXPR, Nullstab, Nullarg, $1), $3); }
171         |       expr UNTIL expr
172                         { $$ = addloop(invert(
173                                make_acmd(C_EXPR, Nullstab, Nullarg, $1)), $3); }
174         ;
175
176 cond    :       IF '(' expr ')' compblock
177                         { cmdline = $1;
178                             $$ = make_icmd(C_IF,$3,$5); }
179         |       UNLESS '(' expr ')' compblock
180                         { cmdline = $1;
181                             $$ = invert(make_icmd(C_IF,$3,$5)); }
182         |       IF block compblock
183                         { cmdline = $1;
184                             $$ = make_ccmd(C_IF,cmd_to_arg($2),$3); }
185         |       UNLESS block compblock
186                         { cmdline = $1;
187                             $$ = invert(make_ccmd(C_IF,cmd_to_arg($2),$3)); }
188         ;
189
190 loop    :       label WHILE '(' texpr ')' compblock
191                         { cmdline = $2;
192                             $$ = wopt(add_label($1,
193                             make_ccmd(C_WHILE,$4,$6) )); }
194         |       label UNTIL '(' expr ')' compblock
195                         { cmdline = $2;
196                             $$ = wopt(add_label($1,
197                             invert(make_ccmd(C_WHILE,$4,$6)) )); }
198         |       label WHILE block compblock
199                         { cmdline = $2;
200                             $$ = wopt(add_label($1,
201                             make_ccmd(C_WHILE, cmd_to_arg($3),$4) )); }
202         |       label UNTIL block compblock
203                         { cmdline = $2;
204                             $$ = wopt(add_label($1,
205                             invert(make_ccmd(C_WHILE, cmd_to_arg($3),$4)) )); }
206         |       label FOR REG '(' expr crp compblock
207                         { cmdline = $2;
208                             /*
209                              * The following gobbledygook catches EXPRs that
210                              * aren't explicit array refs and translates
211                              *          foreach VAR (EXPR) {
212                              * into
213                              *          @ary = EXPR;
214                              *          foreach VAR (@ary) {
215                              * where @ary is a hidden array made by genstab().
216                              * (Note that @ary may become a local array if
217                              * it is determined that it might be called
218                              * recursively.  See cmd_tosave().)
219                              */
220                             if ($5->arg_type != O_ARRAY) {
221                                 scrstab = aadd(genstab());
222                                 $$ = append_line(
223                                     make_acmd(C_EXPR, Nullstab,
224                                       l(make_op(O_ASSIGN,2,
225                                         listish(make_op(O_ARRAY, 1,
226                                           stab2arg(A_STAB,scrstab),
227                                           Nullarg,Nullarg )),
228                                         listish(make_list($5)),
229                                         Nullarg)),
230                                       Nullarg),
231                                     wopt(over($3,add_label($1,
232                                       make_ccmd(C_WHILE,
233                                         make_op(O_ARRAY, 1,
234                                           stab2arg(A_STAB,scrstab),
235                                           Nullarg,Nullarg ),
236                                         $7)))));
237                                 $$->c_line = $2;
238                                 $$->c_head->c_line = $2;
239                             }
240                             else {
241                                 $$ = wopt(over($3,add_label($1,
242                                 make_ccmd(C_WHILE,$5,$7) )));
243                             }
244                         }
245         |       label FOR '(' expr crp compblock
246                         { cmdline = $2;
247                             if ($4->arg_type != O_ARRAY) {
248                                 scrstab = aadd(genstab());
249                                 $$ = append_line(
250                                     make_acmd(C_EXPR, Nullstab,
251                                       l(make_op(O_ASSIGN,2,
252                                         listish(make_op(O_ARRAY, 1,
253                                           stab2arg(A_STAB,scrstab),
254                                           Nullarg,Nullarg )),
255                                         listish(make_list($4)),
256                                         Nullarg)),
257                                       Nullarg),
258                                     wopt(over(defstab,add_label($1,
259                                       make_ccmd(C_WHILE,
260                                         make_op(O_ARRAY, 1,
261                                           stab2arg(A_STAB,scrstab),
262                                           Nullarg,Nullarg ),
263                                         $6)))));
264                                 $$->c_line = $2;
265                                 $$->c_head->c_line = $2;
266                             }
267                             else {      /* lisp, anyone? */
268                                 $$ = wopt(over(defstab,add_label($1,
269                                 make_ccmd(C_WHILE,$4,$6) )));
270                             }
271                         }
272         |       label FOR '(' nexpr ';' texpr ';' nexpr ')' block
273                         /* basically fake up an initialize-while lineseq */
274                         {   yyval.compval.comp_true = $10;
275                             yyval.compval.comp_alt = $8;
276                             cmdline = $2;
277                             $$ = append_line($4,wopt(add_label($1,
278                                 make_ccmd(C_WHILE,$6,yyval.compval) ))); }
279         |       label compblock /* a block is a loop that happens once */
280                         { $$ = add_label($1,make_ccmd(C_BLOCK,Nullarg,$2)); }
281         ;
282
283 nexpr   :       /* NULL */
284                         { $$ = Nullcmd; }
285         |       sideff
286         ;
287
288 texpr   :       /* NULL means true */
289                         { (void)scanstr("1"); $$ = yylval.arg; }
290         |       expr
291         ;
292
293 label   :       /* empty */
294                         { $$ = Nullch; }
295         |       WORD ':'
296         ;
297
298 decl    :       format
299                         { $$ = 0; }
300         |       subrout
301                         { $$ = 0; }
302         |       package
303                         { $$ = 0; }
304         ;
305
306 format  :       FORMAT WORD '=' FORMLIST
307                         { if (strEQ($2,"stdout"))
308                             make_form(stabent("STDOUT",TRUE),$4);
309                           else if (strEQ($2,"stderr"))
310                             make_form(stabent("STDERR",TRUE),$4);
311                           else
312                             make_form(stabent($2,TRUE),$4);
313                           Safefree($2); $2 = Nullch; }
314         |       FORMAT '=' FORMLIST
315                         { make_form(stabent("STDOUT",TRUE),$3); }
316         ;
317
318 subrout :       SUB WORD block
319                         { make_sub($2,$3);
320                           cmdline = NOLINE;
321                           if (savestack->ary_fill > $1)
322                             restorelist($1); }
323         ;
324
325 package :       PACKAGE WORD ';'
326                         { char tmpbuf[256];
327                           STAB *tmpstab;
328
329                           savehptr(&curstash);
330                           saveitem(curstname);
331                           str_set(curstname,$2);
332                           sprintf(tmpbuf,"'_%s",$2);
333                           tmpstab = stabent(tmpbuf,TRUE);
334                           if (!stab_xhash(tmpstab))
335                               stab_xhash(tmpstab) = hnew(0);
336                           curstash = stab_xhash(tmpstab);
337                           if (!curstash->tbl_name)
338                               curstash->tbl_name = savestr($2);
339                           curstash->tbl_coeffsize = 0;
340                           Safefree($2); $2 = Nullch;
341                           cmdline = NOLINE;
342                         }
343         ;
344
345 cexpr   :       ',' expr
346                         { $$ = $2; }
347         ;
348
349 expr    :       expr ',' sexpr
350                         { $$ = make_op(O_COMMA, 2, $1, $3, Nullarg); }
351         |       sexpr
352         ;
353
354 csexpr  :       ',' sexpr
355                         { $$ = $2; }
356         ;
357
358 sexpr   :       sexpr '=' sexpr
359                         {   $1 = listish($1);
360                             if ($1->arg_type == O_ASSIGN && $1->arg_len == 1)
361                                 $1->arg_type = O_ITEM;  /* a local() */
362                             if ($1->arg_type == O_LIST)
363                                 $3 = listish($3);
364                             $$ = l(make_op(O_ASSIGN, 2, $1, $3, Nullarg)); }
365         |       sexpr POW '=' sexpr
366                         { $$ = l(make_op(O_POW, 2, $1, $4, Nullarg)); }
367         |       sexpr MULOP '=' sexpr
368                         { $$ = l(make_op($2, 2, $1, $4, Nullarg)); }
369         |       sexpr ADDOP '=' sexpr
370                         { $$ = rcatmaybe(l(make_op($2, 2, $1, $4, Nullarg)));}
371         |       sexpr LS '=' sexpr
372                         { $$ = l(make_op(O_LEFT_SHIFT, 2, $1, $4, Nullarg)); }
373         |       sexpr RS '=' sexpr
374                         { $$ = l(make_op(O_RIGHT_SHIFT, 2, $1, $4, Nullarg)); }
375         |       sexpr '&' '=' sexpr
376                         { $$ = l(make_op(O_BIT_AND, 2, $1, $4, Nullarg)); }
377         |       sexpr '^' '=' sexpr
378                         { $$ = l(make_op(O_XOR, 2, $1, $4, Nullarg)); }
379         |       sexpr '|' '=' sexpr
380                         { $$ = l(make_op(O_BIT_OR, 2, $1, $4, Nullarg)); }
381
382
383         |       sexpr POW sexpr
384                         { $$ = make_op(O_POW, 2, $1, $3, Nullarg); }
385         |       sexpr MULOP sexpr
386                         { if ($2 == O_REPEAT)
387                               $1 = listish($1);
388                             $$ = make_op($2, 2, $1, $3, Nullarg);
389                             if ($2 == O_REPEAT) {
390                                 if ($$[1].arg_type != A_EXPR ||
391                                   $$[1].arg_ptr.arg_arg->arg_type != O_LIST)
392                                     $$[1].arg_flags &= ~AF_ARYOK;
393                             } }
394         |       sexpr ADDOP sexpr
395                         { $$ = make_op($2, 2, $1, $3, Nullarg); }
396         |       sexpr LS sexpr
397                         { $$ = make_op(O_LEFT_SHIFT, 2, $1, $3, Nullarg); }
398         |       sexpr RS sexpr
399                         { $$ = make_op(O_RIGHT_SHIFT, 2, $1, $3, Nullarg); }
400         |       sexpr RELOP sexpr
401                         { $$ = make_op($2, 2, $1, $3, Nullarg); }
402         |       sexpr EQOP sexpr
403                         { $$ = make_op($2, 2, $1, $3, Nullarg); }
404         |       sexpr '&' sexpr
405                         { $$ = make_op(O_BIT_AND, 2, $1, $3, Nullarg); }
406         |       sexpr '^' sexpr
407                         { $$ = make_op(O_XOR, 2, $1, $3, Nullarg); }
408         |       sexpr '|' sexpr
409                         { $$ = make_op(O_BIT_OR, 2, $1, $3, Nullarg); }
410         |       sexpr DOTDOT sexpr
411                         { arg4 = Nullarg;
412                           $$ = make_op(O_F_OR_R, 4, $1, $3, Nullarg); }
413         |       sexpr ANDAND sexpr
414                         { $$ = make_op(O_AND, 2, $1, $3, Nullarg); }
415         |       sexpr OROR sexpr
416                         { $$ = make_op(O_OR, 2, $1, $3, Nullarg); }
417         |       sexpr '?' sexpr ':' sexpr
418                         { $$ = make_op(O_COND_EXPR, 3, $1, $3, $5); }
419         |       sexpr MATCH sexpr
420                         { $$ = mod_match(O_MATCH, $1, $3); }
421         |       sexpr NMATCH sexpr
422                         { $$ = mod_match(O_NMATCH, $1, $3); }
423         |       term
424                         { $$ = $1; }
425         ;
426
427 term    :       '-' term %prec UMINUS
428                         { $$ = make_op(O_NEGATE, 1, $2, Nullarg, Nullarg); }
429         |       '+' term %prec UMINUS
430                         { $$ = $2; }
431         |       '!' term
432                         { $$ = make_op(O_NOT, 1, $2, Nullarg, Nullarg); }
433         |       '~' term
434                         { $$ = make_op(O_COMPLEMENT, 1, $2, Nullarg, Nullarg);}
435         |       term INC
436                         { $$ = addflags(1, AF_POST|AF_UP,
437                             l(make_op(O_ITEM,1,$1,Nullarg,Nullarg))); }
438         |       term DEC
439                         { $$ = addflags(1, AF_POST,
440                             l(make_op(O_ITEM,1,$1,Nullarg,Nullarg))); }
441         |       INC term
442                         { $$ = addflags(1, AF_PRE|AF_UP,
443                             l(make_op(O_ITEM,1,$2,Nullarg,Nullarg))); }
444         |       DEC term
445                         { $$ = addflags(1, AF_PRE,
446                             l(make_op(O_ITEM,1,$2,Nullarg,Nullarg))); }
447         |       FILETEST WORD
448                         { opargs[$1] = 0;       /* force it special */
449                             $$ = make_op($1, 1,
450                                 stab2arg(A_STAB,stabent($2,TRUE)),
451                                 Nullarg, Nullarg);
452                         }
453         |       FILETEST sexpr
454                         { opargs[$1] = 1;
455                             $$ = make_op($1, 1, $2, Nullarg, Nullarg); }
456         |       FILETEST
457                         { opargs[$1] = ($1 != O_FTTTY);
458                             $$ = make_op($1, 1,
459                                 stab2arg(A_STAB,
460                                   $1 == O_FTTTY?stabent("STDIN",TRUE):defstab),
461                                 Nullarg, Nullarg); }
462         |       LOCAL '(' expr crp
463                         { $$ = l(localize(make_op(O_ASSIGN, 1,
464                                 localize(listish(make_list($3))),
465                                 Nullarg,Nullarg))); }
466         |       '(' expr crp
467                         { $$ = make_list($2); }
468         |       '(' ')'
469                         { $$ = make_list(Nullarg); }
470         |       DO sexpr        %prec FILETEST
471                         { $$ = make_op(O_DOFILE,2,$2,Nullarg,Nullarg);
472                           allstabs = TRUE;}
473         |       DO block        %prec '('
474                         { $$ = cmd_to_arg($2); }
475         |       REG     %prec '('
476                         { $$ = stab2arg(A_STAB,$1); }
477         |       STAR    %prec '('
478                         { $$ = stab2arg(A_STAR,$1); }
479         |       REG '[' expr ']'        %prec '('
480                         { $$ = make_op(O_AELEM, 2,
481                                 stab2arg(A_STAB,aadd($1)), $3, Nullarg); }
482         |       HSH     %prec '('
483                         { $$ = make_op(O_HASH, 1,
484                                 stab2arg(A_STAB,$1),
485                                 Nullarg, Nullarg); }
486         |       ARY     %prec '('
487                         { $$ = make_op(O_ARRAY, 1,
488                                 stab2arg(A_STAB,$1),
489                                 Nullarg, Nullarg); }
490         |       REG '{' expr '}'        %prec '('
491                         { $$ = make_op(O_HELEM, 2,
492                                 stab2arg(A_STAB,hadd($1)),
493                                 jmaybe($3),
494                                 Nullarg); }
495         |       '(' expr crp '[' expr ']'       %prec '('
496                         { $$ = make_op(O_LSLICE, 3,
497                                 Nullarg,
498                                 listish(make_list($5)),
499                                 listish(make_list($2))); }
500         |       '(' ')' '[' expr ']'    %prec '('
501                         { $$ = make_op(O_LSLICE, 3,
502                                 Nullarg,
503                                 listish(make_list($4)),
504                                 Nullarg); }
505         |       ARY '[' expr ']'        %prec '('
506                         { $$ = make_op(O_ASLICE, 2,
507                                 stab2arg(A_STAB,aadd($1)),
508                                 listish(make_list($3)),
509                                 Nullarg); }
510         |       ARY '{' expr '}'        %prec '('
511                         { $$ = make_op(O_HSLICE, 2,
512                                 stab2arg(A_STAB,hadd($1)),
513                                 listish(make_list($3)),
514                                 Nullarg); }
515         |       DELETE REG '{' expr '}' %prec '('
516                         { $$ = make_op(O_DELETE, 2,
517                                 stab2arg(A_STAB,hadd($2)),
518                                 jmaybe($4),
519                                 Nullarg); }
520         |       ARYLEN  %prec '('
521                         { $$ = stab2arg(A_ARYLEN,$1); }
522         |       RSTRING %prec '('
523                         { $$ = $1; }
524         |       PATTERN %prec '('
525                         { $$ = $1; }
526         |       SUBST   %prec '('
527                         { $$ = $1; }
528         |       TRANS   %prec '('
529                         { $$ = $1; }
530         |       DO WORD '(' expr crp
531                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
532                                 stab2arg(A_WORD,stabent($2,MULTI)),
533                                 make_list($4),
534                                 Nullarg); Safefree($2); $2 = Nullch;
535                             $$->arg_flags |= AF_DEPR; }
536         |       AMPER WORD '(' expr crp
537                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
538                                 stab2arg(A_WORD,stabent($2,MULTI)),
539                                 make_list($4),
540                                 Nullarg); Safefree($2); $2 = Nullch; }
541         |       DO WORD '(' ')'
542                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
543                                 stab2arg(A_WORD,stabent($2,MULTI)),
544                                 make_list(Nullarg),
545                                 Nullarg);
546                             $$->arg_flags |= AF_DEPR; }
547         |       AMPER WORD '(' ')'
548                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
549                                 stab2arg(A_WORD,stabent($2,MULTI)),
550                                 make_list(Nullarg),
551                                 Nullarg); }
552         |       AMPER WORD
553                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
554                                 stab2arg(A_WORD,stabent($2,MULTI)),
555                                 Nullarg,
556                                 Nullarg); }
557         |       DO REG '(' expr crp
558                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
559                                 stab2arg(A_STAB,$2),
560                                 make_list($4),
561                                 Nullarg);
562                             $$->arg_flags |= AF_DEPR; }
563         |       AMPER REG '(' expr crp
564                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
565                                 stab2arg(A_STAB,$2),
566                                 make_list($4),
567                                 Nullarg); }
568         |       DO REG '(' ')'
569                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
570                                 stab2arg(A_STAB,$2),
571                                 make_list(Nullarg),
572                                 Nullarg);
573                             $$->arg_flags |= AF_DEPR; }
574         |       AMPER REG '(' ')'
575                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
576                                 stab2arg(A_STAB,$2),
577                                 make_list(Nullarg),
578                                 Nullarg); }
579         |       AMPER REG
580                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
581                                 stab2arg(A_STAB,$2),
582                                 Nullarg,
583                                 Nullarg); }
584         |       LOOPEX
585                         { $$ = make_op($1,0,Nullarg,Nullarg,Nullarg); }
586         |       LOOPEX WORD
587                         { $$ = make_op($1,1,cval_to_arg($2),
588                             Nullarg,Nullarg); }
589         |       UNIOP
590                         { $$ = make_op($1,0,Nullarg,Nullarg,Nullarg); }
591         |       UNIOP block
592                         { $$ = make_op($1,1,cmd_to_arg($2),Nullarg,Nullarg); }
593         |       UNIOP sexpr
594                         { $$ = make_op($1,1,$2,Nullarg,Nullarg); }
595         |       SSELECT
596                         { $$ = make_op(O_SELECT, 0, Nullarg, Nullarg, Nullarg);}
597         |       SSELECT  WORD
598                         { $$ = make_op(O_SELECT, 1,
599                             stab2arg(A_WORD,stabent($2,TRUE)),
600                             Nullarg,
601                             Nullarg);
602                             Safefree($2); $2 = Nullch; }
603         |       SSELECT '(' handle ')'
604                         { $$ = make_op(O_SELECT, 1, $3, Nullarg, Nullarg); }
605         |       SSELECT '(' sexpr csexpr csexpr csexpr ')'
606                         { arg4 = $6;
607                           $$ = make_op(O_SSELECT, 4, $3, $4, $5); }
608         |       OPEN WORD       %prec '('
609                         { $$ = make_op(O_OPEN, 2,
610                             stab2arg(A_WORD,stabent($2,TRUE)),
611                             stab2arg(A_STAB,stabent($2,TRUE)),
612                             Nullarg); }
613         |       OPEN '(' WORD ')'
614                         { $$ = make_op(O_OPEN, 2,
615                             stab2arg(A_WORD,stabent($3,TRUE)),
616                             stab2arg(A_STAB,stabent($3,TRUE)),
617                             Nullarg); }
618         |       OPEN '(' handle cexpr ')'
619                         { $$ = make_op(O_OPEN, 2,
620                             $3,
621                             $4, Nullarg); }
622         |       FILOP '(' handle ')'
623                         { $$ = make_op($1, 1,
624                             $3,
625                             Nullarg, Nullarg); }
626         |       FILOP WORD
627                         { $$ = make_op($1, 1,
628                             stab2arg(A_WORD,stabent($2,TRUE)),
629                             Nullarg, Nullarg);
630                           Safefree($2); $2 = Nullch; }
631         |       FILOP REG
632                         { $$ = make_op($1, 1,
633                             stab2arg(A_STAB,$2),
634                             Nullarg, Nullarg); }
635         |       FILOP '(' ')'
636                         { $$ = make_op($1, 1,
637                             stab2arg(A_WORD,Nullstab),
638                             Nullarg, Nullarg); }
639         |       FILOP   %prec '('
640                         { $$ = make_op($1, 0,
641                             Nullarg, Nullarg, Nullarg); }
642         |       FILOP2 '(' handle cexpr ')'
643                         { $$ = make_op($1, 2, $3, $4, Nullarg); }
644         |       FILOP3 '(' handle csexpr cexpr ')'
645                         { $$ = make_op($1, 3, $3, $4, make_list($5)); }
646         |       FILOP22 '(' handle ',' handle ')'
647                         { $$ = make_op($1, 2, $3, $5, Nullarg); }
648         |       FILOP4 '(' handle csexpr csexpr cexpr ')'
649                         { arg4 = $6; $$ = make_op($1, 4, $3, $4, $5); }
650         |       FILOP25 '(' handle ',' handle csexpr csexpr cexpr ')'
651                         { arg4 = $7; arg5 = $8;
652                           $$ = make_op($1, 5, $3, $5, $6); }
653         |       PUSH '(' aryword ',' expr crp
654                         { $$ = make_op($1, 2,
655                             $3,
656                             make_list($5),
657                             Nullarg); }
658         |       POP aryword     %prec '('
659                         { $$ = make_op(O_POP, 1, $2, Nullarg, Nullarg); }
660         |       POP '(' aryword ')'
661                         { $$ = make_op(O_POP, 1, $3, Nullarg, Nullarg); }
662         |       SHIFT aryword   %prec '('
663                         { $$ = make_op(O_SHIFT, 1, $2, Nullarg, Nullarg); }
664         |       SHIFT '(' aryword ')'
665                         { $$ = make_op(O_SHIFT, 1, $3, Nullarg, Nullarg); }
666         |       SHIFT   %prec '('
667                         { $$ = make_op(O_SHIFT, 1,
668                             stab2arg(A_STAB,
669                               aadd(stabent(subline ? "_" : "ARGV", TRUE))),
670                             Nullarg, Nullarg); }
671         |       SPLIT   %prec '('
672                         {   static char p[]="/\\s+/";
673                             char *oldend = bufend;
674                             ARG *oldarg = yylval.arg;
675                             
676                             bufend=p+5;
677                             (void)scanpat(p);
678                             bufend=oldend;
679                             $$ = make_split(defstab,yylval.arg,Nullarg);
680                             yylval.arg = oldarg; }
681         |       SPLIT '(' sexpr csexpr csexpr ')'
682                         { $$ = mod_match(O_MATCH, $4,
683                           make_split(defstab,$3,$5));}
684         |       SPLIT '(' sexpr csexpr ')'
685                         { $$ = mod_match(O_MATCH, $4,
686                           make_split(defstab,$3,Nullarg) ); }
687         |       SPLIT '(' sexpr ')'
688                         { $$ = mod_match(O_MATCH,
689                             stab2arg(A_STAB,defstab),
690                             make_split(defstab,$3,Nullarg) ); }
691         |       FLIST2 '(' sexpr cexpr ')'
692                         { $$ = make_op($1, 2,
693                             $3,
694                             listish(make_list($4)),
695                             Nullarg); }
696         |       FLIST '(' expr crp
697                         { $$ = make_op($1, 1,
698                             make_list($3),
699                             Nullarg,
700                             Nullarg); }
701         |       LVALFUN sexpr   %prec '('
702                         { $$ = l(make_op($1, 1, fixl($1,$2),
703                             Nullarg, Nullarg)); }
704         |       LVALFUN
705                         { $$ = l(make_op($1, 1,
706                             stab2arg(A_STAB,defstab),
707                             Nullarg, Nullarg)); }
708         |       FUNC0
709                         { $$ = make_op($1, 0, Nullarg, Nullarg, Nullarg); }
710         |       FUNC0 '(' ')'
711                         { $$ = make_op($1, 0, Nullarg, Nullarg, Nullarg); }
712         |       FUNC1 '(' ')'
713                         { $$ = make_op($1, 0, Nullarg, Nullarg, Nullarg); }
714         |       FUNC1 '(' expr ')'
715                         { $$ = make_op($1, 1, $3, Nullarg, Nullarg); }
716         |       FUNC2 '(' sexpr cexpr ')'
717                         { $$ = make_op($1, 2, $3, $4, Nullarg);
718                             if ($1 == O_INDEX && $$[2].arg_type == A_SINGLE)
719                                 fbmcompile($$[2].arg_ptr.arg_str,0); }
720         |       FUNC2x '(' sexpr csexpr ')'
721                         { $$ = make_op($1, 2, $3, $4, Nullarg);
722                             if ($1 == O_INDEX && $$[2].arg_type == A_SINGLE)
723                                 fbmcompile($$[2].arg_ptr.arg_str,0); }
724         |       FUNC2x '(' sexpr csexpr cexpr ')'
725                         { $$ = make_op($1, 3, $3, $4, $5);
726                             if ($1 == O_INDEX && $$[2].arg_type == A_SINGLE)
727                                 fbmcompile($$[2].arg_ptr.arg_str,0); }
728         |       FUNC3 '(' sexpr csexpr cexpr ')'
729                         { $$ = make_op($1, 3, $3, $4, $5); }
730         |       FUNC4 '(' sexpr csexpr csexpr cexpr ')'
731                         { arg4 = $6;
732                           $$ = make_op($1, 4, $3, $4, $5); }
733         |       FUNC5 '(' sexpr csexpr csexpr csexpr cexpr ')'
734                         { arg4 = $6; arg5 = $7;
735                           $$ = make_op($1, 5, $3, $4, $5); }
736         |       HSHFUN '(' hshword ')'
737                         { $$ = make_op($1, 1,
738                                 $3,
739                                 Nullarg,
740                                 Nullarg); }
741         |       HSHFUN hshword
742                         { $$ = make_op($1, 1,
743                                 $2,
744                                 Nullarg,
745                                 Nullarg); }
746         |       HSHFUN3 '(' hshword csexpr cexpr ')'
747                         { $$ = make_op($1, 3, $3, $4, $5); }
748         |       bareword
749         |       listop
750         ;
751
752 listop  :       LISTOP
753                         { $$ = make_op($1,2,
754                                 stab2arg(A_WORD,Nullstab),
755                                 stab2arg(A_STAB,defstab),
756                                 Nullarg); }
757         |       LISTOP expr
758                         { $$ = make_op($1,2,
759                                 stab2arg(A_WORD,Nullstab),
760                                 maybelistish($1,make_list($2)),
761                                 Nullarg); }
762         |       LISTOP WORD
763                         { $$ = make_op($1,2,
764                                 stab2arg(A_WORD,stabent($2,TRUE)),
765                                 stab2arg(A_STAB,defstab),
766                                 Nullarg); }
767         |       LISTOP WORD expr
768                         { $$ = make_op($1,2,
769                                 stab2arg(A_WORD,stabent($2,TRUE)),
770                                 maybelistish($1,make_list($3)),
771                                 Nullarg); Safefree($2); $2 = Nullch; }
772         |       LISTOP REG expr
773                         { $$ = make_op($1,2,
774                                 stab2arg(A_STAB,$2),
775                                 maybelistish($1,make_list($3)),
776                                 Nullarg); }
777         |       LISTOP block expr
778                         { $$ = make_op($1,2,
779                                 cmd_to_arg($2),
780                                 maybelistish($1,make_list($3)),
781                                 Nullarg); }
782         ;
783
784 handle  :       WORD
785                         { $$ = stab2arg(A_WORD,stabent($1,TRUE));
786                           Safefree($1); $1 = Nullch;}
787         |       sexpr
788         ;
789
790 aryword :       WORD
791                         { $$ = stab2arg(A_WORD,aadd(stabent($1,TRUE)));
792                             Safefree($1); $1 = Nullch; }
793         |       ARY
794                         { $$ = stab2arg(A_STAB,$1); }
795         ;
796
797 hshword :       WORD
798                         { $$ = stab2arg(A_WORD,hadd(stabent($1,TRUE)));
799                             Safefree($1); $1 = Nullch; }
800         |       HSH
801                         { $$ = stab2arg(A_STAB,$1); }
802         ;
803
804 crp     :       ',' ')'
805                         { $$ = 1; }
806         |       ')'
807                         { $$ = 0; }
808         ;
809
810 /*
811  * NOTE:  The following entry must stay at the end of the file so that
812  * reduce/reduce conflicts resolve to it only if it's the only option.
813  */
814
815 bareword:       WORD
816                         { char *s;
817                             $$ = op_new(1);
818                             $$->arg_type = O_ITEM;
819                             $$[1].arg_type = A_SINGLE;
820                             $$[1].arg_ptr.arg_str = str_make($1,0);
821                             for (s = $1; *s && isLOWER(*s); s++) ;
822                             if (dowarn && !*s)
823                                 warn(
824                                   "\"%s\" may clash with future reserved word",
825                                   $1 );
826                         }
827                 ;
828 %% /* PROGRAM */