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