File Coverage

blib/lib/Syntax/Highlight/Engine/Kate/Template.pm
Criterion Covered Total %
statement 525 575 91.3
branch 190 232 81.9
condition 15 18 83.3
subroutine 73 73 100.0
pod 57 63 90.4
total 860 961 89.4


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.09';
8              
9 7     7   51 use strict;
  7         16  
  7         291  
10 6     6   40 use Carp qw(cluck);
  6         10  
  6         320  
11 6     6   79 use Data::Dumper;
  6         12  
  6         34443  
12              
13             #my $regchars = '\\^.$|()[]*+?';
14              
15             sub new {
16 229     229 0 572 my $proto = shift;
17 229   33     1364 my $class = ref($proto) || $proto;
18 229         1117 my %args = (@_);
19              
20 229         617 my $debug = delete $args{'debug'};
21 229 50       717 unless (defined($debug)) { $debug = 0 };
  229         549  
22 229         529 my $substitutions = delete $args{'substitutions'};
23 229 100       6716 unless (defined($substitutions)) { $substitutions = {} };
  98         301  
24 229         603 my $formattable = delete $args{'format_table'};
25 229 100       985 unless (defined($formattable)) { $formattable = {} };
  93         464  
26 229         463 my $engine = delete $args{'engine'};
27              
28 229         592 my $self = {};
29 229         1344 $self->{'attributes'} = {},
30             $self->{'captured'} = [];
31 229         670 $self->{'contextdata'} = {};
32 229         583 $self->{'basecontext'} = '';
33 229         658 $self->{'debug'} = $debug;
34 229         520 $self->{'deliminators'} = '';
35 229         661 $self->{'engine'} = '';
36 229         9167 $self->{'format_table'} = $formattable;
37 229         666 $self->{'keywordcase'} = 1;
38 229         541 $self->{'lastchar'} = '';
39 229         567 $self->{'linesegment'} = '';
40 229         753 $self->{'lists'} = {};
41 229         525 $self->{'linestart'} = 1;
42 229         536 $self->{'out'} = [];
43 229         576 $self->{'plugins'} = {};
44 229         868 $self->{'snippet'} = '';
45 229         617 $self->{'snippetattribute'} = '';
46 229         722 $self->{'stack'} = [];
47 229         417 $self->{'substitutions'} = $substitutions;
48 229         797 bless ($self, $class);
49 229 100       714 unless (defined $engine) { $engine = $self };
  143         268  
50 229         6613 $self->engine($engine);
51 229         1663 $self->initialize;
52 229         1180 return $self;
53             }
54              
55             sub attributes {
56 220621     220621 1 349983 my $self = shift;
57 220621 100       515647 if (@_) { $self->{'attributes'} = shift; };
  217         545  
58 220621         814547 return $self->{'attributes'};
59             }
60              
61             sub basecontext {
62 23479     23479 1 35699 my $self = shift;
63 23479 100       48586 if (@_) { $self->{'basecontext'} = shift; };
  217         697  
64 23479         52449 return $self->{'basecontext'};
65             }
66              
67             sub captured {
68 1219     1219 1 2589 my ($self, $c) = @_;
69 1219 50       4722 if (defined($c)) {
70 1219         3919 my $t = $self->engine->stackTop;
71 1219         2496 my $n = 0;
72 1219         3260 my @o = ();
73 1219         7678 while (defined($c->[$n])) {
74 1319         3497 push @o, $c->[$n];
75 1319         4037 $n ++;
76             }
77 1219 100       4246 if (@o) {
78 1195         4709 $t->[2] = \@o;
79             }
80             };
81             }
82              
83             sub capturedGet {
84 5334     5334 1 10412 my ($self, $num) = @_;
85 5334         10682 my $s = $self->engine->stack;
86 5334 50       12252 if (defined($s->[1])) {
87 5334         8343 my $c = $s->[1]->[2];
88 5334         7711 $num --;
89 5334 50       8240 if (defined($c)) {
90 5334 50       9518 if (defined($c->[$num])) {
91 5334         7052 my $r = $c->[$num];
92 5334         12948 return $r;
93             } else {
94 1         60 warn "capture number $num not defined";
95             }
96             } else {
97 1         9 warn "dynamic substitution is called for but nothing to substitute\n";
98 1         3 return undef;
99             }
100             } else {
101 1         40 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 8603 my ($self, $string, $mode) = @_;
145 5334         6331 my $s = '';
146 5334 100       9327 if (defined($mode)) {
147 35 50       152 if ($string =~ s/^(\d)//) {
148 35         78 $s = $self->capturedGet($1);
149 35 50       129 if ($string ne '') {
150 1         13 $self->logwarning("character class is longer then 1 character, ignoring the rest");
151             }
152             }
153             } else {
154 5300         12996 while ($string ne '') {
155 15739 100       45981 if ($string =~ s/^([^\%]*)\%(\d)//) {
156 5300         10498 my $r = $self->capturedGet($2);
157 5300 50       11323 if ($r ne '') {
158 5300         22040 $s = $s . $1 . $r
159             } else {
160 1         8 $s = $s . $1 . '%' . $2;
161 1         2 $self->logwarning("target is an empty string");
162             }
163             } else {
164 10440         21051 $string =~ s/^(.)//;
165 10440         27095 $s = "$s$1";
166             }
167             }
168             }
169 5334         11710 return $s;
170             }
171              
172             sub column {
173 281     281 1 491 my $self = shift;
174 281         776 return length($self->linesegment);
175             }
176              
177             sub contextdata {
178 1391797     1391797 1 1860903 my $self = shift;
179 1391797 100       3151297 if (@_) { $self->{'contextdata'} = shift; };
  217         601  
180 1391797         4067099 return $self->{'contextdata'};
181             }
182              
183             sub contextInfo {
184 695791     695791 1 1321583 my ($self, $context, $item) = @_;
185 695791 50       1672722 if (exists $self->contextdata->{$context}) {
186 695791         1429832 my $c = $self->contextdata->{$context};
187 695791 100       1812447 if (exists $c->{$item}) {
188 506541         1485681 return $c->{$item}
189             } else {
190 189251         544242 return undef;
191             }
192             } else {
193 1         46 $self->logwarning("undefined context '$context'");
194 1         10 return undef;
195             }
196             }
197              
198             sub contextParse {
199 45639     45639 1 128319 my ($self, $plug, $context) = @_;
200 45639 100       294468 if ($context =~ /^#pop/i) {
    100          
    100          
201 7671         61058 while ($context =~ s/#pop//i) {
202 9598         29941 $self->stackPull;
203             }
204             } elsif ($context =~ /^#stay/i) {
205             #don't do anything
206             } elsif ($context =~ /^##(.+)/) {
207 7         77 my $new = $self->pluginGet($1);
208 7         40 $self->stackPush([$new, $new->basecontext]);
209             } else {
210 9842         43751 $self->stackPush([$plug, $context]);
211             }
212             }
213              
214             sub debug {
215 1     1 0 44 my $self = shift;
216 1 0       11 if (@_) { $self->{'debug'} = shift; };
  1         2  
217 1         46 return $self->{'debug'};
218             }
219              
220             sub debugTest {
221 1     1 0 11 my $self = shift;
222 1 0       3 if (@_) { $self->{'debugtest'} = shift; };
  1         42  
223 1         12 return $self->{'debugtest'};
224             }
225              
226             sub deliminators {
227 372719     372719 1 516983 my $self = shift;
228 372719 100       875493 if (@_) { $self->{'deliminators'} = shift; };
  217         516  
229 372719         838217 return $self->{'deliminators'};
230             }
231              
232             sub engine {
233 2319101     2319101 1 3267475 my $self = shift;
234 2319101 100       5085701 if (@_) { $self->{'engine'} = shift; };
  229         1565  
235 2319101         5712682 return $self->{'engine'};
236             }
237              
238              
239             sub firstnonspace {
240 235     235 1 808 my ($self, $string) = @_;
241 235         694 my $line = $self->linesegment;
242 235 100 66     2425 if (($line =~ /^\s*$/) and ($string =~ /^[^\s]/)) {
243 197         677 return 1
244             }
245 39         162 return ''
246             }
247              
248             sub formatTable {
249 55818     55818 1 69651 my $self = shift;
250 55818 50       114496 if (@_) { $self->{'format_table'} = shift; };
  1         2  
251 55818         107185 return $self->{'format_table'};
252             }
253              
254             sub highlight {
255 108     108 1 516 my ($self, $text) = @_;
256 108         679 $self->snippet('');
257 108         727 my $out = $self->out;
258 108         430 @$out = ();
259 108         437 while ($text ne '') {
260 222843         633025 my $top = $self->stackTop;
261 222843 100       572302 if (defined($top)) {
262 222837         482551 my ($plug, $context) = @$top;
263 222837 100       650559 if ($text =~ s/^(\n)//) {
264 11815         35511 $self->snippetForce;
265 11815         36704 my $e = $plug->contextInfo($context, 'lineending');
266 11815 100       32765 if (defined($e)) {
267 1643         4731 $self->contextParse($plug, $e)
268             }
269 11815         34532 my $attr = $plug->attributes->{$plug->contextInfo($context, 'attribute')};
270 11815         36308 $self->snippetParse($1, $attr);
271 11815         30975 $self->snippetForce;
272 11815         28776 $self->linesegment('');
273 11815         33861 my $b = $plug->contextInfo($context, 'linebeginning');
274 11815 50       56877 if (defined($b)) {
275 1         3 $self->contextParse($plug, $b)
276             }
277             } else {
278 211023         628705 my $sub = $plug->contextInfo($context, 'callback');
279 211023         949328 my $result = &$sub($plug, \$text);
280 211023 100       689187 unless($result) {
281 168699         547930 my $f = $plug->contextInfo($context, 'fallthrough');
282 168699 100       436805 if (defined($f)) {
283 1435         5172 $self->contextParse($plug, $f);
284             } else {
285 167265         1317141 $text =~ s/^(.)//;
286 167265         541338 my $attr = $plug->attributes->{$plug->contextInfo($context, 'attribute')};
287 167265         556851 $self->snippetParse($1, $attr);
288             }
289             }
290             }
291             } else {
292 7         84 push @$out, length($text), 'Normal';
293 7         35 $text = '';
294             }
295             }
296 108         336 $self->snippetForce;
297 108         105807 return @$out;
298             }
299              
300             sub highlightText {
301 108     108 1 73658 my ($self, $text) = @_;
302 108         302 my $res = '';
303 108         894 my @hl = $self->highlight($text);
304 108         6091 while (@hl) {
305 55818         112049 my $f = shift @hl;
306 55818         88750 my $t = shift @hl;
307 55818 50       121091 unless (defined($t)) { $t = 'Normal' }
  1         4  
308 55818         124796 my $s = $self->substitutions;
309 55818         84244 my $rr = '';
310 55818         124561 while ($f ne '') {
311 323784         491544 my $k = substr($f , 0, 1);
312 323784         446301 $f = substr($f, 1, length($f) -1);
313 323784 100       561866 if (exists $s->{$k}) {
314 9735         44457 $rr = $rr . $s->{$k}
315             } else {
316 314049         703225 $rr = $rr . $k;
317             }
318             }
319 55817         132698 my $rt = $self->formatTable;
320 55817 50       152624 if (exists $rt->{$t}) {
321 55817         81956 my $o = $rt->{$t};
322 55817         553844 $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 107         10939 return $res;
329             }
330              
331             sub includePlugin {
332 22883     22884 1 44253 my ($self, $language, $text) = @_;
333 22883         49947 my $eng = $self->engine;
334 22883         63115 my $plug = $eng->pluginGet($language);
335 22883 50       61918 if (defined($plug)) {
336 22883         58973 my $context = $plug->basecontext;
337 22883         69937 my $call = $plug->contextInfo($context, 'callback');
338 22883 50       48014 if (defined($call)) {
339 22883         75105 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 81916     81917 1 139897 my ($self, $context, $text) = @_;
349 81916         181011 my $call = $self->contextInfo($context, 'callback');
350 81916 50       167913 if (defined($call)) {
351 81916         263219 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 432     433 0 1109 my $self = shift;
360 432 100       1201 if ($self->engine eq $self) {
361 260         1263 $self->stack([[$self, $self->basecontext]]);
362             }
363             }
364              
365             sub keywordscase {
366 72478     72479 1 116614 my $self = shift;
367 72478 100       189363 if (@_) { $self->{'keywordcase'} = shift; }
  216         445  
368 72478         219891 return $self->{'keywordscase'}
369             }
370              
371             sub languagePlug {
372 21     22 0 61 my ($cw, $name) = @_;
373 21         307 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       89 if ($name =~ s/^(\d)//) {
386 0         0 $name = $numb{$1} . $name;
387             }
388 21         47 $name =~ s/\.//;
389 21         54 $name =~ s/\+/plus/g;
390 21         37 $name =~ s/\-/minus/g;
391 21         37 $name =~ s/#/dash/g;
392 21         68 $name =~ s/[^0-9a-zA-Z]/_/g;
393 21         37 $name =~ s/__/_/g;
394 21         38 $name =~ s/_$//;
395 21         61 $name = ucfirst($name);
396 21         103 return $name;
397             }
398              
399             sub lastchar {
400 838445     838446 1 1188845 my $self = shift;
401 838445         1577211 my $l = $self->linesegment;
402 838445 100       2122380 if ($l eq '') { return "\n" } #last character was a newline
  24120         57163  
403 814325         4656508 return substr($l, length($l) - 1, 1);
404             }
405              
406             sub lastcharDeliminator {
407 566031     566032 1 794603 my $self = shift;
408 566031         812441 my $deliminators = '\s|\~|\!|\%|\^|\&|\*|\+|\(|\)|-|=|\{|\}|\[|\]|:|;|<|>|,|\\|\||\.|\?|\/';
409 566031 100 100     1087591 if ($self->linestart or ($self->lastchar =~ /$deliminators/)) {
410 309957         2638029 return 1;
411             }
412 256074         981955 return '';
413             }
414              
415             sub linesegment {
416 2151496     2151497 1 2850926 my $self = shift;
417 2151496 100       4928469 if (@_) { $self->{'linesegment'} = shift; };
  232204         461194  
418 2151496         6476115 return $self->{'linesegment'};
419             }
420              
421             sub linestart {
422 859943     859944 1 1135848 my $self = shift;
423 859943 100       1712375 if ($self->linesegment eq '') {
424 48432         180166 return 1
425             }
426 811511         3388068 return '';
427             }
428              
429             sub lists {
430 72927     72928 1 116259 my $self = shift;
431 72927 50       234882 if (@_) { $self->{'lists'} = shift; }
  0         0  
432 72927         207956 return $self->{'lists'}
433             }
434              
435             sub out {
436 222     223 1 598 my $self = shift;
437 222 100       636 if (@_) { $self->{'out'} = shift; }
  115         408  
438 222         13658 return $self->{'out'};
439             }
440              
441             sub listAdd {
442 665     666 1 1085 my $self = shift;
443 665         983 my $listname = shift;
444 665         2045 my $lst = $self->lists;
445 665 100       1544 if (@_) {
446 664         22050 my @l = reverse sort @_;
447 664         2894 $lst->{$listname} = \@l;
448             } else {
449 1         4 $lst->{$listname} = [];
450             }
451             }
452              
453             sub logwarning {
454 2     3 0 7 my ($self, $warning) = @_;
455 2         11 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         7 $warning = "$warning\n STACK IS EMPTY: PANIC\n"
462             }
463 2         32 cluck($warning);
464             }
465              
466             sub parseResult {
467 42651     42652 1 123000 my ($self, $text, $string, $lahead, $column, $fnspace, $context, $attr) = @_;
468 42651         119716 my $eng = $self->engine;
469 42651 100       111792 if ($fnspace) {
470 234 100       1240 unless ($eng->firstnonspace($$text)) {
471 38         294 return ''
472             }
473             }
474 42613 100       98663 if (defined($column)) {
475 280 100       1309 if ($column ne $eng->column) {
476 51         315 return '';
477             }
478             }
479 42562 100       102926 unless ($lahead) {
480 41326         319868 $$text = substr($$text, length($string));
481 41326         71933 my $r;
482 41326 100       103344 unless (defined($attr)) {
483 8565         23113 my $t = $eng->stackTop;
484 8565         19515 my ($plug, $ctext) = @$t;
485 8565         24120 $r = $plug->attributes->{$plug->contextInfo($ctext, 'attribute')};
486             } else {
487 32761         106794 $r = $self->attributes->{$attr};
488             }
489 41326         123816 $eng->snippetParse($string, $r);
490             }
491 42562         122028 $eng->contextParse($self, $context);
492 42562         339074 return 1
493             }
494              
495             sub pluginGet {
496 23004     23005 1 39603 my ($self, $language) = @_;
497 23004         52327 my $plugs = $self->{'plugins'};
498 23004 100       59448 unless (exists($plugs->{$language})) {
499 88         568 my $modname = 'Syntax::Highlight::Engine::Kate::' . $self->languagePlug($language);
500 88 50       335 unless (defined($modname)) {
501 0         0 $self->logwarning("no valid module found for language '$language'");
502 0         0 return undef;
503             }
504 88         130 my $plug;
505 5     5   5008 eval "use $modname; \$plug = new $modname(engine => \$self);";
  5     5   18  
  5     4   243  
  5     4   3129  
  5     4   17  
  5         227  
  4         2802  
  4         10  
  4         159  
  4         547  
  3         7  
  3         111  
  4         1667  
  3         8  
  3         123  
  88         25547  
506 88 100       448 if (defined($plug)) {
507 86         315 $plugs->{$language} = $plug;
508             } else {
509 2         24 $self->logwarning("cannot create plugin for language '$language'\n--------------\n$@");
510             }
511             }
512 23004 100       85852 if (exists($plugs->{$language})) {
513 23002         82688 return $plugs->{$language};
514             }
515 2         8 return undef;
516             }
517              
518             sub reset {
519 0     1 1 0 my $self = shift;
520 0         0 $self->stack([[$self, $self->basecontext]]);
521 0         0 $self->out([]);
522 0         0 $self->snippet('');
523             }
524              
525             sub snippet {
526 119793     119794 1 173057 my $self = shift;
527 119793 100       284431 if (@_) { $self->{'snippet'} = shift; }
  56033         111589  
528 119793         332610 return $self->{'snippet'};
529             }
530              
531             sub snippetAppend {
532 220404     220405 1 481645 my ($self, $ch) = @_;
533              
534 220404 100       546384 return if not defined $ch;
535 220390         587051 $self->{'snippet'} = $self->{'snippet'} . $ch;
536 220390 50       593347 if ($ch ne '') {
537 220390         540381 $self->linesegment($self->linesegment . $ch);
538             }
539 220390         956289 return;
540             }
541              
542             sub snippetAttribute {
543 315537     315538 1 498007 my $self = shift;
544 315537 100       767540 if (@_) { $self->{'snippetattribute'} = shift; }
  40025         84686  
545 315537         1621352 return $self->{'snippetattribute'};
546             }
547              
548             sub snippetForce {
549 63760     63761 1 117899 my $self = shift;
550 63760         181311 my $parse = $self->snippet;
551 63760 100       183381 if ($parse ne '') {
552 55811         142278 my $out = $self->{'out'};
553 55811         165304 push(@$out, $parse, $self->snippetAttribute);
554 55811         154433 $self->snippet('');
555             }
556             }
557              
558             sub snippetParse {
559 220404     220405 1 327038 my $self = shift;
560 220404         514378 my $snip = shift;
561 220404         369079 my $attr = shift;
562 220404 100 100     1059773 if ((defined $attr) and ($attr ne $self->snippetAttribute)) {
563 40025         105160 $self->snippetForce;
564 40025         132014 $self->snippetAttribute($attr);
565             }
566 220404         767580 $self->snippetAppend($snip);
567             }
568              
569             sub stack {
570 257779     257780 1 448885 my $self = shift;
571 257779 100       645724 if (@_) { $self->{'stack'} = shift; }
  375         739  
572 257779         729970 return $self->{'stack'};
573             }
574              
575             sub stackPush {
576 9847     9848 1 19808 my ($self, $val) = @_;
577 9847         24287 my $stack = $self->stack;
578 9847         31156 unshift(@$stack, $val);
579             }
580              
581             sub stackPull {
582 9597     9598 1 21814 my ($self, $val) = @_;
583 9597         31385 my $stack = $self->stack;
584 9597         48836 return shift(@$stack);
585             }
586              
587             sub stackTop {
588 232627     232628 1 336266 my $self = shift;
589 232627         496640 return $self->stack->[0];
590             }
591              
592             sub stateCompare {
593 0     1 1 0 my ($self, $state) = @_;
594 0         0 my $h = [ $self->stateGet ];
595 0         0 my $equal = 0;
596 0 0       0 if (Dumper($h) eq Dumper($state)) { $equal = 1 };
  0         0  
597 0         0 return $equal;
598             }
599              
600             sub stateGet {
601 0     1 1 0 my $self = shift;
602 0         0 my $s = $self->stack;
603 0         0 return @$s;
604             }
605              
606             sub stateSet {
607 0     1 1 0 my $self = shift;
608 0         0 my $s = $self->stack;
609 0         0 @$s = (@_);
610             }
611              
612             sub substitutions {
613 55817     55818 1 64559 my $self = shift;
614 55817 50       126791 if (@_) { $self->{'substitutions'} = shift; }
  0         0  
615 55817         100843 return $self->{'substitutions'};
616             }
617              
618             sub testAnyChar {
619 40942     40943 1 68565 my $self = shift;
620 40942         46815 my $text = shift;
621 40942         60395 my $string = shift;
622 40942         81619 my $insensitive = shift;
623 40942         74335 my $test = substr($$text, 0, 1);
624 40942         61656 my $bck = $test;
625 40942 50       90780 if ($insensitive) {
626 0         0 $string = lc($string);
627 0         0 $test = lc($test);
628             }
629 40942 100       120350 if (index($string, $test) > -1) {
630 5107         18054 return $self->parseResult($text, $bck, @_);
631             }
632 35835         156547 return ''
633             }
634              
635             sub testDetectChar {
636 385768     385769 1 616198 my $self = shift;
637 385768         506840 my $text = shift;
638 385768         620823 my $char = shift;
639 385768         457855 my $insensitive = shift;
640 385768         502217 my $dyn = shift;
641 385768 100       780098 if ($dyn) {
642 34         85 $char = $self->capturedParse($char, 1);
643             }
644 385768         653025 my $test = substr($$text, 0, 1);
645 385768         487495 my $bck = $test;
646 385768 50       867658 if ($insensitive) {
647 0         0 $char = lc($char);
648 0         0 $test = lc($test);
649             }
650 385768 100       843631 if ($char eq $test) {
651 9532         36875 return $self->parseResult($text, $bck, @_);
652             }
653 376236         1585758 return ''
654             }
655              
656             sub testDetect2Chars {
657 236059     236060 1 338085 my $self = shift;
658 236059         338867 my $text = shift;
659 236059         343825 my $char = shift;
660 236059         327188 my $char1 = shift;
661 236059         303425 my $insensitive = shift;
662 236059         302140 my $dyn = shift;
663 236059 50       589488 if ($dyn) {
664 0         0 $char = $self->capturedParse($char, 1);
665 0         0 $char1 = $self->capturedParse($char1, 1);
666             }
667 236059         496221 my $string = $char . $char1;
668 236059         388855 my $test = substr($$text, 0, 2);
669 236059         330608 my $bck = $test;
670 236059 50       579967 if ($insensitive) {
671 0         0 $string = lc($string);
672 0         0 $test = lc($test);
673             }
674 236059 100       594345 if ($string eq $test) {
675 1263         5358 return $self->parseResult($text, $bck, @_);
676             }
677 234796         1028194 return ''
678             }
679              
680             sub testDetectIdentifier {
681 29357     29358 1 61272 my $self = shift;
682 29357         40636 my $text = shift;
683 29357 100       108038 if ($$text =~ /^([a-zA-Z_][a-zA-Z0-9_]+)/) {
684 7380         36149 return $self->parseResult($text, $1, @_);
685             }
686 21977         94499 return ''
687             }
688              
689             sub testDetectSpaces {
690 41306     41307 1 67794 my $self = shift;
691 41306         69685 my $text = shift;
692 41306 100       194525 if ($$text =~ /^([\\040|\\t]+)/) {
693 953         3384 return $self->parseResult($text, $1, @_);
694             }
695 40353         191762 return ''
696             }
697              
698             sub testFloat {
699 57822     57823 1 128488 my $self = shift;
700 57822         98338 my $text = shift;
701 57822 100       136449 if ($self->engine->lastcharDeliminator) {
702 31952 100       143679 if ($$text =~ /^((?=\.?\d)\d*(?:\.\d*)?(?:[Ee][+-]?\d+)?)/) {
703 1845         8386 return $self->parseResult($text, $1, @_);
704             }
705             }
706 55977         254375 return ''
707             }
708              
709             sub testHlCChar {
710 24992     24993 1 42417 my $self = shift;
711 24992         32362 my $text = shift;
712 24992 100       111204 if ($$text =~ /^('.')/) {
713 26         135 return $self->parseResult($text, $1, @_);
714             }
715 24966         101311 return ''
716             }
717              
718             sub testHlCHex {
719 39204     39205 1 59826 my $self = shift;
720 39204         49206 my $text = shift;
721 39204 100       96908 if ($self->engine->lastcharDeliminator) {
722 22154 100       60993 if ($$text =~ /^(0x[0-9a-fA-F]+)/) {
723 8         42 return $self->parseResult($text, $1, @_);
724             }
725             }
726 39196         158027 return ''
727             }
728              
729             sub testHlCOct {
730 33366     33367 1 64969 my $self = shift;
731 33366         41800 my $text = shift;
732 33366 100       78173 if ($self->engine->lastcharDeliminator) {
733 19924 50       67951 if ($$text =~ /^(0[0-7]+)/) {
734 0         0 return $self->parseResult($text, $1, @_);
735             }
736             }
737 33366         139202 return ''
738             }
739              
740             sub testHlCStringChar {
741 5020     5021 1 8315 my $self = shift;
742 5020         7170 my $text = shift;
743 5020 100       13005 if ($$text =~ /^(\\[a|b|e|f|n|r|t|v|'|"|\?])/) {
744 34         137 return $self->parseResult($text, $1, @_);
745             }
746 4986 50       14719 if ($$text =~ /^(\\x[0-9a-fA-F][0-9a-fA-F]?)/) {
747 0         0 return $self->parseResult($text, $1, @_);
748             }
749 4986 50       10504 if ($$text =~ /^(\\[0-7][0-7]?[0-7]?)/) {
750 0         0 return $self->parseResult($text, $1, @_);
751             }
752 4986         17646 return ''
753             }
754              
755             sub testInt {
756 63137     63138 1 128843 my $self = shift;
757 63137         92151 my $text = shift;
758 63137 100       182841 if ($self->engine->lastcharDeliminator) {
759 33237 100       153041 if ($$text =~ /^([+-]?\d+)/) {
760 314         2683 return $self->parseResult($text, $1, @_);
761             }
762             }
763 62823         284315 return ''
764             }
765              
766             sub testKeyword {
767 372502     372503 1 568880 my $self = shift;
768 372502         470842 my $text = shift;
769 372502         556419 my $list = shift;
770 372502         815996 my $eng = $self->engine;
771 372502         969049 my $deliminators = $self->deliminators;
772 372502 100 100     874448 if (($eng->lastcharDeliminator) and ($$text =~ /^([^$deliminators]+)/)) {
773 72262         159572 my $match = $1;
774 72262         177417 my $l = $self->lists->{$list};
775 72262 50       177885 if (defined($l)) {
776 72262         1148295 my @list = @$l;
777 72262         134506 my @rl = ();
778 72262 50       211239 unless ($self->keywordscase) {
779 72262         184213 @rl = grep { (lc($match) eq lc($_)) } @list;
  6178918         11514908  
780             } else {
781 0         0 @rl = grep { ($match eq $_) } @list;
  0         0  
782             }
783 72262 100       450986 if (@rl) {
784 5777         31898 return $self->parseResult($text, $match, @_);
785             }
786             } else {
787 0         0 $self->logwarning("list '$list' is not defined, failing test");
788             }
789             }
790 366725         1922261 return ''
791             }
792              
793             sub testLineContinue {
794 6210     6211 1 11157 my $self = shift;
795 6210         8538 my $text = shift;
796 6210         9001 my $lahead = shift;
797 6210 50       16150 if ($lahead) {
798 0 0       0 if ($$text =~ /^\\\n/) {
799 0         0 $self->parseResult($text, "\\", $lahead, @_);
800 0         0 return 1;
801             }
802             } else {
803 6210 100       38724 if ($$text =~ s/^(\\)(\n)/$2/) {
804 14         67 return $self->parseResult($text, "\\", $lahead, @_);
805             }
806             }
807 6196         26951 return ''
808             }
809              
810             sub testRangeDetect {
811 15354     15354 1 26189 my $self = shift;
812 15354         22747 my $text = shift;
813 15354         21889 my $char = shift;
814 15354         20328 my $char1 = shift;
815 15354         20141 my $insensitive = shift;
816 15354         45665 my $string = "$char\[^$char1\]+$char1";
817 15354         63665 return $self->testRegExpr($text, $string, $insensitive, 0, @_);
818             }
819              
820             sub testRegExpr {
821 1369899     1369899 1 2030220 my $self = shift;
822 1369899         1726445 my $text = shift;
823 1369899         2093356 my $reg = shift;
824 1369899         1756824 my $insensitive = shift;
825 1369899         1812900 my $dynamic = shift;
826 1369899 100       2968978 if ($dynamic) {
827 5299         17491 $reg = $self->capturedParse($reg);
828             }
829 1369899         3139862 my $eng = $self->engine;
830 1369899 100       6339502 if ($reg =~ s/^\^//) {
    100          
831 293912 100       748067 unless ($eng->linestart) {
832 283489         1374880 return '';
833             }
834             } elsif ($reg =~ s/^\\(b)//i) {
835 310423         734528 my $lastchar = $self->engine->lastchar;
836 310423 100       905341 if ($1 eq 'b') {
837 309741 100       1067993 if ($lastchar =~ /\w/) { return '' }
  130001         603444  
838             } else {
839 682 100       2240 if ($lastchar =~ /\W/) { return '' }
  308         1415  
840             }
841             }
842             # $reg = "^($reg)";
843 956101         2137819 $reg = "^$reg";
844 956101         1321853 my $pos;
845             # my @cap = ();
846 956101         1494023 my $sample = $$text;
847              
848             # emergency measurements to avoid exception (szabgab)
849 956101         1307820 $reg = eval { qr/$reg/ };
  956101         32746522  
850 956101 50       3043361 if ($@) {
851 0         0 warn $@;
852 0         0 return '';
853             }
854 956101 100       1795056 if ($insensitive) {
855 127708 100       833293 if ($sample =~ /$reg/ig) {
856 158         312 $pos = pos($sample);
857             # @cap = ($1, $2, $3, $4, $5, $6, $7, $8, $9);
858             # my @cap = ();
859 158 100       589 if ($#-) {
860 6     6   1000 no strict 'refs';
  6         14  
  6         731  
861 58         244 my @cap = map {$$_} 1 .. $#-;
  84         464  
862 58         326 $self->captured(\@cap)
863             }
864             # my $r = 1;
865             # my $c = 1;
866             # my @cap = ();
867             # while ($r) {
868             # eval "if (defined\$$c) { push \@cap, \$$c } else { \$r = 0 }";
869             # $c ++;
870             # }
871             # if (@cap) { $self->captured(\@cap) };
872             }
873             } else {
874 828393 100       7719748 if ($sample =~ /$reg/g) {
875 13000         24885 $pos = pos($sample);
876             # @cap = ($1, $2, $3, $4, $5, $6, $7, $8, $9);
877             # my @cap = ();
878 13000 100       62887 if ($#-) {
879 6     6   118 no strict 'refs';
  6         12  
  6         1489  
880 1160         5029 my @cap = map {$$_} 1 .. $#-;
  1294         9295  
881 1160         7713 $self->captured(\@cap);
882             }
883             # my $r = 1;
884             # my $c = 1;
885             # my @cap = ();
886             # while ($r) {
887             # eval "if (defined\$$c) { push \@cap, \$$c } else { \$r = 0 }";
888             # $c ++;
889             # }
890             # if (@cap) { $self->captured(\@cap) };
891             }
892             }
893 956101 100 100     2563148 if (defined($pos) and ($pos > 0)) {
894 9828         26198 my $string = substr($$text, 0, $pos);
895 9828         39297 return $self->parseResult($text, $string, @_);
896             }
897 946273         5251771 return ''
898             }
899              
900             sub testStringDetect {
901 1692912     1692912 1 2249238 my $self = shift;
902 1692912         1912002 my $text = shift;
903 1692912         2259400 my $string = shift;
904 1692912         1843681 my $insensitive = shift;
905 1692912         1899105 my $dynamic = shift;
906 1692912 50       3390374 if ($dynamic) {
907 0         0 $string = $self->capturedParse($string);
908             }
909 1692912         2713655 my $test = substr($$text, 0, length($string));
910 1692912         1947873 my $bck = $test;
911 1692912 100       3116534 if ($insensitive) {
912 3672         5194 $string = lc($string);
913 3672         5320 $test = lc($test);
914             }
915 1692912 100       3202907 if ($string eq $test) {
916 570         2218 return $self->parseResult($text, $bck, @_);
917             }
918 1692342         7012088 return ''
919             }
920              
921              
922             1;
923              
924             __END__