Skip to content

Commit 902d409

Browse files
akiymwchristian
authored andcommitted
support postfix dereference
1 parent 52782d9 commit 902d409

File tree

4 files changed

+81
-4
lines changed

4 files changed

+81
-4
lines changed

lib/PPI/Lexer.pm

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,13 @@ sub _square {
10451045
# $foo[], @foo[]
10461046
return 'PPI::Structure::Subscript';
10471047
}
1048+
if ( $Element->isa('PPI::Token::Cast') and $Element->content =~ /^(?:\@|\%)/ ) {
1049+
my $prior = $Parent->schild(-2);
1050+
if ( $prior and $prior->isa('PPI::Token::Operator') and $prior->content eq '->' ) {
1051+
# Postfix dereference: ->@[...] ->%[...]
1052+
return 'PPI::Structure::Subscript';
1053+
}
1054+
}
10481055
# FIXME - More cases to catch
10491056
}
10501057

@@ -1121,6 +1128,13 @@ sub _curly {
11211128
# $foo{}, @foo{}
11221129
return 'PPI::Structure::Subscript';
11231130
}
1131+
if ( $Element->isa('PPI::Token::Cast') and $Element->content =~ /^(?:\@|\%|\*)/ ) {
1132+
my $prior = $Parent->schild(-2);
1133+
if ( $prior and $prior->isa('PPI::Token::Operator') and $prior->content eq '->' ) {
1134+
# Postfix dereference: ->@{...} ->%{...} ->*{...}
1135+
return 'PPI::Structure::Subscript';
1136+
}
1137+
}
11241138
if ( $Element->isa('PPI::Structure::Block') ) {
11251139
# deference - ${$hash_ref}{foo}
11261140
# or even ${burfle}{foo}

lib/PPI/Token/Cast.pm

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,30 @@ our $VERSION = '1.236';
3636

3737
our @ISA = "PPI::Token";
3838

39+
our %POSTFIX = map { $_ => 1 } (
40+
qw{
41+
%* @* $*
42+
},
43+
'$#*' # throws warnings if it's inside a qw
44+
);
45+
3946

4047

4148

4249
#####################################################################
4350
# Tokenizer Methods
4451

4552
# A cast is either % @ $ or $#
53+
# and also postfix dereference are %* @* $* $#*
4654
sub __TOKENIZER__on_char {
47-
$_[1]->_finalize_token->__TOKENIZER__on_char( $_[1] );
55+
my $t = $_[1];
56+
my $char = substr( $t->{line}, $t->{line_cursor}, 1 );
57+
58+
# Are we still an operator if we add the next character
59+
my $content = $t->{token}->{content};
60+
return 1 if $POSTFIX{ $content . $char };
61+
62+
$t->_finalize_token->__TOKENIZER__on_char( $t );
4863
}
4964

5065
1;

lib/PPI/Token/Unknown.pm

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,15 @@ sub __TOKENIZER__on_char {
7777
}
7878
}
7979

80+
# Postfix dereference: ->**
81+
if ( $char eq '*' ) {
82+
my ( $prev ) = $t->_previous_significant_tokens(1);
83+
if ( $prev and $prev->isa('PPI::Token::Operator') and $prev->content eq '->' ) {
84+
$t->{class} = $t->{token}->set_class( 'Cast' );
85+
return 1;
86+
}
87+
}
88+
8089
if ( $char eq '*' || $char eq '=' ) {
8190
# Power operator '**' or mult-assign '*='
8291
$t->{class} = $t->{token}->set_class( 'Operator' );
@@ -91,6 +100,15 @@ sub __TOKENIZER__on_char {
91100

92101

93102
} elsif ( $c eq '$' ) {
103+
# Postfix dereference: ->$* ->$#*
104+
if ( $char eq '*' || $char eq '#' ) {
105+
my ( $prev ) = $t->_previous_significant_tokens(1);
106+
if ( $prev and $prev->isa('PPI::Token::Operator') and $prev->content eq '->' ) {
107+
$t->{class} = $t->{token}->set_class( 'Cast' );
108+
return 1;
109+
}
110+
}
111+
94112
if ( $char =~ /[a-z_]/i ) {
95113
# Symbol
96114
$t->{class} = $t->{token}->set_class( 'Symbol' );
@@ -120,6 +138,15 @@ sub __TOKENIZER__on_char {
120138

121139

122140
} elsif ( $c eq '@' ) {
141+
# Postfix dereference: ->@*
142+
if ( $char eq '*' ) {
143+
my ( $prev ) = $t->_previous_significant_tokens(1);
144+
if ( $prev and $prev->isa('PPI::Token::Operator') and $prev->content eq '->' ) {
145+
$t->{class} = $t->{token}->set_class( 'Cast' );
146+
return 1;
147+
}
148+
}
149+
123150
if ( $char =~ /[\w:]/ ) {
124151
# Symbol
125152
$t->{class} = $t->{token}->set_class( 'Symbol' );
@@ -149,6 +176,21 @@ sub __TOKENIZER__on_char {
149176

150177

151178
} elsif ( $c eq '%' ) {
179+
# Postfix dereference: ->%* ->%[...]
180+
if ( $char eq '*' || $char eq '[' ) {
181+
my ( $prev ) = $t->_previous_significant_tokens(1);
182+
if ( $prev and $prev->isa('PPI::Token::Operator') and $prev->content eq '->' ) {
183+
if ( $char eq '*' ) {
184+
$t->{class} = $t->{token}->set_class( 'Cast' );
185+
return 1;
186+
}
187+
if ( $char eq '[' ) {
188+
$t->{class} = $t->{token}->set_class( 'Cast' );
189+
return $t->_finalize_token->__TOKENIZER__on_char( $t );
190+
}
191+
}
192+
}
193+
152194
# Is it a number?
153195
if ( $char =~ /\d/ ) {
154196
# bitwise operator
@@ -190,6 +232,15 @@ sub __TOKENIZER__on_char {
190232

191233

192234
} elsif ( $c eq '&' ) {
235+
# Postfix dereference: ->&*
236+
if ( $char eq '*' ) {
237+
my ( $prev ) = $t->_previous_significant_tokens(1);
238+
if ( $prev and $prev->isa('PPI::Token::Operator') and $prev->content eq '->' ) {
239+
$t->{class} = $t->{token}->set_class( 'Cast' );
240+
return 1;
241+
}
242+
}
243+
193244
# Is it a number?
194245
if ( $char =~ /\d/ ) {
195246
# bitwise operator

t/ppi_token_unknown.t

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -463,8 +463,6 @@ OPERATOR_CAST: {
463463
]
464464
);
465465

466-
{
467-
local $TODO = "implement postfix dereference recognition";
468466
# Postfix dereference
469467

470468
test_statement(
@@ -601,7 +599,6 @@ OPERATOR_CAST: {
601599
'PPI::Token::Structure' => '}',
602600
]
603601
);
604-
}
605602

606603
{ # these need to be fixed in PPI::Lexer->_statement, fixing these will break other tests that need to be changed
607604
local $TODO = "clarify type of statement in constructor";

0 commit comments

Comments
 (0)