| Filename | /Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/PPI/Lexer.pm |
| Statements | Executed 1375127 statements in 3.35s |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 10537 | 4 | 1 | 1.31s | 11.1s | PPI::Lexer::_lex_statement (recurses: max depth 7, inclusive time 11.9s) |
| 50565 | 9 | 1 | 676ms | 944ms | PPI::Lexer::_add_element |
| 5789 | 1 | 1 | 655ms | 9.04s | PPI::Lexer::_lex_structure (recurses: max depth 6, inclusive time 7.76s) |
| 111133 | 12 | 1 | 459ms | 7.26s | PPI::Lexer::_get_token |
| 10450 | 2 | 1 | 284ms | 476ms | PPI::Lexer::_statement |
| 22172 | 5 | 1 | 202ms | 231ms | PPI::Lexer::_add_delayed |
| 144 | 1 | 1 | 146ms | 12.7s | PPI::Lexer::_lex_document |
| 4817 | 1 | 1 | 144ms | 444ms | PPI::Lexer::_continues |
| 3157 | 1 | 1 | 95.9ms | 168ms | PPI::Lexer::_round |
| 2273 | 1 | 1 | 79.5ms | 222ms | PPI::Lexer::_curly |
| 7887 | 10 | 1 | 24.0ms | 24.0ms | PPI::Lexer::_rollback |
| 144 | 1 | 1 | 13.1ms | 337ms | PPI::Lexer::_lex_end |
| 7181 | 8 | 1 | 10.9ms | 10.9ms | PPI::Lexer::CORE:match (opcode) |
| 144 | 1 | 1 | 9.07ms | 13.2s | PPI::Lexer::lex_file |
| 359 | 1 | 1 | 6.18ms | 10.6ms | PPI::Lexer::_square |
| 144 | 1 | 1 | 3.50ms | 12.7s | PPI::Lexer::lex_tokenizer |
| 144 | 1 | 1 | 1.32ms | 1.70ms | PPI::Lexer::new |
| 144 | 1 | 1 | 373µs | 373µs | PPI::Lexer::_clear |
| 68 | 3 | 1 | 282µs | 282µs | PPI::Lexer::_buffer |
| 1 | 1 | 1 | 15µs | 15µs | PPI::Lexer::BEGIN@1052 |
| 1 | 1 | 1 | 13µs | 13µs | PPI::Lexer::BEGIN@361 |
| 1 | 1 | 1 | 12µs | 25µs | PPI::Lexer::BEGIN@56 |
| 1 | 1 | 1 | 12µs | 12µs | PPI::Lexer::BEGIN@97 |
| 1 | 1 | 1 | 12µs | 12µs | PPI::Lexer::BEGIN@64 |
| 1 | 1 | 1 | 8µs | 38µs | PPI::Lexer::BEGIN@1051 |
| 1 | 1 | 1 | 7µs | 26µs | PPI::Lexer::BEGIN@360 |
| 1 | 1 | 1 | 7µs | 42µs | PPI::Lexer::BEGIN@100 |
| 1 | 1 | 1 | 7µs | 32µs | PPI::Lexer::BEGIN@58 |
| 1 | 1 | 1 | 7µs | 23µs | PPI::Lexer::BEGIN@96 |
| 1 | 1 | 1 | 6µs | 76µs | PPI::Lexer::BEGIN@63 |
| 1 | 1 | 1 | 3µs | 3µs | PPI::Lexer::BEGIN@59 |
| 1 | 1 | 1 | 3µs | 3µs | PPI::Lexer::BEGIN@57 |
| 1 | 1 | 1 | 3µs | 3µs | PPI::Lexer::BEGIN@61 |
| 1 | 1 | 1 | 3µs | 3µs | PPI::Lexer::BEGIN@60 |
| 0 | 0 | 0 | 0s | 0s | PPI::Lexer::_error |
| 0 | 0 | 0 | 0s | 0s | PPI::Lexer::errstr |
| 0 | 0 | 0 | 0s | 0s | PPI::Lexer::lex_source |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package PPI::Lexer; | ||||
| 2 | |||||
| 3 | =pod | ||||
| 4 | |||||
| 5 | =head1 NAME | ||||
| 6 | |||||
| 7 | PPI::Lexer - The PPI Lexer | ||||
| 8 | |||||
| 9 | =head1 SYNOPSIS | ||||
| 10 | |||||
| 11 | use PPI; | ||||
| 12 | |||||
| 13 | # Create a new Lexer | ||||
| 14 | my $Lexer = PPI::Lexer->new; | ||||
| 15 | |||||
| 16 | # Build a PPI::Document object from a Token stream | ||||
| 17 | my $Tokenizer = PPI::Tokenizer->load('My/Module.pm'); | ||||
| 18 | my $Document = $Lexer->lex_tokenizer($Tokenizer); | ||||
| 19 | |||||
| 20 | # Build a PPI::Document object for some raw source | ||||
| 21 | my $source = "print 'Hello World!'; kill(Humans->all);"; | ||||
| 22 | $Document = $Lexer->lex_source($source); | ||||
| 23 | |||||
| 24 | # Build a PPI::Document object for a particular file name | ||||
| 25 | $Document = $Lexer->lex_file('My/Module.pm'); | ||||
| 26 | |||||
| 27 | =head1 DESCRIPTION | ||||
| 28 | |||||
| 29 | The is the L<PPI> Lexer. In the larger scheme of things, its job is to take | ||||
| 30 | token streams, in a variety of forms, and "lex" them into nested structures. | ||||
| 31 | |||||
| 32 | Pretty much everything in this module happens behind the scenes at this | ||||
| 33 | point. In fact, at the moment you don't really need to instantiate the lexer | ||||
| 34 | at all, the three main methods will auto-instantiate themselves a | ||||
| 35 | C<PPI::Lexer> object as needed. | ||||
| 36 | |||||
| 37 | All methods do a one-shot "lex this and give me a L<PPI::Document> object". | ||||
| 38 | |||||
| 39 | In fact, if you are reading this, what you B<probably> want to do is to | ||||
| 40 | just "load a document", in which case you can do this in a much more | ||||
| 41 | direct and concise manner with one of the following. | ||||
| 42 | |||||
| 43 | use PPI; | ||||
| 44 | |||||
| 45 | $Document = PPI::Document->load( $filename ); | ||||
| 46 | $Document = PPI::Document->new( $string ); | ||||
| 47 | |||||
| 48 | See L<PPI::Document> for more details. | ||||
| 49 | |||||
| 50 | For more unusual tasks, by all means forge onwards. | ||||
| 51 | |||||
| 52 | =head1 METHODS | ||||
| 53 | |||||
| 54 | =cut | ||||
| 55 | |||||
| 56 | 2 | 20µs | 2 | 38µs | # spent 25µs (12+13) within PPI::Lexer::BEGIN@56 which was called:
# once (12µs+13µs) by PPI::BEGIN@29 at line 56 # spent 25µs making 1 call to PPI::Lexer::BEGIN@56
# spent 13µs making 1 call to strict::import |
| 57 | 2 | 22µs | 1 | 3µs | # spent 3µs within PPI::Lexer::BEGIN@57 which was called:
# once (3µs+0s) by PPI::BEGIN@29 at line 57 # spent 3µs making 1 call to PPI::Lexer::BEGIN@57 |
| 58 | 2 | 19µs | 2 | 56µs | # spent 32µs (7+25) within PPI::Lexer::BEGIN@58 which was called:
# once (7µs+25µs) by PPI::BEGIN@29 at line 58 # spent 32µs making 1 call to PPI::Lexer::BEGIN@58
# spent 25µs making 1 call to Exporter::import |
| 59 | 2 | 25µs | 1 | 3µs | # spent 3µs within PPI::Lexer::BEGIN@59 which was called:
# once (3µs+0s) by PPI::BEGIN@29 at line 59 # spent 3µs making 1 call to PPI::Lexer::BEGIN@59 |
| 60 | 2 | 15µs | 1 | 3µs | # spent 3µs within PPI::Lexer::BEGIN@60 which was called:
# once (3µs+0s) by PPI::BEGIN@29 at line 60 # spent 3µs making 1 call to PPI::Lexer::BEGIN@60 |
| 61 | 2 | 18µs | 1 | 3µs | # spent 3µs within PPI::Lexer::BEGIN@61 which was called:
# once (3µs+0s) by PPI::BEGIN@29 at line 61 # spent 3µs making 1 call to PPI::Lexer::BEGIN@61 |
| 62 | |||||
| 63 | 2 | 79µs | 2 | 146µs | # spent 76µs (6+70) within PPI::Lexer::BEGIN@63 which was called:
# once (6µs+70µs) by PPI::BEGIN@29 at line 63 # spent 76µs making 1 call to PPI::Lexer::BEGIN@63
# spent 70µs making 1 call to vars::import |
| 64 | # spent 12µs within PPI::Lexer::BEGIN@64 which was called:
# once (12µs+0s) by PPI::BEGIN@29 at line 93 | ||||
| 65 | 1 | 400ns | $VERSION = '1.215'; | ||
| 66 | 1 | 200ns | $errstr = ''; | ||
| 67 | |||||
| 68 | # Faster than having another method call just | ||||
| 69 | # to set the structure finish token. | ||||
| 70 | 1 | 700ns | *_PARENT = *PPI::Element::_PARENT; | ||
| 71 | |||||
| 72 | # Keyword -> Structure class maps | ||||
| 73 | 1 | 6µs | %ROUND = ( | ||
| 74 | # Conditions | ||||
| 75 | 'if' => 'PPI::Structure::Condition', | ||||
| 76 | 'elsif' => 'PPI::Structure::Condition', | ||||
| 77 | 'unless' => 'PPI::Structure::Condition', | ||||
| 78 | 'while' => 'PPI::Structure::Condition', | ||||
| 79 | 'until' => 'PPI::Structure::Condition', | ||||
| 80 | |||||
| 81 | # For(each) | ||||
| 82 | 'for' => 'PPI::Structure::For', | ||||
| 83 | 'foreach' => 'PPI::Structure::For', | ||||
| 84 | ); | ||||
| 85 | |||||
| 86 | # Opening brace to refining method | ||||
| 87 | 1 | 5µs | %RESOLVE = ( | ||
| 88 | '(' => '_round', | ||||
| 89 | '[' => '_square', | ||||
| 90 | '{' => '_curly', | ||||
| 91 | ); | ||||
| 92 | |||||
| 93 | 1 | 21µs | 1 | 12µs | } # spent 12µs making 1 call to PPI::Lexer::BEGIN@64 |
| 94 | |||||
| 95 | # Allows for experimental overriding of the tokenizer | ||||
| 96 | 2 | 32µs | 2 | 40µs | # spent 23µs (7+17) within PPI::Lexer::BEGIN@96 which was called:
# once (7µs+17µs) by PPI::BEGIN@29 at line 96 # spent 23µs making 1 call to PPI::Lexer::BEGIN@96
# spent 17µs making 1 call to vars::import |
| 97 | # spent 12µs within PPI::Lexer::BEGIN@97 which was called:
# once (12µs+0s) by PPI::BEGIN@29 at line 99 | ||||
| 98 | 1 | 4µs | $X_TOKENIZER ||= 'PPI::Tokenizer'; | ||
| 99 | 1 | 15µs | 1 | 12µs | } # spent 12µs making 1 call to PPI::Lexer::BEGIN@97 |
| 100 | 2 | 527µs | 2 | 77µs | # spent 42µs (7+35) within PPI::Lexer::BEGIN@100 which was called:
# once (7µs+35µs) by PPI::BEGIN@29 at line 100 # spent 42µs making 1 call to PPI::Lexer::BEGIN@100
# spent 35µs making 1 call to constant::import |
| 101 | |||||
| - - | |||||
| 106 | ##################################################################### | ||||
| 107 | # Constructor | ||||
| 108 | |||||
| 109 | =pod | ||||
| 110 | |||||
| 111 | =head2 new | ||||
| 112 | |||||
| 113 | The C<new> constructor creates a new C<PPI::Lexer> object. The object itself | ||||
| 114 | is merely used to hold various buffers and state data during the lexing | ||||
| 115 | process, and holds no significant data between -E<gt>lex_xxxxx calls. | ||||
| 116 | |||||
| 117 | Returns a new C<PPI::Lexer> object | ||||
| 118 | |||||
| 119 | =cut | ||||
| 120 | |||||
| 121 | # spent 1.70ms (1.32+373µs) within PPI::Lexer::new which was called 144 times, avg 12µs/call:
# 144 times (1.32ms+373µs) by PPI::Lexer::lex_file at line 151, avg 12µs/call | ||||
| 122 | 144 | 401µs | 144 | 373µs | my $class = shift->_clear; # spent 373µs making 144 calls to PPI::Lexer::_clear, avg 3µs/call |
| 123 | 144 | 892µs | bless { | ||
| 124 | Tokenizer => undef, # Where we store the tokenizer for a run | ||||
| 125 | buffer => [], # The input token buffer | ||||
| 126 | delayed => [], # The "delayed insignificant tokens" buffer | ||||
| 127 | }, $class; | ||||
| 128 | } | ||||
| 129 | |||||
| - - | |||||
| 134 | ##################################################################### | ||||
| 135 | # Main Lexing Methods | ||||
| 136 | |||||
| 137 | =pod | ||||
| 138 | |||||
| 139 | =head2 lex_file $filename | ||||
| 140 | |||||
| 141 | The C<lex_file> method takes a filename as argument. It then loads the file, | ||||
| 142 | creates a L<PPI::Tokenizer> for the content and lexes the token stream | ||||
| 143 | produced by the tokenizer. Basically, a sort of all-in-one method for | ||||
| 144 | getting a L<PPI::Document> object from a file name. | ||||
| 145 | |||||
| 146 | Returns a L<PPI::Document> object, or C<undef> on error. | ||||
| 147 | |||||
| 148 | =cut | ||||
| 149 | |||||
| 150 | # spent 13.2s (9.07ms+13.2) within PPI::Lexer::lex_file which was called 144 times, avg 92.0ms/call:
# 144 times (9.07ms+13.2s) by PPI::Document::new at line 215 of PPI/Document.pm, avg 92.0ms/call | ||||
| 151 | 144 | 421µs | 144 | 1.70ms | my $self = ref $_[0] ? shift : shift->new; # spent 1.70ms making 144 calls to PPI::Lexer::new, avg 12µs/call |
| 152 | 144 | 527µs | 144 | 128µs | my $file = _STRING(shift); # spent 128µs making 144 calls to Params::Util::_STRING, avg 891ns/call |
| 153 | 144 | 46µs | unless ( defined $file ) { | ||
| 154 | return $self->_error("Did not pass a filename to PPI::Lexer::lex_file"); | ||||
| 155 | } | ||||
| 156 | |||||
| 157 | # Create the Tokenizer | ||||
| 158 | 144 | 126µs | my $Tokenizer = eval { | ||
| 159 | 144 | 786µs | 144 | 503ms | X_TOKENIZER->new($file); # spent 503ms making 144 calls to PPI::Tokenizer::new, avg 3.49ms/call |
| 160 | }; | ||||
| 161 | 144 | 976µs | 144 | 320µs | if ( _INSTANCE($@, 'PPI::Exception') ) { # spent 320µs making 144 calls to Params::Util::_INSTANCE, avg 2µs/call |
| 162 | return $self->_error( $@->message ); | ||||
| 163 | } elsif ( $@ ) { | ||||
| 164 | return $self->_error( $errstr ); | ||||
| 165 | } | ||||
| 166 | |||||
| 167 | 144 | 5.99ms | 144 | 12.7s | $self->lex_tokenizer( $Tokenizer ); # spent 12.7s making 144 calls to PPI::Lexer::lex_tokenizer, avg 88.4ms/call |
| 168 | } | ||||
| 169 | |||||
| 170 | =pod | ||||
| 171 | |||||
| 172 | =head2 lex_source $string | ||||
| 173 | |||||
| 174 | The C<lex_source> method takes a normal scalar string as argument. It | ||||
| 175 | creates a L<PPI::Tokenizer> object for the string, and then lexes the | ||||
| 176 | resulting token stream. | ||||
| 177 | |||||
| 178 | Returns a L<PPI::Document> object, or C<undef> on error. | ||||
| 179 | |||||
| 180 | =cut | ||||
| 181 | |||||
| 182 | sub lex_source { | ||||
| 183 | my $self = ref $_[0] ? shift : shift->new; | ||||
| 184 | my $source = shift; | ||||
| 185 | unless ( defined $source and not ref $source ) { | ||||
| 186 | return $self->_error("Did not pass a string to PPI::Lexer::lex_source"); | ||||
| 187 | } | ||||
| 188 | |||||
| 189 | # Create the Tokenizer and hand off to the next method | ||||
| 190 | my $Tokenizer = eval { | ||||
| 191 | X_TOKENIZER->new(\$source); | ||||
| 192 | }; | ||||
| 193 | if ( _INSTANCE($@, 'PPI::Exception') ) { | ||||
| 194 | return $self->_error( $@->message ); | ||||
| 195 | } elsif ( $@ ) { | ||||
| 196 | return $self->_error( $errstr ); | ||||
| 197 | } | ||||
| 198 | |||||
| 199 | $self->lex_tokenizer( $Tokenizer ); | ||||
| 200 | } | ||||
| 201 | |||||
| 202 | =pod | ||||
| 203 | |||||
| 204 | =head2 lex_tokenizer $Tokenizer | ||||
| 205 | |||||
| 206 | The C<lex_tokenizer> takes as argument a L<PPI::Tokenizer> object. It | ||||
| 207 | lexes the token stream from the tokenizer into a L<PPI::Document> object. | ||||
| 208 | |||||
| 209 | Returns a L<PPI::Document> object, or C<undef> on error. | ||||
| 210 | |||||
| 211 | =cut | ||||
| 212 | |||||
| 213 | # spent 12.7s (3.50ms+12.7) within PPI::Lexer::lex_tokenizer which was called 144 times, avg 88.4ms/call:
# 144 times (3.50ms+12.7s) by PPI::Lexer::lex_file at line 167, avg 88.4ms/call | ||||
| 214 | 144 | 271µs | my $self = ref $_[0] ? shift : shift->new; | ||
| 215 | 144 | 2.21ms | 288 | 2.01ms | my $Tokenizer = _INSTANCE(shift, 'PPI::Tokenizer'); # spent 1.68ms making 144 calls to Params::Util::_INSTANCE, avg 12µs/call
# spent 334µs making 144 calls to UNIVERSAL::isa, avg 2µs/call |
| 216 | 144 | 83µs | return $self->_error( | ||
| 217 | "Did not pass a PPI::Tokenizer object to PPI::Lexer::lex_tokenizer" | ||||
| 218 | ) unless $Tokenizer; | ||||
| 219 | |||||
| 220 | # Create the empty document | ||||
| 221 | 144 | 1.06ms | 144 | 0s | my $Document = PPI::Document->new; # spent 3.10ms making 144 calls to PPI::Document::new, avg 22µs/call, recursion: max depth 1, sum of overlapping time 3.10ms |
| 222 | |||||
| 223 | # Lex the token stream into the document | ||||
| 224 | 144 | 118µs | $self->{Tokenizer} = $Tokenizer; | ||
| 225 | 144 | 115µs | eval { | ||
| 226 | 144 | 401µs | 144 | 12.7s | $self->_lex_document($Document); # spent 12.7s making 144 calls to PPI::Lexer::_lex_document, avg 88.3ms/call |
| 227 | }; | ||||
| 228 | 144 | 40µs | if ( $@ ) { | ||
| 229 | # If an error occurs DESTROY the partially built document. | ||||
| 230 | undef $Document; | ||||
| 231 | if ( _INSTANCE($@, 'PPI::Exception') ) { | ||||
| 232 | return $self->_error( $@->message ); | ||||
| 233 | } else { | ||||
| 234 | return $self->_error( $errstr ); | ||||
| 235 | } | ||||
| 236 | } | ||||
| 237 | |||||
| 238 | 144 | 453µs | return $Document; | ||
| 239 | } | ||||
| 240 | |||||
| - - | |||||
| 245 | ##################################################################### | ||||
| 246 | # Lex Methods - Document Object | ||||
| 247 | |||||
| 248 | =pod | ||||
| 249 | |||||
| 250 | =begin testing _lex_document 3 | ||||
| 251 | |||||
| 252 | # Validate the creation of a null statement | ||||
| 253 | SCOPE: { | ||||
| 254 | my $token = new_ok( 'PPI::Token::Structure' => [ ')' ] ); | ||||
| 255 | my $brace = new_ok( 'PPI::Statement::UnmatchedBrace' => [ $token ] ); | ||||
| 256 | is( $brace->content, ')', '->content ok' ); | ||||
| 257 | } | ||||
| 258 | |||||
| 259 | =end testing | ||||
| 260 | |||||
| 261 | =cut | ||||
| 262 | |||||
| 263 | # spent 12.7s (146ms+12.6) within PPI::Lexer::_lex_document which was called 144 times, avg 88.3ms/call:
# 144 times (146ms+12.6s) by PPI::Lexer::lex_tokenizer at line 226, avg 88.3ms/call | ||||
| 264 | 144 | 128µs | my ($self, $Document) = @_; | ||
| 265 | # my $self = shift; | ||||
| 266 | # my $Document = _INSTANCE(shift, 'PPI::Document') or return undef; | ||||
| 267 | |||||
| 268 | # Start the processing loop | ||||
| 269 | 144 | 44µs | my $Token; | ||
| 270 | 144 | 13.5ms | 9356 | 1.09s | while ( ref($Token = $self->_get_token) ) { # spent 1.09s making 9356 calls to PPI::Lexer::_get_token, avg 117µs/call |
| 271 | # Add insignificant tokens directly beneath us | ||||
| 272 | 9212 | 10.4ms | 9212 | 9.55ms | unless ( $Token->significant ) { # spent 5.48ms making 5248 calls to PPI::Token::Whitespace::significant, avg 1µs/call
# spent 2.95ms making 3024 calls to PPI::Element::significant, avg 977ns/call
# spent 1.11ms making 940 calls to PPI::Token::Comment::significant, avg 1µs/call |
| 273 | 6188 | 6.51ms | 6188 | 77.8ms | $self->_add_element( $Document, $Token ); # spent 77.8ms making 6188 calls to PPI::Lexer::_add_element, avg 13µs/call |
| 274 | 6188 | 2.41ms | next; | ||
| 275 | } | ||||
| 276 | |||||
| 277 | 3024 | 4.11ms | 3024 | 4.79ms | if ( $Token->content eq ';' ) { # spent 4.79ms making 3024 calls to PPI::Token::content, avg 2µs/call |
| 278 | # It's a semi-colon on it's own. | ||||
| 279 | # We call this a null statement. | ||||
| 280 | $self->_add_element( | ||||
| 281 | $Document, | ||||
| 282 | PPI::Statement::Null->new($Token), | ||||
| 283 | ); | ||||
| 284 | next; | ||||
| 285 | } | ||||
| 286 | |||||
| 287 | # Handle anything other than a structural element | ||||
| 288 | 3024 | 1.35ms | unless ( ref $Token eq 'PPI::Token::Structure' ) { | ||
| 289 | # Determine the class for the Statement, and create it | ||||
| 290 | 3018 | 10.9ms | 6036 | 296ms | my $Statement = $self->_statement($Document, $Token)->new($Token); # spent 217ms making 3018 calls to PPI::Lexer::_statement, avg 72µs/call
# spent 78.9ms making 3018 calls to PPI::Statement::new, avg 26µs/call |
| 291 | |||||
| 292 | # Move the lexing down into the statement | ||||
| 293 | 3018 | 4.26ms | 3018 | 9.82ms | $self->_add_delayed( $Document ); # spent 9.82ms making 3018 calls to PPI::Lexer::_add_delayed, avg 3µs/call |
| 294 | 3018 | 3.62ms | 3018 | 27.5ms | $self->_add_element( $Document, $Statement ); # spent 27.5ms making 3018 calls to PPI::Lexer::_add_element, avg 9µs/call |
| 295 | 3018 | 4.01ms | 3018 | 10.9s | $self->_lex_statement( $Statement ); # spent 10.9s making 3018 calls to PPI::Lexer::_lex_statement, avg 3.60ms/call |
| 296 | |||||
| 297 | 3018 | 1.85ms | next; | ||
| 298 | } | ||||
| 299 | |||||
| 300 | # Is this the opening of a structure? | ||||
| 301 | 6 | 10µs | 6 | 39µs | if ( $Token->__LEXER__opens ) { # spent 39µs making 6 calls to PPI::Token::__LEXER__opens, avg 6µs/call |
| 302 | # This should actually have a Statement instead | ||||
| 303 | 6 | 10µs | 6 | 17µs | $self->_rollback( $Token ); # spent 17µs making 6 calls to PPI::Lexer::_rollback, avg 3µs/call |
| 304 | 6 | 14µs | 6 | 52µs | my $Statement = PPI::Statement->new; # spent 52µs making 6 calls to PPI::Statement::new, avg 9µs/call |
| 305 | 6 | 20µs | 6 | 82µs | $self->_add_element( $Document, $Statement ); # spent 82µs making 6 calls to PPI::Lexer::_add_element, avg 14µs/call |
| 306 | 6 | 78µs | 6 | 180ms | $self->_lex_statement( $Statement ); # spent 180ms making 6 calls to PPI::Lexer::_lex_statement, avg 30.0ms/call |
| 307 | 6 | 7µs | next; | ||
| 308 | } | ||||
| 309 | |||||
| 310 | # Is this the close of a structure. | ||||
| 311 | if ( $Token->__LEXER__closes ) { | ||||
| 312 | # Because we are at the top of the tree, this is an error. | ||||
| 313 | # This means either a mis-parsing, or an mistake in the code. | ||||
| 314 | # To handle this, we create a "Naked Close" statement | ||||
| 315 | $self->_add_element( $Document, | ||||
| 316 | PPI::Statement::UnmatchedBrace->new($Token) | ||||
| 317 | ); | ||||
| 318 | next; | ||||
| 319 | } | ||||
| 320 | |||||
| 321 | # Shouldn't be able to get here | ||||
| 322 | PPI::Exception->throw('Lexer reached an illegal state'); | ||||
| 323 | } | ||||
| 324 | |||||
| 325 | # Did we leave the main loop because of a Tokenizer error? | ||||
| 326 | 144 | 57µs | unless ( defined $Token ) { | ||
| 327 | my $errstr = $self->{Tokenizer} ? $self->{Tokenizer}->errstr : ''; | ||||
| 328 | $errstr ||= 'Unknown Tokenizer Error'; | ||||
| 329 | PPI::Exception->throw($errstr); | ||||
| 330 | } | ||||
| 331 | |||||
| 332 | # No error, it's just the end of file. | ||||
| 333 | # Add any insignificant trailing tokens. | ||||
| 334 | 144 | 243µs | 144 | 528µs | $self->_add_delayed( $Document ); # spent 528µs making 144 calls to PPI::Lexer::_add_delayed, avg 4µs/call |
| 335 | |||||
| 336 | # If the Tokenizer has any v6 blocks to attach, do so now. | ||||
| 337 | # Checking once at the end is faster than adding a special | ||||
| 338 | # case check for every statement parsed. | ||||
| 339 | 144 | 122µs | my $perl6 = $self->{Tokenizer}->{'perl6'}; | ||
| 340 | 144 | 61µs | if ( @$perl6 ) { | ||
| 341 | my $includes = $Document->find( 'PPI::Statement::Include::Perl6' ); | ||||
| 342 | foreach my $include ( @$includes ) { | ||||
| 343 | unless ( @$perl6 ) { | ||||
| 344 | PPI::Exception->throw('Failed to find a perl6 section'); | ||||
| 345 | } | ||||
| 346 | $include->{perl6} = shift @$perl6; | ||||
| 347 | } | ||||
| 348 | } | ||||
| 349 | |||||
| 350 | 144 | 352µs | return 1; | ||
| 351 | } | ||||
| 352 | |||||
| - - | |||||
| 357 | ##################################################################### | ||||
| 358 | # Lex Methods - Statement Object | ||||
| 359 | |||||
| 360 | 2 | 90µs | 2 | 45µs | # spent 26µs (7+19) within PPI::Lexer::BEGIN@360 which was called:
# once (7µs+19µs) by PPI::BEGIN@29 at line 360 # spent 26µs making 1 call to PPI::Lexer::BEGIN@360
# spent 19µs making 1 call to vars::import |
| 361 | # spent 13µs within PPI::Lexer::BEGIN@361 which was called:
# once (13µs+0s) by PPI::BEGIN@29 at line 411 | ||||
| 362 | # Keyword -> Statement Subclass | ||||
| 363 | 1 | 16µs | %STATEMENT_CLASSES = ( | ||
| 364 | # Things that affect the timing of execution | ||||
| 365 | 'BEGIN' => 'PPI::Statement::Scheduled', | ||||
| 366 | 'CHECK' => 'PPI::Statement::Scheduled', | ||||
| 367 | 'UNITCHECK' => 'PPI::Statement::Scheduled', | ||||
| 368 | 'INIT' => 'PPI::Statement::Scheduled', | ||||
| 369 | 'END' => 'PPI::Statement::Scheduled', | ||||
| 370 | |||||
| 371 | # Loading and context statement | ||||
| 372 | 'package' => 'PPI::Statement::Package', | ||||
| 373 | # 'use' => 'PPI::Statement::Include', | ||||
| 374 | 'no' => 'PPI::Statement::Include', | ||||
| 375 | 'require' => 'PPI::Statement::Include', | ||||
| 376 | |||||
| 377 | # Various declarations | ||||
| 378 | 'my' => 'PPI::Statement::Variable', | ||||
| 379 | 'local' => 'PPI::Statement::Variable', | ||||
| 380 | 'our' => 'PPI::Statement::Variable', | ||||
| 381 | 'state' => 'PPI::Statement::Variable', | ||||
| 382 | # Statements starting with 'sub' could be any one of... | ||||
| 383 | # 'sub' => 'PPI::Statement::Sub', | ||||
| 384 | # 'sub' => 'PPI::Statement::Scheduled', | ||||
| 385 | # 'sub' => 'PPI::Statement', | ||||
| 386 | |||||
| 387 | # Compound statement | ||||
| 388 | 'if' => 'PPI::Statement::Compound', | ||||
| 389 | 'unless' => 'PPI::Statement::Compound', | ||||
| 390 | 'for' => 'PPI::Statement::Compound', | ||||
| 391 | 'foreach' => 'PPI::Statement::Compound', | ||||
| 392 | 'while' => 'PPI::Statement::Compound', | ||||
| 393 | 'until' => 'PPI::Statement::Compound', | ||||
| 394 | |||||
| 395 | # Switch statement | ||||
| 396 | 'given' => 'PPI::Statement::Given', | ||||
| 397 | 'when' => 'PPI::Statement::When', | ||||
| 398 | 'default' => 'PPI::Statement::When', | ||||
| 399 | |||||
| 400 | # Various ways of breaking out of scope | ||||
| 401 | 'redo' => 'PPI::Statement::Break', | ||||
| 402 | 'next' => 'PPI::Statement::Break', | ||||
| 403 | 'last' => 'PPI::Statement::Break', | ||||
| 404 | 'return' => 'PPI::Statement::Break', | ||||
| 405 | 'goto' => 'PPI::Statement::Break', | ||||
| 406 | |||||
| 407 | # Special sections of the file | ||||
| 408 | '__DATA__' => 'PPI::Statement::Data', | ||||
| 409 | '__END__' => 'PPI::Statement::End', | ||||
| 410 | ); | ||||
| 411 | 1 | 1.34ms | 1 | 13µs | } # spent 13µs making 1 call to PPI::Lexer::BEGIN@361 |
| 412 | |||||
| 413 | sub _statement { | ||||
| 414 | 10450 | 2.86ms | my ($self, $Parent, $Token) = @_; | ||
| 415 | # my $self = shift; | ||||
| 416 | # my $Parent = _INSTANCE(shift, 'PPI::Node') or die "Bad param 1"; | ||||
| 417 | # my $Token = _INSTANCE(shift, 'PPI::Token') or die "Bad param 2"; | ||||
| 418 | |||||
| 419 | # Check for things like ( parent => ... ) | ||||
| 420 | 10450 | 57.9ms | 19096 | 33.1ms | if ( # spent 23.0ms making 17102 calls to UNIVERSAL::isa, avg 1µs/call
# spent 9.04ms making 1804 calls to PPI::Structure::List::isa, avg 5µs/call
# spent 1.05ms making 190 calls to PPI::Structure::For::isa, avg 6µs/call |
| 421 | $Parent->isa('PPI::Structure::List') | ||||
| 422 | or | ||||
| 423 | $Parent->isa('PPI::Structure::Constructor') | ||||
| 424 | ) { | ||||
| 425 | 2078 | 6.78ms | 2078 | 2.31ms | if ( $Token->isa('PPI::Token::Word') ) { # spent 2.31ms making 2078 calls to UNIVERSAL::isa, avg 1µs/call |
| 426 | # Is the next significant token a => | ||||
| 427 | # Read ahead to the next significant token | ||||
| 428 | 203 | 37µs | my $Next; | ||
| 429 | 203 | 1.34ms | 724 | 7.69ms | while ( $Next = $self->_get_token ) { # spent 7.48ms making 362 calls to PPI::Lexer::_get_token, avg 21µs/call
# spent 206µs making 362 calls to PPI::Util::TRUE, avg 568ns/call |
| 430 | 362 | 428µs | 362 | 331µs | unless ( $Next->significant ) { # spent 169µs making 203 calls to PPI::Element::significant, avg 834ns/call
# spent 161µs making 159 calls to PPI::Token::Whitespace::significant, avg 1µs/call |
| 431 | 159 | 132µs | push @{$self->{delayed}}, $Next; | ||
| 432 | # $self->_delay_element( $Next ); | ||||
| 433 | 159 | 74µs | next; | ||
| 434 | } | ||||
| 435 | |||||
| 436 | # Got the next token | ||||
| 437 | 203 | 868µs | 343 | 413µs | if ( # spent 210µs making 140 calls to PPI::Token::content, avg 2µs/call
# spent 203µs making 203 calls to UNIVERSAL::isa, avg 1µs/call |
| 438 | $Next->isa('PPI::Token::Operator') | ||||
| 439 | and | ||||
| 440 | $Next->content eq '=>' | ||||
| 441 | ) { | ||||
| 442 | # Is an ordinary expression | ||||
| 443 | 119 | 144µs | 119 | 364µs | $self->_rollback( $Next ); # spent 364µs making 119 calls to PPI::Lexer::_rollback, avg 3µs/call |
| 444 | 119 | 318µs | return 'PPI::Statement::Expression'; | ||
| 445 | } else { | ||||
| 446 | 84 | 44µs | last; | ||
| 447 | } | ||||
| 448 | } | ||||
| 449 | |||||
| 450 | # Rollback and continue | ||||
| 451 | 84 | 111µs | 84 | 240µs | $self->_rollback( $Next ); # spent 240µs making 84 calls to PPI::Lexer::_rollback, avg 3µs/call |
| 452 | } | ||||
| 453 | } | ||||
| 454 | |||||
| 455 | # Is it a token in our known classes list | ||||
| 456 | 10331 | 16.6ms | 10331 | 14.6ms | my $class = $STATEMENT_CLASSES{$Token->content}; # spent 14.6ms making 10331 calls to PPI::Token::content, avg 1µs/call |
| 457 | |||||
| 458 | # Handle potential barewords for subscripts | ||||
| 459 | 10331 | 33.0ms | 10331 | 25.3ms | if ( $Parent->isa('PPI::Structure::Subscript') ) { # spent 14.6ms making 1791 calls to PPI::Structure::List::isa, avg 8µs/call
# spent 10.3ms making 8445 calls to UNIVERSAL::isa, avg 1µs/call
# spent 413µs making 95 calls to PPI::Structure::For::isa, avg 4µs/call |
| 460 | # Fast obvious case, just an expression | ||||
| 461 | 498 | 1.27ms | unless ( $class and $class->isa('PPI::Statement::Expression') ) { | ||
| 462 | return 'PPI::Statement::Expression'; | ||||
| 463 | } | ||||
| 464 | |||||
| 465 | # This is something like "my" or "our" etc... more subtle. | ||||
| 466 | # Check if the next token is a closing curly brace. | ||||
| 467 | # This means we are something like $h{my} | ||||
| 468 | my $Next; | ||||
| 469 | while ( $Next = $self->_get_token ) { | ||||
| 470 | unless ( $Next->significant ) { | ||||
| 471 | push @{$self->{delayed}}, $Next; | ||||
| 472 | # $self->_delay_element( $Next ); | ||||
| 473 | next; | ||||
| 474 | } | ||||
| 475 | |||||
| 476 | # Found the next significant token. | ||||
| 477 | # Is it a closing curly brace? | ||||
| 478 | if ( $Next->content eq '}' ) { | ||||
| 479 | $self->_rollback( $Next ); | ||||
| 480 | return 'PPI::Statement::Expression'; | ||||
| 481 | } else { | ||||
| 482 | $self->_rollback( $Next ); | ||||
| 483 | return $class; | ||||
| 484 | } | ||||
| 485 | } | ||||
| 486 | |||||
| 487 | # End of file... this means it is something like $h{our | ||||
| 488 | # which is probably going to be $h{our} ... I think | ||||
| 489 | $self->_rollback( $Next ); | ||||
| 490 | return 'PPI::Statement::Expression'; | ||||
| 491 | } | ||||
| 492 | |||||
| 493 | # If it's a token in our list, use that class | ||||
| 494 | 9833 | 14.6ms | return $class if $class; | ||
| 495 | |||||
| 496 | # Handle the more in-depth sub detection | ||||
| 497 | 5818 | 9.98ms | 5818 | 7.37ms | if ( $Token->content eq 'sub' ) { # spent 7.37ms making 5818 calls to PPI::Token::content, avg 1µs/call |
| 498 | # Read ahead to the next significant token | ||||
| 499 | 1022 | 145µs | my $Next; | ||
| 500 | 1022 | 11.5ms | 4088 | 24.8ms | while ( $Next = $self->_get_token ) { # spent 23.7ms making 2044 calls to PPI::Lexer::_get_token, avg 12µs/call
# spent 1.16ms making 2044 calls to PPI::Util::TRUE, avg 567ns/call |
| 501 | 2044 | 2.05ms | 2044 | 1.81ms | unless ( $Next->significant ) { # spent 969µs making 1022 calls to PPI::Token::Whitespace::significant, avg 948ns/call
# spent 844µs making 1022 calls to PPI::Element::significant, avg 826ns/call |
| 502 | 1022 | 762µs | push @{$self->{delayed}}, $Next; | ||
| 503 | # $self->_delay_element( $Next ); | ||||
| 504 | 1022 | 409µs | next; | ||
| 505 | } | ||||
| 506 | |||||
| 507 | # Got the next significant token | ||||
| 508 | 1022 | 1.65ms | 1022 | 1.36ms | my $sclass = $STATEMENT_CLASSES{$Next->content}; # spent 1.36ms making 1022 calls to PPI::Token::content, avg 1µs/call |
| 509 | 1022 | 103µs | if ( $sclass and $sclass eq 'PPI::Statement::Scheduled' ) { | ||
| 510 | $self->_rollback( $Next ); | ||||
| 511 | return 'PPI::Statement::Scheduled'; | ||||
| 512 | } | ||||
| 513 | 1022 | 3.04ms | 1022 | 832µs | if ( $Next->isa('PPI::Token::Word') ) { # spent 832µs making 1022 calls to UNIVERSAL::isa, avg 814ns/call |
| 514 | 1016 | 954µs | 1016 | 2.56ms | $self->_rollback( $Next ); # spent 2.56ms making 1016 calls to PPI::Lexer::_rollback, avg 3µs/call |
| 515 | 1016 | 2.74ms | return 'PPI::Statement::Sub'; | ||
| 516 | } | ||||
| 517 | |||||
| 518 | ### Comment out these two, as they would return PPI::Statement anyway | ||||
| 519 | # if ( $content eq '{' ) { | ||||
| 520 | # Anonymous sub at start of statement | ||||
| 521 | # return 'PPI::Statement'; | ||||
| 522 | # } | ||||
| 523 | # | ||||
| 524 | # if ( $Next->isa('PPI::Token::Prototype') ) { | ||||
| 525 | # Anonymous sub at start of statement | ||||
| 526 | # return 'PPI::Statement'; | ||||
| 527 | # } | ||||
| 528 | |||||
| 529 | # PPI::Statement is the safest fall-through | ||||
| 530 | 6 | 6µs | 6 | 14µs | $self->_rollback( $Next ); # spent 14µs making 6 calls to PPI::Lexer::_rollback, avg 2µs/call |
| 531 | 6 | 15µs | return 'PPI::Statement'; | ||
| 532 | } | ||||
| 533 | |||||
| 534 | # End of file... PPI::Statement::Sub is the most likely | ||||
| 535 | $self->_rollback( $Next ); | ||||
| 536 | return 'PPI::Statement::Sub'; | ||||
| 537 | } | ||||
| 538 | |||||
| 539 | 4796 | 5.65ms | 4796 | 6.04ms | if ( $Token->content eq 'use' ) { # spent 6.04ms making 4796 calls to PPI::Token::content, avg 1µs/call |
| 540 | # Add a special case for "use v6" lines. | ||||
| 541 | 981 | 98µs | my $Next; | ||
| 542 | 981 | 7.37ms | 3924 | 20.2ms | while ( $Next = $self->_get_token ) { # spent 19.0ms making 1962 calls to PPI::Lexer::_get_token, avg 10µs/call
# spent 1.20ms making 1962 calls to PPI::Util::TRUE, avg 613ns/call |
| 543 | 1962 | 2.19ms | 1962 | 1.99ms | unless ( $Next->significant ) { # spent 1.10ms making 981 calls to PPI::Token::Whitespace::significant, avg 1µs/call
# spent 886µs making 981 calls to PPI::Element::significant, avg 903ns/call |
| 544 | 981 | 704µs | push @{$self->{delayed}}, $Next; | ||
| 545 | # $self->_delay_element( $Next ); | ||||
| 546 | 981 | 470µs | next; | ||
| 547 | } | ||||
| 548 | |||||
| 549 | # Found the next significant token. | ||||
| 550 | # Is it a v6 use? | ||||
| 551 | 981 | 1.20ms | 981 | 1.45ms | if ( $Next->content eq 'v6' ) { # spent 1.45ms making 981 calls to PPI::Token::content, avg 1µs/call |
| 552 | $self->_rollback( $Next ); | ||||
| 553 | return 'PPI::Statement::Include::Perl6'; | ||||
| 554 | } else { | ||||
| 555 | 981 | 1.16ms | 981 | 3.41ms | $self->_rollback( $Next ); # spent 3.41ms making 981 calls to PPI::Lexer::_rollback, avg 3µs/call |
| 556 | 981 | 2.52ms | return 'PPI::Statement::Include'; | ||
| 557 | } | ||||
| 558 | } | ||||
| 559 | |||||
| 560 | # End of file... this means it is an incomplete use | ||||
| 561 | # line, just treat it as a normal include. | ||||
| 562 | $self->_rollback( $Next ); | ||||
| 563 | return 'PPI::Statement::Include'; | ||||
| 564 | } | ||||
| 565 | |||||
| 566 | # If our parent is a Condition, we are an Expression | ||||
| 567 | 3815 | 9.55ms | 3815 | 10.3ms | if ( $Parent->isa('PPI::Structure::Condition') ) { # spent 7.60ms making 1777 calls to PPI::Structure::List::isa, avg 4µs/call
# spent 2.27ms making 1946 calls to UNIVERSAL::isa, avg 1µs/call
# spent 385µs making 92 calls to PPI::Structure::For::isa, avg 4µs/call |
| 568 | return 'PPI::Statement::Expression'; | ||||
| 569 | } | ||||
| 570 | |||||
| 571 | # If our parent is a List, we are also an expression | ||||
| 572 | 3390 | 20.2ms | 3390 | 12.5ms | if ( $Parent->isa('PPI::Structure::List') ) { # spent 10.6ms making 1777 calls to PPI::Structure::List::isa, avg 6µs/call
# spent 1.53ms making 1521 calls to UNIVERSAL::isa, avg 1µs/call
# spent 349µs making 92 calls to PPI::Structure::For::isa, avg 4µs/call |
| 573 | return 'PPI::Statement::Expression'; | ||||
| 574 | } | ||||
| 575 | |||||
| 576 | # Switch statements use expressions, as well. | ||||
| 577 | 1613 | 8.85ms | 3226 | 4.11ms | if ( # spent 3.37ms making 3042 calls to UNIVERSAL::isa, avg 1µs/call
# spent 737µs making 184 calls to PPI::Structure::For::isa, avg 4µs/call |
| 578 | $Parent->isa('PPI::Structure::Given') | ||||
| 579 | or | ||||
| 580 | $Parent->isa('PPI::Structure::When') | ||||
| 581 | ) { | ||||
| 582 | return 'PPI::Statement::Expression'; | ||||
| 583 | } | ||||
| 584 | |||||
| 585 | 1613 | 11.8ms | 3240 | 10.7ms | if ( _INSTANCE($Token, 'PPI::Token::Label') ) { # spent 8.82ms making 1613 calls to Params::Util::_INSTANCE, avg 5µs/call
# spent 1.86ms making 1613 calls to UNIVERSAL::isa, avg 1µs/call
# spent 8µs making 14 calls to PPI::Util::TRUE, avg 564ns/call |
| 586 | return 'PPI::Statement::Compound'; | ||||
| 587 | } | ||||
| 588 | |||||
| 589 | # Beyond that, I have no idea for the moment. | ||||
| 590 | # Just keep adding more conditions above this. | ||||
| 591 | 1599 | 3.93ms | return 'PPI::Statement'; | ||
| 592 | } | ||||
| 593 | |||||
| 594 | # spent 11.1s (1.31+9.75) within PPI::Lexer::_lex_statement which was called 10537 times, avg 1.05ms/call:
# 7432 times (954ms+-954ms) by PPI::Lexer::_lex_structure at line 1338, avg 0s/call
# 3018 times (338ms+10.5s) by PPI::Lexer::_lex_document at line 295, avg 3.60ms/call
# 81 times (15.8ms+-15.8ms) by PPI::Lexer::_lex_structure at line 1349, avg 0s/call
# 6 times (680µs+180ms) by PPI::Lexer::_lex_document at line 306, avg 30.0ms/call | ||||
| 595 | 10537 | 2.52ms | my ($self, $Statement) = @_; | ||
| 596 | # my $self = shift; | ||||
| 597 | # my $Statement = _INSTANCE(shift, 'PPI::Statement') or die "Bad param 1"; | ||||
| 598 | |||||
| 599 | # Handle some special statements | ||||
| 600 | 10537 | 39.5ms | 10681 | 351ms | if ( $Statement->isa('PPI::Statement::End') ) { # spent 337ms making 144 calls to PPI::Lexer::_lex_end, avg 2.34ms/call
# spent 14.1ms making 10537 calls to UNIVERSAL::isa, avg 1µs/call |
| 601 | return $self->_lex_end( $Statement ); | ||||
| 602 | } | ||||
| 603 | |||||
| 604 | # Begin processing tokens | ||||
| 605 | 10393 | 1.28ms | my $Token; | ||
| 606 | 10393 | 85.2ms | 61803 | 2.32s | while ( ref( $Token = $self->_get_token ) ) { # spent 2.32s making 61803 calls to PPI::Lexer::_get_token, avg 38µs/call |
| 607 | # Delay whitespace and comment tokens | ||||
| 608 | 67592 | 77.7ms | 67592 | 66.6ms | unless ( $Token->significant ) { # spent 36.3ms making 39289 calls to PPI::Element::significant, avg 925ns/call
# spent 29.5ms making 27638 calls to PPI::Token::Whitespace::significant, avg 1µs/call
# spent 813µs making 665 calls to PPI::Token::Comment::significant, avg 1µs/call |
| 609 | 28303 | 15.7ms | push @{$self->{delayed}}, $Token; | ||
| 610 | # $self->_delay_element( $Token ); | ||||
| 611 | 28303 | 11.5ms | next; | ||
| 612 | } | ||||
| 613 | |||||
| 614 | # Structual closes, and __DATA__ and __END__ tags implicitly | ||||
| 615 | # end every type of statement | ||||
| 616 | 39289 | 220ms | 78578 | 173ms | if ( # spent 116ms making 39289 calls to PPI::Token::__LEXER__closes, avg 3µs/call
# spent 44.7ms making 35232 calls to UNIVERSAL::isa, avg 1µs/call
# spent 12.3ms making 4057 calls to PPI::Lexer::_rollback, avg 3µs/call |
| 617 | $Token->__LEXER__closes | ||||
| 618 | or | ||||
| 619 | $Token->isa('PPI::Token::Separator') | ||||
| 620 | ) { | ||||
| 621 | # Rollback and end the statement | ||||
| 622 | return $self->_rollback( $Token ); | ||||
| 623 | } | ||||
| 624 | |||||
| 625 | # Normal statements never implicitly end | ||||
| 626 | 35232 | 47.7ms | 41442 | 481ms | unless ( $Statement->__LEXER__normal ) { # spent 444ms making 4817 calls to PPI::Lexer::_continues, avg 92µs/call
# spent 26.7ms making 30415 calls to PPI::Statement::__LEXER__normal, avg 879ns/call
# spent 4.56ms making 1393 calls to PPI::Lexer::_rollback, avg 3µs/call
# spent 3.39ms making 3042 calls to PPI::Statement::Sub::__LEXER__normal, avg 1µs/call
# spent 2.24ms making 1775 calls to PPI::Statement::Compound::__LEXER__normal, avg 1µs/call |
| 627 | # Have we hit an implicit end to the statement | ||||
| 628 | unless ( $self->_continues( $Statement, $Token ) ) { | ||||
| 629 | # Rollback and finish the statement | ||||
| 630 | return $self->_rollback( $Token ); | ||||
| 631 | } | ||||
| 632 | } | ||||
| 633 | |||||
| 634 | # Any normal character just gets added | ||||
| 635 | 33839 | 107ms | 33839 | 31.4ms | unless ( $Token->isa('PPI::Token::Structure') ) { # spent 31.4ms making 33839 calls to UNIVERSAL::isa, avg 928ns/call |
| 636 | 23107 | 23.7ms | 23107 | 571ms | $self->_add_element( $Statement, $Token ); # spent 571ms making 23107 calls to PPI::Lexer::_add_element, avg 25µs/call |
| 637 | 23107 | 9.28ms | next; | ||
| 638 | } | ||||
| 639 | |||||
| 640 | # Handle normal statement terminators | ||||
| 641 | 10732 | 12.0ms | 10732 | 14.8ms | if ( $Token->content eq ';' ) { # spent 14.8ms making 10732 calls to PPI::Token::content, avg 1µs/call |
| 642 | 4943 | 5.21ms | 4943 | 85.8ms | $self->_add_element( $Statement, $Token ); # spent 85.8ms making 4943 calls to PPI::Lexer::_add_element, avg 17µs/call |
| 643 | 4943 | 10.7ms | return 1; | ||
| 644 | } | ||||
| 645 | |||||
| 646 | # Which leaves us with a new structure | ||||
| 647 | |||||
| 648 | # Determine the class for the structure and create it | ||||
| 649 | 5789 | 9.02ms | 5789 | 7.12ms | my $method = $RESOLVE{$Token->content}; # spent 7.12ms making 5789 calls to PPI::Token::content, avg 1µs/call |
| 650 | 5789 | 20.0ms | 11578 | 540ms | my $Structure = $self->$method($Statement)->new($Token); # spent 222ms making 2273 calls to PPI::Lexer::_curly, avg 98µs/call
# spent 168ms making 3157 calls to PPI::Lexer::_round, avg 53µs/call
# spent 139ms making 5789 calls to PPI::Structure::new, avg 24µs/call
# spent 10.6ms making 359 calls to PPI::Lexer::_square, avg 30µs/call |
| 651 | |||||
| 652 | # Move the lexing down into the Structure | ||||
| 653 | 5789 | 7.75ms | 5789 | 44.0ms | $self->_add_delayed( $Statement ); # spent 44.0ms making 5789 calls to PPI::Lexer::_add_delayed, avg 8µs/call |
| 654 | 5789 | 6.60ms | 5789 | 99.5ms | $self->_add_element( $Statement, $Structure ); # spent 99.5ms making 5789 calls to PPI::Lexer::_add_element, avg 17µs/call |
| 655 | 5789 | 21.2ms | 11578 | 9.10s | $self->_lex_structure( $Structure ); # spent 16.8s making 5789 calls to PPI::Lexer::_lex_structure, avg 2.90ms/call, recursion: max depth 6, sum of overlapping time 7.76s
# spent 55.9ms making 5789 calls to PPI::Lexer::_get_token, avg 10µs/call |
| 656 | } | ||||
| 657 | |||||
| 658 | # Was it an error in the tokenizer? | ||||
| 659 | unless ( defined $Token ) { | ||||
| 660 | PPI::Exception->throw; | ||||
| 661 | } | ||||
| 662 | |||||
| 663 | # No, it's just the end of the file... | ||||
| 664 | # Roll back any insignificant tokens, they'll get added at the Document level | ||||
| 665 | $self->_rollback; | ||||
| 666 | } | ||||
| 667 | |||||
| 668 | # spent 337ms (13.1+324) within PPI::Lexer::_lex_end which was called 144 times, avg 2.34ms/call:
# 144 times (13.1ms+324ms) by PPI::Lexer::_lex_statement at line 600, avg 2.34ms/call | ||||
| 669 | 144 | 56µs | my ($self, $Statement) = @_; | ||
| 670 | # my $self = shift; | ||||
| 671 | # my $Statement = _INSTANCE(shift, 'PPI::Statement::End') or die "Bad param 1"; | ||||
| 672 | |||||
| 673 | # End of the file, EVERYTHING is ours | ||||
| 674 | 144 | 28µs | my $Token; | ||
| 675 | 144 | 622µs | 288 | 1.20ms | while ( $Token = $self->_get_token ) { # spent 1.11ms making 144 calls to PPI::Lexer::_get_token, avg 8µs/call
# spent 88µs making 144 calls to PPI::Util::TRUE, avg 608ns/call |
| 676 | # Inlined $Statement->__add_element($Token); | ||||
| 677 | 576 | 3.29ms | 1152 | 956µs | Scalar::Util::weaken( # spent 497µs making 576 calls to Scalar::Util::weaken, avg 863ns/call
# spent 459µs making 576 calls to Scalar::Util::refaddr, avg 796ns/call |
| 678 | $_PARENT{Scalar::Util::refaddr $Token} = $Statement | ||||
| 679 | ); | ||||
| 680 | 576 | 2.28ms | 1008 | 321ms | push @{$Statement->{children}}, $Token; # spent 321ms making 576 calls to PPI::Lexer::_get_token, avg 557µs/call
# spent 262µs making 432 calls to PPI::Util::TRUE, avg 607ns/call |
| 681 | } | ||||
| 682 | |||||
| 683 | # Was it an error in the tokenizer? | ||||
| 684 | 144 | 42µs | unless ( defined $Token ) { | ||
| 685 | PPI::Exception->throw; | ||||
| 686 | } | ||||
| 687 | |||||
| 688 | # No, it's just the end of the file... | ||||
| 689 | # Roll back any insignificant tokens, they get added at the Document level | ||||
| 690 | 144 | 489µs | 144 | 276µs | $self->_rollback; # spent 276µs making 144 calls to PPI::Lexer::_rollback, avg 2µs/call |
| 691 | } | ||||
| 692 | |||||
| 693 | # For many statements, it can be dificult to determine the end-point. | ||||
| 694 | # This method takes a statement and the next significant token, and attempts | ||||
| 695 | # to determine if the there is a statement boundary between the two, or if | ||||
| 696 | # the statement can continue with the token. | ||||
| 697 | # spent 444ms (144+300) within PPI::Lexer::_continues which was called 4817 times, avg 92µs/call:
# 4817 times (144ms+300ms) by PPI::Lexer::_lex_statement at line 626, avg 92µs/call | ||||
| 698 | 4817 | 1.46ms | my ($self, $Statement, $Token) = @_; | ||
| 699 | # my $self = shift; | ||||
| 700 | # my $Statement = _INSTANCE(shift, 'PPI::Statement') or die "Bad param 1"; | ||||
| 701 | # my $Token = _INSTANCE(shift, 'PPI::Token') or die "Bad param 2"; | ||||
| 702 | |||||
| 703 | # Handle the simple block case | ||||
| 704 | # { print 1; } | ||||
| 705 | 4817 | 17.6ms | 7857 | 87.4ms | if ( # spent 75.1ms making 4817 calls to PPI::Node::schildren, avg 16µs/call
# spent 10.2ms making 1520 calls to PPI::Node::schild, avg 7µs/call
# spent 2.11ms making 1520 calls to UNIVERSAL::isa, avg 1µs/call |
| 706 | $Statement->schildren == 1 | ||||
| 707 | and | ||||
| 708 | $Statement->schild(0)->isa('PPI::Structure::Block') | ||||
| 709 | ) { | ||||
| 710 | return ''; | ||||
| 711 | } | ||||
| 712 | |||||
| 713 | # Alrighty then, there are only five implied end statement types, | ||||
| 714 | # ::Scheduled blocks, ::Sub declarations, ::Compound, ::Given, and ::When | ||||
| 715 | # statements. | ||||
| 716 | 4810 | 18.0ms | 4810 | 8.76ms | unless ( ref($Statement) =~ /\b(?:Scheduled|Sub|Compound|Given|When)$/ ) { # spent 8.76ms making 4810 calls to PPI::Lexer::CORE:match, avg 2µs/call |
| 717 | return 1; | ||||
| 718 | } | ||||
| 719 | |||||
| 720 | # Of these five, ::Scheduled, ::Sub, ::Given, and ::When follow the same | ||||
| 721 | # simple rule and can be handled first. | ||||
| 722 | 4810 | 8.53ms | 4810 | 103ms | my @part = $Statement->schildren; # spent 103ms making 4810 calls to PPI::Node::schildren, avg 21µs/call |
| 723 | 4810 | 1.36ms | my $LastChild = $part[-1]; | ||
| 724 | 4810 | 54.1ms | 7852 | 8.75ms | unless ( $Statement->isa('PPI::Statement::Compound') ) { # spent 8.75ms making 7852 calls to UNIVERSAL::isa, avg 1µs/call |
| 725 | # If the last significant element of the statement is a block, | ||||
| 726 | # then a scheduled statement is done, no questions asked. | ||||
| 727 | return ! $LastChild->isa('PPI::Structure::Block'); | ||||
| 728 | } | ||||
| 729 | |||||
| 730 | # Now we get to compound statements, which kind of suck (to lex). | ||||
| 731 | # However, of them all, the 'if' type, which includes unless, are | ||||
| 732 | # relatively easy to handle compared to the others. | ||||
| 733 | 1768 | 2.62ms | 1768 | 77.3ms | my $type = $Statement->type; # spent 77.3ms making 1768 calls to PPI::Statement::Compound::type, avg 44µs/call |
| 734 | 1768 | 569µs | if ( $type eq 'if' ) { | ||
| 735 | # This should be one of the following | ||||
| 736 | # if (EXPR) BLOCK | ||||
| 737 | # if (EXPR) BLOCK else BLOCK | ||||
| 738 | # if (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK | ||||
| 739 | |||||
| 740 | # We only implicitly end on a block | ||||
| 741 | 1151 | 5.56ms | 1151 | 1.26ms | unless ( $LastChild->isa('PPI::Structure::Block') ) { # spent 1.26ms making 1151 calls to UNIVERSAL::isa, avg 1µs/call |
| 742 | # if (EXPR) ... | ||||
| 743 | # if (EXPR) BLOCK else ... | ||||
| 744 | # if (EXPR) BLOCK elsif (EXPR) BLOCK ... | ||||
| 745 | return 1; | ||||
| 746 | } | ||||
| 747 | |||||
| 748 | # If the token before the block is an 'else', | ||||
| 749 | # it's over, no matter what. | ||||
| 750 | 329 | 475µs | 329 | 4.42ms | my $NextLast = $Statement->schild(-2); # spent 4.42ms making 329 calls to PPI::Node::schild, avg 13µs/call |
| 751 | 329 | 6.18ms | 694 | 628µs | if ( # spent 376µs making 347 calls to UNIVERSAL::isa, avg 1µs/call
# spent 227µs making 329 calls to PPI::Util::TRUE, avg 689ns/call
# spent 25µs making 18 calls to PPI::Token::content, avg 1µs/call |
| 752 | $NextLast | ||||
| 753 | and | ||||
| 754 | $NextLast->isa('PPI::Token') | ||||
| 755 | and | ||||
| 756 | $NextLast->isa('PPI::Token::Word') | ||||
| 757 | and | ||||
| 758 | $NextLast->content eq 'else' | ||||
| 759 | ) { | ||||
| 760 | return ''; | ||||
| 761 | } | ||||
| 762 | |||||
| 763 | # Otherwise, we continue for 'elsif' or 'else' only. | ||||
| 764 | 311 | 1.72ms | 847 | 930µs | if ( # spent 693µs making 536 calls to PPI::Token::content, avg 1µs/call
# spent 237µs making 311 calls to UNIVERSAL::isa, avg 762ns/call |
| 765 | $Token->isa('PPI::Token::Word') | ||||
| 766 | and ( | ||||
| 767 | $Token->content eq 'else' | ||||
| 768 | or | ||||
| 769 | $Token->content eq 'elsif' | ||||
| 770 | ) | ||||
| 771 | ) { | ||||
| 772 | return 1; | ||||
| 773 | } | ||||
| 774 | |||||
| 775 | 227 | 626µs | return ''; | ||
| 776 | } | ||||
| 777 | |||||
| 778 | 617 | 107µs | if ( $type eq 'label' ) { | ||
| 779 | # We only have the label so far, could be any of | ||||
| 780 | # LABEL while (EXPR) BLOCK | ||||
| 781 | # LABEL while (EXPR) BLOCK continue BLOCK | ||||
| 782 | # LABEL for (EXPR; EXPR; EXPR) BLOCK | ||||
| 783 | # LABEL foreach VAR (LIST) BLOCK | ||||
| 784 | # LABEL foreach VAR (LIST) BLOCK continue BLOCK | ||||
| 785 | # LABEL BLOCK continue BLOCK | ||||
| 786 | |||||
| 787 | # Handle cases with a word after the label | ||||
| 788 | 14 | 151µs | 42 | 55µs | if ( # spent 24µs making 14 calls to PPI::Lexer::CORE:match, avg 2µs/call
# spent 20µs making 14 calls to PPI::Token::content, avg 1µs/call
# spent 11µs making 14 calls to UNIVERSAL::isa, avg 793ns/call |
| 789 | $Token->isa('PPI::Token::Word') | ||||
| 790 | and | ||||
| 791 | $Token->content =~ /^(?:while|until|for|foreach)$/ | ||||
| 792 | ) { | ||||
| 793 | return 1; | ||||
| 794 | } | ||||
| 795 | |||||
| 796 | # Handle labelled blocks | ||||
| 797 | if ( $Token->isa('PPI::Token::Structure') && $Token->content eq '{' ) { | ||||
| 798 | return 1; | ||||
| 799 | } | ||||
| 800 | |||||
| 801 | return ''; | ||||
| 802 | } | ||||
| 803 | |||||
| 804 | # Handle the common "after round braces" case | ||||
| 805 | 603 | 3.29ms | 1189 | 3.68ms | if ( $LastChild->isa('PPI::Structure') and $LastChild->braces eq '()' ) { # spent 2.43ms making 284 calls to PPI::Structure::braces, avg 9µs/call
# spent 651µs making 665 calls to UNIVERSAL::isa, avg 979ns/call
# spent 382µs making 86 calls to PPI::Structure::List::isa, avg 4µs/call
# spent 209µs making 151 calls to PPI::Token::content, avg 1µs/call
# spent 10µs making 3 calls to PPI::Structure::For::isa, avg 4µs/call |
| 806 | # LABEL while (EXPR) ... | ||||
| 807 | # LABEL while (EXPR) ... | ||||
| 808 | # LABEL for (EXPR; EXPR; EXPR) ... | ||||
| 809 | # LABEL for VAR (LIST) ... | ||||
| 810 | # LABEL foreach VAR (LIST) ... | ||||
| 811 | # Only a block will do | ||||
| 812 | return $Token->isa('PPI::Token::Structure') && $Token->content eq '{'; | ||||
| 813 | } | ||||
| 814 | |||||
| 815 | 452 | 99µs | if ( $type eq 'for' ) { | ||
| 816 | # LABEL for (EXPR; EXPR; EXPR) BLOCK | ||||
| 817 | 35 | 230µs | 103 | 102µs | if ( # spent 42µs making 33 calls to PPI::Token::content, avg 1µs/call
# spent 32µs making 33 calls to PPI::Lexer::CORE:match, avg 970ns/call
# spent 27µs making 37 calls to UNIVERSAL::isa, avg 735ns/call |
| 818 | $LastChild->isa('PPI::Token::Word') | ||||
| 819 | and | ||||
| 820 | $LastChild->content =~ /^for(?:each)?\z/ | ||||
| 821 | ) { | ||||
| 822 | # LABEL for ... | ||||
| 823 | 33 | 242µs | 66 | 96µs | if ( # spent 89µs making 60 calls to UNIVERSAL::isa, avg 1µs/call
# spent 7µs making 6 calls to PPI::Token::content, avg 1µs/call |
| 824 | ( | ||||
| 825 | $Token->isa('PPI::Token::Structure') | ||||
| 826 | and | ||||
| 827 | $Token->content eq '(' | ||||
| 828 | ) | ||||
| 829 | or | ||||
| 830 | $Token->isa('PPI::Token::QuoteLike::Words') | ||||
| 831 | ) { | ||||
| 832 | return 1; | ||||
| 833 | } | ||||
| 834 | |||||
| 835 | 27 | 95µs | 27 | 26µs | if ( $LastChild->isa('PPI::Token::QuoteLike::Words') ) { # spent 26µs making 27 calls to UNIVERSAL::isa, avg 956ns/call |
| 836 | # LABEL for VAR QW{} ... | ||||
| 837 | # LABEL foreach VAR QW{} ... | ||||
| 838 | # Only a block will do | ||||
| 839 | return $Token->isa('PPI::Token::Structure') && $Token->content eq '{'; | ||||
| 840 | } | ||||
| 841 | |||||
| 842 | # In this case, we can also behave like a foreach | ||||
| 843 | 27 | 16µs | $type = 'foreach'; | ||
| 844 | |||||
| 845 | } elsif ( $LastChild->isa('PPI::Structure::Block') ) { | ||||
| 846 | # LABEL for (EXPR; EXPR; EXPR) BLOCK | ||||
| 847 | # That's it, nothing can continue | ||||
| 848 | return ''; | ||||
| 849 | |||||
| 850 | } elsif ( $LastChild->isa('PPI::Token::QuoteLike::Words') ) { | ||||
| 851 | # LABEL for VAR QW{} ... | ||||
| 852 | # LABEL foreach VAR QW{} ... | ||||
| 853 | # Only a block will do | ||||
| 854 | return $Token->isa('PPI::Token::Structure') && $Token->content eq '{'; | ||||
| 855 | } | ||||
| 856 | } | ||||
| 857 | |||||
| 858 | # Handle the common continue case | ||||
| 859 | 444 | 6.21ms | 678 | 736µs | if ( $LastChild->isa('PPI::Token::Word') and $LastChild->content eq 'continue' ) { # spent 430µs making 446 calls to UNIVERSAL::isa, avg 964ns/call
# spent 307µs making 232 calls to PPI::Token::content, avg 1µs/call |
| 860 | # LABEL while (EXPR) BLOCK continue ... | ||||
| 861 | # LABEL foreach VAR (LIST) BLOCK continue ... | ||||
| 862 | # LABEL BLOCK continue ... | ||||
| 863 | # Only a block will do | ||||
| 864 | return $Token->isa('PPI::Token::Structure') && $Token->content eq '{'; | ||||
| 865 | } | ||||
| 866 | |||||
| 867 | # Handle the common continuable block case | ||||
| 868 | 442 | 1.36ms | 442 | 458µs | if ( $LastChild->isa('PPI::Structure::Block') ) { # spent 458µs making 442 calls to UNIVERSAL::isa, avg 1µs/call |
| 869 | # LABEL while (EXPR) BLOCK | ||||
| 870 | # LABEL while (EXPR) BLOCK ... | ||||
| 871 | # LABEL for (EXPR; EXPR; EXPR) BLOCK | ||||
| 872 | # LABEL foreach VAR (LIST) BLOCK | ||||
| 873 | # LABEL foreach VAR (LIST) BLOCK ... | ||||
| 874 | # LABEL BLOCK ... | ||||
| 875 | # Is this the block for a continue? | ||||
| 876 | 131 | 1.01ms | 266 | 1.49ms | if ( _INSTANCE($part[-2], 'PPI::Token::Word') and $part[-2]->content eq 'continue' ) { # spent 1.09ms making 131 calls to Params::Util::_INSTANCE, avg 8µs/call
# spent 332µs making 69 calls to PPI::Structure::List::isa, avg 5µs/call
# spent 67µs making 62 calls to UNIVERSAL::isa, avg 1µs/call
# spent 3µs making 2 calls to PPI::Token::content, avg 1µs/call
# spent 1µs making 2 calls to PPI::Util::TRUE, avg 500ns/call |
| 877 | # LABEL while (EXPR) BLOCK continue BLOCK | ||||
| 878 | # LABEL foreach VAR (LIST) BLOCK continue BLOCK | ||||
| 879 | # LABEL BLOCK continue BLOCK | ||||
| 880 | # That's it, nothing can continue this | ||||
| 881 | return ''; | ||||
| 882 | } | ||||
| 883 | |||||
| 884 | # Only a continue will do | ||||
| 885 | 129 | 940µs | 248 | 288µs | return $Token->isa('PPI::Token::Word') && $Token->content eq 'continue'; # spent 185µs making 119 calls to PPI::Token::content, avg 2µs/call
# spent 103µs making 129 calls to UNIVERSAL::isa, avg 797ns/call |
| 886 | } | ||||
| 887 | |||||
| 888 | 311 | 76µs | if ( $type eq 'block' ) { | ||
| 889 | # LABEL BLOCK continue BLOCK | ||||
| 890 | # Every possible case is covered in the common cases above | ||||
| 891 | } | ||||
| 892 | |||||
| 893 | 311 | 697µs | 248 | 242µs | if ( $type eq 'while' ) { # spent 151µs making 124 calls to PPI::Token::content, avg 1µs/call
# spent 91µs making 124 calls to UNIVERSAL::isa, avg 736ns/call |
| 894 | # LABEL while (EXPR) BLOCK | ||||
| 895 | # LABEL while (EXPR) BLOCK continue BLOCK | ||||
| 896 | # LABEL until (EXPR) BLOCK | ||||
| 897 | # LABEL until (EXPR) BLOCK continue BLOCK | ||||
| 898 | # The only case not covered is the while ... | ||||
| 899 | if ( | ||||
| 900 | $LastChild->isa('PPI::Token::Word') | ||||
| 901 | and ( | ||||
| 902 | $LastChild->content eq 'while' | ||||
| 903 | or | ||||
| 904 | $LastChild->content eq 'until' | ||||
| 905 | ) | ||||
| 906 | ) { | ||||
| 907 | # LABEL while ... | ||||
| 908 | # LABEL until ... | ||||
| 909 | # Only a condition structure will do | ||||
| 910 | return $Token->isa('PPI::Token::Structure') && $Token->content eq '('; | ||||
| 911 | } | ||||
| 912 | } | ||||
| 913 | |||||
| 914 | 249 | 70µs | if ( $type eq 'foreach' ) { | ||
| 915 | # LABEL foreach VAR (LIST) BLOCK | ||||
| 916 | # LABEL foreach VAR (LIST) BLOCK continue BLOCK | ||||
| 917 | # The only two cases that have not been covered already are | ||||
| 918 | # 'foreach ...' and 'foreach VAR ...' | ||||
| 919 | |||||
| 920 | 249 | 712µs | 249 | 230µs | if ( $LastChild->isa('PPI::Token::Symbol') ) { # spent 230µs making 249 calls to UNIVERSAL::isa, avg 925ns/call |
| 921 | # LABEL foreach my $scalar ... | ||||
| 922 | # Open round brace, or a quotewords | ||||
| 923 | 83 | 516µs | 166 | 157µs | return 1 if $Token->isa('PPI::Token::Structure') && $Token->content eq '('; # spent 104µs making 83 calls to PPI::Token::content, avg 1µs/call
# spent 53µs making 83 calls to UNIVERSAL::isa, avg 637ns/call |
| 924 | return 1 if $Token->isa('PPI::Token::QuoteLike::Words'); | ||||
| 925 | return ''; | ||||
| 926 | } | ||||
| 927 | |||||
| 928 | 166 | 332µs | 276 | 340µs | if ( $LastChild->content eq 'foreach' or $LastChild->content eq 'for' ) { # spent 340µs making 276 calls to PPI::Token::content, avg 1µs/call |
| 929 | # There are three possibilities here | ||||
| 930 | 83 | 601µs | 166 | 163µs | if ( # spent 99µs making 83 calls to PPI::Token::content, avg 1µs/call
# spent 64µs making 83 calls to UNIVERSAL::isa, avg 772ns/call |
| 931 | $Token->isa('PPI::Token::Word') | ||||
| 932 | and ( | ||||
| 933 | ($STATEMENT_CLASSES{ $Token->content } || '') | ||||
| 934 | eq | ||||
| 935 | 'PPI::Statement::Variable' | ||||
| 936 | ) | ||||
| 937 | ) { | ||||
| 938 | # VAR == 'my ...' | ||||
| 939 | return 1; | ||||
| 940 | } elsif ( $Token->content =~ /^\$/ ) { | ||||
| 941 | # VAR == '$scalar' | ||||
| 942 | return 1; | ||||
| 943 | } elsif ( $Token->isa('PPI::Token::Structure') and $Token->content eq '(' ) { | ||||
| 944 | return 1; | ||||
| 945 | } elsif ( $Token->isa('PPI::Token::QuoteLike::Words') ) { | ||||
| 946 | return 1; | ||||
| 947 | } else { | ||||
| 948 | return ''; | ||||
| 949 | } | ||||
| 950 | } | ||||
| 951 | |||||
| 952 | 83 | 165µs | 83 | 96µs | if ( # spent 96µs making 83 calls to PPI::Token::content, avg 1µs/call |
| 953 | ($STATEMENT_CLASSES{ $LastChild->content } || '') | ||||
| 954 | eq | ||||
| 955 | 'PPI::Statement::Variable' | ||||
| 956 | ) { | ||||
| 957 | # LABEL foreach my ... | ||||
| 958 | # Only a scalar will do | ||||
| 959 | 83 | 514µs | 166 | 179µs | return $Token->content =~ /^\$/; # spent 99µs making 83 calls to PPI::Token::content, avg 1µs/call
# spent 81µs making 83 calls to PPI::Lexer::CORE:match, avg 973ns/call |
| 960 | } | ||||
| 961 | |||||
| 962 | # Handle the rare for my $foo qw{bar} ... case | ||||
| 963 | if ( $LastChild->isa('PPI::Token::QuoteLike::Words') ) { | ||||
| 964 | # LABEL for VAR QW ... | ||||
| 965 | # LABEL foreach VAR QW ... | ||||
| 966 | # Only a block will do | ||||
| 967 | return $Token->isa('PPI::Token::Structure') && $Token->content eq '{'; | ||||
| 968 | } | ||||
| 969 | } | ||||
| 970 | |||||
| 971 | # Something we don't know about... what could it be | ||||
| 972 | PPI::Exception->throw("Illegal state in '$type' compound statement"); | ||||
| 973 | } | ||||
| 974 | |||||
| - - | |||||
| 979 | ##################################################################### | ||||
| 980 | # Lex Methods - Structure Object | ||||
| 981 | |||||
| 982 | # Given a parent element, and a ( token to open a structure, determine | ||||
| 983 | # the class that the structure should be. | ||||
| 984 | # spent 168ms (95.9+72.0) within PPI::Lexer::_round which was called 3157 times, avg 53µs/call:
# 3157 times (95.9ms+72.0ms) by PPI::Lexer::_lex_statement at line 650, avg 53µs/call | ||||
| 985 | 3157 | 952µs | my ($self, $Parent) = @_; | ||
| 986 | # my $self = shift; | ||||
| 987 | # my $Parent = _INSTANCE(shift, 'PPI::Node') or die "Bad param 1"; | ||||
| 988 | |||||
| 989 | # Get the last significant element in the parent | ||||
| 990 | 3157 | 4.22ms | 3157 | 21.1ms | my $Element = $Parent->schild(-1); # spent 21.1ms making 3157 calls to PPI::Node::schild, avg 7µs/call |
| 991 | 3157 | 47.1ms | 9244 | 19.3ms | if ( _INSTANCE($Element, 'PPI::Token::Word') ) { # spent 15.0ms making 3157 calls to Params::Util::_INSTANCE, avg 5µs/call
# spent 2.40ms making 3134 calls to UNIVERSAL::isa, avg 765ns/call
# spent 1.89ms making 2953 calls to PPI::Util::TRUE, avg 641ns/call |
| 992 | # Can it be determined because it is a keyword? | ||||
| 993 | 2953 | 4.74ms | 2953 | 3.91ms | my $rclass = $ROUND{$Element->content}; # spent 3.91ms making 2953 calls to PPI::Token::content, avg 1µs/call |
| 994 | 2953 | 1.98ms | return $rclass if $rclass; | ||
| 995 | } | ||||
| 996 | |||||
| 997 | # If we are part of a for or foreach statement, we are a ForLoop | ||||
| 998 | 2680 | 27.4ms | 7874 | 9.93ms | if ( $Parent->isa('PPI::Statement::Compound') ) { # spent 9.93ms making 7874 calls to UNIVERSAL::isa, avg 1µs/call |
| 999 | 83 | 524µs | 166 | 8.88ms | if ( $Parent->type =~ /^for(?:each)?$/ ) { # spent 8.80ms making 83 calls to PPI::Statement::Compound::type, avg 106µs/call
# spent 79µs making 83 calls to PPI::Lexer::CORE:match, avg 949ns/call |
| 1000 | return 'PPI::Structure::For'; | ||||
| 1001 | } | ||||
| 1002 | } elsif ( $Parent->isa('PPI::Statement::Given') ) { | ||||
| 1003 | return 'PPI::Structure::Given'; | ||||
| 1004 | } elsif ( $Parent->isa('PPI::Statement::When') ) { | ||||
| 1005 | return 'PPI::Structure::When'; | ||||
| 1006 | } | ||||
| 1007 | |||||
| 1008 | # Otherwise, it must be a list | ||||
| 1009 | |||||
| 1010 | # If the previous element is -> then we mark it as a dereference | ||||
| 1011 | 2597 | 25.3ms | 5363 | 13.8ms | if ( _INSTANCE($Element, 'PPI::Token::Operator') and $Element->content eq '->' ) { # spent 11.1ms making 2597 calls to Params::Util::_INSTANCE, avg 4µs/call
# spent 2.50ms making 2574 calls to UNIVERSAL::isa, avg 972ns/call
# spent 130µs making 96 calls to PPI::Token::content, avg 1µs/call
# spent 57µs making 96 calls to PPI::Util::TRUE, avg 598ns/call |
| 1012 | $Element->{_dereference} = 1; | ||||
| 1013 | } | ||||
| 1014 | |||||
| 1015 | 'PPI::Structure::List' | ||||
| 1016 | 2597 | 6.21ms | } | ||
| 1017 | |||||
| 1018 | # Given a parent element, and a [ token to open a structure, determine | ||||
| 1019 | # the class that the structure should be. | ||||
| 1020 | # spent 10.6ms (6.18+4.44) within PPI::Lexer::_square which was called 359 times, avg 30µs/call:
# 359 times (6.18ms+4.44ms) by PPI::Lexer::_lex_statement at line 650, avg 30µs/call | ||||
| 1021 | 359 | 142µs | my ($self, $Parent) = @_; | ||
| 1022 | # my $self = shift; | ||||
| 1023 | # my $Parent = _INSTANCE(shift, 'PPI::Node') or die "Bad param 1"; | ||||
| 1024 | |||||
| 1025 | # Get the last significant element in the parent | ||||
| 1026 | 359 | 531µs | 359 | 2.51ms | my $Element = $Parent->schild(-1); # spent 2.51ms making 359 calls to PPI::Node::schild, avg 7µs/call |
| 1027 | |||||
| 1028 | # Is this a subscript, like $foo[1] or $foo{expr} | ||||
| 1029 | |||||
| 1030 | 359 | 1.14ms | 356 | 242µs | if ( $Element ) { # spent 242µs making 356 calls to PPI::Util::TRUE, avg 681ns/call |
| 1031 | 356 | 1.52ms | 596 | 674µs | if ( $Element->isa('PPI::Token::Operator') and $Element->content eq '->' ) { # spent 334µs making 354 calls to UNIVERSAL::isa, avg 944ns/call
# spent 332µs making 240 calls to PPI::Token::content, avg 1µs/call
# spent 8µs making 2 calls to PPI::Structure::List::isa, avg 4µs/call |
| 1032 | # $foo->[] | ||||
| 1033 | 62 | 47µs | $Element->{_dereference} = 1; | ||
| 1034 | 62 | 155µs | return 'PPI::Structure::Subscript'; | ||
| 1035 | } | ||||
| 1036 | 294 | 1.05ms | 294 | 415µs | if ( $Element->isa('PPI::Structure::Subscript') ) { # spent 407µs making 292 calls to UNIVERSAL::isa, avg 1µs/call
# spent 8µs making 2 calls to PPI::Structure::List::isa, avg 4µs/call |
| 1037 | # $foo{}[] | ||||
| 1038 | return 'PPI::Structure::Subscript'; | ||||
| 1039 | } | ||||
| 1040 | 294 | 1.68ms | 516 | 590µs | if ( $Element->isa('PPI::Token::Symbol') and $Element->content =~ /^(?:\$|\@)/ ) { # spent 298µs making 292 calls to UNIVERSAL::isa, avg 1µs/call
# spent 152µs making 111 calls to PPI::Token::content, avg 1µs/call
# spent 133µs making 111 calls to PPI::Lexer::CORE:match, avg 1µs/call
# spent 8µs making 2 calls to PPI::Structure::List::isa, avg 4µs/call |
| 1041 | # $foo[], @foo[] | ||||
| 1042 | return 'PPI::Structure::Subscript'; | ||||
| 1043 | } | ||||
| 1044 | # FIXME - More cases to catch | ||||
| 1045 | } | ||||
| 1046 | |||||
| 1047 | # Otherwise, we assume that it's an anonymous arrayref constructor | ||||
| 1048 | 186 | 464µs | 'PPI::Structure::Constructor'; | ||
| 1049 | } | ||||
| 1050 | |||||
| 1051 | 2 | 67µs | 2 | 69µs | # spent 38µs (8+30) within PPI::Lexer::BEGIN@1051 which was called:
# once (8µs+30µs) by PPI::BEGIN@29 at line 1051 # spent 38µs making 1 call to PPI::Lexer::BEGIN@1051
# spent 30µs making 1 call to vars::import |
| 1052 | # spent 15µs within PPI::Lexer::BEGIN@1052 which was called:
# once (15µs+0s) by PPI::BEGIN@29 at line 1085 | ||||
| 1053 | # Keyword -> Structure class maps | ||||
| 1054 | 1 | 10µs | %CURLY_CLASSES = ( | ||
| 1055 | # Blocks | ||||
| 1056 | 'sub' => 'PPI::Structure::Block', | ||||
| 1057 | 'grep' => 'PPI::Structure::Block', | ||||
| 1058 | 'map' => 'PPI::Structure::Block', | ||||
| 1059 | 'sort' => 'PPI::Structure::Block', | ||||
| 1060 | 'do' => 'PPI::Structure::Block', | ||||
| 1061 | |||||
| 1062 | # Hash constructors | ||||
| 1063 | 'scalar' => 'PPI::Structure::Constructor', | ||||
| 1064 | '=' => 'PPI::Structure::Constructor', | ||||
| 1065 | '||=' => 'PPI::Structure::Constructor', | ||||
| 1066 | ',' => 'PPI::Structure::Constructor', | ||||
| 1067 | '=>' => 'PPI::Structure::Constructor', | ||||
| 1068 | '+' => 'PPI::Structure::Constructor', # per perlref | ||||
| 1069 | 'return' => 'PPI::Structure::Constructor', # per perlref | ||||
| 1070 | 'bless' => 'PPI::Structure::Constructor', # pragmatic -- | ||||
| 1071 | # perlfunc says first arg is a reference, and | ||||
| 1072 | # bless {; ... } fails to compile. | ||||
| 1073 | ); | ||||
| 1074 | |||||
| 1075 | 1 | 6µs | @CURLY_LOOKAHEAD_CLASSES = ( | ||
| 1076 | {}, # not used | ||||
| 1077 | { | ||||
| 1078 | ';' => 'PPI::Structure::Block', # per perlref | ||||
| 1079 | '}' => 'PPI::Structure::Constructor', | ||||
| 1080 | }, | ||||
| 1081 | { | ||||
| 1082 | '=>' => 'PPI::Structure::Constructor', | ||||
| 1083 | }, | ||||
| 1084 | ); | ||||
| 1085 | 1 | 890µs | 1 | 15µs | } # spent 15µs making 1 call to PPI::Lexer::BEGIN@1052 |
| 1086 | |||||
| 1087 | =pod | ||||
| 1088 | |||||
| 1089 | =begin testing _curly 26 | ||||
| 1090 | |||||
| 1091 | my $document = PPI::Document->new(\<<'END_PERL'); | ||||
| 1092 | use constant { One => 1 }; | ||||
| 1093 | use constant 1 { One => 1 }; | ||||
| 1094 | $foo->{bar}; | ||||
| 1095 | $foo[1]{bar}; | ||||
| 1096 | $foo{bar}; | ||||
| 1097 | sub {1}; | ||||
| 1098 | grep { $_ } 0 .. 2; | ||||
| 1099 | map { $_ => 1 } 0 .. 2; | ||||
| 1100 | sort { $b <=> $a } 0 .. 2; | ||||
| 1101 | do {foo}; | ||||
| 1102 | $foo = { One => 1 }; | ||||
| 1103 | $foo ||= { One => 1 }; | ||||
| 1104 | 1, { One => 1 }; | ||||
| 1105 | One => { Two => 2 }; | ||||
| 1106 | {foo, bar}; | ||||
| 1107 | {foo => bar}; | ||||
| 1108 | {}; | ||||
| 1109 | +{foo, bar}; | ||||
| 1110 | {; => bar}; | ||||
| 1111 | @foo{'bar', 'baz'}; | ||||
| 1112 | @{$foo}{'bar', 'baz'}; | ||||
| 1113 | ${$foo}{bar}; | ||||
| 1114 | return { foo => 'bar' }; | ||||
| 1115 | bless { foo => 'bar' }; | ||||
| 1116 | END_PERL | ||||
| 1117 | |||||
| 1118 | isa_ok( $document, 'PPI::Document' ); | ||||
| 1119 | $document->index_locations(); | ||||
| 1120 | |||||
| 1121 | my @statements; | ||||
| 1122 | foreach my $elem ( @{ $document->find( 'PPI::Statement' ) || [] } ) { | ||||
| 1123 | $statements[ $elem->line_number() - 1 ] ||= $elem; | ||||
| 1124 | } | ||||
| 1125 | |||||
| 1126 | is( scalar(@statements), 24, 'Found 24 statements' ); | ||||
| 1127 | |||||
| 1128 | isa_ok( $statements[0]->schild(2), 'PPI::Structure::Constructor', | ||||
| 1129 | 'The curly in ' . $statements[0]); | ||||
| 1130 | isa_ok( $statements[1]->schild(3), 'PPI::Structure::Constructor', | ||||
| 1131 | 'The curly in ' . $statements[1]); | ||||
| 1132 | isa_ok( $statements[2]->schild(2), 'PPI::Structure::Subscript', | ||||
| 1133 | 'The curly in ' . $statements[2]); | ||||
| 1134 | isa_ok( $statements[3]->schild(2), 'PPI::Structure::Subscript', | ||||
| 1135 | 'The curly in ' . $statements[3]); | ||||
| 1136 | isa_ok( $statements[4]->schild(1), 'PPI::Structure::Subscript', | ||||
| 1137 | 'The curly in ' . $statements[4]); | ||||
| 1138 | isa_ok( $statements[5]->schild(1), 'PPI::Structure::Block', | ||||
| 1139 | 'The curly in ' . $statements[5]); | ||||
| 1140 | isa_ok( $statements[6]->schild(1), 'PPI::Structure::Block', | ||||
| 1141 | 'The curly in ' . $statements[6]); | ||||
| 1142 | isa_ok( $statements[7]->schild(1), 'PPI::Structure::Block', | ||||
| 1143 | 'The curly in ' . $statements[7]); | ||||
| 1144 | isa_ok( $statements[8]->schild(1), 'PPI::Structure::Block', | ||||
| 1145 | 'The curly in ' . $statements[8]); | ||||
| 1146 | isa_ok( $statements[9]->schild(1), 'PPI::Structure::Block', | ||||
| 1147 | 'The curly in ' . $statements[9]); | ||||
| 1148 | isa_ok( $statements[10]->schild(2), 'PPI::Structure::Constructor', | ||||
| 1149 | 'The curly in ' . $statements[10]); | ||||
| 1150 | isa_ok( $statements[11]->schild(3), 'PPI::Structure::Constructor', | ||||
| 1151 | 'The curly in ' . $statements[11]); | ||||
| 1152 | isa_ok( $statements[12]->schild(2), 'PPI::Structure::Constructor', | ||||
| 1153 | 'The curly in ' . $statements[12]); | ||||
| 1154 | isa_ok( $statements[13]->schild(2), 'PPI::Structure::Constructor', | ||||
| 1155 | 'The curly in ' . $statements[13]); | ||||
| 1156 | isa_ok( $statements[14]->schild(0), 'PPI::Structure::Block', | ||||
| 1157 | 'The curly in ' . $statements[14]); | ||||
| 1158 | isa_ok( $statements[15]->schild(0), 'PPI::Structure::Constructor', | ||||
| 1159 | 'The curly in ' . $statements[15]); | ||||
| 1160 | isa_ok( $statements[16]->schild(0), 'PPI::Structure::Constructor', | ||||
| 1161 | 'The curly in ' . $statements[16]); | ||||
| 1162 | isa_ok( $statements[17]->schild(1), 'PPI::Structure::Constructor', | ||||
| 1163 | 'The curly in ' . $statements[17]); | ||||
| 1164 | isa_ok( $statements[18]->schild(0), 'PPI::Structure::Block', | ||||
| 1165 | 'The curly in ' . $statements[18]); | ||||
| 1166 | isa_ok( $statements[19]->schild(1), 'PPI::Structure::Subscript', | ||||
| 1167 | 'The curly in ' . $statements[19]); | ||||
| 1168 | isa_ok( $statements[20]->schild(2), 'PPI::Structure::Subscript', | ||||
| 1169 | 'The curly in ' . $statements[20]); | ||||
| 1170 | isa_ok( $statements[21]->schild(2), 'PPI::Structure::Subscript', | ||||
| 1171 | 'The curly in ' . $statements[21]); | ||||
| 1172 | isa_ok( $statements[22]->schild(1), 'PPI::Structure::Constructor', | ||||
| 1173 | 'The curly in ' . $statements[22]); | ||||
| 1174 | isa_ok( $statements[23]->schild(1), 'PPI::Structure::Constructor', | ||||
| 1175 | 'The curly in ' . $statements[23]); | ||||
| 1176 | |||||
| 1177 | =end testing | ||||
| 1178 | |||||
| 1179 | =cut | ||||
| 1180 | |||||
| 1181 | # Given a parent element, and a { token to open a structure, determine | ||||
| 1182 | # the class that the structure should be. | ||||
| 1183 | # spent 222ms (79.5+142) within PPI::Lexer::_curly which was called 2273 times, avg 98µs/call:
# 2273 times (79.5ms+142ms) by PPI::Lexer::_lex_statement at line 650, avg 98µs/call | ||||
| 1184 | 2273 | 654µs | my ($self, $Parent) = @_; | ||
| 1185 | # my $self = shift; | ||||
| 1186 | # my $Parent = _INSTANCE(shift, 'PPI::Node') or die "Bad param 1"; | ||||
| 1187 | |||||
| 1188 | # Get the last significant element in the parent | ||||
| 1189 | 2273 | 2.68ms | 2273 | 14.4ms | my $Element = $Parent->schild(-1); # spent 14.4ms making 2273 calls to PPI::Node::schild, avg 6µs/call |
| 1190 | 2273 | 9.62ms | 4424 | 73.9ms | my $content = $Element ? $Element->content : ''; # spent 70.2ms making 568 calls to PPI::Structure::content, avg 124µs/call
# spent 2.17ms making 1644 calls to PPI::Token::content, avg 1µs/call
# spent 1.49ms making 2212 calls to PPI::Util::TRUE, avg 674ns/call |
| 1191 | |||||
| 1192 | # Is this a subscript, like $foo[1] or $foo{expr} | ||||
| 1193 | 2273 | 6.03ms | 2212 | 1.28ms | if ( $Element ) { # spent 1.28ms making 2212 calls to PPI::Util::TRUE, avg 581ns/call |
| 1194 | 2212 | 1.08ms | 195 | 152µs | if ( $content eq '->' and $Element->isa('PPI::Token::Operator') ) { # spent 152µs making 195 calls to UNIVERSAL::isa, avg 778ns/call |
| 1195 | # $foo->{} | ||||
| 1196 | 195 | 152µs | $Element->{_dereference} = 1; | ||
| 1197 | 195 | 472µs | return 'PPI::Structure::Subscript'; | ||
| 1198 | } | ||||
| 1199 | 2017 | 6.43ms | 2017 | 2.99ms | if ( $Element->isa('PPI::Structure::Subscript') ) { # spent 2.56ms making 1928 calls to UNIVERSAL::isa, avg 1µs/call
# spent 414µs making 86 calls to PPI::Structure::List::isa, avg 5µs/call
# spent 13µs making 3 calls to PPI::Structure::For::isa, avg 4µs/call |
| 1200 | # $foo[]{} | ||||
| 1201 | return 'PPI::Structure::Subscript'; | ||||
| 1202 | } | ||||
| 1203 | 1993 | 5.62ms | 2185 | 1.94ms | if ( $content =~ /^(?:\$|\@)/ and $Element->isa('PPI::Token::Symbol') ) { # spent 1.74ms making 1993 calls to PPI::Lexer::CORE:match, avg 873ns/call
# spent 196µs making 192 calls to UNIVERSAL::isa, avg 1µs/call |
| 1204 | # $foo{}, @foo{} | ||||
| 1205 | return 'PPI::Structure::Subscript'; | ||||
| 1206 | } | ||||
| 1207 | 1888 | 5.41ms | 1888 | 2.41ms | if ( $Element->isa('PPI::Structure::Block') ) { # spent 2.03ms making 1799 calls to UNIVERSAL::isa, avg 1µs/call
# spent 367µs making 86 calls to PPI::Structure::List::isa, avg 4µs/call
# spent 12µs making 3 calls to PPI::Structure::For::isa, avg 4µs/call |
| 1208 | # deference - ${$hash_ref}{foo} | ||||
| 1209 | # or even ${burfle}{foo} | ||||
| 1210 | # hash slice - @{$hash_ref}{'foo', 'bar'} | ||||
| 1211 | 1 | 5µs | 2 | 9µs | if ( my $prior = $Parent->schild(-2) ) { # spent 8µs making 1 call to PPI::Node::schild
# spent 500ns making 1 call to PPI::Util::TRUE |
| 1212 | 1 | 2µs | 1 | 1µs | my $prior_content = $prior->content(); # spent 1µs making 1 call to PPI::Token::content |
| 1213 | 1 | 7µs | 1 | 700ns | $prior->isa( 'PPI::Token::Cast' ) # spent 700ns making 1 call to UNIVERSAL::isa |
| 1214 | and ( $prior_content eq '@' || | ||||
| 1215 | $prior_content eq '$' ) | ||||
| 1216 | and return 'PPI::Structure::Subscript'; | ||||
| 1217 | } | ||||
| 1218 | } | ||||
| 1219 | 1887 | 1.90ms | if ( $CURLY_CLASSES{$content} ) { | ||
| 1220 | # Known type | ||||
| 1221 | return $CURLY_CLASSES{$content}; | ||||
| 1222 | } | ||||
| 1223 | } | ||||
| 1224 | |||||
| 1225 | # Are we in a compound statement | ||||
| 1226 | 1803 | 11.7ms | 1803 | 1.79ms | if ( $Parent->isa('PPI::Statement::Compound') ) { # spent 1.79ms making 1803 calls to UNIVERSAL::isa, avg 994ns/call |
| 1227 | # We will only encounter blocks in compound statements | ||||
| 1228 | return 'PPI::Structure::Block'; | ||||
| 1229 | } | ||||
| 1230 | |||||
| 1231 | # Are we the second or third argument of use | ||||
| 1232 | 1220 | 9.48ms | 1220 | 1.55ms | if ( $Parent->isa('PPI::Statement::Include') ) { # spent 1.55ms making 1220 calls to UNIVERSAL::isa, avg 1µs/call |
| 1233 | if ( $Parent->schildren == 2 || | ||||
| 1234 | $Parent->schildren == 3 && | ||||
| 1235 | $Parent->schild(2)->isa('PPI::Token::Number') | ||||
| 1236 | ) { | ||||
| 1237 | # This is something like use constant { ... }; | ||||
| 1238 | return 'PPI::Structure::Constructor'; | ||||
| 1239 | } | ||||
| 1240 | } | ||||
| 1241 | |||||
| 1242 | # Unless we are at the start of the statement, everything else should be a block | ||||
| 1243 | ### FIXME This is possibly a bad choice, but will have to do for now. | ||||
| 1244 | 1220 | 5.37ms | 1159 | 614µs | return 'PPI::Structure::Block' if $Element; # spent 614µs making 1159 calls to PPI::Util::TRUE, avg 530ns/call |
| 1245 | |||||
| 1246 | # Special case: Are we the param of a core function | ||||
| 1247 | # i.e. map({ $_ => 1 } @foo) | ||||
| 1248 | 61 | 891µs | 298 | 1.48ms | if ( # spent 669µs making 61 calls to Params::Util::_INSTANCE, avg 11µs/call
# spent 366µs making 61 calls to PPI::Element::parent, avg 6µs/call
# spent 346µs making 54 calls to PPI::Structure::List::isa, avg 6µs/call
# spent 68µs making 68 calls to UNIVERSAL::isa, avg 994ns/call
# spent 34µs making 54 calls to PPI::Util::TRUE, avg 626ns/call |
| 1249 | $Parent->isa('PPI::Statement') | ||||
| 1250 | and | ||||
| 1251 | _INSTANCE($Parent->parent, 'PPI::Structure::List') | ||||
| 1252 | ) { | ||||
| 1253 | 54 | 214µs | 162 | 1.10ms | my $function = $Parent->parent->parent->schild(-2); # spent 741µs making 54 calls to PPI::Node::schild, avg 14µs/call
# spent 356µs making 108 calls to PPI::Element::parent, avg 3µs/call |
| 1254 | 54 | 399µs | 162 | 188µs | if ( $function and $function->content =~ /^(?:map|grep|sort)$/ ) { # spent 81µs making 54 calls to PPI::Lexer::CORE:match, avg 1µs/call
# spent 74µs making 54 calls to PPI::Token::content, avg 1µs/call
# spent 33µs making 54 calls to PPI::Util::TRUE, avg 611ns/call |
| 1255 | return 'PPI::Structure::Block'; | ||||
| 1256 | } | ||||
| 1257 | } | ||||
| 1258 | |||||
| 1259 | # We need to scan ahead. | ||||
| 1260 | 61 | 13µs | my $Next; | ||
| 1261 | 61 | 22µs | my $position = 0; | ||
| 1262 | 61 | 33µs | my @delayed = (); | ||
| 1263 | 61 | 950µs | 512 | 37.3ms | while ( $Next = $self->_get_token ) { # spent 37.2ms making 256 calls to PPI::Lexer::_get_token, avg 145µs/call
# spent 153µs making 256 calls to PPI::Util::TRUE, avg 599ns/call |
| 1264 | 324 | 371µs | 324 | 328µs | unless ( $Next->significant ) { # spent 202µs making 190 calls to PPI::Token::Whitespace::significant, avg 1µs/call
# spent 120µs making 129 calls to PPI::Element::significant, avg 926ns/call
# spent 7µs making 5 calls to PPI::Token::Comment::significant, avg 1µs/call |
| 1265 | 195 | 64µs | push @delayed, $Next; | ||
| 1266 | 195 | 88µs | next; | ||
| 1267 | } | ||||
| 1268 | |||||
| 1269 | # If we are off the end of the lookahead array, | ||||
| 1270 | 129 | 305µs | 122 | 178µs | if ( ++$position >= @CURLY_LOOKAHEAD_CLASSES ) { # spent 178µs making 122 calls to PPI::Token::content, avg 1µs/call |
| 1271 | # default to block. | ||||
| 1272 | 7 | 18µs | 7 | 28µs | $self->_buffer( splice(@delayed), $Next ); # spent 28µs making 7 calls to PPI::Lexer::_buffer, avg 4µs/call |
| 1273 | 7 | 4µs | last; | ||
| 1274 | # If the content at this position is known | ||||
| 1275 | } elsif ( my $class = $CURLY_LOOKAHEAD_CLASSES[$position] | ||||
| 1276 | {$Next->content} ) { | ||||
| 1277 | # return the associated class. | ||||
| 1278 | 54 | 148µs | 54 | 245µs | $self->_buffer( splice(@delayed), $Next ); # spent 245µs making 54 calls to PPI::Lexer::_buffer, avg 5µs/call |
| 1279 | 54 | 178µs | return $class; | ||
| 1280 | } | ||||
| 1281 | |||||
| 1282 | # Delay and continue | ||||
| 1283 | 68 | 6.05ms | 136 | 628µs | push @delayed, $Next; # spent 564µs making 68 calls to PPI::Lexer::_get_token, avg 8µs/call
# spent 64µs making 68 calls to PPI::Util::TRUE, avg 940ns/call |
| 1284 | } | ||||
| 1285 | |||||
| 1286 | # Hit the end of the document, or bailed out, go with block | ||||
| 1287 | 7 | 10µs | 7 | 9µs | $self->_buffer( splice(@delayed) ); # spent 9µs making 7 calls to PPI::Lexer::_buffer, avg 1µs/call |
| 1288 | 7 | 15µs | if ( ref $Parent eq 'PPI::Statement' ) { | ||
| 1289 | bless $Parent, 'PPI::Statement::Compound'; | ||||
| 1290 | } | ||||
| 1291 | 7 | 23µs | return 'PPI::Structure::Block'; | ||
| 1292 | } | ||||
| 1293 | |||||
| 1294 | =pod | ||||
| 1295 | |||||
| 1296 | =begin testing _lex_structure 4 | ||||
| 1297 | |||||
| 1298 | # Validate the creation of a null statement | ||||
| 1299 | SCOPE: { | ||||
| 1300 | my $token = new_ok( 'PPI::Token::Structure' => [ ';' ] ); | ||||
| 1301 | my $null = new_ok( 'PPI::Statement::Null' => [ $token ] ); | ||||
| 1302 | is( $null->content, ';', '->content ok' ); | ||||
| 1303 | } | ||||
| 1304 | |||||
| 1305 | # Validate the creation of an empty statement | ||||
| 1306 | new_ok( 'PPI::Statement' => [ ] ); | ||||
| 1307 | |||||
| 1308 | =end testing | ||||
| 1309 | |||||
| 1310 | =cut | ||||
| 1311 | |||||
| 1312 | # spent 9.04s (655ms+8.39) within PPI::Lexer::_lex_structure which was called 5789 times, avg 1.56ms/call:
# 5789 times (655ms+8.39s) by PPI::Lexer::_lex_statement at line 655, avg 1.56ms/call | ||||
| 1313 | 5789 | 1.34ms | my ($self, $Structure) = @_; | ||
| 1314 | # my $self = shift; | ||||
| 1315 | # my $Structure = _INSTANCE(shift, 'PPI::Structure') or die "Bad param 1"; | ||||
| 1316 | |||||
| 1317 | # Start the processing loop | ||||
| 1318 | 5789 | 686µs | my $Token; | ||
| 1319 | 5789 | 38.0ms | 28772 | 3.38s | while ( ref($Token = $self->_get_token) ) { # spent 3.38s making 28772 calls to PPI::Lexer::_get_token, avg 117µs/call |
| 1320 | # Is this a direct type token | ||||
| 1321 | 28773 | 31.2ms | 28773 | 28.9ms | unless ( $Token->significant ) { # spent 15.5ms making 14524 calls to PPI::Token::Whitespace::significant, avg 1µs/call
# spent 12.3ms making 13303 calls to PPI::Element::significant, avg 923ns/call
# spent 1.19ms making 944 calls to PPI::Token::Comment::significant, avg 1µs/call
# spent 3µs making 2 calls to PPI::Token::Pod::significant, avg 1µs/call |
| 1322 | 15470 | 8.22ms | push @{$self->{delayed}}, $Token; | ||
| 1323 | # $self->_delay_element( $Token ); | ||||
| 1324 | 15470 | 6.15ms | next; | ||
| 1325 | } | ||||
| 1326 | |||||
| 1327 | # Anything other than a Structure starts a Statement | ||||
| 1328 | 13303 | 90.4ms | 13303 | 14.9ms | unless ( $Token->isa('PPI::Token::Structure') ) { # spent 14.9ms making 13303 calls to UNIVERSAL::isa, avg 1µs/call |
| 1329 | # Because _statement may well delay and rollback itself, | ||||
| 1330 | # we need to add the delayed tokens early | ||||
| 1331 | 7432 | 8.37ms | 7432 | 117ms | $self->_add_delayed( $Structure ); # spent 117ms making 7432 calls to PPI::Lexer::_add_delayed, avg 16µs/call |
| 1332 | |||||
| 1333 | # Determine the class for the Statement and create it | ||||
| 1334 | 7432 | 23.0ms | 14864 | 445ms | my $Statement = $self->_statement($Structure, $Token)->new($Token); # spent 259ms making 7432 calls to PPI::Lexer::_statement, avg 35µs/call
# spent 186ms making 7432 calls to PPI::Statement::new, avg 25µs/call |
| 1335 | |||||
| 1336 | # Move the lexing down into the Statement | ||||
| 1337 | 7432 | 9.27ms | 7432 | 81.2ms | $self->_add_element( $Structure, $Statement ); # spent 81.2ms making 7432 calls to PPI::Lexer::_add_element, avg 11µs/call |
| 1338 | 7432 | 10.1ms | 7432 | 0s | $self->_lex_statement( $Statement ); # spent 11.2s making 7432 calls to PPI::Lexer::_lex_statement, avg 1.51ms/call, recursion: max depth 7, sum of overlapping time 11.2s |
| 1339 | |||||
| 1340 | 7432 | 4.10ms | next; | ||
| 1341 | } | ||||
| 1342 | |||||
| 1343 | # Is this the opening of another structure directly inside us? | ||||
| 1344 | 5871 | 6.59ms | 5871 | 29.3ms | if ( $Token->__LEXER__opens ) { # spent 29.3ms making 5871 calls to PPI::Token::__LEXER__opens, avg 5µs/call |
| 1345 | # Rollback the Token, and recurse into the statement | ||||
| 1346 | 81 | 113µs | 81 | 277µs | $self->_rollback( $Token ); # spent 277µs making 81 calls to PPI::Lexer::_rollback, avg 3µs/call |
| 1347 | 81 | 150µs | 81 | 515µs | my $Statement = PPI::Statement->new; # spent 515µs making 81 calls to PPI::Statement::new, avg 6µs/call |
| 1348 | 81 | 125µs | 81 | 811µs | $self->_add_element( $Structure, $Statement ); # spent 811µs making 81 calls to PPI::Lexer::_add_element, avg 10µs/call |
| 1349 | 81 | 144µs | 81 | 0s | $self->_lex_statement( $Statement ); # spent 660ms making 81 calls to PPI::Lexer::_lex_statement, avg 8.14ms/call, recursion: max depth 5, sum of overlapping time 660ms |
| 1350 | 81 | 73µs | next; | ||
| 1351 | } | ||||
| 1352 | |||||
| 1353 | # Is this the close of a structure ( which would be an error ) | ||||
| 1354 | 5790 | 6.46ms | 5790 | 36.1ms | if ( $Token->__LEXER__closes ) { # spent 36.1ms making 5790 calls to PPI::Token::__LEXER__closes, avg 6µs/call |
| 1355 | # Is this OUR closing structure | ||||
| 1356 | 5789 | 20.0ms | 17367 | 26.3ms | if ( $Token->content eq $Structure->start->__LEXER__opposite ) { # spent 10.0ms making 5789 calls to PPI::Token::Structure::__LEXER__opposite, avg 2µs/call
# spent 8.13ms making 5789 calls to PPI::Structure::start, avg 1µs/call
# spent 8.10ms making 5789 calls to PPI::Token::content, avg 1µs/call |
| 1357 | # Add any delayed tokens, and the finishing token (the ugly way) | ||||
| 1358 | 5789 | 7.31ms | 5789 | 59.4ms | $self->_add_delayed( $Structure ); # spent 59.4ms making 5789 calls to PPI::Lexer::_add_delayed, avg 10µs/call |
| 1359 | 5789 | 3.25ms | $Structure->{finish} = $Token; | ||
| 1360 | 5789 | 41.5ms | 11578 | 9.36ms | Scalar::Util::weaken( # spent 4.99ms making 5789 calls to Scalar::Util::weaken, avg 862ns/call
# spent 4.38ms making 5789 calls to Scalar::Util::refaddr, avg 756ns/call |
| 1361 | $_PARENT{Scalar::Util::refaddr $Token} = $Structure | ||||
| 1362 | ); | ||||
| 1363 | |||||
| 1364 | # Confirm that ForLoop structures are actually so, and | ||||
| 1365 | # aren't really a list. | ||||
| 1366 | 5789 | 17.6ms | 5789 | 18.8ms | if ( $Structure->isa('PPI::Structure::For') ) { # spent 13.8ms making 2597 calls to PPI::Structure::List::isa, avg 5µs/call
# spent 4.59ms making 3103 calls to UNIVERSAL::isa, avg 1µs/call
# spent 394µs making 89 calls to PPI::Structure::For::isa, avg 4µs/call |
| 1367 | 329 | 4.84ms | 329 | 457µs | if ( 2 > scalar grep { # spent 245µs making 89 calls to PPI::Node::children, avg 3µs/call
# spent 212µs making 240 calls to UNIVERSAL::isa, avg 883ns/call |
| 1368 | $_->isa('PPI::Statement') | ||||
| 1369 | } $Structure->children ) { | ||||
| 1370 | bless($Structure, 'PPI::Structure::List'); | ||||
| 1371 | } | ||||
| 1372 | } | ||||
| 1373 | 5789 | 22.5ms | return 1; | ||
| 1374 | } | ||||
| 1375 | |||||
| 1376 | # Unmatched closing brace. | ||||
| 1377 | # Either they typed the wrong thing, or haven't put | ||||
| 1378 | # one at all. Either way it's an error we need to | ||||
| 1379 | # somehow handle gracefully. For now, we'll treat it | ||||
| 1380 | # as implicitly ending the structure. This causes the | ||||
| 1381 | # least damage across the various reasons why this | ||||
| 1382 | # might have happened. | ||||
| 1383 | return $self->_rollback( $Token ); | ||||
| 1384 | } | ||||
| 1385 | |||||
| 1386 | # It's a semi-colon on it's own, just inside the block. | ||||
| 1387 | # This is a null statement. | ||||
| 1388 | $self->_add_element( | ||||
| 1389 | 1 | 33µs | 3 | 120µs | $Structure, # spent 103µs making 1 call to PPI::Statement::new
# spent 9µs making 1 call to PPI::Lexer::_add_element
# spent 8µs making 1 call to PPI::Lexer::_get_token |
| 1390 | PPI::Statement::Null->new($Token), | ||||
| 1391 | ); | ||||
| 1392 | } | ||||
| 1393 | |||||
| 1394 | # Is this an error | ||||
| 1395 | unless ( defined $Token ) { | ||||
| 1396 | PPI::Exception->throw; | ||||
| 1397 | } | ||||
| 1398 | |||||
| 1399 | # No, it's just the end of file. | ||||
| 1400 | # Add any insignificant trailing tokens. | ||||
| 1401 | $self->_add_delayed( $Structure ); | ||||
| 1402 | } | ||||
| 1403 | |||||
| - - | |||||
| 1408 | ##################################################################### | ||||
| 1409 | # Support Methods | ||||
| 1410 | |||||
| 1411 | # Get the next token for processing, handling buffering | ||||
| 1412 | # spent 7.26s (459ms+6.80) within PPI::Lexer::_get_token which was called 111133 times, avg 65µs/call:
# 61803 times (263ms+2.06s) by PPI::Lexer::_lex_statement at line 606, avg 38µs/call
# 28772 times (111ms+3.27s) by PPI::Lexer::_lex_structure at line 1319, avg 117µs/call
# 9356 times (40.7ms+1.05s) by PPI::Lexer::_lex_document at line 270, avg 117µs/call
# 5789 times (23.0ms+32.9ms) by PPI::Lexer::_lex_statement at line 655, avg 10µs/call
# 2044 times (9.93ms+13.7ms) by PPI::Lexer::_statement at line 500, avg 12µs/call
# 1962 times (6.26ms+12.7ms) by PPI::Lexer::_statement at line 542, avg 10µs/call
# 576 times (1.81ms+319ms) by PPI::Lexer::_lex_end at line 680, avg 557µs/call
# 362 times (1.07ms+6.41ms) by PPI::Lexer::_statement at line 429, avg 21µs/call
# 256 times (880µs+36.3ms) by PPI::Lexer::_curly at line 1263, avg 145µs/call
# 144 times (431µs+684µs) by PPI::Lexer::_lex_end at line 675, avg 8µs/call
# 68 times (232µs+333µs) by PPI::Lexer::_curly at line 1283, avg 8µs/call
# once (3µs+5µs) by PPI::Lexer::_lex_structure at line 1389 | ||||
| 1413 | 111133 | 476ms | 111133 | 6.80s | shift(@{$_[0]->{buffer}}) or $_[0]->{Tokenizer}->get_token; # spent 6.79s making 94513 calls to PPI::Tokenizer::get_token, avg 72µs/call
# spent 9.35ms making 16620 calls to PPI::Util::TRUE, avg 563ns/call |
| 1414 | } | ||||
| 1415 | |||||
| 1416 | # Old long version of the above | ||||
| 1417 | # my $self = shift; | ||||
| 1418 | # # First from the buffer | ||||
| 1419 | # if ( @{$self->{buffer}} ) { | ||||
| 1420 | # return shift @{$self->{buffer}}; | ||||
| 1421 | # } | ||||
| 1422 | # | ||||
| 1423 | # # Then from the Tokenizer | ||||
| 1424 | # $self->{Tokenizer}->get_token; | ||||
| 1425 | # } | ||||
| 1426 | |||||
| 1427 | # Delay the addition of a insignificant elements. | ||||
| 1428 | # This ended up being inlined. | ||||
| 1429 | # sub _delay_element { | ||||
| 1430 | # my $self = shift; | ||||
| 1431 | # my $Element = _INSTANCE(shift, 'PPI::Element') or die "Bad param 1"; | ||||
| 1432 | # push @{ $_[0]->{delayed} }, $_[1]; | ||||
| 1433 | # } | ||||
| 1434 | |||||
| 1435 | # Add an Element to a Node, including any delayed Elements | ||||
| 1436 | # spent 944ms (676+268) within PPI::Lexer::_add_element which was called 50565 times, avg 19µs/call:
# 23107 times (389ms+182ms) by PPI::Lexer::_lex_statement at line 636, avg 25µs/call
# 7432 times (71.0ms+10.2ms) by PPI::Lexer::_lex_structure at line 1337, avg 11µs/call
# 6188 times (68.1ms+9.71ms) by PPI::Lexer::_lex_document at line 273, avg 13µs/call
# 5789 times (67.2ms+32.3ms) by PPI::Lexer::_lex_statement at line 654, avg 17µs/call
# 4943 times (56.6ms+29.2ms) by PPI::Lexer::_lex_statement at line 642, avg 17µs/call
# 3018 times (23.2ms+4.36ms) by PPI::Lexer::_lex_document at line 294, avg 9µs/call
# 81 times (668µs+143µs) by PPI::Lexer::_lex_structure at line 1348, avg 10µs/call
# 6 times (72µs+10µs) by PPI::Lexer::_lex_document at line 305, avg 14µs/call
# once (7µs+2µs) by PPI::Lexer::_lex_structure at line 1389 | ||||
| 1437 | 50565 | 12.3ms | my ($self, $Parent, $Element) = @_; | ||
| 1438 | # my $self = shift; | ||||
| 1439 | # my $Parent = _INSTANCE(shift, 'PPI::Node') or die "Bad param 1"; | ||||
| 1440 | # my $Element = _INSTANCE(shift, 'PPI::Element') or die "Bad param 2"; | ||||
| 1441 | |||||
| 1442 | # Handle a special case, where a statement is not fully resolved | ||||
| 1443 | 50565 | 15.8ms | if ( ref $Parent eq 'PPI::Statement' ) { | ||
| 1444 | 6883 | 7.88ms | 6883 | 49.4ms | my $first = $Parent->schild(0); # spent 49.4ms making 6883 calls to PPI::Node::schild, avg 7µs/call |
| 1445 | 6883 | 8.05ms | 6883 | 106ms | my $second = $Parent->schild(1); # spent 106ms making 6883 calls to PPI::Node::schild, avg 15µs/call |
| 1446 | 6883 | 54.4ms | 13606 | 12.3ms | if ( $first and $first->isa('PPI::Token::Label') and ! $second ) { # spent 7.49ms making 6737 calls to UNIVERSAL::isa, avg 1µs/call
# spent 4.48ms making 6803 calls to PPI::Util::TRUE, avg 659ns/call
# spent 297µs making 66 calls to PPI::Structure::List::isa, avg 4µs/call |
| 1447 | # It's a labelled statement | ||||
| 1448 | if ( $STATEMENT_CLASSES{$second->content} ) { | ||||
| 1449 | bless $Parent, $STATEMENT_CLASSES{$second->content}; | ||||
| 1450 | } | ||||
| 1451 | } | ||||
| 1452 | } | ||||
| 1453 | |||||
| 1454 | # Add first the delayed, from the front, then the passed element | ||||
| 1455 | 50565 | 29.9ms | foreach my $el ( @{$self->{delayed}} ) { | ||
| 1456 | 18659 | 133ms | 37318 | 27.7ms | Scalar::Util::weaken( # spent 14.3ms making 18659 calls to Scalar::Util::weaken, avg 768ns/call
# spent 13.3ms making 18659 calls to Scalar::Util::refaddr, avg 714ns/call |
| 1457 | $_PARENT{Scalar::Util::refaddr $el} = $Parent | ||||
| 1458 | ); | ||||
| 1459 | # Inlined $Parent->__add_element($el); | ||||
| 1460 | } | ||||
| 1461 | Scalar::Util::weaken( | ||||
| 1462 | 50565 | 357ms | 101130 | 72.5ms | $_PARENT{Scalar::Util::refaddr $Element} = $Parent # spent 40.1ms making 50565 calls to Scalar::Util::weaken, avg 793ns/call
# spent 32.4ms making 50565 calls to Scalar::Util::refaddr, avg 641ns/call |
| 1463 | ); | ||||
| 1464 | 50565 | 41.2ms | push @{$Parent->{children}}, @{$self->{delayed}}, $Element; | ||
| 1465 | |||||
| 1466 | # Clear the delayed elements | ||||
| 1467 | 50565 | 148ms | $self->{delayed} = []; | ||
| 1468 | } | ||||
| 1469 | |||||
| 1470 | # Specifically just add any delayed tokens, if any. | ||||
| 1471 | # spent 231ms (202+28.9) within PPI::Lexer::_add_delayed which was called 22172 times, avg 10µs/call:
# 7432 times (100ms+17.1ms) by PPI::Lexer::_lex_structure at line 1331, avg 16µs/call
# 5789 times (52.2ms+7.17ms) by PPI::Lexer::_lex_structure at line 1358, avg 10µs/call
# 5789 times (39.3ms+4.68ms) by PPI::Lexer::_lex_statement at line 653, avg 8µs/call
# 3018 times (9.82ms+0s) by PPI::Lexer::_lex_document at line 293, avg 3µs/call
# 144 times (528µs+0s) by PPI::Lexer::_lex_document at line 334, avg 4µs/call | ||||
| 1472 | 22172 | 5.51ms | my ($self, $Parent) = @_; | ||
| 1473 | # my $self = shift; | ||||
| 1474 | # my $Parent = _INSTANCE(shift, 'PPI::Node') or die "Bad param 1"; | ||||
| 1475 | |||||
| 1476 | # Add any delayed | ||||
| 1477 | 22172 | 15.8ms | foreach my $el ( @{$self->{delayed}} ) { | ||
| 1478 | 18723 | 156ms | 37446 | 28.9ms | Scalar::Util::weaken( # spent 15.7ms making 18723 calls to Scalar::Util::weaken, avg 836ns/call
# spent 13.3ms making 18723 calls to Scalar::Util::refaddr, avg 708ns/call |
| 1479 | $_PARENT{Scalar::Util::refaddr $el} = $Parent | ||||
| 1480 | ); | ||||
| 1481 | # Inlined $Parent->__add_element($el); | ||||
| 1482 | } | ||||
| 1483 | 22172 | 16.2ms | push @{$Parent->{children}}, @{$self->{delayed}}; | ||
| 1484 | |||||
| 1485 | # Clear the delayed elements | ||||
| 1486 | 22172 | 60.4ms | $self->{delayed} = []; | ||
| 1487 | } | ||||
| 1488 | |||||
| 1489 | # Rollback the delayed tokens, plus any passed. Once all the tokens | ||||
| 1490 | # have been moved back on to the buffer, the order should be. | ||||
| 1491 | # <--- @{$self->{delayed}}, @_, @{$self->{buffer}} <---- | ||||
| 1492 | # spent 24.0ms within PPI::Lexer::_rollback which was called 7887 times, avg 3µs/call:
# 4057 times (12.3ms+0s) by PPI::Lexer::_lex_statement at line 616, avg 3µs/call
# 1393 times (4.56ms+0s) by PPI::Lexer::_lex_statement at line 626, avg 3µs/call
# 1016 times (2.56ms+0s) by PPI::Lexer::_statement at line 514, avg 3µs/call
# 981 times (3.41ms+0s) by PPI::Lexer::_statement at line 555, avg 3µs/call
# 144 times (276µs+0s) by PPI::Lexer::_lex_end at line 690, avg 2µs/call
# 119 times (364µs+0s) by PPI::Lexer::_statement at line 443, avg 3µs/call
# 84 times (240µs+0s) by PPI::Lexer::_statement at line 451, avg 3µs/call
# 81 times (277µs+0s) by PPI::Lexer::_lex_structure at line 1346, avg 3µs/call
# 6 times (17µs+0s) by PPI::Lexer::_lex_document at line 303, avg 3µs/call
# 6 times (14µs+0s) by PPI::Lexer::_statement at line 530, avg 2µs/call | ||||
| 1493 | 7887 | 1.96ms | my $self = shift; | ||
| 1494 | |||||
| 1495 | # First, put any passed objects back | ||||
| 1496 | 7887 | 7.66ms | if ( @_ ) { | ||
| 1497 | unshift @{$self->{buffer}}, splice @_; | ||||
| 1498 | } | ||||
| 1499 | |||||
| 1500 | # Then, put back anything delayed | ||||
| 1501 | 7887 | 5.25ms | if ( @{$self->{delayed}} ) { | ||
| 1502 | unshift @{$self->{buffer}}, splice @{$self->{delayed}}; | ||||
| 1503 | } | ||||
| 1504 | |||||
| 1505 | 7887 | 27.6ms | 1; | ||
| 1506 | } | ||||
| 1507 | |||||
| 1508 | # Partial rollback, just return a single list to the buffer | ||||
| 1509 | sub _buffer { | ||||
| 1510 | 68 | 23µs | my $self = shift; | ||
| 1511 | |||||
| 1512 | # Put any passed objects back | ||||
| 1513 | 68 | 143µs | if ( @_ ) { | ||
| 1514 | unshift @{$self->{buffer}}, splice @_; | ||||
| 1515 | } | ||||
| 1516 | |||||
| 1517 | 68 | 192µs | 1; | ||
| 1518 | } | ||||
| 1519 | |||||
| - - | |||||
| 1524 | ##################################################################### | ||||
| 1525 | # Error Handling | ||||
| 1526 | |||||
| 1527 | # Set the error message | ||||
| 1528 | sub _error { | ||||
| 1529 | $errstr = $_[1]; | ||||
| 1530 | undef; | ||||
| 1531 | } | ||||
| 1532 | |||||
| 1533 | # Clear the error message. | ||||
| 1534 | # Returns the object as a convenience. | ||||
| 1535 | # spent 373µs within PPI::Lexer::_clear which was called 144 times, avg 3µs/call:
# 144 times (373µs+0s) by PPI::Lexer::new at line 122, avg 3µs/call | ||||
| 1536 | 144 | 107µs | $errstr = ''; | ||
| 1537 | 144 | 445µs | $_[0]; | ||
| 1538 | } | ||||
| 1539 | |||||
| 1540 | =pod | ||||
| 1541 | |||||
| 1542 | =head2 errstr | ||||
| 1543 | |||||
| 1544 | For any error that occurs, you can use the C<errstr>, as either | ||||
| 1545 | a static or object method, to access the error message. | ||||
| 1546 | |||||
| 1547 | If no error occurs for any particular action, C<errstr> will return false. | ||||
| 1548 | |||||
| 1549 | =cut | ||||
| 1550 | |||||
| 1551 | sub errstr { | ||||
| 1552 | $errstr; | ||||
| 1553 | } | ||||
| 1554 | |||||
| - - | |||||
| 1559 | ##################################################################### | ||||
| 1560 | # PDOM Extensions | ||||
| 1561 | # | ||||
| 1562 | # This is something of a future expansion... ignore it for now :) | ||||
| 1563 | # | ||||
| 1564 | # use PPI::Statement::Sub (); | ||||
| 1565 | # | ||||
| 1566 | # sub PPI::Statement::Sub::__LEXER__normal { '' } | ||||
| 1567 | |||||
| 1568 | 1 | 2µs | 1; | ||
| 1569 | |||||
| 1570 | =pod | ||||
| 1571 | |||||
| 1572 | =head1 TO DO | ||||
| 1573 | |||||
| 1574 | - Add optional support for some of the more common source filters | ||||
| 1575 | |||||
| 1576 | - Some additional checks for blessing things into various Statement | ||||
| 1577 | and Structure subclasses. | ||||
| 1578 | |||||
| 1579 | =head1 SUPPORT | ||||
| 1580 | |||||
| 1581 | See the L<support section|PPI/SUPPORT> in the main module. | ||||
| 1582 | |||||
| 1583 | =head1 AUTHOR | ||||
| 1584 | |||||
| 1585 | Adam Kennedy E<lt>adamk@cpan.orgE<gt> | ||||
| 1586 | |||||
| 1587 | =head1 COPYRIGHT | ||||
| 1588 | |||||
| 1589 | Copyright 2001 - 2011 Adam Kennedy. | ||||
| 1590 | |||||
| 1591 | This program is free software; you can redistribute | ||||
| 1592 | it and/or modify it under the same terms as Perl itself. | ||||
| 1593 | |||||
| 1594 | The full text of the license can be found in the | ||||
| 1595 | LICENSE file included with this module. | ||||
| 1596 | |||||
| 1597 | =cut | ||||
# spent 10.9ms within PPI::Lexer::CORE:match which was called 7181 times, avg 2µs/call:
# 4810 times (8.76ms+0s) by PPI::Lexer::_continues at line 716, avg 2µs/call
# 1993 times (1.74ms+0s) by PPI::Lexer::_curly at line 1203, avg 873ns/call
# 111 times (133µs+0s) by PPI::Lexer::_square at line 1040, avg 1µs/call
# 83 times (81µs+0s) by PPI::Lexer::_continues at line 959, avg 973ns/call
# 83 times (79µs+0s) by PPI::Lexer::_round at line 999, avg 949ns/call
# 54 times (81µs+0s) by PPI::Lexer::_curly at line 1254, avg 1µs/call
# 33 times (32µs+0s) by PPI::Lexer::_continues at line 817, avg 970ns/call
# 14 times (24µs+0s) by PPI::Lexer::_continues at line 788, avg 2µs/call |