source: trunk/third/perl/perly.y @ 20075

Revision 20075, 21.5 KB checked in by zacheiss, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20074, which included commits to RCS files with non-trunk default branches.
Line 
1/*    perly.y
2 *
3 *    Copyright (c) 1991-2002, 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 */
9
10/*
11 * 'I see,' laughed Strider.  'I look foul and feel fair.  Is that it?
12 * All that is gold does not glitter, not all those who wander are lost.'
13 */
14
15%{
16#include "EXTERN.h"
17#define PERL_IN_PERLY_C
18#include "perl.h"
19#ifdef EBCDIC
20#undef YYDEBUG
21#endif
22#define dep() deprecate("\"do\" to call subroutines")
23
24/* stuff included here to make perly_c.diff apply better */
25
26#define yydebug     PL_yydebug
27#define yynerrs     PL_yynerrs
28#define yyerrflag   PL_yyerrflag
29#define yychar      PL_yychar
30#define yyval       PL_yyval
31#define yylval      PL_yylval
32
33struct ysv {
34    short* yyss;
35    YYSTYPE* yyvs;
36    int oldyydebug;
37    int oldyynerrs;
38    int oldyyerrflag;
39    int oldyychar;
40    YYSTYPE oldyyval;
41    YYSTYPE oldyylval;
42};
43
44static void yydestruct(pTHX_ void *ptr);
45
46%}
47
48%start prog
49
50%{
51#if 0 /* get this from perly.h instead */
52%}
53
54%union {
55    I32 ival;
56    char *pval;
57    OP *opval;
58    GV *gvval;
59}
60
61%{
62#endif /* 0 */
63
64#ifdef USE_PURE_BISON
65#define YYLEX_PARAM (&yychar)
66#define yylex yylex_r
67#endif
68
69%}
70
71%token <ival> '{'
72
73%token <opval> WORD METHOD FUNCMETH THING PMFUNC PRIVATEREF
74%token <opval> FUNC0SUB UNIOPSUB LSTOPSUB
75%token <pval> LABEL
76%token <ival> FORMAT SUB ANONSUB PACKAGE USE
77%token <ival> WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE FOR
78%token <ival> LOOPEX DOTDOT
79%token <ival> FUNC0 FUNC1 FUNC UNIOP LSTOP
80%token <ival> RELOP EQOP MULOP ADDOP
81%token <ival> DOLSHARP DO HASHBRACK NOAMP
82%token <ival> LOCAL MY MYSUB
83%token COLONATTR
84
85%type <ival> prog decl format startsub startanonsub startformsub
86%type <ival> progstart remember mremember '&'
87%type <opval> block mblock lineseq line loop cond else
88%type <opval> expr term subscripted scalar ary hsh arylen star amper sideff
89%type <opval> argexpr nexpr texpr iexpr mexpr mnexpr mtexpr miexpr
90%type <opval> listexpr listexprcom indirob listop method
91%type <opval> formname subname proto subbody cont my_scalar
92%type <opval> subattrlist myattrlist mysubrout myattrterm myterm
93%type <opval> termbinop termunop anonymous termdo
94%type <pval> label
95
96%nonassoc PREC_LOW
97%nonassoc LOOPEX
98
99%left <ival> OROP
100%left ANDOP
101%right NOTOP
102%nonassoc LSTOP LSTOPSUB
103%left ','
104%right <ival> ASSIGNOP
105%right '?' ':'
106%nonassoc DOTDOT
107%left OROR
108%left ANDAND
109%left <ival> BITOROP
110%left <ival> BITANDOP
111%nonassoc EQOP
112%nonassoc RELOP
113%nonassoc UNIOP UNIOPSUB
114%left <ival> SHIFTOP
115%left ADDOP
116%left MULOP
117%left <ival> MATCHOP
118%right '!' '~' UMINUS REFGEN
119%right <ival> POWOP
120%nonassoc PREINC PREDEC POSTINC POSTDEC
121%left ARROW
122%nonassoc <ival> ')'
123%left '('
124%left '[' '{'
125
126%% /* RULES */
127
128/* The whole program */
129prog    :       progstart
130        /*CONTINUED*/   lineseq
131                        { $$ = $1; newPROG(block_end($1,$2)); }
132        ;
133
134/* An ordinary block */
135block   :       '{' remember lineseq '}'
136                        { if (PL_copline > (line_t)$1)
137                              PL_copline = (line_t)$1;
138                          $$ = block_end($2, $3); }
139        ;
140
141remember:       /* NULL */      /* start a full lexical scope */
142                        { $$ = block_start(TRUE); }
143        ;
144
145progstart:
146                {
147#if defined(YYDEBUG) && defined(DEBUGGING)
148                    yydebug = (DEBUG_p_TEST);
149#endif
150                    PL_expect = XSTATE; $$ = block_start(TRUE);
151                }
152        ;
153
154
155mblock  :       '{' mremember lineseq '}'
156                        { if (PL_copline > (line_t)$1)
157                              PL_copline = (line_t)$1;
158                          $$ = block_end($2, $3); }
159        ;
160
161mremember:      /* NULL */      /* start a partial lexical scope */
162                        { $$ = block_start(FALSE); }
163        ;
164
165/* A collection of "lines" in the program */
166lineseq :       /* NULL */
167                        { $$ = Nullop; }
168        |       lineseq decl
169                        { $$ = $1; }
170        |       lineseq line
171                        {   $$ = append_list(OP_LINESEQ,
172                                (LISTOP*)$1, (LISTOP*)$2);
173                            PL_pad_reset_pending = TRUE;
174                            if ($1 && $2) PL_hints |= HINT_BLOCK_SCOPE; }
175        ;
176
177/* A "line" in the program */
178line    :       label cond
179                        { $$ = newSTATEOP(0, $1, $2); }
180        |       loop    /* loops add their own labels */
181        |       label ';'
182                        { if ($1 != Nullch) {
183                              $$ = newSTATEOP(0, $1, newOP(OP_NULL, 0));
184                            }
185                            else {
186                              $$ = Nullop;
187                              PL_copline = NOLINE;
188                            }
189                            PL_expect = XSTATE; }
190        |       label sideff ';'
191                        { $$ = newSTATEOP(0, $1, $2);
192                          PL_expect = XSTATE; }
193        ;
194
195/* An expression which may have a side-effect */
196sideff  :       error
197                        { $$ = Nullop; }
198        |       expr
199                        { $$ = $1; }
200        |       expr IF expr
201                        { $$ = newLOGOP(OP_AND, 0, $3, $1); }
202        |       expr UNLESS expr
203                        { $$ = newLOGOP(OP_OR, 0, $3, $1); }
204        |       expr WHILE expr
205                        { $$ = newLOOPOP(OPf_PARENS, 1, scalar($3), $1); }
206        |       expr UNTIL iexpr
207                        { $$ = newLOOPOP(OPf_PARENS, 1, $3, $1);}
208        |       expr FOR expr
209                        { $$ = newFOROP(0, Nullch, (line_t)$2,
210                                        Nullop, $3, $1, Nullop); }
211        ;
212
213/* else and elsif blocks */
214else    :       /* NULL */
215                        { $$ = Nullop; }
216        |       ELSE mblock
217                        { ($2)->op_flags |= OPf_PARENS; $$ = scope($2); }
218        |       ELSIF '(' mexpr ')' mblock else
219                        { PL_copline = (line_t)$1;
220                            $$ = newCONDOP(0, $3, scope($5), $6);
221                            PL_hints |= HINT_BLOCK_SCOPE; }
222        ;
223
224/* Real conditional expressions */
225cond    :       IF '(' remember mexpr ')' mblock else
226                        { PL_copline = (line_t)$1;
227                            $$ = block_end($3,
228                                   newCONDOP(0, $4, scope($6), $7)); }
229        |       UNLESS '(' remember miexpr ')' mblock else
230                        { PL_copline = (line_t)$1;
231                            $$ = block_end($3,
232                                   newCONDOP(0, $4, scope($6), $7)); }
233        ;
234
235/* Continue blocks */
236cont    :       /* NULL */
237                        { $$ = Nullop; }
238        |       CONTINUE block
239                        { $$ = scope($2); }
240        ;
241
242/* Loops: while, until, for, and a bare block */
243loop    :       label WHILE '(' remember mtexpr ')' mblock cont
244                        { PL_copline = (line_t)$2;
245                            $$ = block_end($4,
246                                   newSTATEOP(0, $1,
247                                     newWHILEOP(0, 1, (LOOP*)Nullop,
248                                                $2, $5, $7, $8))); }
249        |       label UNTIL '(' remember miexpr ')' mblock cont
250                        { PL_copline = (line_t)$2;
251                            $$ = block_end($4,
252                                   newSTATEOP(0, $1,
253                                     newWHILEOP(0, 1, (LOOP*)Nullop,
254                                                $2, $5, $7, $8))); }
255        |       label FOR MY remember my_scalar '(' mexpr ')' mblock cont
256                        { $$ = block_end($4,
257                                 newFOROP(0, $1, (line_t)$2, $5, $7, $9, $10)); }
258        |       label FOR scalar '(' remember mexpr ')' mblock cont
259                        { $$ = block_end($5,
260                                 newFOROP(0, $1, (line_t)$2, mod($3, OP_ENTERLOOP),
261                                          $6, $8, $9)); }
262        |       label FOR '(' remember mexpr ')' mblock cont
263                        { $$ = block_end($4,
264                                 newFOROP(0, $1, (line_t)$2, Nullop, $5, $7, $8)); }
265        |       label FOR '(' remember mnexpr ';' mtexpr ';' mnexpr ')' mblock
266                        /* basically fake up an initialize-while lineseq */
267                        { OP *forop;
268                          PL_copline = (line_t)$2;
269                          forop = newSTATEOP(0, $1,
270                                            newWHILEOP(0, 1, (LOOP*)Nullop,
271                                                $2, scalar($7),
272                                                $11, $9));
273                          if ($5) {
274                                forop = append_elem(OP_LINESEQ,
275                                        newSTATEOP(0, ($1?savepv($1):Nullch),
276                                                   $5),
277                                        forop);
278                          }
279
280                          $$ = block_end($4, forop); }
281        |       label block cont  /* a block is a loop that happens once */
282                        { $$ = newSTATEOP(0, $1,
283                                 newWHILEOP(0, 1, (LOOP*)Nullop,
284                                            NOLINE, Nullop, $2, $3)); }
285        ;
286
287/* Normal expression */
288nexpr   :       /* NULL */
289                        { $$ = Nullop; }
290        |       sideff
291        ;
292
293/* Boolean expression */
294texpr   :       /* NULL means true */
295                        { (void)scan_num("1", &yylval); $$ = yylval.opval; }
296        |       expr
297        ;
298
299/* Inverted boolean expression */
300iexpr   :       expr
301                        { $$ = invert(scalar($1)); }
302        ;
303
304/* Expression with its own lexical scope */
305mexpr   :       expr
306                        { $$ = $1; intro_my(); }
307        ;
308
309mnexpr  :       nexpr
310                        { $$ = $1; intro_my(); }
311        ;
312
313mtexpr  :       texpr
314                        { $$ = $1; intro_my(); }
315        ;
316
317miexpr  :       iexpr
318                        { $$ = $1; intro_my(); }
319        ;
320
321/* Optional "MAIN:"-style loop labels */
322label   :       /* empty */
323                        { $$ = Nullch; }
324        |       LABEL
325        ;
326
327/* Some kind of declaration - does not take part in the parse tree */
328decl    :       format
329                        { $$ = 0; }
330        |       subrout
331                        { $$ = 0; }
332        |       mysubrout
333                        { $$ = 0; }
334        |       package
335                        { $$ = 0; }
336        |       use
337                        { $$ = 0; }
338        ;
339
340format  :       FORMAT startformsub formname block
341                        { newFORM($2, $3, $4); }
342        ;
343
344formname:       WORD            { $$ = $1; }
345        |       /* NULL */      { $$ = Nullop; }
346        ;
347
348/* Unimplemented "my sub foo { }" */
349mysubrout:      MYSUB startsub subname proto subattrlist subbody
350                        { newMYSUB($2, $3, $4, $5, $6); }
351        ;
352
353/* Subroutine definition */
354subrout :       SUB startsub subname proto subattrlist subbody
355                        { newATTRSUB($2, $3, $4, $5, $6); }
356        ;
357
358startsub:       /* NULL */      /* start a regular subroutine scope */
359                        { $$ = start_subparse(FALSE, 0); }
360        ;
361
362startanonsub:   /* NULL */      /* start an anonymous subroutine scope */
363                        { $$ = start_subparse(FALSE, CVf_ANON); }
364        ;
365
366startformsub:   /* NULL */      /* start a format subroutine scope */
367                        { $$ = start_subparse(TRUE, 0); }
368        ;
369
370/* Name of a subroutine - must be a bareword, could be special */
371subname :       WORD    { STRLEN n_a; char *name = SvPV(((SVOP*)$1)->op_sv,n_a);
372                          if (strEQ(name, "BEGIN") || strEQ(name, "END")
373                              || strEQ(name, "INIT") || strEQ(name, "CHECK"))
374                              CvSPECIAL_on(PL_compcv);
375                          $$ = $1; }
376        ;
377
378/* Subroutine prototype */
379proto   :       /* NULL */
380                        { $$ = Nullop; }
381        |       THING
382        ;
383
384/* Optional list of subroutine attributes */
385subattrlist:    /* NULL */
386                        { $$ = Nullop; }
387        |       COLONATTR THING
388                        { $$ = $2; }
389        |       COLONATTR
390                        { $$ = Nullop; }
391        ;
392
393/* List of attributes for a "my" variable declaration */
394myattrlist:     COLONATTR THING
395                        { $$ = $2; }
396        |       COLONATTR
397                        { $$ = Nullop; }
398        ;
399
400/* Subroutine body - either null or a block */
401subbody :       block   { $$ = $1; }
402        |       ';'     { $$ = Nullop; PL_expect = XSTATE; }
403        ;
404
405package :       PACKAGE WORD ';'
406                        { package($2); }
407        |       PACKAGE ';'
408                        { package(Nullop); }
409        ;
410
411use     :       USE startsub
412                        { CvSPECIAL_on(PL_compcv); /* It's a BEGIN {} */ }
413                    WORD WORD listexpr ';'
414                        { utilize($1, $2, $4, $5, $6); }
415        ;
416
417/* Ordinary expressions; logical combinations */
418expr    :       expr ANDOP expr
419                        { $$ = newLOGOP(OP_AND, 0, $1, $3); }
420        |       expr OROP expr
421                        { $$ = newLOGOP($2, 0, $1, $3); }
422        |       argexpr %prec PREC_LOW
423        ;
424
425/* Expressions are a list of terms joined by commas */
426argexpr :       argexpr ','
427                        { $$ = $1; }
428        |       argexpr ',' term
429                        { $$ = append_elem(OP_LIST, $1, $3); }
430        |       term %prec PREC_LOW
431        ;
432
433/* List operators */
434listop  :       LSTOP indirob argexpr          /* print $fh @args */
435                        { $$ = convert($1, OPf_STACKED,
436                                prepend_elem(OP_LIST, newGVREF($1,$2), $3) ); }
437        |       FUNC '(' indirob expr ')'      /* print ($fh @args */
438                        { $$ = convert($1, OPf_STACKED,
439                                prepend_elem(OP_LIST, newGVREF($1,$3), $4) ); }
440        |       term ARROW method '(' listexprcom ')' /* $foo->bar(list) */
441                        { $$ = convert(OP_ENTERSUB, OPf_STACKED,
442                                append_elem(OP_LIST,
443                                    prepend_elem(OP_LIST, scalar($1), $5),
444                                    newUNOP(OP_METHOD, 0, $3))); }
445        |       term ARROW method                     /* $foo->bar */
446                        { $$ = convert(OP_ENTERSUB, OPf_STACKED,
447                                append_elem(OP_LIST, scalar($1),
448                                    newUNOP(OP_METHOD, 0, $3))); }
449        |       METHOD indirob listexpr              /* new Class @args */
450                        { $$ = convert(OP_ENTERSUB, OPf_STACKED,
451                                append_elem(OP_LIST,
452                                    prepend_elem(OP_LIST, $2, $3),
453                                    newUNOP(OP_METHOD, 0, $1))); }
454        |       FUNCMETH indirob '(' listexprcom ')' /* method $object (@args) */
455                        { $$ = convert(OP_ENTERSUB, OPf_STACKED,
456                                append_elem(OP_LIST,
457                                    prepend_elem(OP_LIST, $2, $4),
458                                    newUNOP(OP_METHOD, 0, $1))); }
459        |       LSTOP listexpr                       /* print @args */
460                        { $$ = convert($1, 0, $2); }
461        |       FUNC '(' listexprcom ')'             /* print (@args) */
462                        { $$ = convert($1, 0, $3); }
463        |       LSTOPSUB startanonsub block          /* map { foo } ... */
464                        { $3 = newANONATTRSUB($2, 0, Nullop, $3); }
465                    listexpr            %prec LSTOP  /* ... @bar */
466                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
467                                 append_elem(OP_LIST,
468                                   prepend_elem(OP_LIST, $3, $5), $1)); }
469        ;
470
471/* Names of methods. May use $object->$methodname */
472method  :       METHOD
473        |       scalar
474        ;
475
476/* Some kind of subscripted expression */
477subscripted:    star '{' expr ';' '}'        /* *main::{something} */
478                        /* In this and all the hash accessors, ';' is
479                         * provided by the tokeniser */
480                        { $$ = newBINOP(OP_GELEM, 0, $1, scalar($3));
481                            PL_expect = XOPERATOR; }
482        |       scalar '[' expr ']'          /* $array[$element] */
483                        { $$ = newBINOP(OP_AELEM, 0, oopsAV($1), scalar($3)); }
484        |       term ARROW '[' expr ']'      /* somearef->[$element] */
485                        { $$ = newBINOP(OP_AELEM, 0,
486                                        ref(newAVREF($1),OP_RV2AV),
487                                        scalar($4));}
488        |       subscripted '[' expr ']'    /* $foo->[$bar]->[$baz] */
489                        { $$ = newBINOP(OP_AELEM, 0,
490                                        ref(newAVREF($1),OP_RV2AV),
491                                        scalar($3));}
492        |       scalar '{' expr ';' '}'    /* $foo->{bar();} */
493                        { $$ = newBINOP(OP_HELEM, 0, oopsHV($1), jmaybe($3));
494                            PL_expect = XOPERATOR; }
495        |       term ARROW '{' expr ';' '}' /* somehref->{bar();} */
496                        { $$ = newBINOP(OP_HELEM, 0,
497                                        ref(newHVREF($1),OP_RV2HV),
498                                        jmaybe($4));
499                            PL_expect = XOPERATOR; }
500        |       subscripted '{' expr ';' '}' /* $foo->[bar]->{baz;} */
501                        { $$ = newBINOP(OP_HELEM, 0,
502                                        ref(newHVREF($1),OP_RV2HV),
503                                        jmaybe($3));
504                            PL_expect = XOPERATOR; }
505        |       term ARROW '(' ')'          /* $subref->() */
506                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
507                                   newCVREF(0, scalar($1))); }
508        |       term ARROW '(' expr ')'     /* $subref->(@args) */
509                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
510                                   append_elem(OP_LIST, $4,
511                                       newCVREF(0, scalar($1)))); }
512
513        |       subscripted '(' expr ')'   /* $foo->{bar}->(@args) */
514                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
515                                   append_elem(OP_LIST, $3,
516                                               newCVREF(0, scalar($1)))); }
517        |       subscripted '(' ')'        /* $foo->{bar}->() */
518                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
519                                   newCVREF(0, scalar($1))); }
520    ;
521
522/* Binary operators between terms */
523termbinop       :       term ASSIGNOP term             /* $x = $y */
524                        { $$ = newASSIGNOP(OPf_STACKED, $1, $2, $3); }
525        |       term POWOP term                        /* $x ** $y */
526                        { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
527        |       term MULOP term                        /* $x * $y, $x x $y */
528                        {   if ($2 != OP_REPEAT)
529                                scalar($1);
530                            $$ = newBINOP($2, 0, $1, scalar($3)); }
531        |       term ADDOP term                        /* $x + $y */
532                        { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
533        |       term SHIFTOP term                      /* $x >> $y, $x << $y */
534                        { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
535        |       term RELOP term                        /* $x > $y, etc. */
536                        { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
537        |       term EQOP term                         /* $x == $y, $x eq $y */
538                        { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
539        |       term BITANDOP term                     /* $x & $y */
540                        { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
541        |       term BITOROP term                      /* $x | $y */
542                        { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
543        |       term DOTDOT term                       /* $x..$y, $x...$y */
544                        { $$ = newRANGE($2, scalar($1), scalar($3));}
545        |       term ANDAND term                       /* $x && $y */
546                        { $$ = newLOGOP(OP_AND, 0, $1, $3); }
547        |       term OROR term                         /* $x || $y */
548                        { $$ = newLOGOP(OP_OR, 0, $1, $3); }
549        |       term MATCHOP term                      /* $x =~ /$y/ */
550                        { $$ = bind_match($2, $1, $3); }
551    ;
552
553/* Unary operators and terms */
554termunop : '-' term %prec UMINUS                       /* -$x */
555                        { $$ = newUNOP(OP_NEGATE, 0, scalar($2)); }
556        |       '+' term %prec UMINUS                  /* +$x */
557                        { $$ = $2; }
558        |       '!' term                               /* !$x */
559                        { $$ = newUNOP(OP_NOT, 0, scalar($2)); }
560        |       '~' term                               /* ~$x */
561                        { $$ = newUNOP(OP_COMPLEMENT, 0, scalar($2));}
562        |       term POSTINC                           /* $x++ */
563                        { $$ = newUNOP(OP_POSTINC, 0,
564                                        mod(scalar($1), OP_POSTINC)); }
565        |       term POSTDEC                           /* $x-- */
566                        { $$ = newUNOP(OP_POSTDEC, 0,
567                                        mod(scalar($1), OP_POSTDEC)); }
568        |       PREINC term                            /* ++$x */
569                        { $$ = newUNOP(OP_PREINC, 0,
570                                        mod(scalar($2), OP_PREINC)); }
571        |       PREDEC term                            /* --$x */
572                        { $$ = newUNOP(OP_PREDEC, 0,
573                                        mod(scalar($2), OP_PREDEC)); }
574
575    ;
576
577/* Constructors for anonymous data */
578anonymous:      '[' expr ']'
579                        { $$ = newANONLIST($2); }
580        |       '[' ']'
581                        { $$ = newANONLIST(Nullop); }
582        |       HASHBRACK expr ';' '}'  %prec '(' /* { foo => "Bar" } */
583                        { $$ = newANONHASH($2); }
584        |       HASHBRACK ';' '}'       %prec '(' /* { } (';' by tokener) */
585                        { $$ = newANONHASH(Nullop); }
586        |       ANONSUB startanonsub proto subattrlist block    %prec '('
587                        { $$ = newANONATTRSUB($2, $3, $4, $5); }
588
589    ;
590
591/* Things called with "do" */
592termdo  :       DO term %prec UNIOP                     /* do $filename */
593                        { $$ = dofile($2); }
594        |       DO block        %prec '('               /* do { code */
595                        { $$ = newUNOP(OP_NULL, OPf_SPECIAL, scope($2)); }
596        |       DO WORD '(' ')'                         /* do somesub() */
597                        { $$ = newUNOP(OP_ENTERSUB,
598                            OPf_SPECIAL|OPf_STACKED,
599                            prepend_elem(OP_LIST,
600                                scalar(newCVREF(
601                                    (OPpENTERSUB_AMPER<<8),
602                                    scalar($2)
603                                )),Nullop)); dep();}
604        |       DO WORD '(' expr ')'                    /* do somesub(@args) */
605                        { $$ = newUNOP(OP_ENTERSUB,
606                            OPf_SPECIAL|OPf_STACKED,
607                            append_elem(OP_LIST,
608                                $4,
609                                scalar(newCVREF(
610                                    (OPpENTERSUB_AMPER<<8),
611                                    scalar($2)
612                                )))); dep();}
613        |       DO scalar '(' ')'                      /* do $subref () */
614                        { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
615                            prepend_elem(OP_LIST,
616                                scalar(newCVREF(0,scalar($2))), Nullop)); dep();}
617        |       DO scalar '(' expr ')'                 /* do $subref (@args) */
618                        { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
619                            prepend_elem(OP_LIST,
620                                $4,
621                                scalar(newCVREF(0,scalar($2))))); dep();}
622
623        ;
624
625term    :       termbinop
626        |       termunop
627        |       anonymous
628        |       termdo
629        |       term '?' term ':' term
630                        { $$ = newCONDOP(0, $1, $3, $5); }
631        |       REFGEN term                          /* \$x, \@y, \%z */
632                        { $$ = newUNOP(OP_REFGEN, 0, mod($2,OP_REFGEN)); }
633        |       myattrterm      %prec UNIOP
634                        { $$ = $1; }
635        |       LOCAL term      %prec UNIOP
636                        { $$ = localize($2,$1); }
637        |       '(' expr ')'
638                        { $$ = sawparens($2); }
639        |       '(' ')'
640                        { $$ = sawparens(newNULLLIST()); }
641        |       scalar  %prec '('
642                        { $$ = $1; }
643        |       star    %prec '('
644                        { $$ = $1; }
645        |       hsh     %prec '('
646                        { $$ = $1; }
647        |       ary     %prec '('
648                        { $$ = $1; }
649        |       arylen  %prec '('                    /* $#x, $#{ something } */
650                        { $$ = newUNOP(OP_AV2ARYLEN, 0, ref($1, OP_AV2ARYLEN));}
651        |       subscripted
652                        { $$ = $1; }
653        |       '(' expr ')' '[' expr ']'            /* list slice */
654                        { $$ = newSLICEOP(0, $5, $2); }
655        |       '(' ')' '[' expr ']'                 /* empty list slice! */
656                        { $$ = newSLICEOP(0, $4, Nullop); }
657        |       ary '[' expr ']'                     /* array slice */
658                        { $$ = prepend_elem(OP_ASLICE,
659                                newOP(OP_PUSHMARK, 0),
660                                    newLISTOP(OP_ASLICE, 0,
661                                        list($3),
662                                        ref($1, OP_ASLICE))); }
663        |       ary '{' expr ';' '}'                 /* @hash{@keys} */
664                        { $$ = prepend_elem(OP_HSLICE,
665                                newOP(OP_PUSHMARK, 0),
666                                    newLISTOP(OP_HSLICE, 0,
667                                        list($3),
668                                        ref(oopsHV($1), OP_HSLICE)));
669                            PL_expect = XOPERATOR; }
670        |       THING   %prec '('
671                        { $$ = $1; }
672        |       amper                                /* &foo; */
673                        { $$ = newUNOP(OP_ENTERSUB, 0, scalar($1)); }
674        |       amper '(' ')'                        /* &foo() */
675                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar($1)); }
676        |       amper '(' expr ')'                   /* &foo(@args) */
677                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
678                            append_elem(OP_LIST, $3, scalar($1))); }
679        |       NOAMP WORD listexpr                  /* foo(@args) */
680                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
681                            append_elem(OP_LIST, $3, scalar($2))); }
682        |       LOOPEX  /* loop exiting command (goto, last, dump, etc) */
683                        { $$ = newOP($1, OPf_SPECIAL);
684                            PL_hints |= HINT_BLOCK_SCOPE; }
685        |       LOOPEX term
686                        { $$ = newLOOPEX($1,$2); }
687        |       NOTOP argexpr                        /* not $foo */
688                        { $$ = newUNOP(OP_NOT, 0, scalar($2)); }
689        |       UNIOP                                /* Unary op, $_ implied */
690                        { $$ = newOP($1, 0); }
691        |       UNIOP block                          /* eval { foo }, I *think* */
692                        { $$ = newUNOP($1, 0, $2); }
693        |       UNIOP term                           /* Unary op */
694                        { $$ = newUNOP($1, 0, $2); }
695        |       UNIOPSUB term                        /* Sub treated as unop */
696                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
697                            append_elem(OP_LIST, $2, scalar($1))); }
698        |       FUNC0                                /* Nullary operator */
699                        { $$ = newOP($1, 0); }
700        |       FUNC0 '(' ')'
701                        { $$ = newOP($1, 0); }
702        |       FUNC0SUB                             /* Sub treated as nullop */
703                        { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
704                                scalar($1)); }
705        |       FUNC1 '(' ')'                        /* not () */
706                        { $$ = newOP($1, OPf_SPECIAL); }
707        |       FUNC1 '(' expr ')'                   /* not($foo) */
708                        { $$ = newUNOP($1, 0, $3); }
709        |       PMFUNC '(' term ')'                  /* split (/foo/) */
710                        { $$ = pmruntime($1, $3, Nullop); }
711        |       PMFUNC '(' term ',' term ')'         /* split (/foo/,$bar) */
712                        { $$ = pmruntime($1, $3, $5); }
713        |       WORD
714        |       listop
715        ;
716
717/* "my" declarations, with optional attributes */
718myattrterm:     MY myterm myattrlist
719                        { $$ = my_attrs($2,$3); }
720        |       MY myterm
721                        { $$ = localize($2,$1); }
722        ;
723
724/* Things that can be "my"'d */
725myterm  :       '(' expr ')'
726                        { $$ = sawparens($2); }
727        |       '(' ')'
728                        { $$ = sawparens(newNULLLIST()); }
729        |       scalar  %prec '('
730                        { $$ = $1; }
731        |       hsh     %prec '('
732                        { $$ = $1; }
733        |       ary     %prec '('
734                        { $$ = $1; }
735        ;
736
737/* Basic list expressions */
738listexpr:       /* NULL */ %prec PREC_LOW
739                        { $$ = Nullop; }
740        |       argexpr    %prec PREC_LOW
741                        { $$ = $1; }
742        ;
743
744listexprcom:    /* NULL */
745                        { $$ = Nullop; }
746        |       expr
747                        { $$ = $1; }
748        |       expr ','
749                        { $$ = $1; }
750        ;
751
752/* A little bit of trickery to make "for my $foo (@bar)" actually be
753   lexical */
754my_scalar:      scalar
755                        { PL_in_my = 0; $$ = my($1); }
756        ;
757
758amper   :       '&' indirob
759                        { $$ = newCVREF($1,$2); }
760        ;
761
762scalar  :       '$' indirob
763                        { $$ = newSVREF($2); }
764        ;
765
766ary     :       '@' indirob
767                        { $$ = newAVREF($2); }
768        ;
769
770hsh     :       '%' indirob
771                        { $$ = newHVREF($2); }
772        ;
773
774arylen  :       DOLSHARP indirob
775                        { $$ = newAVREF($2); }
776        ;
777
778star    :       '*' indirob
779                        { $$ = newGVREF(0,$2); }
780        ;
781
782/* Indirect objects */
783indirob :       WORD
784                        { $$ = scalar($1); }
785        |       scalar %prec PREC_LOW
786                        { $$ = scalar($1);  }
787        |       block
788                        { $$ = scope($1); }
789
790        |       PRIVATEREF
791                        { $$ = $1; }
792        ;
793
794%% /* PROGRAM */
795
796/* more stuff added to make perly_c.diff easier to apply */
797
798#ifdef yyparse
799#undef yyparse
800#endif
801#define yyparse() Perl_yyparse(pTHX)
802
Note: See TracBrowser for help on using the repository browser.