File Coverage

blib/lib/Devel/Declare/Lexer.pm
Criterion Covered Total %
statement 312 324 96.3
branch 126 194 64.9
condition 6 9 66.6
subroutine 27 27 100.0
pod 0 4 0.0
total 471 558 84.4


line stmt bran cond sub pod time code
1             package Devel::Declare::Lexer;
2              
3 10     10   124013 use strict;
  10         22  
  10         397  
4 10     10   98 use warnings;
  10         18  
  10         253  
5 10     10   119 use v5;
  10         34  
  10         612  
6              
7             our $VERSION = '0.014';
8              
9 10     10   12113 use Data::Dumper;
  10         129780  
  10         805  
10 10     10   12380 use Devel::Declare;
  10         156328  
  10         123  
11 10     10   8613 use Devel::Declare::Lexer::Stream;
  10         37  
  10         312  
12 10     10   6887 use Devel::Declare::Lexer::Token;
  10         26  
  10         350  
13 10     10   6680 use Devel::Declare::Lexer::Token::Bareword;
  10         29  
  10         271  
14 10     10   12885 use Devel::Declare::Lexer::Token::Declarator;
  10         29  
  10         280  
15 10     10   6420 use Devel::Declare::Lexer::Token::EndOfStatement;
  10         27  
  10         261  
16 10     10   17796 use Devel::Declare::Lexer::Token::Heredoc;
  10         30  
  10         279  
17 10     10   6811 use Devel::Declare::Lexer::Token::LeftBracket;
  10         29  
  10         355  
18 10     10   6868 use Devel::Declare::Lexer::Token::Newline;
  10         183  
  10         322  
19 10     10   7274 use Devel::Declare::Lexer::Token::Operator;
  10         29  
  10         277  
20 10     10   6888 use Devel::Declare::Lexer::Token::RightBracket;
  10         29  
  10         377  
21 10     10   6733 use Devel::Declare::Lexer::Token::String;
  10         33  
  10         344  
22 10     10   13670 use Devel::Declare::Lexer::Token::Variable;
  10         35  
  10         278  
23 10     10   6667 use Devel::Declare::Lexer::Token::Whitespace;
  10         33  
  10         344  
24              
25 10     10   142 use vars qw/ @ISA $DEBUG $SHOWTRANSLATE /;
  10         919  
  10         2190  
26             @ISA = ();
27             $DEBUG = 0;
28             $SHOWTRANSLATE = 0;
29              
30             sub import
31             {
32 10     10   124 my $class = shift;
33 10         51 my $caller = caller;
34              
35 10         129 import_for($caller, @_);
36             }
37              
38             sub import_for
39             {
40 10     10 0 78 my ($caller, @args) = @_;
41 10         28 my $class = shift;
42              
43 10     10   63 no strict 'refs';
  10         20  
  10         58635  
44              
45 10         28 my %subinject = ();
46 10 100       78 if(ref($args[0]) =~ /HASH/) {
47 1 50       3 $DEBUG and print STDERR "Using hash for import\n";
48 1         2 %subinject = %{$args[0]};
  1         6  
49 1         4 @args = keys %subinject;
50             }
51              
52 10         21 my @consts;
53              
54 10         35 my %tags = map { $_ => 1 } @args;
  14         167  
55 10 50       59 if($tags{":debug"}) {
56 0         0 $DEBUG = 1;
57             }
58 10 100       56 if($tags{":lexer_test"}) {
59 2 50       7 $DEBUG and print STDERR "Adding 'lexer_test' to keyword list\n";
60              
61 2         6 push @consts, "lexer_test";
62             }
63              
64 10         29 my @names = @args;
65 10         28 for my $name (@names) {
66 14 100       67 next if $name =~ /:/;
67 12 50       40 $DEBUG and print STDERR "Adding '$name' to keyword list\n";
68              
69 12         39 push @consts, $name;
70             }
71              
72 10         28 for my $word (@consts) {
73 14 50       92 $DEBUG and print STDERR "Injecting '$word' into '$caller'\n";
74 14         201 Devel::Declare->setup_for(
75             $caller,
76             {
77             $word => { const => \&lexer }
78             }
79             );
80 14 100       527 if($subinject{$word}) {
81 1 50       4 $DEBUG and print STDERR "- Using sub provided in import\n";
82 1         2 *{$caller.'::'.$word} = $subinject{$word};
  1         40  
83             } else {
84 13 50       49 $DEBUG and print STDERR "- Using default sub\n";
85 13         31 *{$caller.'::'.$word} = sub () { 1; };
  13         580  
86             }
87             }
88             }
89              
90             my %named_lexed_stack = ();
91             sub lexed
92             {
93 12     12 0 209860 my ($key, $callback) = @_;
94 12 50       76 $DEBUG and print STDERR "Registered callback for keyword '$key'\n";
95 12         312 $named_lexed_stack{$key} = $callback;
96             }
97              
98             sub call_lexed
99             {
100 69     69 0 119 my ($name, $stream) = @_;
101              
102 69 50       148 $DEBUG and print STDERR "Checking for callbacks for keyword '$name'\n";
103 69 50       134 $DEBUG and print STDERR Dumper($stream) . "\n";
104              
105 69         125 my $callback = $named_lexed_stack{$name};
106 69 100       163 if($callback) {
107 50 50       109 $DEBUG and print STDERR "Found callback '$callback' for keyword '$name'\n";
108 50         148 $stream = &$callback($stream);
109             }
110              
111 69 50       856 $DEBUG and print STDERR Dumper($stream) . "\n";
112              
113 69         359 return $stream;
114             }
115              
116             sub lexer
117             {
118 69     69 0 32273 my ($symbol, $offset) = @_;
119              
120 69 50       331 $DEBUG and print "=" x 80, "\n";
121              
122 69         207 my $linestr = Devel::Declare::get_linestr;
123 69         100 my $original_linestr = $linestr;
124 69         133 my $original_offset = $offset;
125 69 50       170 $DEBUG and print STDERR "Starting with linestr '$linestr'\n";
126              
127 69         116 my @tokens = ();
128 69         424 tie @tokens, "Devel::Declare::Lexer::Stream";
129 69         498 my ($len, $tok);
130 69         89 my $eoleos = 0;
131 69         85 my $line = 1;
132              
133             # Skip the declarator
134 69         190 $offset += Devel::Declare::toke_move_past_token($offset);
135 69         333 push @tokens, new Devel::Declare::Lexer::Token::Declarator( value => $symbol );
136 69 50       511 $DEBUG and print STDERR "Skipped declarator '$symbol'\n";
137              
138 69         420 my %lineoffsets = ( 1 => $offset );
139              
140             # We call this from a few places inside the loop
141             my $skipspace = sub {
142             # Move past any whitespace
143 425     425   878 $len = Devel::Declare::toke_skipspace($offset);
144 425 100       1019 if($len > 0) {
    50          
    50          
145 278         437 $tok = substr($linestr, $offset, $len);
146 278 50       521 $DEBUG and print STDERR "Skipped whitespace '$tok', length [$len]\n";
147 278         1095 push @tokens, new Devel::Declare::Lexer::Token::Whitespace( value => $tok );
148 278         1675 $offset += $len;
149              
150 278 100       885 if($tok =~ /\n/) {
151             # its odd that this works without handling any line numbering
152             # I think we end up here when an end of line is found after a bareword (e.g. print\n"something")
153             # It probably still needs some work on line numbering, but everything just seems to work!
154 1 50       4 $DEBUG and print STDERR "Got end of line in skipspace, probable bareword preceeding EOL\n";
155 1         3 Devel::Declare::clear_lex_stuff;
156              
157             # We've got a new line so we need to refresh our linestr
158 1         4 $linestr = Devel::Declare::get_linestr;
159 1         2 $original_linestr = $linestr;
160              
161 1 50       2 $DEBUG and print STDERR "Refreshed linestr [$linestr]\n";
162             }
163             } elsif ($len < 0) {
164             # Again, its odd that we don't handle any line numbering here, and a $len of < 0 is a definite EOL
165 0 0       0 $DEBUG and print STDERR "Got end of line in skipspace\n";
166             } elsif ($len == 0) {
167 147 50       400 $DEBUG and print STDERR "No whitespace skipped\n";
168             }
169 425         995 return $len;
170 69         360 };
171              
172             # Capture the tokens
173 69 50       164 $DEBUG and print STDERR "Linestr length [", length $linestr, "]\n";
174 69         188 my $heredoc = undef;
175 69         84 my $heredoc_end_re = undef;
176 69         87 my $heredoc_end_re2 = undef;
177 69         87 my $nest = 0; # nested bracket tracking, just in case we get ; inside a block
178 69         179 while($offset < length $linestr) {
179 563 50       991 $DEBUG and print STDERR Dumper(\%lineoffsets) . "\n";
180 563 100 100     1675 if($heredoc && !(substr($linestr, $offset, 2) eq "\n")) {
181 22         28 my $c = substr($linestr, $offset, 1);
182 22 50       37 $DEBUG and print STDERR "Consuming char from heredoc: '$c'\n";
183 22         22 $offset += 1;
184 22 100       42 if($c =~ /\n/) {
185 2 50       4 $DEBUG and print STDERR "Newline found in heredoc (current line $line)\n";
186             #$line++;
187             #$lineoffsets{$line} = $offset;
188             } else {
189 20         33 $heredoc->{value} .= $c;
190             }
191 22 50       34 $DEBUG and print STDERR "New heredoc value: " . $heredoc->{value} . "\n";
192 22         30 my $heredoc_name = $heredoc->{name};
193 22 100       72 if($heredoc->{value} =~ /$heredoc_end_re/) {
194 1         6 $heredoc->{value} =~ s/$heredoc_end_re2//;
195 1 50       4 $DEBUG and print STDERR "Consumed heredoc, name [$heredoc_name]:\n" . $heredoc->{value} . "\n";
196 1         4 push @tokens, $heredoc;
197 1         5 $heredoc = undef;
198 1         2 $heredoc_end_re = undef;
199 1         2 $heredoc_end_re2 = undef;
200             }
201 22         50 next;
202             }
203              
204 541 50       972 $DEBUG and print STDERR "Offset[$offset], nest [$nest], Remaining[", substr($linestr, $offset), "]\n";
205              
206 541 100       1325 if(substr($linestr, $offset, 1) eq ';') {
207 80 50       168 $DEBUG and print STDERR "Got end of statement\n";
208 80         352 push @tokens, new Devel::Declare::Lexer::Token::EndOfStatement;
209 80         482 $offset += 1;
210 80         106 $eoleos = 1;
211 80 100       220 last unless $nest;
212 11         29 next;
213             }
214              
215 461 100       924 if(substr($linestr, $offset, 2) eq "\n") {
216 36 100       69 if($heredoc) {
217 2 50       4 $DEBUG and print STDERR "Got end of line in heredoc\n";
218 2         5 $heredoc->{value} .= "\n";
219             }
220              
221 36 100       82 if(!$heredoc) {
222 34 50       98 $DEBUG and print STDERR "Got end of line in loop (current line $line)\n";
223 34         156 push @tokens, new Devel::Declare::Lexer::Token::Newline;
224 34         153 $offset += 1;
225             }
226              
227             # this lets us capture a newline directly after a semicolon
228             # and immediately exit the loop - otherwise we might start
229             # consuming code that doesn't belong to us
230 36 50 66     196 last if $eoleos && !$nest;
231 36         84 $eoleos = 0;
232              
233             # If we're here, it's just a new line inside the statement that
234             # we do want to consume
235              
236             # We don't use skipspace here - it does too much!
237             #&$skipspace;
238 36         110 $len = Devel::Declare::toke_skipspace($offset);
239 36 100       86 if($len != 0) {
240             # TODO it seems odd that we don't add $len to the
241             # offset... this might come back to bite us later!
242             #$offset += $len - 6;
243 21 50       54 $DEBUG and print STDERR "Skipped $len whitespace following EOL, not added to \$offset\n";
244             }
245              
246 36         67 Devel::Declare::clear_lex_stuff;
247              
248             # Got a new line, so we need to refresh linestr
249 36         90 $linestr = Devel::Declare::get_linestr;
250             # It's not the next line, its everything upto and including the next line
251             # so really our original_linestr is wrong!
252 36         118 $original_linestr = $linestr;
253              
254             # Record some offsets for later - we start on line 1 and the first $line++ is 2
255             # so we make a special case for recording line 1's offset
256 36 100       75 if($line == 1) {
257 11         30 $lineoffsets{1} = (length $symbol) + 1;
258             };
259 36         44 $line++;
260 36 100       98 $lineoffsets{$line} = $heredoc ? $offset + 1 : $offset;
261              
262 36 50       87 $DEBUG and print STDERR "Refreshed linestr [$linestr], added lineoffset for line $line, offset $offset\n";
263 36         81 next;
264             }
265              
266             # FIXME Does this ever happen?
267 425 50       672 if(&$skipspace < 0) {
268 0 0       0 $DEBUG and print STDERR "Got skipspace < 0\n";
269 0         0 last;
270             }
271              
272             # Check if its a opening bracket
273 425 100       1685 if(substr($linestr, $offset, 1) =~ /(\{|\[|\()/) {
274 32         71 my $b = substr($linestr, $offset, 1);
275 32         166 push @tokens, new Devel::Declare::Lexer::Token::LeftBracket( value => $b );
276 32         422 $nest++;
277 32 50       83 $DEBUG and print STDERR "Got left bracket '$b', nest[$nest]\n";
278 32         42 $offset += 1;
279 32         77 next;
280             }
281             # Check if its a closing bracket
282 393 100       1224 if(substr($linestr, $offset, 1) =~ /(\}|\]|\))/) {
283 32         57 my $b = substr($linestr, $offset, 1);
284 32         156 push @tokens, new Devel::Declare::Lexer::Token::RightBracket( value => $b );
285 32         159 $nest--;
286 32 50       93 $DEBUG and print STDERR "Got right bracket '$b', nest[$nest]\n";
287 32         57 $offset += 1;
288 32         78 next;
289             }
290             # Check for a reference
291 361 100       813 if(substr($linestr, $offset, 1) =~ /\\/) {
292 1         3 $tok = substr($linestr, $offset, 1);
293 1 50       3 $DEBUG and print STDERR "Got reference operator '$tok'\n";
294 1         5 push @tokens, new Devel::Declare::Lexer::Token::Operator( value => $tok);
295 1         5 $offset += 1;
296 1         3 next;
297             }
298             # Check for variable
299 360 100       1221 if(substr($linestr, $offset, 1) =~ /(\$|\%|\@|\*)/) {
300             # get the sign
301             # TODO the variable name is captured later - it should probably be done here
302 54         83 $tok = substr($linestr, $offset, 1);
303 54 50       121 $DEBUG and print STDERR "Got variable '$tok'\n";
304 54         227 push @tokens, new Devel::Declare::Lexer::Token::Variable( value => $tok );
305 54         276 $offset += 1;
306 54         2201 next;
307             }
308             # Check for string
309 306 100       1002 if(substr($linestr, $offset, 1) =~ /^(q|\"|\')/) {
310             # FIXME need to determine string type properly
311 74         127 my $strstype = substr($linestr, $offset, 1);
312              
313 74         98 my $allow_string = 1;
314              
315 74 100       1773 if($strstype eq 'q') {
316 13 50       42 if(substr($linestr, $offset + 1, 1) !~ /\|\{\[\(\#/) {
317 13 50       44 $DEBUG and print STDERR "This 'q' isnt a string type\n";
318 13         19 $allow_string = 0;
319             }
320             }
321              
322 74 100       153 if($allow_string) {
323 61         96 my $stretype = $strstype;
324 61 50       137 if($strstype =~ /q/) {
325 0 0       0 if(substr($linestr, $offset, 2) =~ /qq/) {
326 0         0 $strstype = substr($linestr, $offset, 3);
327 0         0 $offset += 2;
328             } else {
329 0         0 $strstype = substr($linestr, $offset, 2);
330 0         0 $offset += 1;
331             }
332 0         0 $stretype = substr($linestr, $offset, 1);
333 0         0 $stretype =~ tr/\(/)/;
334 0         0 $len = Devel::Declare::toke_scan_str($offset);
335             } else {
336 61         377 $len = Devel::Declare::toke_scan_str($offset);
337             }
338 61 50       150 $DEBUG and print STDERR "Got string type '$strstype', end type '$stretype'\n";
339 61         434 $tok = Devel::Declare::get_lex_stuff;
340 61         117 Devel::Declare::clear_lex_stuff;
341 61 50       142 $DEBUG and print STDERR "Got string '$tok'\n";
342 61         487 push @tokens, new Devel::Declare::Lexer::Token::String( start => $strstype, end => $stretype, value => $tok );
343             # get a new linestr - we might have captured multiple lines
344 61         377 $linestr = Devel::Declare::get_linestr;
345 61         78 $offset += $len;
346              
347             # If we do have multiple lines, we'll fix line numbering at the end
348              
349 61         177 next;
350             }
351             }
352             # Check for heredoc
353 245 100       602 if(substr($linestr, $offset)=~ /^(<<\s*([\w\d]+)\s*\n)/) {
354             # Heredocs are weird - we'll just remember we're in a heredoc until we get the end token
355 1 50       4 $DEBUG and print STDERR "Got a heredoc with name '$2'\n";
356 1         1322 $heredoc = new Devel::Declare::Lexer::Token::Heredoc( name => $2, value => '' );
357 1         30 $heredoc_end_re = qr/\n$2\n$/;
358 1         10 $heredoc_end_re2 = qr/$2\n$/;
359 1 50       5 $DEBUG and print STDERR "Created regex $heredoc_end_re and $heredoc_end_re2\n";
360              
361             # get a new linestr - we might have captured multiple lines
362 1         3 $offset += 2 + (length $1);
363            
364 1         5 $len = Devel::Declare::toke_skipspace($offset);
365 1         3 $linestr = Devel::Declare::get_linestr;
366 1         3 $offset += $len;
367 1 50       4 $DEBUG and print STDERR "Skipped $len whitespace at start of heredoc, got new linestr[$linestr]\n";
368              
369 1         1 $line++;
370 1         3 $lineoffsets{$line} = $offset;
371              
372             # If we do have multiple lines, we'll fix line numbering at the end
373              
374 1         4 next;
375             }
376             # Check for operator after strings (so heredocs <
377 244 100       681 if(substr($linestr, $offset, 1) =~ /[!\+\-\*\/\.><=,|&\?:]/) {
378 88         134 $tok = substr($linestr, $offset, 1);
379 88 50       173 $DEBUG and print STDERR "Got operator '$tok'\n";
380 88         401 push @tokens, new Devel::Declare::Lexer::Token::Operator( value => $tok );
381 88         460 $offset += 1;
382 88         277 next;
383             }
384             # Check for bareword
385 156         370 $len = Devel::Declare::toke_scan_word($offset, 1);
386 156 100       309 if($len) {
387 155         275 $tok = substr($linestr, $offset, $len);
388 155 50       294 $DEBUG and print STDERR "Got bareword '$tok'\n";
389 155         586 push @tokens, new Devel::Declare::Lexer::Token::Bareword( value => $tok );
390 155         693 $offset += $len;
391 155         398 next;
392             }
393              
394             }
395              
396             # Callback (AT COMPILE TIME) to allow manipulation of the token stream before injection
397 69 50       149 $DEBUG and print STDERR Dumper(\@tokens) . "\n";
398 69         90 @tokens = @{call_lexed($symbol, \@tokens)};
  69         250  
399              
400 69         6248 my $stmt = "";
401 69         221 for my $token (@tokens) {
402 982         6705 $stmt .= $token->get;
403             }
404              
405 69 50       726 $DEBUG and print "=" x 80, "\n";
406              
407 69 100       248 if($symbol =~ /^lexer_test$/) {
408 19 50       41 $DEBUG and print STDERR "Escaping statement for variable assignment\n";
409 19         33 $stmt =~ s/\\/\\\\/g;
410 19         53 $stmt =~ s/\"/\\"/g;
411 19         38 $stmt =~ s/\$/\\\$/g;
412 19         42 $stmt =~ s/\n/\\n/g;
413 19         31 chomp $stmt;
414 19         37 $stmt = substr($stmt, 0, (length $stmt)); # strip the final \\n
415             } else {
416 50         124 $stmt =~ s/\n//g; # remove multiline on final statement
417 50         96 chomp $stmt;
418             }
419 69 50       156 $DEBUG and print STDERR "Final statement: [$stmt]\n";
420              
421             # FIXME line numbering is broken if a \n appears inside a block, e.g. keyword { print "\n"; }
422             #my @lcnt = split /[^\\]\\n/, $stmt;
423 69         275 my @lcnt = split /\\n/, $stmt;
424 69         148 my $lc = scalar @lcnt;
425 69 50       158 $DEBUG and print STDERR "Lines:\n", Dumper(\@lcnt) . "\n";
426 69         113 my $lineadjust = $lc - $line;
427 69 50       149 $DEBUG and print STDERR "Linecount[$lc] lines[$line] - missing $lineadjust lines\n";
428              
429             # we've got a new linestr, we need to re-fix all our offsets
430 69 50       173 $DEBUG and print STDERR "\n\nStarted with linestr [$linestr]\n";
431 10     10   104 use Data::Dumper;
  10         40  
  10         8753  
432 69 50       153 $DEBUG and print STDERR Dumper(\%lineoffsets) . "\n";
433              
434 69         264 for my $l (sort keys %lineoffsets) {
435 106         165 my $sol = $lineoffsets{$l};
436 106 100       556 last if !defined $lineoffsets{$l+1}; # don't mess with the current line, yet!
437 37         67 my $eol = $lineoffsets{$l + 1} - 1;
438 37         109 my $diff = $eol - $sol;
439 37         70 my $substr = substr($linestr, $sol, $diff);
440 37 50       81 $DEBUG and print STDERR "\nLine $l, sol[$sol], eol[$eol], diff[$diff], linestr[$linestr], substr[$substr]\n";
441 37         105 substr($linestr, $sol, $diff) = " " x $diff;
442             }
443              
444             # now clear up the last line
445 69 50       172 $DEBUG and print STDERR "Still got linestr[$linestr]\n";
446 69 100       223 my $sol = $line == 1 ? (length $symbol) + 1 + $original_offset : $lineoffsets{$line};
447 69         104 my $eol = (length $linestr) - 1;
448 69         89 my $diff = $eol - $sol;
449 69         141 my $substr = substr($linestr, $sol, $diff);
450 69 50       390 $DEBUG and print STDERR "Got substr[$substr] sol[$sol] eol[$eol] diff[$diff]\n";
451              
452 69         143 my $newline = "\n" x $lineadjust;
453 69 100       175 if($symbol =~ /^lexer_test$/) {
454 19         40 $newline .= "and \$lexed = \"$stmt\";";
455             } else {
456 50         142 $newline .= " and " . substr($stmt, length $symbol);
457             }
458              
459 69         158 substr($linestr, $sol, (length $linestr) - $sol - 1) = $newline; # put the rest of the statement in
460              
461 69 50 33     1884 ($DEBUG || $SHOWTRANSLATE) and print STDERR "Got new linestr[$linestr] from original_linestr[$original_linestr]\n";
462              
463 69 50       150 $DEBUG and print "=" x 80, "\n";
464 69         2899 Devel::Declare::set_linestr($linestr);
465             }
466              
467             1;
468              
469             =encoding utf8
470              
471             =head1 NAME
472              
473             Devel::Declare::Lexer - Easier than Devel::Declare
474              
475             =head1 SYNOPSIS
476              
477             # Add :debug tag to enable debugging
478             # Add :lexer_test to enable variable assignment
479             # Anything not starting with : becomes a keyword
480             use Devel::Declare::Lexer qw/ keyword /;
481              
482             BEGIN {
483             # Create a callback for the keyword (inside a BEGIN block!)
484             Devel::Declare::Lexer::lexed(keyword => sub {
485             # Get the stream out (given as an arrayref)
486             my ($stream_r) = @_;
487             my @stream = @$stream_r;
488              
489             my $str = $stream[2]; # in the example below, the string is the 3rd token
490              
491             # Create a new stream (we could manipulate the existing one though)
492             my @ns = ();
493             tie @ns, "Devel::Declare::Lexer::Stream";
494              
495             # Add a few tokens to print the string
496             push @ns, (
497             # You need this (for now)
498             new Devel::Declare::Lexer::Token::Declarator( value => 'keyword' ),
499             new Devel::Declare::Lexer::Token::Whitespace( value => ' ' ),
500              
501             # Everything else is your own custom code
502             new Devel::Declare::Lexer::Token( value => 'print' ),
503             new Devel::Declare::Lexer::Token::Whitespace( value => ' ' ),
504             $string,
505             new Devel::Declare::Lexer::Token::EndOfStatement,
506             new Devel::Declare::Lexer::Token::Newline,
507             );
508              
509             # Stream now contains:
510             # keyword and print "This is a string";
511             # keyword evaluates to 1, everything after the and gets executed
512              
513             # Return an arrayref
514             return \@ns;
515             });
516             }
517              
518             # Use the keyword anywhere in this package
519             keyword "This is a string";
520              
521             =head1 DESCRIPTION
522              
523             L makes it easier to parse code using L
524             by generating a token stream from the statement and providing a callback for
525             you to manipulate it before its parsed by Perl.
526              
527             The example in the synopsis creates a keyword named 'keyword', which accepts
528             a string and prints it.
529              
530             Although this simple example could be done using print, say or any other simple
531             subroutine, L supports much more flexible syntax.
532              
533             For example, it could be used to auto-expand subroutine declarations, e.g.
534             method MethodName ( $a, @b ) {
535             ...
536             }
537             into
538             sub MethodName ($@) {
539             my ($self, $a, @b) = @_;
540             ...
541             }
542              
543             Unlike L, there's no need to worry about parsing text and
544             taking care of multiline strings or code blocks - it's all done for you.
545              
546             =head1 ADVANCED USAGE
547              
548             L's standard behaviour is to inject a sub into the
549             calling package which returns a 1. Because your statement typically gets
550             transformed into something like
551             keyword and [your statement here];
552             the fact keyword evaluates to 1 means everything following the and will always
553             be executed.
554              
555             You can extend this by using a different import syntax when loading L
556             use Devel::Declare::Lexer { keyword => sub { $Some::Package::variable } };
557             which will cause the provided sub to be injected instead of the default sub.
558              
559             =head1 SEE ALSO
560              
561             Some examples can be found in the source download.
562              
563             For more information about how L works, read the
564             documentation for L.
565              
566             =head1 AUTHORS
567              
568             Ian Kent - L - original author
569              
570             http://www.iankent.co.uk/
571              
572             =head1 COPYRIGHT AND LICENSE
573              
574             This library is free software under the same terms as perl itself
575              
576             Copyright (c) 2013 Ian Kent
577              
578             Devel::Declare::Lexer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
579             without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
580              
581             =cut