File Coverage

lib/Parse/Gnaw/Blocks/ParsingMethods.pm
Criterion Covered Total %
statement 148 197 75.1
branch 54 84 64.2
condition 8 12 66.6
subroutine 13 16 81.2
pod 9 9 100.0
total 232 318 72.9


line stmt bran cond sub pod time code
1              
2              
3             package Parse::Gnaw::Blocks::ParsingMethods;
4              
5             our $VERSION = '0.001';
6              
7             #BEGIN {print "Parse::Gnaw::Blocks::ParsingMethods\n";}
8              
9 19     19   128 use warnings;
  19         32  
  19         575  
10 19     19   96 use strict;
  19         35  
  19         533  
11 19     19   96 use Carp;
  19         35  
  19         1316  
12 19     19   103 use Data::Dumper;
  19         41  
  19         906  
13 19     19   106 use Storable 'dclone';
  19         32  
  19         918  
14              
15 19     19   107 use Parse::Gnaw::Blocks::LetterConstants;
  19         53  
  19         1828  
16 19     19   104 use Parse::Gnaw::LinkedListConstants;
  19         38  
  19         42835  
17              
18              
19             =head1 NAME
20              
21             Parse::Gnaw::Blocks::ParsingMethods - A base package containing all the methods that derived "letter" type classes will inherit.
22              
23              
24              
25             =head2 parse_grammarref
26              
27             We get a starting letter, and a reference to a rule.
28             Because rules can be called like subroutines, we have to process the rule in such a way
29             that it can be called from anywhere and we don't know who is calling us (or where we will return to).
30              
31             Note that we need to keep track of whether a rule consumes the current letter or not.
32             some rules might not consume anything (rules that execute callbacks, for example, or configure flags)
33             So, we need to call rules until we consume at least the current letter.
34              
35             if that is the last subrule, then return current letter.
36              
37             if there are more subrules, we need to get a list of possible connections to go to next.
38             then loop through each possible connection and try the subrule.
39             If it succeeds, great.
40             If it fails, eval/trap the failure and loop to next connection.
41              
42             ============================
43             This is a recursive call.
44             ============================
45              
46              
47             grammar is ('a', 'b', 'c')
48              
49             text is
50             c b b
51             j a k
52             m n o
53              
54             start at "g", look for 'a'. fail, move to next starting position. repeat until hit 'a' in center position.
55             match 'a' at center. look a next rule, it's defined and true, so we need to look for it.
56             Howerver, we need to try every possible direction from "A".
57             'b', 'b', 'k', 'o', 'n', 'm', 'j', 'c'
58            
59             This means every connection needs to trap for die "GRAMMARFAIL"
60             if we try direction 'h', and it dies,
61             we need to trap the error and try the next option.
62              
63              
64              
65             =cut
66             sub parse_grammarref{
67 35     35 1 74 my ($llobj, $grammarref, $then_call )=@_;
68              
69 35         58 my $debug=0;
70              
71             # first element in grammarref array has information about this rule. get it.
72 35         65 my $first_subrule = $grammarref->[0];
73              
74 35         56 my $ruleinfo = $first_subrule->[2];
75 35         78 my $rulename = $ruleinfo->{payload};
76 35 50       144 my $quantifiertype= exists($ruleinfo->{quantifier}) ? $ruleinfo->{quantifier} : '';
77 35 100       93 my $isquantifier = ($quantifiertype eq '') ? '' : 1;
78              
79 35         313 my ($min,$max)=(1,1); # if not a quantifier, then want to match this rule exactly once
80              
81 35 100       111 if($isquantifier){
82 6         13 $min=$ruleinfo->{min};
83 6         14 $max=$ruleinfo->{max};
84             }
85              
86 35         70 my $start_letter = $llobj->[LIST__CURR_START];
87 35         67 my $entry_letter_payload = $start_letter->[LETTER__DATA_PAYLOAD];
88 35 50       94 my $minstr=defined($min) ? $min : 'undef';
89 35 50       83 my $maxstr=defined($max) ? $max : 'undef';
90              
91 35         231 my $parse_grammarref_identification_string = "parse_grammarref, called with rule='$rulename', ".
92             "letter='$entry_letter_payload', quantifiertype='$quantifiertype', isquantifier='$isquantifier', ".
93             "min='$minstr', max='$maxstr', then_call='$then_call'";
94 35 50       124 if($debug){warn "$parse_grammarref_identification_string: begin";}
  0         0  
95              
96              
97             # We're going to pretend that every rule is like a quantifier
98             # if it's not REALLY a quantifier, then min/max is 1/1 and we must match exactly once.
99             # if it IS really a quantifier, then we need to match min times
100              
101             # first, match "min" number of times.
102             # if we fail that,then this rule fails, therefore, no need to trap error
103              
104             # if the minimum is 3, then we need to call the rule 3 times.
105 35         110 foreach my $minimal_match (1 .. $min){
106              
107 38 50       102 if($debug){warn "parse_grammarref($rulename): about to try one_iteration_of_grammarref";}
  0         0  
108            
109 38         807 my $discard_retval = $llobj->one_iteration_of_grammarref($grammarref,1);
110              
111 27 50       115 if($debug){warn "parse_grammarref($rulename): just tried one_iteration_of_grammarref and succeeded";}
  0         0  
112            
113              
114             }
115              
116             # matched MIN number of times
117             # now try 0 to ($max-$min) more times.
118             # if min=3 and max=7, then we would try 0 to 4 more times.
119              
120 24         54 my $remainingattempts = -1;
121 24 100       70 if($max>0){
122 18         39 $remainingattempts=($max-$min);
123             }
124            
125              
126 24 50       62 if($debug){warn "remainingattempts='$remainingattempts'";}
  0         0  
127              
128 24   100     150 for(my $quant_counter=0; (($remainingattempts<0) or ($quant_counter<=$remainingattempts)); $quant_counter++){
129              
130 32 50       122 if($debug){warn "quant_counter='$quant_counter'";}
  0         0  
131              
132             ##################################################################################
133             # try one iteration of grammarref
134             ##################################################################################
135 32 100       91 if($quant_counter>0){
136 8 50       25 if($debug){warn "parse_grammarref($rulename): try anotehr iteration of grammarref";}
  0         0  
137 8         23 my $discard_retval = $llobj->one_iteration_of_grammarref($grammarref,1);
138             }
139              
140              
141             ##################################################################################
142             # then try the then_call rule.
143             ##################################################################################
144 32 100 66     223 if( not defined($then_call) or ($then_call eq '') ){
145             # there is no then_call, we're done and we must have matched. huzzah! return
146 13 50       45 if($debug){warn "parse_grammarref($rulename): no then_call, return success"; }
  0         0  
147 13         69 return;
148             } else {
149 19 50       46 if($debug){warn "parse_grammarref($rulename): try the then_call rule";}
  0         0  
150             # there is a then_call, try it, if it fails, catch and try another quant_counter.
151              
152 19         31 my $save_position=$llobj->[LIST__CURR_START]; # if all fail, go back to here
153              
154             #warn "then_call is '$then_call'";
155              
156 19         332 eval{
157 19         67 my $thencall_grammarref=$llobj->convert_rule_name_to_rule_reference($then_call);
158 19         80 my $discard_retval = $llobj->one_iteration_of_grammarref($thencall_grammarref,1);
159             };
160 19 100       60 if($@){
161 9 50       48 if($@ =~ m{GRAMMARFAIL}){
162 9         49 $llobj->[LIST__CURR_START]=$save_position;
163             } else {
164 0         0 die $@;
165             }
166             } else {
167             # didn't die. must have matched. huzzah!
168 10 50       32 if($debug){warn "parse_grammarref($rulename): returning";}
  0         0  
169 10         52 return;
170             }
171             }
172             }
173              
174             # note that if the above for(my $quant_counter=0; loop
175             # ever finds a match of the quantifier plus successfully runs then_call
176             # then it will return in the "else" part of "if($@)".
177 1 50       4 if($debug){warn "parse_grammarref($rulename): tried looping on quant_counter but failed to match";}
  0         0  
178 1         13 die "GRAMMARFAIL";
179             }
180              
181             =head2 one_iteration_of_grammarref
182              
183             This runs an entire rule exactly one time.
184              
185             It does not call then_call.
186              
187             It does not address quantifier issues.
188              
189              
190              
191             =cut
192              
193             my $counter=0;
194              
195             # pass in subrule_iterator, return subrule_iterator
196             sub one_iteration_of_grammarref{
197 107     107 1 174 my ($llobj, $grammarref,$subrule_iterator)=@_; # no "$thencall" here.
198            
199 107         138 my $debug=0;
200              
201 107         147 my $size_rule=scalar(@$grammarref);
202              
203 107         129 my $number_of_possible_connections=1;
204              
205 107         151 my $initial_subrule=$grammarref->[$subrule_iterator];
206 107         243 my $sub_method=$initial_subrule->[0];
207 107         234 my $sub_payload=$initial_subrule->[1];
208 107         236 my $initial_state_of_call = "called one_iteration_of_grammarref with sub_method='$sub_method' and sub_payload='$sub_payload'";
209 107 50       242 if($debug){warn $initial_state_of_call;}
  0         0  
210 107         795 my @caller=caller(0);
211             #print Dumper \@caller;
212             #warn "called from (see above)";
213              
214 107   33     574 while(($number_of_possible_connections==1) and ($subrule_iterator<$size_rule)){
215              
216 161 50       330 if($debug){warn "WHILE: $initial_state_of_call subrule_iterator=$subrule_iterator";}
  0         0  
217             #############################################################################################
218             #############################################################################################
219             #############################################################################################
220             # if currentletter is not consumed yet
221             # go through the grammar rules until its consumed, then stop this part of loop.
222             #############################################################################################
223             #############################################################################################
224             #############################################################################################
225 161   66     912 while( ($llobj->[LIST__CURR_START]->[LETTER__LETTER_HAS_BEEN_CONSUMED]==0) and ($subrule_iterator<$size_rule) ){
226              
227             # get the subrule, i.e. ['lit','a',...]
228 131         187 my $subrule = $grammarref->[$subrule_iterator];
229 131         148 $subrule_iterator++;
230              
231             # get the subrule name, i.e. 'lit'
232 131         184 my $methodname=$subrule->[0];
233            
234             #my $payloadify = $subrule->[1]; warn "trying methodname '$methodname' with payload '$payloadify'";
235            
236             # if we can't call the methodname, then die a miserable death.
237 131 50       647 if(not($llobj->can($methodname))){
238 0         0 print "no method found for '$methodname'\n"; warn;
  0         0  
239 0         0 my $hashref=$subrule->[2];
240 0         0 print Dumper $hashref;
241 0         0 my $filename=$hashref->{filename};
242 0         0 my $linenum =$hashref->{linenum};
243 0         0 confess "grammar method not defined '$methodname' in $filename line $linenum";
244             }
245            
246 131 50       299 if($debug){warn "methodname is '$methodname', subrule is"; print Dumper $subrule; }
  0         0  
  0         0  
247            
248             # call the method, i.e. $letter->lit(['lit','a',...]);
249 131         339 $llobj->$methodname($subrule);
250              
251 81 50       467 unless(defined($llobj->[LIST__CURR_START])){
252 0         0 die "ERROR: called method and got undefined letter back (method == $methodname)";
253             }
254             }
255              
256             # we consumed the current letter, so if there ARE MORE RULES in this grammar,
257             # we need to figure out which connection to use to get to move to the next letter.
258             # If there are NO MORE RULES left, just return letter (marked as consumed)
259             # because we can't iterate the connections from that letter without knowing
260             # what the next rule is. The next rule to get called will see letter is consumed
261             # and skip to the possible connections section.
262 111 100       261 if($subrule_iterator>=$size_rule){
263 45         210 return $subrule_iterator;
264             }
265            
266            
267             #############################################################################################
268             #############################################################################################
269             #############################################################################################
270             # current letter is consumed and there are more subrules in this rule.
271             # get a list of all possible letters connected to the current letter
272             # for each possible connection, try setting current letter to that connected letter
273             # and see if rest of rule matches. If doesn't match, trap failure, and try next possible letter.
274             #############################################################################################
275             #############################################################################################
276             #############################################################################################
277              
278             # get a list of letter objects to try.
279 66         252 my @list_of_possible_next_letters = $llobj->[LIST__CURR_START]->get_list_of_connecting_letters();
280            
281 66         108 $number_of_possible_connections=scalar(@list_of_possible_next_letters);
282 66 50       159 if($number_of_possible_connections==0) {
283 0         0 die "somehow we mannaged to get into a letter that has no connections?";
284             }
285            
286             # if there is only 1 possible connection, then we can avoid recursion here.
287             # just move current letter to the next possible letter, and loop around.
288             # when we're parsing a simple string, this should save us time and memory.
289 66 100       2249 if($number_of_possible_connections==1){
290 54 50       129 if($debug){warn "only 1 connection";}
  0         0  
291 54 50       146 die "stuck in a loop" if($counter++>4000);
292              
293 54         114 $llobj->[LIST__CURR_START] = shift(@list_of_possible_next_letters);
294 54         318 $llobj->[LIST__CURR_START] ->[LETTER__LETTER_HAS_BEEN_CONSUMED]=0;
295             } else {
296 12 50       22 if($debug){warn "multiple connections";}
  0         0  
297             # else there are multiple possible connections.
298             # will have to try each one in sequence until we get a match.
299             # will have to be recursive because next letter will also have a bunch of connections
300             # and we will have to loop through and try each possible connection for that letter.
301              
302 12         15 my $save_position=$llobj->[LIST__CURR_START]; # if all fail, go back to here
303 12         14 my $save_iterator=$subrule_iterator;
304              
305 12         20 TRYCONNECTION : foreach my $possible_letter (@list_of_possible_next_letters){
306              
307 42         50 $llobj->[LIST__CURR_START] = $possible_letter;
308              
309             # mark letter as not consumed.
310 42         51 $llobj->[LIST__CURR_START]->[LETTER__LETTER_HAS_BEEN_CONSUMED]=0;
311            
312 42         50 eval{
313 42         101 $subrule_iterator = $llobj->one_iteration_of_grammarref($grammarref,$subrule_iterator);
314             };
315 42 100       81 if($@){
316 36 50       81 if($@ =~ m{GRAMMARFAIL}){
317             # grammar failed, so this connection didn't work. Try another connection.
318 36         40 $llobj->[LIST__CURR_START] =$save_position;
319 36         45 $subrule_iterator =$save_iterator;
320 36         69 next TRYCONNECTION;
321             } else {
322             # else we died, and it wasn't a grammar failure. rethrow the die
323 0         0 die $@;
324             }
325             } else {
326             ######
327             # we eval'ed and didn't get $@. must have matched. Hazzah!
328             ######
329              
330             # at the end of recursive calls, the iterator should equal the size of the rule.
331             # (i.e. if rule has 3 elements in it, iterator will go 0,1,2 to try each subrule
332             # and then it will increment to 3 and should return as matcihng the entire rule)
333             # if iterator doesn't equal size of rule, then something went wrong in the process of parsing.
334 6 50       12 unless($subrule_iterator==$size_rule){
335 0         0 die "ERROR: somehow managed to return a rule without matching all of the rule.";
336             }
337            
338             # OK, we didn't get $@, AND it looks like the recursive calls matched the entire rule.
339             # return as a successful match.
340 6         26 return $subrule_iterator;
341             }
342             }
343 6         40 die "GRAMMARFAIL"; #tried all possible connections. none worked. Die.
344             }
345              
346             # if there is only 1 possible connection, the if($number_of_possible_connections==1) statement will kick out here
347             # we will use the enclosing while() loop to loop around and try the next letter.
348             }
349              
350             # end of while(($number_of_possible_connections==1) and ($subrule_iterator<$size_rule)){
351             # Should only reach this point when we're parsing a one-dimensional string (connectins==1)
352             # and the entire rule matched (iterator==size of rule)
353             # return as a successful match.
354 0         0 return $subrule_iterator;
355             }
356              
357              
358              
359             =head2 rule
360              
361             The "rule" method is just a placeholder for the first index into each rule array.
362             This is where we store the name of the rule and any othe rule-specific info.
363             For now, it doesn't do anything.
364              
365             =cut
366              
367             sub rule {
368 0     0 1 0 my ($llobj, $subrule)=@_;
369 0         0 return;
370             }
371              
372              
373             =head2 call
374              
375             When one grammar rule needs to call another rule (including itself),
376             this method will get executed.
377              
378             Note that this supports recursive calling. A rule can call itself.
379             A first rule can call a second rule which calls the first rule.
380              
381             The main reason this works is that when a rule "calls" another rule,
382             it doesn't actually CONTAIN the rule. A rule is actually made up of
383             a perl array.
384              
385             my $rule1=[
386             [ 'lit', 'a' ],
387             [ 'lit', 'b' ],
388             ];
389              
390             If a rule "calls" itself, it simply points to the name of the rule its calling:
391              
392             my $rule1=[
393             [ 'lit', 'a' ],
394             [ 'call', 'rule1' ],
395             [ 'lit', 'b' ],
396             ];
397              
398             If a call to a rule resulted in the rule being called being expanded and
399             embedded into the original rule, then recursive rules would explode.
400              
401              
402             my $rule1;
403            
404             $rule1=[
405             [ 'lit', 'a' ],
406             [ 'call', $rule1 ],
407             [ 'lit', 'b' ],
408             ];
409              
410             This would become problematic because it would want to expand itself forever
411             (which would be grammatically correct, but explode your memory) or it would
412             only expand one level (which would fit in memory, and be grammatically incorrect).
413              
414             If a call to another rule only contains the NAME of the rule being called,
415             then it won't explode memory.
416              
417             A rule will call a rule only when it needs to, and not explode memory.
418              
419             So then the only other issue that can cause a recursive rule ot explode
420             is if a rule calls itself before matching any text in the source string.
421              
422             This rule will explode when we try to match it against some text:
423              
424             $rule1=[
425             [ 'call', 'rule1' ],
426             [ 'lit', 'b' ],
427             ];
428              
429             The above example will break because rule1 will keep calling itself infinitely
430             without ever matching anything.
431              
432             For the above example NOT to crash, we will eventually have to upgrade the
433             "call" method to detect whether a recursive call is taking place, and
434             if so, check to see that at least SOME text has been consumed. If not,
435             skip the call and look for an alternation or something.
436              
437             For now, we can handle recurssion, but only if we match some text first:
438              
439             $rule1=[
440             ['lit','a'],
441             ['call', 'rule1'],
442              
443             ];
444              
445             =cut
446              
447             sub call{
448 13     13 1 28 my ($llobj, $subrule)=@_;
449              
450 13         20 my $debug=0;
451              
452 13 50       43 if($debug){warn "call subrule is ";print Dumper $subrule;}
  0         0  
  0         0  
453              
454             #print "INSIDE CALL\n";
455             #print "letter IS\n"; print Dumper $letter;
456             #print "SUBRULE IS\n"; print Dumper $subrule;
457 13         20 my $hash_info=$subrule->[2];
458              
459 13         33 my $rule = $hash_info->{payload};
460 13         31 my $package = $hash_info->{package};
461              
462             # then_call is in caller hash.
463             # when we get the grammarref, that will be the callee, so need to get next_call here and pass it in separtely
464             # can't make it part of callee because multiple things could call this rule.
465 13         31 my $then_call = $hash_info->{then_call};
466              
467 13 50       42 if(length($package)){
468 13         35 $rule = $package.'::'.$rule;
469 13         32 $then_call = $package.'::'.$then_call;
470             }
471              
472              
473 13 50       46 if($debug){warn "inside ParsingMethods::call. rule is '$rule', then_call is '$then_call'";}
  0         0  
474              
475              
476 13         51 my $grammarref=$llobj->convert_rule_name_to_rule_reference($rule);
477              
478 13 50       50 if($debug){warn "grammarref for rule '$rule' is "; print Dumper $grammarref;}
  0         0  
  0         0  
479              
480 13         104 $llobj->parse_grammarref($grammarref, $then_call );
481              
482 10 50       30 if($debug){warn "call returned";}
  0         0  
483 10         34 return; # must have matched.
484              
485             }
486              
487              
488              
489             =head2 lit
490              
491             lit is short for literal. It is looking for the current letter object to match the letter value in $subrule.
492              
493             my $rule1=[
494             [ 'lit', 'a' ],
495             [ 'lit', 'b' ],
496             ];
497              
498             The above example is looking for 'a' followed by 'b'.
499              
500             =cut
501              
502             sub lit {
503 112     112 1 161 my ($llobj, $subrule)=@_;
504              
505 112         223 my $grammar_letter=$subrule->[1];
506 112         185 my $letter_payload = $llobj->[LIST__CURR_START]->[LETTER__DATA_PAYLOAD];
507             #warn "lit rule '$grammar_letter' versus letter text '$letter_payload' ";
508 112 100       256 if($grammar_letter ne $letter_payload){
509 44         707 die "GRAMMARFAIL";
510             }
511              
512 68         375 $llobj->[LIST__CURR_START]->[LETTER__LETTER_HAS_BEEN_CONSUMED]=1;
513             }
514              
515             =head2 cc
516              
517             This is short for "character class".
518             In perl regular expressions, this is represented with [].
519             The letters in the square brackets are letters in teh character class you wnat to match.
520             For example, [aeiou] would match a character class of any single vowel.
521              
522             =cut
523              
524             sub cc{
525 4     4 1 6 my ($llobj, $subrule)=@_;
526 4         5 my $href_info=$subrule->[2];
527 4         7 my $hash_of_letters = $href_info->{hash_of_letters};
528              
529              
530 4         7 my $letter_payload = $llobj->[LIST__CURR_START]->[LETTER__DATA_PAYLOAD];
531              
532             #print "called cc with letter_payload '$letter_payload' and class hash "; print Dumper $class_hashref; warn " ";
533              
534 4 100       20 unless(exists($hash_of_letters->{$letter_payload})){
535             #warn "dying ";
536 2         25 die "GRAMMARFAIL";
537             }
538 2         4 $llobj->[LIST__CURR_START]->[LETTER__LETTER_HAS_BEEN_CONSUMED]=1;
539             }
540              
541             =head2 notcc
542              
543             This is short for "not character class".
544             In perl regular expressions, this is represented with [^ ].
545             The letters in the square brackets are letters in teh character class you do NOT want to match.
546             For example, [^aeiou] would NOT match a character class of any single vowel.
547             Or it WOULD match any character that is NOT a vowel.
548              
549             =cut
550              
551             sub notcc{
552 2     2 1 3 my ($llobj, $subrule)=@_;
553 2         3 my $href_info=$subrule->[2];
554 2         4 my $hash_of_letters = $href_info->{hash_of_letters};
555              
556              
557 2         4 my $letter_payload = $llobj->[LIST__CURR_START]->[LETTER__DATA_PAYLOAD];
558              
559             #print "called cc with letter_payload '$letter_payload' and class hash "; print Dumper $class_hashref; warn " ";
560              
561 2 100       6 if(exists($hash_of_letters->{$letter_payload})){
562             #warn "dying ";
563 1         11 die "GRAMMARFAIL";
564             }
565 1         3 $llobj->[LIST__CURR_START]->[LETTER__LETTER_HAS_BEEN_CONSUMED]=1;
566             }
567              
568             =head2 thrifty
569              
570             perform a thrifty quantifier match
571              
572             Note: Since we want to be able to read petabytes of streamed data,
573             we will default to using thrifty matching.
574             i.e. match as little as possible and move on.
575             if we do greedy matching, then the first .* we run into will
576             read in the entire stream (petabytes) into memory and crash the system.
577             if it doesn't crash, it will back up until it finds amatch.
578             We default to thrifty matching, meaning we only read in as little as possible
579             to still find a match. This means we only read in just as much of the
580             stream as we need to find a match.
581             We can DO greedy matching, but it can be a problem if we're streaming massive quantities of data.
582              
583             basic thrifty algorithm:
584             try the rule at least min times.
585             if that matches, then return and let rest of grammar try.
586             If rest of grammar dies, then revert to min location
587             and try matching one more time.
588             if that passes, then return and let rest of grammar try.
589             if rest of grammar dies, then revert to min+1 location
590             and try another rule.
591              
592             keep doing this until you reach "max" number of matches.
593             if that doesn't make things happy, then quantifier dies
594             and the expression fails.
595              
596             rule1 : 'a' rule2 'b'
597              
598             rule2 : 'c' d+ rule3 e+
599              
600             rule3 : f g+ rule4 h
601              
602             rule4 : i*
603              
604              
605              
606             =cut
607              
608             sub thrifty {
609 0     0 1   my ($llobj, $subrule)=@_;
610              
611 0           my $payload=$subrule->[1];
612              
613 0           my $rule = $payload->{rule};
614 0           my $then_call = $payload->{then_call};
615              
616 0           my $grammarref=$llobj->convert_grammar_name_to_array_ref($rule);
617              
618 0           $llobj->parse_grammarref($grammarref, $then_call );
619              
620              
621            
622              
623 0           return; # must have matched.
624             }
625              
626             =head2 greedy
627              
628             basic greedy algorithm.
629             try the rule max times.
630             if not even zero match, die.
631             at the end of every match, record the letter location of that specific match.
632              
633             return and let rest of grammar try.
634             if rest of grammar dies, then revert to max-1 location,
635             and try another rule.
636             return and let rest of grammar try.
637             if rest of grammar dies, then revert to max-2 location
638             and try another rule.
639              
640             keep doing this until you reach "min" number of matches.
641             we can't find a match even at "min", then quantifier dies
642             and the expression fails.
643              
644             =cut
645              
646             sub greedy {
647 0     0 1   my($llobj, $subrule, $overalldirectionforrule)=@_;
648              
649 0           my $payload=$subrule->[1];
650              
651 0           my $min = $payload->{min};
652 0           my $max = $payload->{max};
653 0           my $rule = $payload->{rule};
654              
655              
656             }
657              
658             1;
659