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