1PPI(3) User Contributed Perl Documentation PPI(3)
2
3
4
6 PPI - Parse, Analyze and Manipulate Perl (without perl)
7
9 use PPI;
10
11 # Create a new empty document
12 my $Document = PPI::Document->new;
13
14 # Create a document from source
15 $Document = PPI::Document->new(\'print "Hello World!\n"');
16
17 # Load a Document from a file
18 $Document = PPI::Document->new('Module.pm');
19
20 # Does it contain any POD?
21 if ( $Document->find_any('PPI::Token::Pod') ) {
22 print "Module contains POD\n";
23 }
24
25 # Get the name of the main package
26 $pkg = $Document->find_first('PPI::Statement::Package')->namespace;
27
28 # Remove all that nasty documentation
29 $Document->prune('PPI::Token::Pod');
30 $Document->prune('PPI::Token::Comment');
31
32 # Save the file
33 $Document->save('Module.pm.stripped');
34
36 About this Document
37
38 This is the PPI manual. It describes its reason for existing, its gen‐
39 eral structure, its use, an overview of the API, and provides a few
40 implementation samples.
41
42 Background
43
44 The ability to read, and manipulate Perl (the language) programmati‐
45 cally other than with perl (the application) was one that caused diffi‐
46 culty for a long time.
47
48 The cause of this problem was Perl's complex and dynamic grammar.
49 Although there is typically not a huge diversity in the grammar of most
50 Perl code, certain issues cause large problems when it comes to pars‐
51 ing.
52
53 Indeed, quite early in Perl's history Tom Christenson introduced the
54 Perl community to the quote "Nothing but perl can parse Perl", or as it
55 is more often stated now as a truism:
56
57 "Only perl can parse Perl"
58
59 One example of the sorts of things the prevent Perl being easily parsed
60 are function signatures, as demonstrated by the following.
61
62 @result = (dothis $foo, $bar);
63
64 # Which of the following is it equivalent to?
65 @result = (dothis($foo), $bar);
66 @result = dothis($foo, $bar);
67
68 The first line above can be interpreted in two different ways, depend‐
69 ing on whether the &dothis function is expecting one argument, or two,
70 or several.
71
72 A "code parser" (something that parses for the purpose of execution)
73 such as perl needs information that is not found in the immediate
74 vicinity of the statement being parsed.
75
76 The information might not just be elsewhere in the file, it might not
77 even be in the same file at all. It might also not be able to determine
78 this information without the prior execution of a "BEGIN {}" block, or
79 the loading and execution of one or more external modules. Or worse the
80 &dothis function may not even have been written yet.
81
82 When parsing Perl as code, you must also execute it
83
84 Even perl itself never really fully understands the structure of the
85 source code after and indeed as it processes it, and in that sense
86 doesn't "parse" Perl source into anything remotely like a structured
87 document. This makes it of no real use for any task that needs to
88 treat the source code as a document, and do so reliably and robustly.
89
90 For more information on why it is impossible to parse perl, see Randal
91 Schwartz's seminal response to the question of "Why can't you parse
92 Perl".
93
94 <http://www.perlmonks.org/index.pl?node_id=44722>
95
96 The purpose of PPI is not to parse Perl Code, but to parse Perl Docu‐
97 ments. By treating the problem this way, we are able to parse a single
98 file containing Perl source code "isolated" from any other resources,
99 such as libraries upon which the code may depend, and without needing
100 to run an instance of perl alongside or inside the parser.
101
102 Historically, using an embedded perl parser was widely considered to be
103 the most likely avenue for finding a solution to "Parse::Perl". It was
104 investigated from time to time and attempts have generally failed or
105 suffered from sufficiently bad corner cases that they were abandoned.
106
107 What Does PPI Stand For?
108
109 "PPI" is an acronym for the longer original module name
110 "Parse::Perl::Isolated". And in the spirit or the silly acronym games
111 played by certain unnamed Open Source projects you may have hurd of, it
112 also a reverse backronym of "I Parse Perl".
113
114 Of course, I could just be lying and have just made that second bit up
115 10 minutes before the release of PPI 1.000. Besides, all the cool Perl
116 packages have TLAs (Three Letter Acronyms). It's a rule or something.
117
118 Why don't you just think of it as the Perl Parsing Interface for sim‐
119 plicity.
120
121 The original name was shortened to prevent the author (and you the
122 users) from contracting RSI by having to type crazy things like
123 "Parse::Perl::Isolated::Token::QuoteLike::Backtick" 100 times a day.
124
125 In acknowledgment that someone may some day come up with a valid solu‐
126 tion for the grammar problem it was decided at the commencement of the
127 project to leave the "Parse::Perl" namespace free for any such effort.
128
129 Since that time I've been able to prove to my own satisfaction that it
130 is truly impossible to accurately parse Perl as both code and document
131 at once. For the academics, parsing Perl suffers from the "Halting
132 Problem".
133
134 With this in mind "Parse::Perl" has now been co-opted as the title for
135 the SourceForge project that publishes PPI and a large collection of
136 other applications and modules related to the (document) parsing of
137 Perl source code.
138
139 You can find this project at <http://sf.net/projects/parseperl>, how‐
140 ever we no longer use the SourceForge CVS server. Instead, the current
141 development version of PPI is available via SVN at
142 <http://svn.phase-n.com/svn/cpan/trunk/PPI/>.
143
144 Why Parse Perl?
145
146 Once you can accept that we will never be able to parse Perl well
147 enough to meet the standards of things that treat Perl as code, it is
148 worth re-examining "why" we want to "parse" Perl at all.
149
150 What are the things that people might want a "Perl parser" for.
151
152 Documentation
153 Analyzing the contents of a Perl document to automatically generate
154 documentation, in parallel to, or as a replacement for, POD docu‐
155 mentation.
156
157 Allow an indexer to to locate and process all the comments and doc‐
158 umentation from code for "full text search" applications.
159
160 Structural and Quality Analysis
161 Determine quality or other metrics across a body of code, and iden‐
162 tify situations relating to particular phrases, techniques or loca‐
163 tions.
164
165 Index functions, variables and packages within Perl code, and doing
166 search and graph (in the node/edge sense) analysis of large code
167 bases.
168
169 Refactoring
170 Make structural, syntax, or other changes to code in an automated
171 manner, either independently or in assistance to an editor. This
172 sort of task list includes backporting, forward porting, partial
173 evaluation, "improving" code, or whatever. All the sort of things
174 you'd want from a Perl::Editor.
175
176 Layout
177 Change the layout of code without changing its meaning. This
178 includes techniques such as tidying (like perltidy), obfuscation,
179 compressing and "squishing", or to implement formatting preferences
180 or policies.
181
182 Presentation
183 This includes methods of improving the presentation of code, with‐
184 out changing the content of the code. Modify, improve, syntax
185 colour etc the presentation of a Perl document. Generating "Intel‐
186 liText"-like functions.
187
188 If we treat this as a baseline for the sort of things we are going to
189 have to build on top of Perl, then it becomes possible to identify a
190 standard for how good a Perl parser needs to be.
191
192 How good is Good Enough(TM)
193
194 PPI seeks to be good enough to achieve all of the above tasks, or to
195 provide a sufficiently good API on which to allow others to implement
196 modules in these and related areas.
197
198 However, there are going to be limits to this process. Because PPI can‐
199 not adapt to changing grammars, any code written using source filters
200 should not be assumed to be parsable.
201
202 At one extreme, this includes anything munged by Acme::Bleach, as well
203 as (arguably) more common cases like Switch. We do not pretend to be
204 able to always parse code using these modules, although as long as it
205 still follows a format that looks like Perl syntax, it may be possible
206 to extend the lexer to handle them.
207
208 The ability to extend PPI to handle lexical additions to the language
209 is on the drawing board to be done some time post-1.0
210
211 The goal for success was originally to be able to successfully parse
212 99% of all Perl documents contained in CPAN. This means the entire file
213 in each case.
214
215 PPI has succeeded in this goal far beyond the expectations of even the
216 author. At time of writing there are only 28 non-Acme Perl modules in
217 CPAN that PPI is incapable of parsing. Most of these are so badly bro‐
218 ken they do not compile as Perl code anyway.
219
220 So unless you are actively going out of your way to break PPI, you
221 should expect that it will handle your code just fine.
222
223 Internationalisation
224
225 PPI provides partial support for internationalisation and localisation.
226
227 Specifically, it allows the use characters from the Latin-1 character
228 set to be used in quotes, comments, and POD. Primarily, this covers
229 languages from Europe and South America.
230
231 PPI does not currently provide support for Unicode, although there is
232 an initial implementation available in a development branch from CVS.
233
234 If you need Unicode support, and would like to help stress test the
235 Unicode support so we can move it to the main branch and enable it in
236 the main release should contact the author. (contact details below)
237
238 Round Trip Safe
239
240 When PPI parses a file it builds everything into the model, including
241 whitespace. This is needed in order to make the Document fully "Round
242 Trip" safe.
243
244 The general concept behind a "Round Trip" parser is that it knows what
245 it is parsing is somewhat uncertain, and so expects to get things wrong
246 from time to time. In the cases where it parses code wrongly the tree
247 will serialize back out to the same string of code that was read in,
248 repairing the parser's mistake as it heads back out to the file.
249
250 The end result is that if you parse in a file and serialize it back out
251 without changing the tree, you are guaranteed to get the same file you
252 started with. PPI does this correctly and reliably for 100% of all
253 known cases.
254
255 What goes in, will come out. Every time.
256
257 The one minor exception at this time is that if the newlines for your
258 file are wrong (meaning not matching the platform newline format), PPI
259 will localisation of them for you. (It isn't to be convenient, support‐
260 ing arbitrary newlines would make some of the code more complicated)
261
262 Better control of the newline type is on the wish list though, and any‐
263 one wanting to help out is encouraged to contact the author.
264
266 General Layout
267
268 PPI is built upon two primary "parsing" components, PPI::Tokenizer and
269 PPI::Lexer, and a large tree of about 50 classes which implement the
270 various the Perl Document Object Model (PDOM).
271
272 The PDOM is conceptually similar in style and intent to the regular DOM
273 or other code Abstract Syntax Trees (ASTs), but contains some differ‐
274 ences to handle perl-specific cases, and to assist in treating the code
275 as a document. Please note that it is not an implementation of the
276 official Document Object Model specification, only somewhat similar to
277 it.
278
279 On top of the Tokenizer, Lexer and the classes of the PDOM, sit a num‐
280 ber of classes intended to make life a little easier when dealing with
281 PDOM trees.
282
283 Both the major parsing components were hand-coded from scratch with
284 only plain Perl code and a few small utility modules. There are no
285 grammar or patterns mini-languages, no YACC or LEX style tools and only
286 a small number of regular expressions.
287
288 This is primarily because of the sheer volume of accumulated cruft that
289 exists in Perl. Not even perl itself is capable of parsing Perl docu‐
290 ments (remember, it just parses and executes it as code).
291
292 As a result, PPI needed to be cruftier than perl itself. Feel free to
293 shudder at this point, and hope you never have to understand the Tok‐
294 enizer codebase. Speaking of which...
295
296 The Tokenizer
297
298 The Tokenizer takes source code and converts it into a series of
299 tokens. It does this using a slow but thorough character by character
300 manual process, rather than using a pattern system or complex regexes.
301
302 Or at least it does so conceptually. If you were to actually trace the
303 code you would find it's not truly character by character due to a num‐
304 ber of regexps and optimisations throughout the code. This lets the
305 Tokenizer "skip ahead" when it can find shortcuts, so it tends to jump
306 around a line a bit wildly at times.
307
308 In practice, the number of times the Tokenizer will actually move the
309 character cursor itself is only about 5% - 10% higher than the number
310 of tokens contained in the file. This makes it about as optimal as it
311 can be made without implementing it in something other than Perl.
312
313 In 2001 when PPI was started, this structure made PPI quite slow, and
314 not really suitable for interactive tasks. This situation has improved
315 greatly with multi-gigahertz processors, but can still be painful when
316 working with very large files.
317
318 The target parsing rate for PPI is about 5000 lines per gigacycle. It
319 is currently believed to be at about 1500, and main avenue for making
320 it to the target speed has now become PPI::XS, a drop-in XS accelerator
321 for PPI.
322
323 Since PPI::XS has only just gotten off the ground and is currently only
324 at proof-of-concept stage, this may take a little while. Anyone inter‐
325 ested in helping out with PPI::XS is highly encouraged to contact the
326 author. In fact, the design of PPI::XS means it's possible to port one
327 function at a time safely and reliably. So every little bit will help.
328
329 The Lexer
330
331 The Lexer takes a token stream, and converts it to a lexical tree.
332 Because we are parsing Perl documents this includes whitespace, com‐
333 ments, and all number of weird things that have no relevance when code
334 is actually executed.
335
336 An instantiated PPI::Lexer consumes PPI::Tokenizer objects and produces
337 PPI::Document objects. However you should probably never be working
338 with the Lexer directly. You should just be able to create PPI::Docu‐
339 ment objects and work with them directly.
340
341 The Perl Document Object Model
342
343 The PDOM is a structured collection of data classes that together pro‐
344 vide a correct and scalable model for documents that follow the stan‐
345 dard Perl syntax.
346
347 The PDOM Class Tree
348
349 The following lists all of the 62 current PDOM classes, listing with
350 indentation based on inheritance.
351
352 PPI::Element
353 PPI::Node
354 PPI::Document
355 PPI::Document::Fragment
356 PPI::Statement
357 PPI::Statement::Package
358 PPI::Statement::Include
359 PPI::Statement::Sub
360 PPI::Statement::Scheduled
361 PPI::Statement::Compound
362 PPI::Statement::Break
363 PPI::Statement::Data
364 PPI::Statement::End
365 PPI::Statement::Expression
366 PPI::Statement::Variable
367 PPI::Statement::Null
368 PPI::Statement::UnmatchedBrace
369 PPI::Statement::Unknown
370 PPI::Structure
371 PPI::Structure::Block
372 PPI::Structure::Subscript
373 PPI::Structure::Constructor
374 PPI::Structure::Condition
375 PPI::Structure::List
376 PPI::Structure::ForLoop
377 PPI::Structure::Unknown
378 PPI::Token
379 PPI::Token::Whitespace
380 PPI::Token::Comment
381 PPI::Token::Pod
382 PPI::Token::Number
383 PPI::Token::Word
384 PPI::Token::DashedWord
385 PPI::Token::Symbol
386 PPI::Token::Magic
387 PPI::Token::ArrayIndex
388 PPI::Token::Operator
389 PPI::Token::Quote
390 PPI::Token::Quote::Single
391 PPI::Token::Quote::Double
392 PPI::Token::Quote::Literal
393 PPI::Token::Quote::Interpolate
394 PPI::Token::QuoteLike
395 PPI::Token::QuoteLike::Backtick
396 PPI::Token::QuoteLike::Command
397 PPI::Token::QuoteLike::Regexp
398 PPI::Token::QuoteLike::Words
399 PPI::Token::QuoteLike::Readline
400 PPI::Token::Regexp
401 PPI::Token::Regexp::Match
402 PPI::Token::Regexp::Substitute
403 PPI::Token::Regexp::Transliterate
404 PPI::Token::HereDoc
405 PPI::Token::Cast
406 PPI::Token::Structure
407 PPI::Token::Label
408 PPI::Token::Separator
409 PPI::Token::Data
410 PPI::Token::End
411 PPI::Token::Prototype
412 PPI::Token::Attribute
413 PPI::Token::Unknown
414
415 To summarize the above layout, all PDOM objects inherit from the
416 PPI::Element class.
417
418 Under this are PPI::Token, strings of content with a known type, and
419 PPI::Node, syntactically significant containers that hold other Ele‐
420 ments.
421
422 The three most important of these are the PPI::Document, the
423 PPI::Statement and the PPI::Structure classes.
424
425 The Document, Statement and Structure
426
427 At the top of all complete PDOM trees is a PPI::Document object. It
428 represents a complete file of Perl source code as you might find it on
429 disk.
430
431 Each Document will contain a number of Statements, Structures and
432 Tokens.
433
434 A PPI::Statement is any series of Tokens and Structures that are
435 treated as a single contiguous statement by perl itself. You should
436 note that a Statement is as close as PPI can get to "parsing" the code
437 in the sense that perl-itself parses Perl code when it is building the
438 op-tree. Because of the assumed isolation, PPI cannot accurately deter‐
439 mine precedence of operators or which tokens are implicit arguments to
440 a sub call.
441
442 So rather than lead you on with a bad guess, PPI does not attempt to
443 determine precedence or sub parameters at all.
444
445 At a fundamental level, it only knows that this series of elements rep‐
446 resents a single Statement as perl sees it, and does so with reasonable
447 certainty.
448
449 However for specific Statement types the PDOM is able to derive addi‐
450 tional useful information about their meaning. For the best and most
451 heavily used example, see PPI::Statement::Include.
452
453 A PPI::Structure is any series of tokens contained within matching
454 braces. This includes code blocks, conditions, function argument
455 braces, anonymous array constructors, lists, scoping braces and all
456 other syntactic structures represented by a matching pair of braces,
457 including "<READLINE>" braces.
458
459 Each Structure contains none, one, or many Tokens and Structures (the
460 rules for which vary for the different Structure subclasses)
461
462 In the PDOM structure rules, a Statement can never directly contain
463 another child Statement, a Structure can never directly contain another
464 child Structure, and a Document can never contain another Document any‐
465 where in the tree.
466
467 Aside from these three rules, the PDOM tree is extremely flexible.
468
469 The PDOM at Work
470
471 To demonstrate the PDOM in use lets start with an example showing how
472 the PDOM tree might look for the following chunk of simple Perl code.
473
474 #!/usr/bin/perl
475
476 print( "Hello World!" );
477
478 exit();
479
480 Translated into a PDOM tree it would have the following structure.
481
482 PPI::Document
483 PPI::Token::Comment '#!/usr/bin/perl\n'
484 PPI::Token::Whitespace '\n'
485 PPI::Statement
486 PPI::Token::Bareword 'print'
487 PPI::Structure::List ( ... )
488 PPI::Token::Whitespace ' '
489 PPI::Statement::Expression
490 PPI::Token::Quote::Double '"Hello World!"'
491 PPI::Token::Whitespace ' '
492 PPI::Token::Structure ';'
493 PPI::Token::Whitespace '\n'
494 PPI::Token::Whitespace '\n'
495 PPI::Statement
496 PPI::Token::Bareword 'exit'
497 PPI::Structure::List ( ... )
498 PPI::Token::Structure ';'
499 PPI::Token::Whitespace '\n'
500
501 Please note that in this this example, strings are only listed for the
502 actual PPI::Token that contains that string. Structures are listed with
503 the type of brace characters it represents noted.
504
505 The PPI::Dumper module can be used to generate similar trees yourself.
506
507 We can make that PDOM dump a little easier to read if we strip out all
508 the whitespace. Here it is again, sans the distracting whitespace
509 tokens.
510
511 PPI::Document
512 PPI::Token::Comment '#!/usr/bin/perl\n'
513 PPI::Statement
514 PPI::Token::Bareword 'print'
515 PPI::Structure::List ( ... )
516 PPI::Statement::Expression
517 PPI::Token::Quote::Double '"Hello World!"'
518 PPI::Token::Structure ';'
519 PPI::Statement
520 PPI::Token::Bareword 'exit'
521 PPI::Structure::List ( ... )
522 PPI::Token::Structure ';'
523
524 As you can see, the tree can get fairly deep at time, especially when
525 every isolated token in a bracket becomes its own statement. This is
526 needed to allow anything inside the tree the ability to grow. It also
527 makes the search and analysis algorithms much more flexible.
528
529 Because of the depth and complexity of PDOM trees, a vast number of
530 very easy to use methods have been added wherever possible to help peo‐
531 ple working with PDOM trees do normal tasks relatively quickly and
532 efficiently.
533
534 Overview of the Primary Classes
535
536 The main PPI classes, and links to their own documentation, are listed
537 here in alphabetical order.
538
539 PPI::Document
540 The Document object, the root of the PDOM.
541
542 PPI::Document::Fragment
543 A cohesive fragment of a larger Document. Although not of any real
544 current use, it is planned for use in certain internal tree manipu‐
545 lation algorithms.
546
547 For example, doing things like cut/copy/paste etc. Very similar to
548 a PPI::Document, but has some additional methods and does not rep‐
549 resent a lexical scope boundary.
550
551 PPI::Dumper
552 A simple class for dumping readable debugging version of PDOM
553 structures, such as in the demonstration above.
554
555 PPI::Element
556 The Element class is the abstract base class for all objects within
557 the PDOM
558
559 PPI::Find
560 Implements an instantiable object form of a PDOM tree search.
561
562 PPI::Lexer
563 The PPI Lexer. Converts Token streams into PDOM trees.
564
565 PPI::Node
566 The Node object, the abstract base class for all PDOM objects that
567 can contain other Elements, such as the Document, Statement and
568 Structure objects.
569
570 PPI::Statement
571 The base class for all Perl statements. Generic "evaluate for
572 side-effects" statements are of this actual type. Other more inter‐
573 esting statement types belong to one of its children.
574
575 See it's own documentation for a longer description and list of all
576 of the different statement types and sub-classes.
577
578 PPI::Structure
579 The abstract base class for all structures. A Structure is a lan‐
580 guage construct consisting of matching braces containing a set of
581 other elements.
582
583 See the PPI::Structure documentation for a description and list of
584 all of the different structure types and sub-classes.
585
586 PPI::Token
587 A token is the basic unit of content. At its most basic, a Token is
588 just a string tagged with metadata (its class, and some additional
589 flags in some cases).
590
591 PPI::Token::_QuoteEngine
592 The PPI::Token::Quote and PPI::Token::QuoteLike classes provide
593 abstract base classes for the many and varied types of quote and
594 quote-like things in Perl. However, much of the actual quote login
595 is implemented in a separate quote engine, based at
596 PPI::Token::_QuoteEngine.
597
598 Classes that inherit from PPI::Token::Quote, PPI::Token::QuoteLike
599 and PPI::Token::Regexp are generally parsed only by the Quote
600 Engine.
601
602 PPI::Tokenizer
603 The PPI Tokenizer. One Tokenizer consumes a chunk of text and pro‐
604 vides access to a stream of PPI::Token objects.
605
606 The Tokenizer is very very complicated, to the point where even the
607 author treads carefully when working with it.
608
609 Most of the complication is the result of optimizations which have
610 tripled the tokenization speed, at the expense of maintainability.
611 We cope with the spaghetti by heavily commenting everything.
612
613 PPI::Transform
614 The Perl Document Transformation API. Provides a standard interface
615 and abstract base class for objects and classes that manipulate
616 Documents.
617
619 The core PPI distribution is pure Perl and has been kept as tight as
620 possible and with as few dependencies as possible.
621
622 It should download and install normally on any platform from within the
623 CPAN and CPANPLUS applications, or directly using the distribution tar‐
624 ball. If installing by hand, you may need to install a few small util‐
625 ity modules first. The exact ones will depend on your version of perl.
626
627 There are no special install instructions for PPI, and the normal "Perl
628 Makefile.PL", "make", "make test", "make install" instructions apply.
629
631 The PPI namespace itself is reserved for the sole use of the modules
632 under the umbrella of the "Parse::Perl" SourceForge project.
633
634 <http://sf.net/projects/parseperl>
635
636 You are recommended to use the PPIx:: namespace for PPI-specific modi‐
637 fications or prototypes thereof, or Perl:: for modules which provide a
638 general Perl language-related functions.
639
640 If what you wish to implement looks like it fits into PPIx:: namespace,
641 you should consider contacting the "Parse::Perl" mailing list (detailed
642 on the SourceForge site) first, as what you want may already be in
643 progress, or you may wish to consider joining the team and doing it
644 within the "Parse::Perl" project itself.
645
647 - Many more analysis and utility methods for PDOM classes
648
649 - Creation of a PPI::Tutorial document
650
651 - Add many more key functions to PPI::XS
652
653 - We can always write more and better unit tests
654
655 - Refactor PPI::Token::Number into multiple subclasses (1.200)
656
657 - Complete the full implementation of ->literal (1.200)
658
659 - Full understanding of scoping (due 1.300)
660
662 This module is stored in an Open Repository at the following address.
663
664 <http://svn.phase-n.com/svn/cpan/trunk/PPI>
665
666 Write access to the repository is made available automatically to any
667 published CPAN author, and to most other volunteers on request.
668
669 If you are able to submit your bug report in the form of new (failing)
670 unit tests, or can apply your fix directly instead of submitting a
671 patch, you are strongly encouraged to do so, as the author currently
672 maintains over 100 modules and it can take some time to deal with
673 non-"Critical" bug reports or patches.
674
675 This will also guarentee that your issue will be addressed in the next
676 release of the module.
677
678 For large changes though, please consider creating a branch so that
679 they can be properly reviewed and trialed before being applied to the
680 trunk.
681
682 If you cannot provide a direct test or fix, or don't have time to do
683 so, then regular bug reports are still accepted and appreciated via the
684 CPAN bug tracker.
685
686 <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=PPI>
687
688 For other issues or questions, contact the "Parse::Perl" project mail‐
689 ing list.
690
691 For commercial or media-related enquiries, or to have your SVN commit
692 bit enabled, contact the author.
693
695 Adam Kennedy adamk@cpan.org
696
698 A huge thank you to Phase N Australia (<http://phase-n.com/>) for per‐
699 mitting the original open sourcing and release of this distribution
700 from what was originally several thousand hours of commercial work.
701
702 Another big thank you to The Perl Foundation (<http://www.perlfounda‐
703 tion.org/>) for funding for the final big refactoring and completion
704 run.
705
706 Also, to the various co-maintainers that have contributed both large
707 and small with tests and patches and the especially those rare few who
708 have deep-dived into the guts to (gasp) add a feature.
709
710 - Dan Brook : PPIx::XPath, Acme::PerlML
711 - Audrey Tang : "Line Noise" Testing
712 - Arjen Laarhoven : Three-element -E<gt>location
713
714 Most of all, thanks to those brave soles willing to dive in and use,
715 test drive and provide feedback on PPI before version 1.000, in some
716 cases before it made it to beta quality, and still did extremely dis‐
717 tasteful things (like eating 50 meg of RAM a second).
718
719 I owe you all a beer. Corner me somewhere and collect at your conve‐
720 nience. If I missed someone who wasn't in my email history, thank you
721 too :)
722
723 # In approximate order of appearance
724 - Claes Jacobsson
725 - Michael Schwern
726 - Jeff T. Parsons
727 - CPAN Author "CHOCOLATEBOY"
728 - Robert Rotherberg
729 - CPAN Author "PODMASTER"
730 - Richard Soderberg
731 - Nadim ibn Hamouda el Khemir
732 - Graciliano M. P.
733 - Leon Brocard
734 - Jody Belka
735 - Curtis Ovid
736 - Yuval Kogman
737 - Michael Schilli
738 - Slaven Rezic
739 - Lars Thegler
740 - Tony Stubblebine
741 - Tatsuhiko Miyagawa
742 - CPAN Author "CHROMATIC"
743 - Matisse Enzer
744 - Roy Fulbright
745 - Dan Brook
746 - Johnny Lee
747 - Johan Lindstrom
748
749 And to single one person out, thanks go to Randal Schwartz who (mostly)
750 spent a great number of hours in IRC over a critical 6 month period
751 explaining why Perl is impossibly unparsable and constantly shoving
752 evil and ugly corner cases in my face. He remained a tireless devil's
753 advocate and without his support this project genuinely could never
754 have been completed.
755
756 So for my schooling in the Deep Magik, you have my deepest gratitude
757 Randal.
758
760 Copyright 2001 - 2006 Adam Kennedy.
761
762 This program is free software; you can redistribute it and/or modify it
763 under the same terms as Perl itself.
764
765 The full text of the license can be found in the LICENSE file included
766 with this module.
767
768
769
770perl v5.8.8 2006-09-23 PPI(3)