From b3d13245b5fb1834971bbb315830af27a438d114 Mon Sep 17 00:00:00 2001 From: Pascal Rigaux Date: Wed, 13 Nov 2002 14:21:48 +0000 Subject: *** empty log message *** --- perl_checker.src/parser.mly | 124 ++++++++++++++++++++++---------------------- 1 file changed, 62 insertions(+), 62 deletions(-) (limited to 'perl_checker.src/parser.mly') diff --git a/perl_checker.src/parser.mly b/perl_checker.src/parser.mly index e94f622..dfbbd2f 100644 --- a/perl_checker.src/parser.mly +++ b/perl_checker.src/parser.mly @@ -103,7 +103,7 @@ line: | if_then_else {$1} | loop {$1} | LABEL {sp_cr($1); Label(fst $1), snd $1} -| semi_colon {List [], snd $1} +| semi_colon {Semi_colon, snd $1} | sideff semi_colon {$1} | BRACKET lines BRACKET_END {sp_p($2); sp_p($3); Block(fst $2), snd $1} @@ -113,7 +113,7 @@ if_then_else: /* Real conditional expressions */ elsif: | {[], (Space_none, bpos)} -| ELSIF PAREN expr PAREN_END BRACKET lines BRACKET_END elsif {sp_p($1); sp_n($2); sp_0($3); sp_0_or_cr($4); sp_p($5); sp_p($7); fst $3 :: Block(fst $6) :: fst $8, snd $1} +| ELSIF PAREN expr PAREN_END BRACKET lines BRACKET_END elsif {sp_p($1); sp_n($2); sp_0($3); sp_0_or_cr($4); sp_p($5); sp_p($6); sp_p($7); fst $3 :: Block(fst $6) :: fst $8, snd $1} else_: | { [], (Space_none, bpos) } @@ -129,7 +129,7 @@ loop: cont: /* Continue blocks */ | {(), (Space_none, bpos)} -| CONTINUE BRACKET lines BRACKET_END {sp_p($1); sp_n($2); sp_p($4); (), snd $1} +| CONTINUE BRACKET lines BRACKET_END {sp_p($1); sp_n($2); sp_p($3); sp_p($4); (), snd $1} sideff: /* An expression which may have a side-effect */ | expr {$1} @@ -144,16 +144,16 @@ decl: | FORMAT ASSIGN {Too_complex, snd $1} | func_decl semi_colon {die_rule (if snd (fst $1) = "" then "there is no need to pre-declare in Perl!" else "please don't use prototype pre-declaration") } | func_decl BRACKET BRACKET_END {sp_n($2); sp_0_or_cr($3); let name, proto = fst $1 in sub_declaration (name, proto) [], snd $1} -| func_decl BRACKET lines BRACKET_END {sp_n($2); sp_p($3); sp_p($4); sub_declaration (fst $1) (fst $3), snd $1} +| func_decl BRACKET lines BRACKET_END {sp_n($2); check_lines_after_BRACKET($3); sp_p($4); sub_declaration (fst $1) (fst $3), snd $1} | func_decl BRACKET BRACKET expr BRACKET_END BRACKET_END {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); sub_declaration (fst $1) [Ref(I_hash, fst $4)], snd $1} | func_decl BRACKET BRACKET expr BRACKET_END semi_colon BRACKET_END {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($7); sub_declaration (fst $1) [Ref(I_hash, fst $4)], snd $1} -| PACKAGE word semi_colon {sp_0_or_cr($1); Package(fst $2), snd $1} +| PACKAGE word semi_colon {sp_0_or_cr($1); sp_1($2); Package(fst $2), snd $1} | BEGIN BRACKET lines BRACKET_END {sp_0_or_cr($1); sp_1($2); sp_p($3); sp_p($4); Sub_declaration(Ident(None, "BEGIN", get_pos $1), "", fst $3), snd $1} | END BRACKET lines BRACKET_END {sp_0_or_cr($1); sp_1($2); sp_p($3); sp_p($4); Sub_declaration(Ident(None, "END", get_pos $1), "", fst $3), snd $1} | use {$1} use: -| use_word listexpr semi_colon {Use(fst $1, fst $2), snd $1} +| use_word listexpr semi_colon {sp_n($2); Use(fst $1, fst $2), snd $1} use_word: | use_revision word comma {fst $2, snd $1} @@ -180,20 +180,20 @@ expr: /* Ordinary expressions; logical combinations */ argexpr: /* Expressions are a list of terms joined by commas */ | argexpr comma {fst $1, snd $1} -| argexpr comma term {fst $1 @ [fst $3], snd $1} +| argexpr comma term {if not_simple (fst $3) then sp_p($3); fst $1 @ [fst $3], snd $1} | argexpr comma BRACKET expr BRACKET_END {sp_p($3); sp_p($5); fst $1 @ [ Ref(I_hash, fst $4) ], snd $1} | term %prec PREC_LOW {[fst $1], snd $1} /********************************************************************************/ term: -| term binop term {Call_op(fst $2, [fst $1 ; fst $3]), snd $1} -| term binop BRACKET expr BRACKET_END {sp_p($3); sp_p($5); Call_op(fst $2, [fst $1 ; Ref(I_hash, fst $4)]), snd $1} -| term LT term {Call_op("<", [fst $1 ; fst $3]), snd $1} -| term GT term {Call_op(">", [fst $1 ; fst $3]), snd $1} +| term binop term {call_op(fst $2, $3, [fst $1 ; fst $3]), snd $1} +| term binop BRACKET expr BRACKET_END {sp_p($3); sp_p($4); sp_p($5); call_op(fst $2, $3, [fst $1 ; Ref(I_hash, fst $4)]), snd $1} +| term LT term {sp_n($2); sp_p($3); Call_op("<", [fst $1 ; fst $3]), snd $1} +| term GT term {sp_n($2); sp_p($3); Call_op(">", [fst $1 ; fst $3]), snd $1} -| term PATTERN_MATCH PATTERN {Call_op("m//", fst $1 :: from_PATTERN $3), snd $1} -| term PATTERN_MATCH_NOT PATTERN {Call_op("!m//", fst $1 :: from_PATTERN $3), snd $1} -| term PATTERN_MATCH PATTERN_SUBST {Call_op("s///", fst $1 :: from_PATTERN_SUBST $3), snd $1} +| term PATTERN_MATCH PATTERN {sp_n($2); sp_p($3); Call_op("m//", fst $1 :: from_PATTERN $3), snd $1} +| term PATTERN_MATCH_NOT PATTERN {sp_n($2); sp_p($3); Call_op("!m//", fst $1 :: from_PATTERN $3), snd $1} +| term PATTERN_MATCH PATTERN_SUBST {sp_n($2); sp_p($3); Call_op("s///", fst $1 :: from_PATTERN_SUBST $3), snd $1} | term PATTERN_MATCH scalar { Too_complex, snd $1 } | term PATTERN_MATCH_NOT scalar { Too_complex, snd $1 } @@ -202,11 +202,11 @@ term: | term PATTERN_MATCH_NOT STRING {failwith (msg_with_pos (snd (snd $3)) "use a regexp, not a string")} /* Unary operators and terms */ -| MINUS term %prec UNARY_MINUS {Call_op("- unary", [fst $2]), snd $1} +| MINUS term %prec UNARY_MINUS {sp_0($2); Call_op("- unary", [fst $2]), snd $1} | TIGHT_NOT term {Call_op("not", [fst $2]), snd $1} | BIT_NEG term {Call_op("~", [fst $2]), snd $1} -| INCR term {Call_op("++", [fst $2]), snd $1} -| DECR term {Call_op("--", [fst $2]), snd $1} +| INCR term {sp_0($2); Call_op("++", [fst $2]), snd $1} +| DECR term {sp_0($2); Call_op("--", [fst $2]), snd $1} | term INCR {sp_0($2); Call_op("++ post", [fst $1]), snd $1} | term DECR {sp_0($2); Call_op("-- post", [fst $1]), snd $1} @@ -223,35 +223,35 @@ term: | BRACKET BRACKET_END {Ref(I_hash, List []), snd $1} /* empty hash */ | BRACKET_HASHREF expr BRACKET_END %prec PREC_HIGH {sp_p($3); Ref(I_hash, fst $2), snd $1} /* { foo => "Bar" } */ | SUB BRACKET BRACKET_END %prec PREC_HIGH {sp_n($2); sp_0($3); Anonymous_sub(Block[]), snd $1} -| SUB BRACKET lines BRACKET_END %prec PREC_HIGH {sp_n($2); sp_p($4); Anonymous_sub(Block(fst $3)), snd $1} +| SUB BRACKET lines BRACKET_END %prec PREC_HIGH {sp_n($2); check_lines_after_BRACKET($3); sp_p($4); Anonymous_sub(Block(fst $3)), snd $1} | termdo {$1} | term question_mark_ colon_ { Call_op("?:", [ fst $1 ; fst $2; fst $3]), snd $1} | REF term { Ref(I_scalar, fst $2), snd $1} /* \$x, \@y, \%z */ | my %prec UNIOP {List(fst $1), snd $1} -| LOCAL term %prec UNIOP {Local(fst $2), snd $1} +| LOCAL term %prec UNIOP {sp_n($2); Local(fst $2), snd $1} | parenthesized {List(fst $1), snd $1} /* (1, 2) */ -| parenthesized arrayref {Deref_with(I_array, List(fst $1), List(fst $2)), snd $1} /* list slice */ +| parenthesized arrayref {sp_0($2); Deref_with(I_array, List(fst $1), List(fst $2)), snd $1} /* list slice */ | variable {$1} | subscripted {$1} | array arrayref { Deref_with(I_array, fst $1, List(fst $2)), snd $1} /* array slice: @array[vals] */ -| array BRACKET expr BRACKET_END {sp_0($2); sp_0($4); Deref_with(I_hash, array_ident_to_hash_ident $1, fst $3), snd $1} /* hash slice: @hash{@keys} */ +| array BRACKET expr BRACKET_END {sp_0($2); sp_0($3); sp_0($4); Deref_with(I_hash, array_ident_to_hash_ident $1, fst $3), snd $1} /* hash slice: @hash{@keys} */ /* function_calls */ -| func parenthesized {Call(fst $1, fst $2), snd $1} /* &foo(@args) */ +| func parenthesized {sp_0($2); Call(fst $1, fst $2), snd $1} /* &foo(@args) */ | word argexpr {check_parenthesized_first_argexpr (string_of_Ident (fst $1)) $2; Call(fst $1, fst $2), snd $1} /* foo $a, $b */ | word_paren parenthesized {Call(fst $1, fst $2), snd $1} /* foo(@args) */ -| word BRACKET lines BRACKET_END listexpr %prec LSTOP {sp_n($2); sp_p($4); Call(fst $1, Anonymous_sub(Block(fst $3)) :: fst $5), snd $1} /* map { foo } @bar */ -| word BRACKET BRACKET expr BRACKET_END BRACKET_END listexpr %prec LSTOP {sp_n($2); sp_p($3); sp_p($5); sp_p($6); Call(fst $1, Anonymous_sub(Ref(I_hash, fst $4)) :: fst $7), snd $1} /* map { { foo } } @bar */ -| word BRACKET BRACKET expr BRACKET_END semi_colon BRACKET_END listexpr %prec LSTOP {sp_n($2); sp_p($3); sp_p($5); sp_p($7); Call(fst $1, Anonymous_sub(Ref(I_hash, fst $4)) :: fst $8), snd $1} /* map { { foo }; } @bar */ +| word BRACKET lines BRACKET_END listexpr %prec LSTOP {sp_n($2); check_lines_after_BRACKET($3); sp_p($4); Call(fst $1, Anonymous_sub(Block(fst $3)) :: fst $5), snd $1} /* map { foo } @bar */ +| word BRACKET BRACKET expr BRACKET_END BRACKET_END listexpr %prec LSTOP {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); Call(fst $1, Anonymous_sub(Ref(I_hash, fst $4)) :: fst $7), snd $1} /* map { { foo } } @bar */ +| word BRACKET BRACKET expr BRACKET_END semi_colon BRACKET_END listexpr %prec LSTOP {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($7); Call(fst $1, Anonymous_sub(Ref(I_hash, fst $4)) :: fst $8), snd $1} /* map { { foo }; } @bar */ -| term ARROW word_or_scalar parenthesized {sp_0($2); Method_call(fst $1, fst $3, fst $4), snd $1} /* $foo->bar(list) */ -| term ARROW word_or_scalar {sp_0($2); Method_call(fst $1, fst $3, []), snd $1} /* $foo->bar */ +| term ARROW word_or_scalar parenthesized {sp_0($2); sp_0($3); sp_0($4); Method_call(fst $1, fst $3, fst $4), snd $1} /* $foo->bar(list) */ +| term ARROW word_or_scalar {sp_0($2); sp_0($3); Method_call(fst $1, fst $3, []), snd $1} /* $foo->bar */ | NEW word listexpr { Method_call(fst $2, Ident(None, "new", get_pos $1), fst $3), snd $1} /* new Class @args */ @@ -261,7 +261,7 @@ term: | PRINT_TO_SCALAR { Call_op("print", var_STDOUT :: [ Deref(I_scalar, Ident(None, fst $1, get_pos $1)) ]), snd $1 } | PRINT_TO_SCALAR argexpr { Call_op("print", Deref(I_scalar, Ident(None, fst $1, get_pos $1)) :: fst $2), snd $1 } -| word {$1} +| word {check_word_alone $1, snd $1} | NUM {Num(fst $1, get_pos $1), snd $1} | STRING {to_String $1, snd $1} @@ -275,18 +275,18 @@ term: diamond: | LT GT {sp_0($2); Call_op("<>", []), snd $1} -| LT term GT {sp_0($3); Call_op("<>", [fst $2]), snd $1} +| LT term GT {sp_0($2); sp_0($3); Call_op("<>", [fst $2]), snd $1} subscripted: /* Some kind of subscripted expression */ -| variable PKG_SCOPE bracket_subscript {sp_0($2); Too_complex, snd $1} /* $foo::{something} */ -| scalar bracket_subscript {Deref_with(I_hash , fst $1, fst $2), snd $1} /* $foo{bar} */ -| scalar arrayref {Deref_with(I_array, fst $1, only_one $2), snd $1} /* $array[$element] */ -| term ARROW bracket_subscript {sp_0($2); Deref_with(I_hash , fst $1, fst $3), snd $1} /* somehref->{bar} */ -| term ARROW arrayref {sp_0($2); Deref_with(I_array, fst $1, only_one $3), snd $1} /* somearef->[$element] */ -| term ARROW parenthesized {sp_0($2); Deref_with(I_func , fst $1, List(fst $3)), snd $1} /* $subref->(@args) */ -| subscripted bracket_subscript {Deref_with(I_hash , fst $1, fst $2), snd $1} /* $foo->[bar]{baz} */ -| subscripted arrayref {Deref_with(I_array, fst $1, only_one $2), snd $1} /* $foo->[$bar][$baz] */ -| subscripted parenthesized {Deref_with(I_func , fst $1, List(fst $2)), snd $1} /* $foo->{bar}(@args) */ +| variable PKG_SCOPE bracket_subscript {sp_0($2); sp_0($3); Too_complex, snd $1} /* $foo::{something} */ +| scalar bracket_subscript {sp_0($2); Deref_with(I_hash , fst $1, fst $2), snd $1} /* $foo{bar} */ +| scalar arrayref {sp_0($2); Deref_with(I_array, fst $1, only_one $2), snd $1} /* $array[$element] */ +| term ARROW bracket_subscript {sp_0($2); sp_0($3); Deref_with(I_hash , fst $1, fst $3), snd $1} /* somehref->{bar} */ +| term ARROW arrayref {sp_0($2); sp_0($3); Deref_with(I_array, fst $1, only_one $3), snd $1} /* somearef->[$element] */ +| term ARROW parenthesized {sp_0($2); sp_0($3); Deref_with(I_func , fst $1, List(fst $3)), snd $1} /* $subref->(@args) */ +| subscripted bracket_subscript {sp_0($2); Deref_with(I_hash , fst $1, fst $2), snd $1} /* $foo->[bar]{baz} */ +| subscripted arrayref {sp_0($2); Deref_with(I_array, fst $1, only_one $2), snd $1} /* $foo->[$bar][$baz] */ +| subscripted parenthesized {sp_0($2); Deref_with(I_func , fst $1, List(fst $2)), snd $1} /* $foo->{bar}(@args) */ arrayref: | arrayref_start ARRAYREF_END {sp_0($2); fst $1, snd $1} @@ -299,10 +299,10 @@ parenthesized: arrayref_start: | ARRAYREF {[], snd $1} -| arrayref_start BRACKET expr BRACKET_END comma {sp_p($4); fst $1 @ [Ref(I_hash, fst $3)], snd $1} +| arrayref_start BRACKET expr BRACKET_END comma {sp_p($2); sp_p($3); sp_p($4); fst $1 @ [Ref(I_hash, fst $3)], snd $1} parenthesized_start: | PAREN {[], snd $1} -| parenthesized_start BRACKET expr BRACKET_END comma {sp_p($4); fst $1 @ [Ref(I_hash, fst $3)], snd $1} +| parenthesized_start BRACKET expr BRACKET_END comma {(if fst $1 = [] then sp_0_or_cr else sp_p)($2); sp_p($3); sp_p($4); fst $1 @ [Ref(I_hash, fst $3)], snd $1} my: /* Things that can be "my"'d */ | MY parenthesized {List.map (fun e -> My e) (fst $2), snd $1} @@ -312,32 +312,32 @@ my: /* Things that can be "my"'d */ termdo: /* Things called with "do" */ | DO term %prec UNIOP { die_rule "\"do EXPR\" not allowed" } /* do $filename */ -| DO BRACKET lines BRACKET_END %prec PREC_HIGH {sp_n($2); sp_p($4); Block(fst $3), snd $1} /* do { code */ +| DO BRACKET lines BRACKET_END %prec PREC_HIGH {sp_n($2); check_lines_after_BRACKET($3); sp_p($4); Block(fst $3), snd $1} /* do { code */ question_mark_: | QUESTION_MARK term {sp_n($1); fst $2, snd $1} | QUESTION_MARK BRACKET expr BRACKET_END {sp_n($1); sp_p($2); sp_p($4); Ref(I_hash, fst $3), snd $1} colon_: -| COLON term {sp_n($1); fst $2, snd $1} -| COLON BRACKET expr BRACKET_END {sp_n($1); sp_p($2); sp_p($4); Ref(I_hash, fst $3), snd $1} +| COLON term {sp_p($1); fst $2, snd $1} +| COLON BRACKET expr BRACKET_END {sp_p($1); sp_p($2); sp_p($3); sp_p($4); Ref(I_hash, fst $3), snd $1} bracket_subscript: -| BRACKET expr BRACKET_END {sp_0($1); sp_0($3); only_one_in_List $2, snd $1} +| BRACKET expr BRACKET_END {sp_0($1); sp_0($2); sp_0($3); only_one_in_List $2, snd $1} | COMPACT_HASH_SUBSCRIPT {sp_0($1); to_String $1, snd $1} binop: -| ASSIGN {"=", snd $1} -| POWER {"**", snd $1} -| MULT {"*", snd $1} | DIVISION {"/", snd $1} | MODULO {"%", snd $1} | REPLICATE {"x", snd $1} -| PLUS {"+", snd $1} | MINUS {"-", snd $1} | CONCAT {".", snd $1} -| BIT_SHIFT_LEFT {"<<", snd $1} | BIT_SHIFT_RIGHT {">>", snd $1} -| COMPARE_OP {fst $1, snd $1} -| EQ_OP {fst $1, snd $1} -| BIT_AND {"&", snd $1} -| BIT_OR {"|", snd $1} | BIT_XOR {"^", snd $1} -| DOTDOT {"..", snd $1} | DOTDOTDOT {"...", snd $1} -| AND_TIGHT {"&&", snd $1} -| OR_TIGHT {"||", snd $1} | XOR {"xor", snd $1} +| ASSIGN {op_p "=" $1, snd $1} +| POWER {op "**" $1, snd $1} +| MULT {op "*" $1, snd $1} | DIVISION {op "/" $1, snd $1} | MODULO {op "%" $1, snd $1} | REPLICATE {op_p "x" $1, snd $1} +| PLUS {op "+" $1, snd $1} | MINUS {op "-" $1, snd $1} | CONCAT {op "." $1, snd $1} +| BIT_SHIFT_LEFT {op "<<" $1, snd $1} | BIT_SHIFT_RIGHT {op ">>" $1, snd $1} +| COMPARE_OP {op_p (fst $1) $1, snd $1} +| EQ_OP {op_p (fst $1) $1, snd $1} +| BIT_AND {op_p "&" $1, snd $1} +| BIT_OR {op "|" $1, snd $1} | BIT_XOR {op_p "^" $1, snd $1} +| DOTDOT {op ".." $1, snd $1} | DOTDOTDOT {op_p "..." $1, snd $1} +| AND_TIGHT {op_p "&&" $1, snd $1} +| OR_TIGHT {op_p "||" $1, snd $1} | XOR {op_p "xor" $1, snd $1} variable: | scalar %prec PREC_HIGH {$1} @@ -369,11 +369,11 @@ word_paren: | BAREWORD_PAREN { Ident(None, fst $1, get_pos $1), snd $1 } | RAW_IDENT_PAREN { to_Ident $1, snd $1 } -arraylen: ARRAYLEN_IDENT {Deref(I_arraylen, to_Ident $1), snd $1} | ARRAYLEN scalar {Deref(I_arraylen, fst $2), snd $1} | ARRAYLEN BRACKET lines BRACKET_END {sp_0($2); Deref(I_arraylen, Block(fst $3)), snd $1} -scalar: SCALAR_IDENT {Deref(I_scalar , to_Ident $1), snd $1} | DOLLAR scalar {Deref(I_scalar , fst $2), snd $1} | DOLLAR BRACKET lines BRACKET_END {sp_0($2); Deref(I_scalar , Block(fst $3)), snd $1} | DOLLAR BRACKET BRACKET expr BRACKET_END BRACKET_END {sp_0($2); sp_0($3); sp_p($5); sp_0($6); Deref(I_scalar, Ref(I_hash, fst $4)), snd $1} -func: FUNC_IDENT {Deref(I_func , to_Ident $1), snd $1} | AMPERSAND scalar {Deref(I_func , fst $2), snd $1} | AMPERSAND BRACKET lines BRACKET_END {sp_0($2); Deref(I_func , Block(fst $3)), snd $1} -array: ARRAY_IDENT {Deref(I_array , to_Ident $1), snd $1} | AT scalar {Deref(I_array , fst $2), snd $1} | AT BRACKET lines BRACKET_END {sp_0($2); Deref(I_array , Block(fst $3)), snd $1} -hash: HASH_IDENT {Deref(I_hash , to_Ident $1), snd $1} | PERCENT scalar {Deref(I_hash , fst $2), snd $1} | PERCENT BRACKET lines BRACKET_END {sp_0($2); Deref(I_hash , Block(fst $3)), snd $1} -star: STAR_IDENT {Deref(I_star , to_Ident $1), snd $1} | STAR scalar {Deref(I_star , fst $2), snd $1} | STAR BRACKET lines BRACKET_END {sp_0($2); Deref(I_star , Block(fst $3)), snd $1} +arraylen: ARRAYLEN_IDENT {Deref(I_arraylen, to_Ident $1), snd $1} | ARRAYLEN scalar {sp_0($2); Deref(I_arraylen, fst $2), snd $1} | ARRAYLEN BRACKET lines BRACKET_END {sp_0($2); sp_same $3 $4; Deref(I_arraylen, Block(fst $3)), snd $1} +scalar: SCALAR_IDENT {Deref(I_scalar , to_Ident $1), snd $1} | DOLLAR scalar {sp_0($2); Deref(I_scalar , fst $2), snd $1} | DOLLAR BRACKET lines BRACKET_END {sp_0($2); sp_same $3 $4; Deref(I_scalar , Block(fst $3)), snd $1} | DOLLAR BRACKET BRACKET expr BRACKET_END BRACKET_END {sp_0($2); sp_0($3); sp_p($5); sp_0($6); Deref(I_scalar, Ref(I_hash, fst $4)), snd $1} +func: FUNC_IDENT {Deref(I_func , to_Ident $1), snd $1} | AMPERSAND scalar {sp_0($2); Deref(I_func , fst $2), snd $1} | AMPERSAND BRACKET lines BRACKET_END {sp_0($2); sp_same $3 $4; Deref(I_func , Block(fst $3)), snd $1} +array: ARRAY_IDENT {Deref(I_array , to_Ident $1), snd $1} | AT scalar {sp_0($2); Deref(I_array , fst $2), snd $1} | AT BRACKET lines BRACKET_END {sp_0($2); sp_same $3 $4; Deref(I_array , Block(fst $3)), snd $1} +hash: HASH_IDENT {Deref(I_hash , to_Ident $1), snd $1} | PERCENT scalar {sp_0($2); Deref(I_hash , fst $2), snd $1} | PERCENT BRACKET lines BRACKET_END {sp_0($2); sp_same $3 $4; Deref(I_hash , Block(fst $3)), snd $1} +star: STAR_IDENT {Deref(I_star , to_Ident $1), snd $1} | STAR scalar {sp_0($2); Deref(I_star , fst $2), snd $1} | STAR BRACKET lines BRACKET_END {sp_0($2); sp_same $3 $4; Deref(I_star , Block(fst $3)), snd $1} expr_or_empty: {Block [], (Space_none, bpos)} | expr {$1} -- cgit v1.2.1