1Devel::Declare::Parser(U3s)er Contributed Perl DocumentatDieovnel::Declare::Parser(3)
2
3
4
6 Devel::Declare::Parser - Higher level interface to Devel-Declare
7
9 Devel-Declare-Parser is a higher-level API sitting on top of
10 Devel::Declare. It is used by Devel::Declare::Exporter to simplify
11 exporting of Devel::Declare magic. Writing custom parsers usually only
12 requires subclassing this module and overriding a couple methods.
13
15 Devel::Declare::Interface
16 This is the primary interface for those who want to use Devel-
17 Declare-Parser magic, and don't want to use Exporter-Declare.
18
19 Devel::Declare::Parser
20 This Document covers the API for Devel::Declare::Parser. This API
21 is a useful reference when writing or modifying a custom parser.
22
24 package Devel::Declare::Parser::MyParser;
25 use strict;
26 use warnings;
27
28 use base 'Devel::Declare::Parser';
29 use Devel::Declare::Interface;
30
31 # Create an accessor (See INTERNALS WARNING below)
32 __PACKAGE__->add_accessor( 'my_accessor' );
33
34 # Register the parser for use.
35 Devel::Declare::Interface::register_parser( 'myparser' );
36
37 # Override the rewrite() method to take the parsed bits (parts) and put the
38 # ones you want into new_parts.
39 sub rewrite {
40 my $self = shift;
41
42 my $parts = $self->parts;
43
44 $new_parts = $self->process_parts( $parts );
45
46 $self->new_parts( $new_parts );
47 1;
48 }
49
50 1;
51
53 This is a brief overview of how a parser is used.
54
55 WORKFLOW
56 Parser is constructed
57 Name, Declarator, and Offset are provided by Devel::Declare.
58
59 The process() method is called
60 The process method calls all of the following in sequence, if any
61 returns false, process() will return.
62
63 pre_parse()
64 Check if we want to process the line at all.
65
66 parse() Turn the line into 'parts' (see below).
67
68 post_parse()
69 Hook, currently does nothing.
70
71 rewrite()
72 Hook, currently takes all the arguments between the
73 declarator and the codeblock/semicolon (which have been
74 turned into 'parts' structures in the parts() attribute)
75 and puts them into the new_parts() attribute.
76
77 This is usually the method you want to override.
78
79 write_line()
80 Opens, fills in, and closes the line as a string, then
81 rewrites the actual line using Devel::Declare.
82
83 edit_line()
84 Hook, currently does nothing.
85
86 "PARTS"
87 'Parts' are datastructures created by the parse() method. Every
88 argument on the line (space separated) up until an opening curly brace
89 ({) or a semicolon (;) will be turned into a part. Here are the parts
90 to expect:
91
92 Parts will either be a plain string, or an arrayref containing a string
93 and the quote character used to define the string. "String" or [
94 "String", '"' ]. Variables and operators (excluding those containing
95 only string characters) are typically the only parts left in a plain
96 string form.
97
98 See the format_parts() method for an easy way to get what you need from
99 a 'part' datastructure.
100
101 Bareword or Package Name
102 A bareword name is anything that starts with [a-zA-z] and contains
103 only alpha-numerics plus underscore. It is also not quoted.
104 Examples include my_name, something5, etc.
105
106 The structure will be an arrayref, the first element will be the
107 string form of the bareword name, the second element will be undef.
108
109 Example:
110
111 # my_keyword My::Package;
112 $part = [
113 'My::Package',
114 undef,
115 ];
116
117 # my_keyword some_name;
118 $part = [
119 "some_name",
120 undef,
121 ];
122
123 Quoted or Enclosed Element
124 A quoted or enclosed element includes strings quoted with single or
125 double quotes, and text contained within opening and closing
126 brackets, braces or parens (excluding the curly brace '{').
127
128 Example Structures:
129
130 # my_keyword "double quoted string";
131 $part = [
132 'double quoted string',
133 '"',
134 ];
135
136 # my_keyword 'single quoted string';
137 $part = [
138 'double quoted string',
139 '"',
140 ];
141
142 # my_keyword ... ( a => 'b', c => 'd' );
143 $part = [
144 " a => 'b', c => 'd' ",
145 "(",
146 ];
147
148 Variable or Operator
149 Anything starting with a non-alphanumeric, non-quoting character
150 will be placed as-is (not interpolated) into a string. This catches
151 most variables and operators, the exception are alpha-numeric
152 operators such as 'eq', 'gt', 'cmp', etc. Eventually I plan to add
153 logic to catch all operators, but it appears I will have to hard-
154 code them.
155
156 # my_keyword $variable
157 $part = '$variable';
158
159 # my_keyword <=>
160 $part = '<=>';
161
162 EVENTUAL OUTPUT
163 Parser is designed such that it will transform any and all uses of your
164 keyword into proper function calls.
165
166 That is this:
167
168 function x { ... }
169
170 Will become this:
171
172 function( 'x', sub { ... });
173
174 Note Parser does not read in the entire codeblock, rather it injects a
175 statement into the start of the block that uses a callback to attach
176 the ');' to the end of the statement. This is per the documentation of
177 Devel::Declare. Reading in the entire sub is not a desirable scenario.
178
180 INTERNALS WARNING
181 Parser objects are blessed arrays, not hashrefs.
182
183 If you want to create a new accessor use the add_accessor() class
184 method. It will take care of assigning an unused array element to the
185 attribute, and will create a read/write accessor sub for you.
186
187 __PACKAGE__->add_accessor( 'my_accessor' );
188
189 There are many public and private methods on the parser base class.
190 Only the public methods are fully documented. Be sure to refer often to
191 the list of private methods at the end of this document, accidently
192 overriding a private method could have devastating consequences.
193
194 CLASS METHODS
195 $class->new( $name, $declarator, $offset )
196 The constructor, "DO NOT OVERRIDE THIS!"
197
198 $class->DEBUG($bool)
199 Turn debugging on/off. This will output the line after it has been
200 modified, as well as some context information.
201
202 NOTE: This has a global effect, all parsers will start debugging.
203
204 UTILITY METHODS
205 bail( @messages )
206 Like croak, dies providing you context information. Since any death
207 occurs inside the parser, carp provides useless information.
208
209 diag( @message )
210 Like carp, warns providing you context information. Since the warn
211 occurs inside the parser carp provides useless information.
212
213 end_quote($start_char)
214 Find the end-character for the provide starting quote character. As
215 in '{' returns '}' and '(' returns ')'. If there is no counter-part
216 the start character is returned: "'" returns "'".
217
218 filename()
219 Filename the rewrite is occurring against.
220
221 linenum()
222 Linenum the rewrite is occurring on.
223
224 format_part()
225 Returns the stringified form of a part datastructure. For variables
226 and operators that is just the item itself as a string. For
227 barewords or package names it is the item itself with single quotes
228 wrapped around it. For quoted items it is the string wrapped in its
229 proper quoting characters. If a second parameter is provided (and
230 true) no single quotes will be added to barewords.
231
232 ACCESSORS
233 These are the read/write accessors used by Parser. Not all of these act
234 on an array element, some will directly alter the current line.
235
236 line()
237 This will retrieve the current line from Devel-Declare. If given a
238 value, that value will be set as the current line using Devel-
239 Declare.
240
241 name()
242 Name of the declarator as provided via the parser.
243
244 declarator()
245 Name of the declarator as provided via the Devel-Declare.
246
247 original_offset()
248 Offset on the line when the parsing was started.
249
250 offset()
251 Current line offset.
252
253 parts()
254 Arrayref of parts (may be undef)
255
256 new_parts()
257 Arrayref of new parts (may be undef)
258
259 end_char()
260 Will be set to the character just after the completely parsed line
261 (usually '{' or ';')
262
263 prototype()
264 Used internally for prototype tracking.
265
266 contained()
267 True if the parser determined this was a contained call. This means
268 your keyword was followed by an opening paren, and the statement
269 ended with a closing paren and semicolon. By default Parser will
270 not modify such lines.
271
272 OVERRIDABLE METHODS
273 These are methods you can, should, or may override in your baseclass.
274
275 quote_chars()
276 Specify the starting characters for quoted strings. (returns a
277 list)
278
279 end_chars()
280 Characters to recognise as end of statement characters (';' and
281 '{') (returns a list)
282
283 inject()
284 Code to inject into functions enhanced by this parser.
285
286 pre_parse()
287 Check if we want to process the line at all.
288
289 parse()
290 Turn the line into 'parts'.
291
292 post_parse()
293 Hook, currently does nothing.
294
295 rewrite()
296 Hook, currently takes all the arguments between the declarator and
297 the codeblock/semicolon (which have been turned into 'parts'
298 structures in the parts() attribute) and puts them into the
299 new_parts() attribute.
300
301 This is usually the method you want to override.
302
303 write_line()
304 Opens, fills in, and closes the line as a string, then rewrites the
305 actual line using Devel::Declare.
306
307 edit_line()
308 Hook, currently does nothing.
309
310 open_line()
311 Usually returns '('. This is how to start a line following your
312 keyword
313
314 close_line()
315 End the line, this means either re-inserting the opening '{' on the
316 codeblock, along with any injections, or returning ');'
317
318 POSITION TRACKING
319 advance( $num_chars )
320 Advances the offset by $num_chars.
321
322 skip_declarator()
323 Skips the declarator at the start of the line.
324
325 skipspace()
326 Advances the offset past any whitespace.
327
328 LINE EXAMINATION (NON-MODIFYING)
329 These are used by pre_parse() to examine the line prior to any
330 modification.
331
332 is_contained()
333 True if the line is of the format:
334
335 keyword( ... );
336
337 is_arrow_contained()
338 True if the line is of the format:
339
340 keyword word_or_string => ( ... );
341
342 is_defenition()
343 True if the line matches the regex m/sub[\s\n]+$name/sm
344
345 PART EXAMINATION
346 These are methods that let you investigate the parts already parsed and
347 placed in the parts() attribute.
348
349 has_non_string_or_quote_parts()
350 Returns a list of parts that are not strings, quotes, or barewords.
351
352 has_string_or_quote_parts()
353 Returns a list of parts that are strings, quotes, or barewords.
354
355 has_keyword( $word )
356 Check for a keyword in the parts
357
358 has_comma()
359 has_fat_comma()
360
361 LINE EXAMINATION (MODIFYING)
362 This examines the line returning part structures and removing elements
363 from the line each time they are called.
364
365 strip_item()
366 strip_length()
367 strip_remaining_items()
368
369 LOOKING AHEAD
370 These methods help the parser determine what comes next in a line. In
371 most cases these are non-modifying.
372
373 peek_is_block()
374 peek_is_end()
375 peek_is_other()
376 peek_is_quote()
377 peek_is_word()
378 peek_item()
379 peek_item_type()
380 peek_num_chars()
381 peek_other()
382 peek_quote()
383 peek_remaining()
384 peek_word()
385
386 PRIVATE METHODS
387 Do not use these, and definitely do not override them in a subclass.
388
389 _block_end_injection()
390 _debug()
391 _edit_block_end()
392 _item_via_()
393 _linestr_offset_from_dd()
394 _move_via_()
395 _peek_is_package()
396 _peek_is_word()
397 _quoted_from_dd()
398 _scope_end()
399 _stash()
400 _unstash()
401
403 This module is part of the Fennec project. See Fennec for more details.
404 Fennec is a project to develop an extendable and powerful testing
405 framework. Together the tools that make up the Fennec framework
406 provide a potent testing environment.
407
408 The tools provided by Fennec are also useful on their own. Sometimes a
409 tool created for Fennec is useful outside the greator framework. Such
410 tools are turned into their own projects. This is one such project.
411
412 Fennec - The core framework
413 The primary Fennec project that ties them all together.
414
416 Chad Granum exodist7@gmail.com
417
419 Copyright (C) 2010 Chad Granum
420
421 Devel-Declare-Parser is free software; Standard perl licence.
422
423 Devel-Declare-Parser is distributed in the hope that it will be useful,
424 but WITHOUT ANY WARRANTY; without even the implied warranty of
425 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license
426 for more details.
427
428
429
430perl v5.34.0 2022-01-21 Devel::Declare::Parser(3)