File Coverage

blib/lib/Syntax/Highlight/Engine/Kate/Template.pm
Criterion Covered Total %
statement 518 577 89.7
branch 180 234 76.9
condition 15 18 83.3
subroutine 73 73 100.0
pod 57 63 90.4
total 843 965 87.3


line stmt bran cond sub pod time code
1             # Copyright (c) 2006 Hans Jeuken. All rights reserved.
2             # This program is free software; you can redistribute it and/or
3             # modify it under the same terms as Perl itself.
4              
5             package Syntax::Highlight::Engine::Kate::Template;
6              
7             our $VERSION = '0.14';
8              
9 7     7   45 use strict;
  7         12  
  7         184  
10 7     7   33 use Carp qw(cluck);
  7         14  
  7         228  
11 7     7   45 use Data::Dumper;
  7         13  
  7         22570  
12              
13             #my $regchars = '\\^.$|()[]*+?';
14              
15             sub new {
16 232     232 0 474 my $proto = shift;
17 232   33     745 my $class = ref($proto) || $proto;
18 232         659 my %args = (@_);
19              
20 232         477 my $debug = delete $args{'debug'};
21 232 50       527 unless (defined($debug)) { $debug = 0 };
  232         409  
22 232         417 my $substitutions = delete $args{'substitutions'};
23 232 100       531 unless (defined($substitutions)) { $substitutions = {} };
  101         260  
24 232         417 my $formattable = delete $args{'format_table'};
25 232 100       506 unless (defined($formattable)) { $formattable = {} };
  95         200  
26 232         459 my $engine = delete $args{'engine'};
27              
28 232         358 my $self = {};
29             $self->{'attributes'} = {},
30 232         655 $self->{'captured'} = [];
31 232         470 $self->{'contextdata'} = {};
32 232         501 $self->{'basecontext'} = '';
33 232         439 $self->{'debug'} = $debug;
34 232         460 $self->{'deliminators'} = '';
35 232         368 $self->{'engine'} = '';
36 232         591 $self->{'format_table'} = $formattable;
37 232         435 $self->{'keywordscase'} = 1;
38 232         418 $self->{'lastchar'} = '';
39 232         414 $self->{'linesegment'} = '';
40 232         379 $self->{'lists'} = {};
41 232         381 $self->{'linestart'} = 1;
42 232         475 $self->{'out'} = [];
43 232         451 $self->{'plugins'} = {};
44 232         557 $self->{'snippet'} = '';
45 232         446 $self->{'snippetattribute'} = '';
46 232         418 $self->{'stack'} = [];
47 232         450 $self->{'substitutions'} = $substitutions;
48 232         463 bless ($self, $class);
49 232 100       489 unless (defined $engine) { $engine = $self };
  144         221  
50 232         1030 $self->engine($engine);
51 232         883 $self->initialize;
52 232         703 return $self;
53             }
54              
55             sub attributes {
56 219     219 1 389 my $self = shift;
57 219 50       477 if (@_) { $self->{'attributes'} = shift; };
  219         455  
58 219         442 return $self->{'attributes'};
59             }
60              
61             sub basecontext {
62 333     333 1 527 my $self = shift;
63 333 100       709 if (@_) { $self->{'basecontext'} = shift; };
  219         422  
64 333         646 return $self->{'basecontext'};
65             }
66              
67             sub captured {
68 13174     13174 1 22299 my ($self, $c) = @_;
69 13174 50       23845 if (defined($c)) {
70 13174         23761 my $t = $self->engine->stackTop;
71 13174         20468 my $n = 0;
72 13174         18288 my @o = ();
73 13174         27563 while (defined($c->[$n])) {
74 1324         2833 push @o, $c->[$n];
75 1324         2693 $n ++;
76             }
77 13174 100       32356 if (@o) {
78 1200         3132 $t->[2] = \@o;
79             }
80             };
81             }
82              
83             sub capturedGet {
84 5334     5334 1 12322 my ($self, $num) = @_;
85 5334         10294 my $s = $self->engine->{stack};
86 5334 50       9587 if (defined($s->[1])) {
87 5334         7512 my $c = $s->[1]->[2];
88 5334         8879 $num --;
89 5334 50       8064 if (defined($c)) {
90 5334 50       8127 if (defined($c->[$num])) {
91 5334         6818 my $r = $c->[$num];
92 5334         9677 return $r;
93             } else {
94 1         44 warn "capture number $num not defined";
95             }
96             } else {
97 1         6 warn "dynamic substitution is called for but nothing to substitute\n";
98 1         3 return undef;
99             }
100             } else {
101 1         27 warn "no parent context to take captures from";
102             }
103             }
104              
105             #sub captured {
106             # my $self = shift;
107             # if (@_) {
108             # $self->{'captured'} = shift;
109             ## print Dumper($self->{'captured'});
110             # };
111             # return $self->{'captured'}
112             ## my ($self, $c) = @_;
113             ## if (defined($c)) {
114             ## my $t = $self->engine->stackTop;
115             ## my $n = 0;
116             ## my @o = ();
117             ## while (defined($c->[$n])) {
118             ## push @o, $c->[$n];
119             ## $n ++;
120             ## }
121             ## if (@o) {
122             ## $t->[2] = \@o;
123             ## }
124             ## };
125             #}
126             #
127             #sub capturedGet {
128             # my ($self, $num) = @_;
129             # my $s = $self->captured;
130             # if (defined $s) {
131             # $num --;
132             # if (defined($s->[$num])) {
133             # return $s->[$num];
134             # } else {
135             # $self->logwarning("capture number $num not defined");
136             # }
137             # } else {
138             # $self->logwarning("dynamic substitution is called for but nothing to substitute");
139             # return undef;
140             # }
141             #}
142              
143             sub capturedParse {
144 5334     5334 1 8379 my ($self, $string, $mode) = @_;
145 5334         7173 my $s = '';
146 5334 100       8283 if (defined($mode)) {
147 35 50       126 if ($string =~ s/^(\d)//) {
148 35         60 $s = $self->capturedGet($1);
149 35 50       103 if ($string ne '') {
150 1         8 $self->logwarning("character class is longer then 1 character, ignoring the rest");
151             }
152             }
153             } else {
154 5300         9658 while ($string ne '') {
155 15739 100       36685 if ($string =~ s/^([^\%]*)\%(\d)//) {
156 5300         10330 my $r = $self->capturedGet($2);
157 5300 50       9835 if ($r ne '') {
158 5300         14306 $s = $s . $1 . $r
159             } else {
160 1         7 $s = $s . $1 . '%' . $2;
161 1         2 $self->logwarning("target is an empty string");
162             }
163             } else {
164 10440         18115 $string =~ s/^(.)//;
165 10440         19653 $s = "$s$1";
166             }
167             }
168             }
169 5334         9134 return $s;
170             }
171              
172             sub column {
173 285     285 1 398 my $self = shift;
174 285         755 return length($self->{linesegment});
175             }
176              
177             sub contextdata {
178 219     219 1 431 my $self = shift;
179 219 50       580 if (@_) { $self->{'contextdata'} = shift; };
  219         482  
180 219         506 return $self->{'contextdata'};
181             }
182              
183             sub contextInfo {
184 696216     696216 1 1049839 my ($self, $context, $item) = @_;
185 696216 50       1147345 if (exists $self->{contextdata}->{$context}) {
186 696216         892890 my $c = $self->{contextdata}->{$context};
187 696216 100       1012983 if (exists $c->{$item}) {
188 506856         879295 return $c->{$item}
189             } else {
190 189361         321056 return undef;
191             }
192             } else {
193 1         26 $self->logwarning("undefined context '$context'");
194 1         7 return undef;
195             }
196             }
197              
198             sub contextParse {
199 45696     45696 1 72890 my ($self, $plug, $context) = @_;
200 45696 100       153952 if ($context =~ /^#pop/i) {
    100          
    100          
201 7682         28376 while ($context =~ s/#pop//i) {
202 9608         19460 $self->stackPull;
203             }
204             } elsif ($context =~ /^#stay/i) {
205             #don't do anything
206             } elsif ($context =~ /^##(.+)/) {
207 7         44 my $new = $self->pluginGet($1);
208 7         37 $self->stackPush([$new, $new->{basecontext}]);
209             } else {
210 9851         25394 $self->stackPush([$plug, $context]);
211             }
212             }
213              
214             sub debug {
215 1     1 0 28 my $self = shift;
216 1 0       6 if (@_) { $self->{'debug'} = shift; };
  1         3  
217 1         27 return $self->{'debug'};
218             }
219              
220             sub debugTest {
221 1     1 0 7 my $self = shift;
222 1 0       2 if (@_) { $self->{'debugtest'} = shift; };
  1         27  
223 1         8 return $self->{'debugtest'};
224             }
225              
226             sub deliminators {
227 219     219 1 326 my $self = shift;
228 219 50       504 if (@_) { $self->{'deliminators'} = shift; };
  219         470  
229 219         434 return $self->{'deliminators'};
230             }
231              
232             sub engine {
233 255435     255435 1 328355 my $self = shift;
234 255435 100       414528 if (@_) { $self->{'engine'} = shift; };
  232         678  
235 255435         461149 return $self->{'engine'};
236             }
237              
238              
239             sub firstnonspace {
240 235     235 1 468 my ($self, $string) = @_;
241 235         490 my $line = $self->{linesegment};
242 235 100 66     1414 if (($line =~ /^\s*$/) and ($string =~ /^[^\s]/)) {
243 197         622 return 1
244             }
245 39         134 return ''
246             }
247              
248             sub formatTable {
249 55852     55852 1 65824 my $self = shift;
250 55852 50       82711 if (@_) { $self->{'format_table'} = shift; };
  1         3  
251 55852         74426 return $self->{'format_table'};
252             }
253              
254             sub highlight {
255 109     109 1 380 my ($self, $text) = @_;
256 109         502 $self->snippet('');
257 109         255 my $out = $self->{out};
258 109         256 @$out = ();
259 109         285 while ($text ne '') {
260 222996         389087 my $top = $self->stackTop;
261 222996 100       381297 if (defined($top)) {
262 222990         374791 my ($plug, $context) = @$top;
263 222990 100       436741 if ($text =~ s/^(\n)//) {
264 11829         26532 $self->snippetForce;
265 11829         22022 my $e = $plug->contextInfo($context, 'lineending');
266 11829 100       22509 if (defined($e)) {
267 1646         3118 $self->contextParse($plug, $e)
268             }
269 11829         22230 my $attr = $plug->{attributes}->{$plug->contextInfo($context, 'attribute')};
270 11829         25795 $self->snippetParse($1, $attr);
271 11829         23395 $self->snippetForce;
272 11829         16594 $self->{linesegment} = '';
273 11829         22121 my $b = $plug->contextInfo($context, 'linebeginning');
274 11829 50       31216 if (defined($b)) {
275 1         2 $self->contextParse($plug, $b)
276             }
277             } else {
278 211162         362383 my $sub = $plug->contextInfo($context, 'callback');
279 211162         492730 my $result = &$sub($plug, \$text);
280 211162 100       406051 unless($result) {
281 168787         318246 my $f = $plug->contextInfo($context, 'fallthrough');
282 168787 100       263123 if (defined($f)) {
283 1438         2398 $self->contextParse($plug, $f);
284             } else {
285 167350         796414 $text =~ s/^(.)//;
286 167350         359773 my $attr = $plug->{attributes}->{$plug->contextInfo($context, 'attribute')};
287 167350         320990 $self->snippetParse($1, $attr);
288             }
289             }
290             }
291             } else {
292 7         52 push @$out, length($text), 'Normal';
293 7         21 $text = '';
294             }
295             }
296 109         340 $self->snippetForce;
297 109         27615 return @$out;
298             }
299              
300             sub highlightText {
301 109     109 1 49437 my ($self, $text) = @_;
302 109         223 my $res = '';
303 109         525 my @hl = $self->highlight($text);
304 109         753 while (@hl) {
305 55852         79182 my $f = shift @hl;
306 55852         70612 my $t = shift @hl;
307 55852 50       83184 unless (defined($t)) { $t = 'Normal' }
  1         3  
308 55852         66809 my $s = $self->{substitutions};
309 55852         64906 my $rr = '';
310 55852         82723 while ($f ne '') {
311 324031         394685 my $k = substr($f , 0, 1);
312 324031         410087 $f = substr($f, 1, length($f) -1);
313 324031 100       427586 if (exists $s->{$k}) {
314 9735         16995 $rr = $rr . $s->{$k}
315             } else {
316 314296         482744 $rr = $rr . $k;
317             }
318             }
319 55851         81984 my $rt = $self->formatTable;
320 55851 50       83286 if (exists $rt->{$t}) {
321 55851         67121 my $o = $rt->{$t};
322 55851         269241 $res = $res . $o->[0] . $rr . $o->[1];
323             } else {
324 0         0 $res = $res . $rr;
325 0         0 $self->logwarning("undefined format tag '$t'");
326             }
327             }
328 108         4650 return $res;
329             }
330              
331             sub includePlugin {
332 22906     22907 1 36770 my ($self, $language, $text) = @_;
333 22906         32163 my $eng = $self->{engine};
334 22906         39322 my $plug = $eng->pluginGet($language);
335 22906 50       45011 if (defined($plug)) {
336 22906         32764 my $context = $plug->{basecontext};
337 22906         36604 my $call = $plug->contextInfo($context, 'callback');
338 22906 50       35705 if (defined($call)) {
339 22906         46212 return &$call($plug, $text);
340             } else {
341 0         0 $self->logwarning("cannot find callback for context '$context'");
342             }
343             }
344 0         0 return 0;
345             }
346              
347             sub includeRules {
348 81937     81938 1 140452 my ($self, $context, $text) = @_;
349 81937         141631 my $call = $self->contextInfo($context, 'callback');
350 81937 50       123908 if (defined($call)) {
351 81937         153215 return &$call($self, $text);
352             } else {
353 0         0 $self->logwarning("cannot find callback for context '$context'");
354             }
355 0         0 return 0;
356             }
357              
358             sub initialize {
359 436     437 0 761 my $self = shift;
360 436 100       728 if ($self->engine eq $self) {
361 260         1041 $self->stack([[$self, $self->{basecontext}]]);
362             }
363             }
364              
365             sub keywordscase {
366 218     219 1 351 my $self = shift;
367 218 50       499 if (@_) { $self->{'keywordscase'} = shift; }
  218         365  
368 218         432 return $self->{'keywordscase'}
369             }
370              
371             sub languagePlug {
372 21     22 0 57 my ($cw, $name) = @_;
373 21         190 my %numb = (
374             '1' => 'One',
375             '2' => 'Two',
376             '3' => 'Three',
377             '4' => 'Four',
378             '5' => 'Five',
379             '6' => 'Six',
380             '7' => 'Seven',
381             '8' => 'Eight',
382             '9' => 'Nine',
383             '0' => 'Zero',
384             );
385 21 50       83 if ($name =~ s/^(\d)//) {
386 0         0 $name = $numb{$1} . $name;
387             }
388 21         57 $name =~ s/\.//;
389 21         45 $name =~ s/\+/plus/g;
390 21         44 $name =~ s/\-/minus/g;
391 21         42 $name =~ s/#/dash/g;
392 21         45 $name =~ s/[^0-9a-zA-Z]/_/g;
393 21         39 $name =~ s/__/_/g;
394 21         42 $name =~ s/_$//;
395 21         65 $name = ucfirst($name);
396 21         84 return $name;
397             }
398              
399             sub lastchar {
400 838627     838628 1 1054288 my $self = shift;
401 838627         1147466 my $l = $self->{linesegment};
402 838627 100       1257039 if ($l eq '') { return "\n" } #last character was a newline
  24123         39032  
403 814504         2479848 return substr($l, length($l) - 1, 1);
404             }
405              
406             sub lastcharDeliminator {
407 566144     566145 1 697958 my $self = shift;
408 566144         705833 my $deliminators = '\s|\~|\!|\%|\^|\&|\*|\+|\(|\)|-|=|\{|\}|\[|\]|:|;|<|>|,|\\|\||\.|\?|\/';
409 566144 100 100     784216 if ($self->linestart or ($self->lastchar =~ /$deliminators/)) {
410 310033         1309893 return 1;
411             }
412 256111         556216 return '';
413             }
414              
415             sub linesegment {
416 860067     860068 1 1053158 my $self = shift;
417 860067 50       1319878 if (@_) { $self->{'linesegment'} = shift; };
  0         0  
418 860067         1694101 return $self->{'linesegment'};
419             }
420              
421             sub linestart {
422 860067     860068 1 1011131 my $self = shift;
423 860067 100       1142860 if ($self->linesegment eq '') {
424 48445         100918 return 1
425             }
426 811622         1710443 return '';
427             }
428              
429             sub lists {
430 0     1 1 0 my $self = shift;
431 0 0       0 if (@_) { $self->{'lists'} = shift; }
  0         0  
432 0         0 return $self->{'lists'}
433             }
434              
435             sub out {
436 116     117 1 178 my $self = shift;
437 116 50       277 if (@_) { $self->{'out'} = shift; }
  116         6319  
438 116         243 return $self->{'out'};
439             }
440              
441             sub listAdd {
442 670     671 1 1031 my $self = shift;
443 670         900 my $listname = shift;
444 670         866 my $lst = $self->{lists};
445 670 100       1150 if (@_) {
446 669         12063 my @l = reverse sort @_;
447 669         2069 $lst->{$listname} = \@l;
448             } else {
449 1         3 $lst->{$listname} = [];
450             }
451             }
452              
453             sub logwarning {
454 2     3 0 7 my ($self, $warning) = @_;
455 2         6 my $top = $self->engine->stackTop;
456 2 50       6 if (defined $top) {
457 0         0 my $lang = $top->[0]->language;
458 0         0 my $context = $top->[1];
459 0         0 $warning = "$warning\n Language => $lang, Context => $context\n";
460             } else {
461 2         5 $warning = "$warning\n STACK IS EMPTY: PANIC\n"
462             }
463 2         37 cluck($warning);
464             }
465              
466             sub parseResult {
467 42702     42703 1 98637 my ($self, $text, $string, $lahead, $column, $fnspace, $context, $attr) = @_;
468 42702         74778 my $eng = $self->engine;
469 42702 100       75451 if ($fnspace) {
470 234 100       725 unless ($eng->firstnonspace($$text)) {
471 38         176 return ''
472             }
473             }
474 42664 100       70995 if (defined($column)) {
475 284 100       597 if ($column ne $eng->column) {
476 51         184 return '';
477             }
478             }
479 42613 100       70306 unless ($lahead) {
480 41376         169735 $$text = substr($$text, length($string));
481 41376         55094 my $r;
482 41376 100       66868 unless (defined($attr)) {
483 8592         14254 my $t = $eng->stackTop;
484 8592         14794 my ($plug, $ctext) = @$t;
485 8592         16279 $r = $plug->{attributes}->{$plug->contextInfo($ctext, 'attribute')};
486             } else {
487 32784         57613 $r = $self->{attributes}->{$attr};
488             }
489 41376         77003 $eng->snippetParse($string, $r);
490             }
491 42613         96943 $eng->contextParse($self, $context);
492 42613         162090 return 1
493             }
494              
495             sub pluginGet {
496 23028     23029 1 34459 my ($self, $language) = @_;
497 23028         32566 my $plugs = $self->{'plugins'};
498 23028 100       42391 unless (exists($plugs->{$language})) {
499 90         350 my $lang_plug = $self->languagePlug($language);
500 90         179 my $modname = 'Syntax::Highlight::Engine::Kate::';
501 90 100       241 if (defined $lang_plug) {
502 88         168 $modname .= $lang_plug;
503             }
504 90 50       240 unless (defined($modname)) {
505 0         0 $self->logwarning("no valid module found for language '$language'");
506 0         0 return undef;
507             }
508 90         228 my $plug;
509 5     5   2691 eval "use $modname; \$plug = new $modname(engine => \$self);";
  5     5   18  
  5     4   165  
  5     4   1540  
  5     4   14  
  5         150  
  4         1349  
  4         11  
  4         106  
  4         263  
  3         6  
  3         72  
  4         667  
  3         7  
  3         84  
  90         14119  
510 90 100       342 if (defined($plug)) {
511 88         244 $plugs->{$language} = $plug;
512             } else {
513 2         16 $self->logwarning("cannot create plugin for language '$language'\n--------------\n$@");
514             }
515             }
516 23028 100       45454 if (exists($plugs->{$language})) {
517 23026         40809 return $plugs->{$language};
518             }
519 2         7 return undef;
520             }
521              
522             sub reset {
523 0     1 1 0 my $self = shift;
524 0         0 $self->stack([[$self, $self->{basecontext}]]);
525 0         0 $self->out([]);
526 0         0 $self->snippet('');
527             }
528              
529             sub snippet {
530 119878     119879 1 142855 my $self = shift;
531 119878 100       190018 if (@_) { $self->{'snippet'} = shift; }
  56069         80083  
532 119878         196540 return $self->{'snippet'};
533             }
534              
535             sub snippetAppend {
536 220553     220554 1 335606 my ($self, $ch) = @_;
537              
538 220553 100       370707 return if not defined $ch;
539 220539         368574 $self->{'snippet'} = $self->{'snippet'} . $ch;
540 220539 50       383604 if ($ch ne '') {
541 220539         377976 $self->{linesegment} = $self->{linesegment} . $ch;
542             }
543 220539         469753 return;
544             }
545              
546             sub snippetAttribute {
547 0     1 1 0 my $self = shift;
548 0 0       0 if (@_) { $self->{'snippetattribute'} = shift; }
  0         0  
549 0         0 return $self->{'snippetattribute'};
550             }
551              
552             sub snippetForce {
553 63809     63810 1 82799 my $self = shift;
554 63809         103784 my $parse = $self->snippet;
555 63809 100       120337 if ($parse ne '') {
556 55845         74973 my $out = $self->{'out'};
557 55845         103312 push(@$out, $parse, $self->{snippetattribute});
558 55845         85347 $self->snippet('');
559             }
560             }
561              
562             sub snippetParse {
563 220553     220554 1 287402 my $self = shift;
564 220553         357699 my $snip = shift;
565 220553         290805 my $attr = shift;
566 220553 100 100     677624 if ((defined $attr) and ($attr ne $self->{snippetattribute})) {
567 40045         83096 $self->snippetForce;
568 40045         55165 $self->{snippetattribute} = $attr;
569             }
570 220553         394083 $self->snippetAppend($snip);
571             }
572              
573             sub stack {
574 376     377 1 562 my $self = shift;
575 376 50       730 if (@_) { $self->{'stack'} = shift; }
  376         892  
576 376         799 return $self->{'stack'};
577             }
578              
579             sub stackPush {
580 9856     9857 1 16770 my ($self, $val) = @_;
581 9856         14332 my $stack = $self->{stack};
582 9856         19829 unshift(@$stack, $val);
583             }
584              
585             sub stackPull {
586 9607     9608 1 15877 my ($self, $val) = @_;
587 9607         13257 my $stack = $self->{stack};
588 9607         29707 return shift(@$stack);
589             }
590              
591             sub stackTop {
592 244762     244763 1 322329 my $self = shift;
593 244762         379189 return $self->{stack}->[0];
594             }
595              
596             sub stateCompare {
597 0     1 1 0 my ($self, $state) = @_;
598 0         0 my $h = [ $self->stateGet ];
599 0         0 my $equal = 0;
600 0 0       0 if (Dumper($h) eq Dumper($state)) { $equal = 1 };
  0         0  
601 0         0 return $equal;
602             }
603              
604             sub stateGet {
605 0     1 1 0 my $self = shift;
606 0         0 my $s = $self->{stack};
607 0         0 return @$s;
608             }
609              
610             sub stateSet {
611 0     1 1 0 my $self = shift;
612 0         0 my $s = $self->{stack};
613 0         0 @$s = (@_);
614             }
615              
616             sub substitutions {
617 0     1 1 0 my $self = shift;
618 0 0       0 if (@_) { $self->{'substitutions'} = shift; }
  0         0  
619 0         0 return $self->{'substitutions'};
620             }
621              
622             sub testAnyChar {
623 40969     40970 1 58515 my $self = shift;
624 40969         51836 my $text = shift;
625 40969         53330 my $string = shift;
626 40969         52335 my $insensitive = shift;
627 40969         62557 my $test = substr($$text, 0, 1);
628 40969         50916 my $bck = $test;
629 40969 50       69440 if ($insensitive) {
630 0         0 $string = lc($string);
631 0         0 $test = lc($test);
632             }
633 40969 100       79890 if (index($string, $test) > -1) {
634 5110         12769 return $self->parseResult($text, $bck, @_);
635             }
636 35859         76314 return ''
637             }
638              
639             sub testDetectChar {
640 385776     385777 1 514525 my $self = shift;
641 385776         461600 my $text = shift;
642 385776         459163 my $char = shift;
643 385776         446279 my $insensitive = shift;
644 385776         445867 my $dyn = shift;
645 385776 100       564641 if ($dyn) {
646 34         70 $char = $self->capturedParse($char, 1);
647             }
648 385776         554023 my $test = substr($$text, 0, 1);
649 385776         467384 my $bck = $test;
650 385776 50       562908 if ($insensitive) {
651 0         0 $char = lc($char);
652 0         0 $test = lc($test);
653             }
654 385776 100       603230 if ($char eq $test) {
655 9537         23410 return $self->parseResult($text, $bck, @_);
656             }
657 376239         776184 return ''
658             }
659              
660             sub testDetect2Chars {
661 236118     236119 1 311764 my $self = shift;
662 236118         310530 my $text = shift;
663 236118         295581 my $char = shift;
664 236118         282089 my $char1 = shift;
665 236118         275513 my $insensitive = shift;
666 236118         288163 my $dyn = shift;
667 236118 50       356797 if ($dyn) {
668 0         0 $char = $self->capturedParse($char, 1);
669 0         0 $char1 = $self->capturedParse($char1, 1);
670             }
671 236118         326345 my $string = $char . $char1;
672 236118         325525 my $test = substr($$text, 0, 2);
673 236118         291092 my $bck = $test;
674 236118 50       337950 if ($insensitive) {
675 0         0 $string = lc($string);
676 0         0 $test = lc($test);
677             }
678 236118 100       376731 if ($string eq $test) {
679 1263         3301 return $self->parseResult($text, $bck, @_);
680             }
681 234855         515326 return ''
682             }
683              
684             sub testDetectIdentifier {
685 29422     29423 1 39749 my $self = shift;
686 29422         34838 my $text = shift;
687 29422 100       67109 if ($$text =~ /^([a-zA-Z_][a-zA-Z0-9_]+)/) {
688 7405         17180 return $self->parseResult($text, $1, @_);
689             }
690 22017         45846 return ''
691             }
692              
693             sub testDetectSpaces {
694 41375     41376 1 55205 my $self = shift;
695 41375         50875 my $text = shift;
696 41375 100       107007 if ($$text =~ /^([\\040|\\t]+)/) {
697 955         2366 return $self->parseResult($text, $1, @_);
698             }
699 40420         90197 return ''
700             }
701              
702             sub testFloat {
703 57829     57830 1 77965 my $self = shift;
704 57829         69517 my $text = shift;
705 57829 100       100609 if ($self->engine->lastcharDeliminator) {
706 31956 100       91465 if ($$text =~ /^((?=\.?\d)\d*(?:\.\d*)?(?:[Ee][+-]?\d+)?)/) {
707 1845         4949 return $self->parseResult($text, $1, @_);
708             }
709             }
710 55984         126538 return ''
711             }
712              
713             sub testHlCChar {
714 24992     24993 1 36431 my $self = shift;
715 24992         33314 my $text = shift;
716 24992 100       49806 if ($$text =~ /^('.')/) {
717 26         89 return $self->parseResult($text, $1, @_);
718             }
719 24966         56839 return ''
720             }
721              
722             sub testHlCHex {
723 39211     39212 1 52818 my $self = shift;
724 39211         52087 my $text = shift;
725 39211 100       58550 if ($self->engine->lastcharDeliminator) {
726 22158 100       42024 if ($$text =~ /^(0x[0-9a-fA-F]+)/) {
727 8         27 return $self->parseResult($text, $1, @_);
728             }
729             }
730 39203         87145 return ''
731             }
732              
733             sub testHlCOct {
734 33373     33374 1 46450 my $self = shift;
735 33373         41409 my $text = shift;
736 33373 100       55043 if ($self->engine->lastcharDeliminator) {
737 19928 50       38309 if ($$text =~ /^(0[0-7]+)/) {
738 0         0 return $self->parseResult($text, $1, @_);
739             }
740             }
741 33373         74666 return ''
742             }
743              
744             sub testHlCStringChar {
745 5020     5021 1 10853 my $self = shift;
746 5020         5972 my $text = shift;
747 5020 100       9528 if ($$text =~ /^(\\[a|b|e|f|n|r|t|v|'|"|\?])/) {
748 34         109 return $self->parseResult($text, $1, @_);
749             }
750 4986 50       8053 if ($$text =~ /^(\\x[0-9a-fA-F][0-9a-fA-F]?)/) {
751 0         0 return $self->parseResult($text, $1, @_);
752             }
753 4986 50       8283 if ($$text =~ /^(\\[0-7][0-7]?[0-7]?)/) {
754 0         0 return $self->parseResult($text, $1, @_);
755             }
756 4986         10445 return ''
757             }
758              
759             sub testInt {
760 63144     63145 1 94144 my $self = shift;
761 63144         74960 my $text = shift;
762 63144 100       94068 if ($self->engine->lastcharDeliminator) {
763 33241 100       83262 if ($$text =~ /^([+-]?\d+)/) {
764 314         877 return $self->parseResult($text, $1, @_);
765             }
766             }
767 62830         140041 return ''
768             }
769              
770             sub testKeyword {
771 372587     372588 1 487899 my $self = shift;
772 372587         451248 my $text = shift;
773 372587         450975 my $list = shift;
774 372587         505054 my $eng = $self->{engine};
775 372587         460285 my $deliminators = $self->{deliminators};
776 372587 100 100     567487 if (($eng->lastcharDeliminator) and ($$text =~ /^([^$deliminators]+)/)) {
777 72284         150498 my $match = $1;
778 72284         115262 my $l = $self->{lists}->{$list};
779 72284 50       110467 if (defined($l)) {
780 72284         515980 my @list = @$l;
781 72284         92390 my @rl = ();
782 72284 100       116336 unless ($self->{keywordscase}) {
783 66046         106962 @rl = grep { (lc($match) eq lc($_)) } @list;
  6068764         8533644  
784             } else {
785 6238         9639 @rl = grep { ($match eq $_) } @list;
  111076         151500  
786             }
787 72284 100       244940 if (@rl) {
788 5778         15030 return $self->parseResult($text, $match, @_);
789             }
790             } else {
791 0         0 $self->logwarning("list '$list' is not defined, failing test");
792             }
793             }
794 366809         879227 return ''
795             }
796              
797             sub testLineContinue {
798 6210     6211 1 9168 my $self = shift;
799 6210         8020 my $text = shift;
800 6210         8041 my $lahead = shift;
801 6210 50       8832 if ($lahead) {
802 0 0       0 if ($$text =~ /^\\\n/) {
803 0         0 $self->parseResult($text, "\\", $lahead, @_);
804 0         0 return 1;
805             }
806             } else {
807 6210 100       11893 if ($$text =~ s/^(\\)(\n)/$2/) {
808 14         41 return $self->parseResult($text, "\\", $lahead, @_);
809             }
810             }
811 6196         13745 return ''
812             }
813              
814             sub testRangeDetect {
815 15374     15374 1 22220 my $self = shift;
816 15374         19129 my $text = shift;
817 15374         19345 my $char = shift;
818 15374         18957 my $char1 = shift;
819 15374         21193 my $insensitive = shift;
820 15374         24643 my $string = "$char\[^$char1\]+$char1";
821 15374         28710 return $self->testRegExpr($text, $string, $insensitive, 0, @_);
822             }
823              
824             sub testRegExpr {
825 1370097     1370097 1 1754938 my $self = shift;
826 1370097         1631215 my $text = shift;
827 1370097         1701901 my $reg = shift;
828 1370097         1545748 my $insensitive = shift;
829 1370097         1541684 my $dynamic = shift;
830 1370097 100       2056269 if ($dynamic) {
831 5299         10455 $reg = $self->capturedParse($reg);
832             }
833 1370097         1784466 my $eng = $self->{engine};
834 1370097 100       3496295 if ($reg =~ s/^\^//) {
    100          
835 293923 100       451227 unless ($eng->linestart) {
836 283496         636824 return '';
837             }
838             } elsif ($reg =~ s/^\\(b)//i) {
839 310501         511308 my $lastchar = $eng->lastchar;
840 310501 100       596655 if ($1 eq 'b') {
841 309819 100       669366 if ($lastchar =~ /\w/) { return '' }
  130011         320553  
842             } else {
843 682 100       1543 if ($lastchar =~ /\W/) { return '' }
  308         791  
844             }
845             }
846 956282         1660751 $reg = "^($reg)";
847 956282         1251416 my $sample = $$text;
848              
849             # emergency measurements to avoid exception (szabgab)
850 956282         1158101 $reg = eval { qr/$reg/ };
  956282         11936181  
851 956282 50       2078958 if ($@) {
852 0         0 warn $@;
853 0         0 return '';
854             }
855 956282         1103471 my $match;
856 956282 100       1467177 if ($insensitive) {
857 127708 100       443243 if ($sample =~ /$reg/i) {
858 158         320 $match = $1;
859 158 50       425 if ($#-) {
860 6     6   466 no strict 'refs';
  6         13  
  6         494  
861 158         490 my @cap = map {$$_} 2 .. $#-;
  84         362  
862 158         480 $self->captured(\@cap)
863             }
864             }
865             } else {
866 828574 100       2988884 if ($sample =~ /$reg/) {
867 13015         27379 $match = $1;
868 13015 50       27765 if ($#-) {
869 6     6   37 no strict 'refs';
  6         14  
  6         970  
870 13015         27915 my @cap = map {$$_} 2 .. $#-;
  1299         5865  
871 13015         31142 $self->captured(\@cap);
872             }
873             }
874             }
875 956282 100 100     1769318 if ((defined($match)) and ($match ne '')) {
876 9843         23496 return $self->parseResult($text, $match, @_);
877             }
878 946439         2605769 return ''
879             }
880              
881             sub testStringDetect {
882 1692834     1692834 1 2057686 my $self = shift;
883 1692834         1928998 my $text = shift;
884 1692834         1926096 my $string = shift;
885 1692834         1856745 my $insensitive = shift;
886 1692834         1852364 my $dynamic = shift;
887 1692834 50       2379313 if ($dynamic) {
888 0         0 $string = $self->capturedParse($string);
889             }
890 1692834         2308821 my $test = substr($$text, 0, length($string));
891 1692834         1948275 my $bck = $test;
892 1692834 100       2375419 if ($insensitive) {
893 3672         4964 $string = lc($string);
894 3672         4344 $test = lc($test);
895             }
896 1692834 100       2438038 if ($string eq $test) {
897 570         1531 return $self->parseResult($text, $bck, @_);
898             }
899 1692264         3322865 return ''
900             }
901              
902              
903             1;
904              
905             __END__