%token <ival> '{' ')'
%token <opval> WORD METHOD FUNCMETH THING PMFUNC PRIVATEREF
+%token <opval> FUNC0SUB UNIOPSUB LSTOPSUB
%token <pval> LABEL
%token <ival> FORMAT SUB ANONSUB PACKAGE USE
%token <ival> WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE FOR
%token <ival> RELOP EQOP MULOP ADDOP
%token <ival> DOLSHARP DO LOCAL HASHBRACK NOAMP
-%type <ival> prog decl format remember startsub
+%type <ival> prog decl format remember startsub '&'
%type <opval> block lineseq line loop cond nexpr else argexpr
%type <opval> expr term scalar ary hsh arylen star amper sideff
%type <opval> listexpr listexprcom indirob
-%type <opval> texpr listop method
+%type <opval> texpr listop method proto
%type <pval> label
%type <opval> cont
%left <ival> OROP
%left ANDOP
-%left NOTOP
+%right NOTOP
%nonassoc <ival> LSTOP
%left ','
%right <ival> ASSIGNOP
| ELSIF '(' expr ')' block else
{ copline = $1;
$$ = newSTATEOP(0, 0,
- newCONDOP(0, $3, scope($5), $6)); }
+ newCONDOP(0, $3, scope($5), $6));
+ hints |= HINT_BLOCK_SCOPE; }
;
cond : IF '(' expr ')' block else
{ newFORM($2, Nullop, $3); }
;
-subrout : SUB startsub WORD block
- { newSUB($2, $3, $4); }
- | SUB startsub WORD ';'
- { newSUB($2, $3, Nullop); expect = XSTATE; }
+subrout : SUB startsub WORD proto block
+ { newSUB($2, $3, $4, $5); }
+ | SUB startsub WORD proto ';'
+ { newSUB($2, $3, $4, Nullop); expect = XSTATE; }
;
+proto : /* NULL */
+ { $$ = Nullop; }
+ | THING
+ ;
+
startsub: /* NULL */ /* start a subroutine scope */
{ $$ = start_subparse(); }
;
{ package(Nullop); }
;
-use : USE WORD listexpr ';'
- { utilize($1, $2, $3); }
+use : USE startsub WORD WORD listexpr ';'
+ { utilize($1, $2, $3, $4, $5); }
;
expr : expr ANDOP expr
{ $$ = newLOGOP(OP_AND, 0, $1, $3); }
| expr OROP expr
{ $$ = newLOGOP($2, 0, $1, $3); }
- | NOTOP expr
- { $$ = newUNOP(OP_NOT, 0, scalar($2)); }
| argexpr
;
{ $$ = convert($1, OPf_STACKED,
prepend_elem(OP_LIST, newGVREF($1,$3), $4) ); }
| term ARROW method '(' listexprcom ')'
- { $$ = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL,
+ { $$ = convert(OP_ENTERSUB, OPf_STACKED,
append_elem(OP_LIST,
- prepend_elem(OP_LIST, $1, list($5)),
+ prepend_elem(OP_LIST, $1, $5),
newUNOP(OP_METHOD, 0, $3))); }
| METHOD indirob listexpr
- { $$ = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL,
+ { $$ = convert(OP_ENTERSUB, OPf_STACKED,
append_elem(OP_LIST,
- prepend_elem(OP_LIST, $2, list($3)),
+ prepend_elem(OP_LIST, $2, $3),
newUNOP(OP_METHOD, 0, $1))); }
| FUNCMETH indirob '(' listexprcom ')'
- { $$ = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL,
+ { $$ = convert(OP_ENTERSUB, OPf_STACKED,
append_elem(OP_LIST,
- prepend_elem(OP_LIST, $2, list($4)),
+ prepend_elem(OP_LIST, $2, $4),
newUNOP(OP_METHOD, 0, $1))); }
| LSTOP listexpr
{ $$ = convert($1, 0, $2); }
| FUNC '(' listexprcom ')'
{ $$ = convert($1, 0, $3); }
+ | LSTOPSUB startsub block listexpr %prec LSTOP
+ { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
+ append_elem(OP_LIST,
+ prepend_elem(OP_LIST, newANONSUB($2, 0, $3), $4),
+ $1)); }
;
method : METHOD
{ $$ = newANONHASH($2); }
| HASHBRACK ';' '}' %prec '('
{ $$ = newANONHASH(Nullop); }
- | ANONSUB startsub block %prec '('
- { $$ = newANONSUB($2, $3); }
+ | ANONSUB startsub proto block %prec '('
+ { $$ = newANONSUB($2, $3, $4); }
| scalar %prec '('
{ $$ = $1; }
+ | star '{' expr ';' '}'
+ { $$ = newBINOP(OP_GELEM, 0, newGVREF(0,$1), $3); }
| star %prec '('
{ $$ = $1; }
| scalar '[' expr ']' %prec '('
| THING %prec '('
{ $$ = $1; }
| amper
- { $$ = newUNOP(OP_ENTERSUB, 0,
- scalar($1)); }
+ { $$ = newUNOP(OP_ENTERSUB, 0, scalar($1)); }
| amper '(' ')'
{ $$ = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar($1)); }
| amper '(' expr ')'
{ $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
- list(append_elem(OP_LIST, $3, scalar($1)))); }
+ append_elem(OP_LIST, $3, scalar($1))); }
| NOAMP WORD listexpr
{ $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
- list(append_elem(OP_LIST,
- $3, newCVREF(scalar($2))))); }
+ append_elem(OP_LIST, $3, scalar($2))); }
| DO term %prec UNIOP
{ $$ = newUNOP(OP_DOFILE, 0, scalar($2)); }
| DO block %prec '('
{ $$ = newUNOP(OP_NULL, OPf_SPECIAL, scope($2)); }
| DO WORD '(' ')'
- { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
- list(prepend_elem(OP_LIST,
- scalar(newCVREF(scalar($2))), Nullop))); dep();}
+ { $$ = newUNOP(OP_ENTERSUB,
+ OPf_SPECIAL|OPf_STACKED,
+ prepend_elem(OP_LIST,
+ scalar(newCVREF(
+ (OPpENTERSUB_AMPER<<8),
+ scalar($2)
+ )),Nullop)); dep();}
| DO WORD '(' expr ')'
- { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
- list(append_elem(OP_LIST,
+ { $$ = newUNOP(OP_ENTERSUB,
+ OPf_SPECIAL|OPf_STACKED,
+ append_elem(OP_LIST,
$4,
- scalar(newCVREF(scalar($2)))))); dep();}
+ scalar(newCVREF(
+ (OPpENTERSUB_AMPER<<8),
+ scalar($2)
+ )))); dep();}
| DO scalar '(' ')'
{ $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
- list(prepend_elem(OP_LIST,
- scalar(newCVREF(scalar($2))), Nullop))); dep();}
+ prepend_elem(OP_LIST,
+ scalar(newCVREF(0,scalar($2))), Nullop)); dep();}
| DO scalar '(' expr ')'
{ $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
- list(prepend_elem(OP_LIST,
+ prepend_elem(OP_LIST,
$4,
- scalar(newCVREF(scalar($2)))))); dep();}
+ scalar(newCVREF(0,scalar($2))))); dep();}
| LOOPEX
{ $$ = newOP($1, OPf_SPECIAL);
hints |= HINT_BLOCK_SCOPE; }
| LOOPEX term
{ $$ = newLOOPEX($1,$2); }
+ | NOTOP argexpr
+ { $$ = newUNOP(OP_NOT, 0, scalar($2)); }
| UNIOP
{ $$ = newOP($1, 0); }
| UNIOP block
{ $$ = newUNOP($1, 0, $2); }
| UNIOP term
{ $$ = newUNOP($1, 0, $2); }
+ | UNIOPSUB term
+ { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
+ append_elem(OP_LIST, $2, scalar($1))); }
| FUNC0
{ $$ = newOP($1, 0); }
| FUNC0 '(' ')'
{ $$ = newOP($1, 0); }
+ | FUNC0SUB
+ { $$ = newUNOP(OP_ENTERSUB, 0,
+ scalar($1)); }
| FUNC1 '(' ')'
{ $$ = newOP($1, OPf_SPECIAL); }
| FUNC1 '(' expr ')'
;
amper : '&' indirob
- { $$ = newCVREF($2); }
+ { $$ = newCVREF($1,$2); }
;
scalar : '$' indirob