Commit | Line | Data |
3fea05b9 |
1 | package PPI::Structure; |
2 | |
3 | =pod |
4 | |
5 | =head1 NAME |
6 | |
7 | PPI::Structure - The base class for Perl braced structures |
8 | |
9 | =head1 INHERITANCE |
10 | |
11 | PPI::Structure |
12 | isa PPI::Node |
13 | isa PPI::Element |
14 | |
15 | =head1 DESCRIPTION |
16 | |
17 | PPI::Structure is the root class for all Perl bracing structures. This |
18 | covers all forms of C< [ ... ] >, C< { ... } >, and C< ( ... ) > brace |
19 | types, and includes cases where only one half of the pair exist. |
20 | |
21 | The class PPI::Structure itself is full abstract and no objects of that |
22 | type should actually exist in the tree. |
23 | |
24 | =head2 Elements vs Children |
25 | |
26 | A B<PPI::Structure> has an unusual existance. Unlike a L<PPI::Document> |
27 | or L<PPI::Statement>, which both simply contain other elements, a |
28 | structure B<both> contains and consists of content. |
29 | |
30 | That is, the brace tokens are B<not> considered to be "children" of the |
31 | structure, but are part of it. |
32 | |
33 | In practice, this will mean that while the -E<gt>elements and -E<gt>tokens |
34 | methods (and related) B<will> return a list with the brace tokens at either |
35 | end, the -E<gt>children method explicitly will B<not> return the brace. |
36 | |
37 | =head1 STRUCTURE CLASSES |
38 | |
39 | Excluding the transient L<PPI::Structure::Unknown> that exists briefly |
40 | inside the parser, there are eight types of structure. |
41 | |
42 | =head2 L<PPI::Structure::List> |
43 | |
44 | This covers all round braces used for function arguments, in C<foreach> |
45 | loops, literal lists, and braces used for precedence-ordering purposes. |
46 | |
47 | =head2 L<PPI::Structure::For> |
48 | |
49 | Although B<not> used for the C<foreach> loop list, this B<is> used for |
50 | the special case of the round-brace three-part semicolon-seperated C<for> |
51 | loop expression (the traditional C style for loop). |
52 | |
53 | =head2 L<PPI::Structure::Given> |
54 | |
55 | This is for the expression being matched in switch statements. |
56 | |
57 | =head2 L<PPI::Structure::When> |
58 | |
59 | This is for the matching expression in "when" statements. |
60 | |
61 | =head2 L<PPI::Structure::Condition> |
62 | |
63 | This round-brace structure covers boolean conditional braces, such as |
64 | for C<if> and C<while> blocks. |
65 | |
66 | =head2 L<PPI::Structure::Block> |
67 | |
68 | This curly-brace and common structure is used for all form of code |
69 | blocks. This includes those for C<if>, C<do> and similar, as well |
70 | as C<grep>, C<map>, C<sort>, C<sub> and (labelled or anonymous) |
71 | scoping blocks. |
72 | |
73 | =head2 L<PPI::Structure::Constructor> |
74 | |
75 | This class covers brace structures used for the construction of |
76 | anonymous C<ARRAY> and C<HASH> references. |
77 | |
78 | =head2 L<PPI::Structure::Subscript> |
79 | |
80 | This class covers square-braces and curly-braces used after a |
81 | -E<gt> pointer to access the subscript of an C<ARRAY> or C<HASH>. |
82 | |
83 | =head1 METHODS |
84 | |
85 | C<PPI::Structure> itself has very few methods. Most of the time, you will be |
86 | working with the more generic L<PPI::Element> or L<PPI::Node> methods, or one |
87 | of the methods that are subclass-specific. |
88 | |
89 | =cut |
90 | |
91 | use strict; |
92 | use Scalar::Util (); |
93 | use Params::Util qw{_INSTANCE}; |
94 | use PPI::Node (); |
95 | use PPI::Exception (); |
96 | |
97 | use vars qw{$VERSION @ISA *_PARENT}; |
98 | BEGIN { |
99 | $VERSION = '1.206'; |
100 | @ISA = 'PPI::Node'; |
101 | *_PARENT = *PPI::Element::_PARENT; |
102 | } |
103 | |
104 | use PPI::Structure::Block (); |
105 | use PPI::Structure::Condition (); |
106 | use PPI::Structure::Constructor (); |
107 | use PPI::Structure::For (); |
108 | use PPI::Structure::Given (); |
109 | use PPI::Structure::List (); |
110 | use PPI::Structure::Subscript (); |
111 | use PPI::Structure::Unknown (); |
112 | use PPI::Structure::When (); |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | ##################################################################### |
119 | # Constructor |
120 | |
121 | sub new { |
122 | my $class = shift; |
123 | my $Token = PPI::Token::__LEXER__opens($_[0]) ? shift : return undef; |
124 | |
125 | # Create the object |
126 | my $self = bless { |
127 | children => [], |
128 | start => $Token, |
129 | }, $class; |
130 | |
131 | # Set the start braces parent link |
132 | Scalar::Util::weaken( |
133 | $_PARENT{Scalar::Util::refaddr $Token} = $self |
134 | ); |
135 | |
136 | $self; |
137 | } |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | ##################################################################### |
144 | # PPI::Structure API methods |
145 | |
146 | =pod |
147 | |
148 | =head2 start |
149 | |
150 | For lack of better terminology (like "open" and "close") that has not |
151 | already in use for some other more important purpose, the two individual |
152 | braces for the structure are known within PPI as the "start" and "finish" |
153 | braces (at least for method purposes). |
154 | |
155 | The C<start> method returns the start brace for the structure (i.e. the |
156 | opening brace). |
157 | |
158 | Returns the brace as a L<PPI::Token::Structure> or C<undef> if the |
159 | structure does not have a starting brace. |
160 | |
161 | Under normal parsing circumstances this should never occur, but may happen |
162 | due to manipulation of the PDOM tree. |
163 | |
164 | =cut |
165 | |
166 | sub start { $_[0]->{start} } |
167 | |
168 | =pod |
169 | |
170 | =head2 finish |
171 | |
172 | The C<finish> method returns the finish brace for the structure (i.e. the |
173 | closing brace). |
174 | |
175 | Returns the brace as a L<PPI::Token::Structure> or C<undef> if the |
176 | structure does not have a starting brace. This can be quite common if |
177 | the document is not complete (for example, from an editor where the user |
178 | may be halfway through typeing a subroutine). |
179 | |
180 | =cut |
181 | |
182 | sub finish { $_[0]->{finish} } |
183 | |
184 | =pod |
185 | |
186 | =head2 braces |
187 | |
188 | The C<braces> method is a utility method which returns the brace type, |
189 | regardless of whether has both braces defined, or just the starting |
190 | brace, or just the ending brace. |
191 | |
192 | Returns on of the three strings C<'[]'>, C<'{}'>, or C<'()'>, or C<undef> |
193 | on error (primarily not having a start brace, as mentioned above). |
194 | |
195 | =cut |
196 | |
197 | sub braces { |
198 | my $self = $_[0]->{start} ? shift : return undef; |
199 | return { |
200 | '[' => '[]', |
201 | '(' => '()', |
202 | '{' => '{}', |
203 | }->{ $self->{start}->{content} }; |
204 | } |
205 | |
206 | =pod |
207 | |
208 | =head1 complete |
209 | |
210 | The C<complete> method is a convenience method that returns true if |
211 | the both braces are defined for the structure, or false if only one |
212 | brace is defined. |
213 | |
214 | Unlike the top level C<complete> method which checks for completeness |
215 | in depth, the structure complete method ONLY confirms completeness |
216 | for the braces, and does not recurse downwards. |
217 | |
218 | =cut |
219 | |
220 | sub complete { |
221 | !! ($_[0]->{start} and $_[0]->{finish}); |
222 | } |
223 | |
224 | |
225 | |
226 | |
227 | |
228 | ##################################################################### |
229 | # PPI::Node overloaded methods |
230 | |
231 | # For us, the "elements" concept includes the brace tokens |
232 | sub elements { |
233 | my $self = shift; |
234 | |
235 | if ( wantarray ) { |
236 | # Return a list in array context |
237 | return ( $self->{start} || (), @{$self->{children}}, $self->{finish} || () ); |
238 | } else { |
239 | # Return the number of elements in scalar context. |
240 | # This is memory-cheaper than creating another big array |
241 | return scalar(@{$self->{children}}) |
242 | + ($self->{start} ? 1 : 0) |
243 | + ($self->{finish} ? 1 : 0); |
244 | } |
245 | } |
246 | |
247 | # For us, the first element is probably the opening brace |
248 | sub first_element { |
249 | # Technically, if we have no children and no opening brace, |
250 | # then the first element is the closing brace. |
251 | $_[0]->{start} or $_[0]->{children}->[0] or $_[0]->{finish}; |
252 | } |
253 | |
254 | # For us, the last element is probably the closing brace |
255 | sub last_element { |
256 | # Technically, if we have no children and no closing brace, |
257 | # then the last element is the opening brace |
258 | $_[0]->{finish} or $_[0]->{children}->[-1] or $_[0]->{start}; |
259 | } |
260 | |
261 | # Location is same as the start token, if any |
262 | sub location { |
263 | my $self = shift; |
264 | my $first = $self->first_element or return undef; |
265 | $first->location; |
266 | } |
267 | |
268 | |
269 | |
270 | |
271 | |
272 | ##################################################################### |
273 | # PPI::Element overloaded methods |
274 | |
275 | # Get the full set of tokens, including start and finish |
276 | sub tokens { |
277 | my $self = shift; |
278 | my @tokens = ( |
279 | $self->{start} || (), |
280 | $self->SUPER::tokens(@_), |
281 | $self->{finish} || (), |
282 | ); |
283 | @tokens; |
284 | } |
285 | |
286 | # Like the token method ->content, get our merged contents. |
287 | # This will recurse downwards through everything |
288 | ### Reimplement this using List::Utils stuff |
289 | sub content { |
290 | my $self = shift; |
291 | my $content = $self->{start} ? $self->{start}->content : ''; |
292 | foreach my $child ( @{$self->{children}} ) { |
293 | $content .= $child->content; |
294 | } |
295 | $content .= $self->{finish}->content if $self->{finish}; |
296 | $content; |
297 | } |
298 | |
299 | # Is the structure completed |
300 | sub _complete { |
301 | !! ( defined $_[0]->{finish} ); |
302 | } |
303 | |
304 | # You can insert either another structure, or a token |
305 | sub insert_before { |
306 | my $self = shift; |
307 | my $Element = _INSTANCE(shift, 'PPI::Element') or return undef; |
308 | if ( $Element->isa('PPI::Structure') ) { |
309 | return $self->__insert_before($Element); |
310 | } elsif ( $Element->isa('PPI::Token') ) { |
311 | return $self->__insert_before($Element); |
312 | } |
313 | ''; |
314 | } |
315 | |
316 | # As above, you can insert either another structure, or a token |
317 | sub insert_after { |
318 | my $self = shift; |
319 | my $Element = _INSTANCE(shift, 'PPI::Element') or return undef; |
320 | if ( $Element->isa('PPI::Structure') ) { |
321 | return $self->__insert_after($Element); |
322 | } elsif ( $Element->isa('PPI::Token') ) { |
323 | return $self->__insert_after($Element); |
324 | } |
325 | ''; |
326 | } |
327 | |
328 | 1; |
329 | |
330 | =pod |
331 | |
332 | =head1 SUPPORT |
333 | |
334 | See the L<support section|PPI/SUPPORT> in the main module. |
335 | |
336 | =head1 AUTHOR |
337 | |
338 | Adam Kennedy E<lt>adamk@cpan.orgE<gt> |
339 | |
340 | =head1 COPYRIGHT |
341 | |
342 | Copyright 2001 - 2009 Adam Kennedy. |
343 | |
344 | This program is free software; you can redistribute |
345 | it and/or modify it under the same terms as Perl itself. |
346 | |
347 | The full text of the license can be found in the |
348 | LICENSE file included with this module. |
349 | |
350 | =cut |