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 | _lex_statement (recurses: max depth 7, inclusive time 11.9s) | PPI::Lexer::
50565 | 9 | 1 | 676ms | 944ms | _add_element | PPI::Lexer::
5789 | 1 | 1 | 655ms | 9.04s | _lex_structure (recurses: max depth 6, inclusive time 7.76s) | PPI::Lexer::
111133 | 12 | 1 | 459ms | 7.26s | _get_token | PPI::Lexer::
10450 | 2 | 1 | 284ms | 476ms | _statement | PPI::Lexer::
22172 | 5 | 1 | 202ms | 231ms | _add_delayed | PPI::Lexer::
144 | 1 | 1 | 146ms | 12.7s | _lex_document | PPI::Lexer::
4817 | 1 | 1 | 144ms | 444ms | _continues | PPI::Lexer::
3157 | 1 | 1 | 95.9ms | 168ms | _round | PPI::Lexer::
2273 | 1 | 1 | 79.5ms | 222ms | _curly | PPI::Lexer::
7887 | 10 | 1 | 24.0ms | 24.0ms | _rollback | PPI::Lexer::
144 | 1 | 1 | 13.1ms | 337ms | _lex_end | PPI::Lexer::
7181 | 8 | 1 | 10.9ms | 10.9ms | CORE:match (opcode) | PPI::Lexer::
144 | 1 | 1 | 9.07ms | 13.2s | lex_file | PPI::Lexer::
359 | 1 | 1 | 6.18ms | 10.6ms | _square | PPI::Lexer::
144 | 1 | 1 | 3.50ms | 12.7s | lex_tokenizer | PPI::Lexer::
144 | 1 | 1 | 1.32ms | 1.70ms | new | PPI::Lexer::
144 | 1 | 1 | 373µs | 373µs | _clear | PPI::Lexer::
68 | 3 | 1 | 282µs | 282µs | _buffer | PPI::Lexer::
1 | 1 | 1 | 15µs | 15µs | BEGIN@1052 | PPI::Lexer::
1 | 1 | 1 | 13µs | 13µs | BEGIN@361 | PPI::Lexer::
1 | 1 | 1 | 12µs | 25µs | BEGIN@56 | PPI::Lexer::
1 | 1 | 1 | 12µs | 12µs | BEGIN@97 | PPI::Lexer::
1 | 1 | 1 | 12µs | 12µs | BEGIN@64 | PPI::Lexer::
1 | 1 | 1 | 8µs | 38µs | BEGIN@1051 | PPI::Lexer::
1 | 1 | 1 | 7µs | 26µs | BEGIN@360 | PPI::Lexer::
1 | 1 | 1 | 7µs | 42µs | BEGIN@100 | PPI::Lexer::
1 | 1 | 1 | 7µs | 32µs | BEGIN@58 | PPI::Lexer::
1 | 1 | 1 | 7µs | 23µs | BEGIN@96 | PPI::Lexer::
1 | 1 | 1 | 6µs | 76µs | BEGIN@63 | PPI::Lexer::
1 | 1 | 1 | 3µs | 3µs | BEGIN@59 | PPI::Lexer::
1 | 1 | 1 | 3µs | 3µs | BEGIN@57 | PPI::Lexer::
1 | 1 | 1 | 3µs | 3µs | BEGIN@61 | PPI::Lexer::
1 | 1 | 1 | 3µs | 3µs | BEGIN@60 | PPI::Lexer::
0 | 0 | 0 | 0s | 0s | _error | PPI::Lexer::
0 | 0 | 0 | 0s | 0s | errstr | PPI::Lexer::
0 | 0 | 0 | 0s | 0s | lex_source | PPI::Lexer::
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 |