|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #Copyright 2008-10 Arthur S Goldstein  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Parse::Stallion::EBNF;  | 
| 
4
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
 
 | 
27882
 | 
 use Carp;  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
329
 | 
    | 
| 
5
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
 
 | 
24
 | 
 use strict;  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
164
 | 
    | 
| 
6
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
 
 | 
20
 | 
 use warnings;  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
    | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
289
 | 
    | 
| 
7
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
 
 | 
1268
 | 
 use Parse::Stallion;  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
    | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21815
 | 
    | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $VERSION='0.7';  | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub ebnf {  | 
| 
11
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
  
0
  
 | 
796
 | 
   shift;  | 
| 
12
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   my $parser = shift;  | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
14
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   my @queue;  | 
| 
15
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   unshift @queue, keys %{$parser->{rule}};  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
171
 | 
    | 
| 
16
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
37
 | 
   my $start_rule = $parser->{start_rule};  | 
| 
17
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
   unshift @queue, $start_rule;  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
19
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
   my $results;  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my %covered;  | 
| 
21
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
   while (my $rule = shift @queue) {  | 
| 
22
 | 
1018
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
3251
 | 
     if (!$covered{$rule}++) {  | 
| 
23
 | 
422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
621
 | 
       $results .= "$rule = ";  | 
| 
24
 | 
422
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1983
 | 
       if ($parser->{rule}->{$rule}->{rule_type} eq 'MULTIPLE') {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
25
 | 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
105
 | 
         my $min = $parser->{rule}->{$rule}->{minimum_child};  | 
| 
26
 | 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
278
 | 
         my $max = $parser->{rule}->{$rule}->{maximum_child};  | 
| 
27
 | 
50
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
199
 | 
         if ($min == 0 && $max == 1) {  | 
| 
28
 | 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
45
 | 
           $results .= "[ ";  | 
| 
29
 | 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
91
 | 
           $results .= $parser->{rule}->{$rule}->{subrule_list}->[0]->{name};  | 
| 
30
 | 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
233
 | 
           $results .= " ]";  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         else {  | 
| 
33
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
           $results .= "{ ";  | 
| 
34
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
41
 | 
           $results .= $parser->{rule}->{$rule}->{subrule_list}->[0]->{name};  | 
| 
35
 | 
14
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
65
 | 
           if ($min != 0 || $max != 0) {  | 
| 
36
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
             $results .= "($min, $max)";  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           }  | 
| 
38
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
           $results .= " }";  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       elsif ($parser->{rule}->{$rule}->{rule_type} eq 'AND') {  | 
| 
42
 | 
433
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1203
 | 
         $results .= join (" , ",  | 
| 
43
 | 
145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
158
 | 
          map {$_->{name}} @{$parser->{rule}->{$rule}->{subrule_list}});  | 
| 
 
 | 
145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
343
 | 
    | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       elsif ($parser->{rule}->{$rule}->{rule_type} eq 'OR') {  | 
| 
46
 | 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
237
 | 
         $results .= join (" | ",  | 
| 
47
 | 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
          map {$_->{name}} @{$parser->{rule}->{$rule}->{subrule_list}});  | 
| 
 
 | 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
75
 | 
    | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       elsif ($parser->{rule}->{$rule}->{rule_type} eq 'LEAF') {  | 
| 
50
 | 
199
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
507
 | 
         if (defined $parser->{rule}->{$rule}->{leaf_display}) {  | 
| 
51
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
413
 | 
           $results .= $parser->{rule}->{$rule}->{leaf_display};  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       else {  | 
| 
55
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         croak "Rule $rule unknown type ".$parser->{rule}->{$rule}->{rule_type};  | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
57
 | 
422
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
1136
 | 
       if ($parser->{rule}->{$rule}->{subrule_list}) {  | 
| 
58
 | 
422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
411
 | 
         my @new_rules;  | 
| 
59
 | 
422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
406
 | 
         foreach my $subrule (@{$parser->{rule}->{$rule}->{subrule_list}}) {  | 
| 
 
 | 
422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1146
 | 
    | 
| 
60
 | 
591
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1009
 | 
           push @new_rules, $subrule->{name};  | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
62
 | 
422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1098
 | 
         unshift @queue, @new_rules;  | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
64
 | 
422
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
1088
 | 
       if ($parser->{rule}->{$rule}->{minimize_children}) {  | 
| 
65
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $results .= ' -MATCH_MIN_FIRST- ';  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
67
 | 
422
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
989
 | 
       if ($parser->{rule}->{$rule}->{parsing_evaluation}) {  | 
| 
68
 | 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
165
 | 
         $results .= ' -EVALUATION- ';  | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
70
 | 
422
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5628
 | 
       if ($parser->{rule}->{$rule}->{parsing_unevaluation}) {  | 
| 
71
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $results .= ' -UNEVALUATION- ';  | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
73
 | 
422
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
918
 | 
       if ($parser->{rule}->{$rule}->{use_string_match}) {  | 
| 
74
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $results .= ' -USE_STRING_MATCH- ';  | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
76
 | 
422
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
862
 | 
       if ($parser->{rule}->{$rule}->{match_once}) {  | 
| 
77
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $results .= ' -MATCH_ONCE- ';  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
79
 | 
422
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
813
 | 
       if ($parser->{rule_info}->{$rule}) {  | 
| 
80
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $results .= ' -RULE_INFO- ';  | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
82
 | 
422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1393
 | 
       $results .= " ;\n";  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
85
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
134
 | 
   return $results;  | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my %ebnf_rules = (  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    ebnf_rule_list => A(L(PF(sub{$_[0]->{parse_hash}->{max_position} = 0;  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return 1, undef, 0})), 'some_white_space',  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     M(A(O('rule','failed_rule'),'some_white_space')),  | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {  | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my $parse_hash = $_[3];  | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my $any_errors = 0;  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $parse_hash->{errors} = [];  | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if ($_[0]->{failed_rule}) {  | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           push @{$parse_hash->{errors}}, @{$_[0]->{failed_rule}};  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           $any_errors = 1;  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        foreach my $rule (@{$_[0]->{rule}}) {  | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          if ($rule->{error}) {  | 
| 
102
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
            push @{$parse_hash->{errors}}, $rule->{error};  | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
            $any_errors = 1;  | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          }  | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        }  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        if ($any_errors) {croak join("\n",@{$parse_hash->{errors}})}  | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        return $_[0]->{rule};})),  | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    rule =>  | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     A('rule_name', 'some_white_space', qr/\=/, 'some_white_space',  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      'rule_def', 'some_white_space', qr /\;/,  | 
| 
111
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      E(sub {  | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          return {rule_name => $_[0]->{rule_name},  | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           rule_definition => $_[0]->{rule_def}}})),  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    real_white_space => A(qr/\s/, 'some_white_space'),  | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    some_white_space => A(L(PF(  | 
| 
116
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sub {my $parameters = shift;  | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $cv = $parameters->{current_position};  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $ph = $parameters->{parse_hash};  | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if ($ph->{max_position} < $cv) {  | 
| 
120
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $ph->{max_position} = $cv;  | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return 1, undef, 0;  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     })), O(  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     A(qr/\s*\#/, 'comment', 'some_white_space'),  | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     qr/\s*/,  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    )),  | 
| 
127
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    rule_def =>  | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     O(  | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      A(qr/\(/, 'some_white_space', 'the_rule', 'some_white_space', qr/\)/,  | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       Z(A('some_white_space', 'eval_subroutine'))),  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      A('the_rule'),  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       E(sub {  | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          my $the_rule = $_[0]->{the_rule};  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          my $rule_def;  | 
| 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          if ($_[0]->{eval_subroutine}->{sub}) {  | 
| 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
            push @{$the_rule->{elements}}, $_[0]->{eval_subroutine}->{sub};  | 
| 
137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          }  | 
| 
138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          if ($the_rule->{rule_type} eq 'AND') {  | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
            $rule_def = A(@{$the_rule->{elements}});  | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          }  | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          elsif ($the_rule->{rule_type} eq 'OR') {  | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
            $rule_def = O(@{$the_rule->{elements}});  | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          }  | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          elsif ($the_rule->{rule_type} eq 'LEAF') {  | 
| 
145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
            $rule_def = L(@{$the_rule->{elements}});  | 
| 
146
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          }  | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          elsif ($the_rule->{rule_type} eq 'MULTIPLE') {  | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
            $rule_def = M(@{$the_rule->{elements}});  | 
| 
149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          }  | 
| 
150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          elsif ($the_rule->{rule_type} eq 'OPTIONAL') {  | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
            $rule_def = Z(@{$the_rule->{elements}});  | 
| 
152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          }  | 
| 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          return $rule_def})),  | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    the_rule => O('leaf', 'quote', 'pf_pb', 'multiple', 'optional', 'and', 'or'),  | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    comment => qr/[^\n]*/,  | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    failed_rule => A(  | 
| 
157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     L(PF(sub {${$_[0]->{__current_node_ref}}->{error_position} =  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      $_[0]->{parse_hash}->{max_position};  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      my $new_position = $_[0]->{current_position};  | 
| 
160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      if ($new_position < $_[0]->{parse_hash}->{max_position}) {  | 
| 
161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        $new_position = $_[0]->{parse_hash}->{max_position};  | 
| 
162
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      }  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      return 1, undef, 0;})),  | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     qr/[^;]*\;/,  | 
| 
165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {my (undef, $parameters) = @_;  | 
| 
166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $text = $parameters->{parse_this_ref};  | 
| 
167
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $pos = $parameters->{current_node}->{error_position} || 0;  | 
| 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my ($line, $position) = LOCATION($text, $pos);  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $before_length = 10;  | 
| 
170
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $before_start = $pos - 10;  | 
| 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if ($pos < 10) {  | 
| 
172
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $before_length = $pos;  | 
| 
173
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $before_start = 0;  | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $before = substr($$text, $before_start, $before_length);  | 
| 
176
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       $before =~ s/.*\s(.+)/$1/;  | 
| 
177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $after = substr($$text, $pos, 10);  | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       $after =~ s/(.+?)\s(.*)/$1/;  | 
| 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return "Error at line $line tab stop $position near '$before".$after."'";  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      })),  | 
| 
181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    and => A( 'element' ,  | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      M(A('real_white_space', 'element')),  | 
| 
183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      return {rule_type => 'AND', elements => $_[0]->{element}};})),  | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    element => A(Z(A({alias=>'rule_name'}, qr/\./)), 'sub_element',  | 
| 
186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E( sub {  | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if (defined $_[0]->{alias}) {  | 
| 
188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return {$_[0]->{alias} => $_[0]->{sub_element}}  | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return $_[0]->{sub_element}})),  | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    sub_element => O('rule_name', 'sub_rule',  | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'optional_sub_rule',  | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'multiple_sub_rule', 'leaf_sub_rule', 'pf_pb_subrule', 'quote_sub_rule',  | 
| 
194
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'use_string_match', 'match_once', 'match_min_first'),  | 
| 
195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    use_string_match => L(qr/\=SM/,  | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {return USE_STRING_MATCH})),  | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    match_once => L(qr/\=MO/,  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {return MATCH_ONCE})),  | 
| 
199
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    match_min_first => L(qr/\=MMF/,  | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {return MATCH_MIN_FIRST})),  | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    optional_sub_rule => A( qr/\[/, 'some_white_space',  | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      'rule_def', 'some_white_space', qr/\]/i,  | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {  | 
| 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return Z($_[0]->{rule_def});})),  | 
| 
205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    multiple_sub_rule => A( qr/\{/,  | 
| 
206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'some_white_space', 'rule_def', 'some_white_space', qr/\}/,  | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Z('use_min_first'), Z('min_max'),  | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {  | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $min = 0;  | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $max = 0;  | 
| 
211
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if ($_[0]->{min_max}) {  | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $min = $_[0]->{min_max}->{min};  | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $max = $_[0]->{min_max}->{max};  | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if ($_[0]->{use_min_first}) {  | 
| 
216
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return M($_[0]->{rule_def},$min,$max, MATCH_MIN_FIRST());  | 
| 
217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return M($_[0]->{rule_def},$min,$max);}  | 
| 
219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      )),  | 
| 
220
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    sub_rule => A( qr/\(/, 'some_white_space', 'rule_def', 'some_white_space',  | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     qr/\)/,  | 
| 
222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub { return $_[0]->{rule_def};})  | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    ),  | 
| 
224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    rule_name => qr/[a-zA-Z]\w*/,  | 
| 
225
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    or => A( 'element' , M(A('some_white_space', qr/\|/, 'some_white_space',  | 
| 
226
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'element'), 1, 0),  | 
| 
227
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {return {rule_type => 'OR', elements => $_[0]->{element}}})),  | 
| 
228
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    multiple => A( qr/\{/, 'some_white_space',  | 
| 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    'element', 'some_white_space', qr/\}/, Z('use_min_first'),  | 
| 
230
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Z('min_max'),  | 
| 
231
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {  | 
| 
232
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $min = 0;  | 
| 
233
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $max = 0;  | 
| 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if ($_[0]->{min_max}) {  | 
| 
235
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $min = $_[0]->{min_max}->{min};  | 
| 
236
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $max = $_[0]->{min_max}->{max};  | 
| 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
238
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if ($_[0]->{use_min_first}) {  | 
| 
239
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return {rule_type => 'MULTIPLE',  | 
| 
240
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          elements => [$_[0]->{element},$min,$max, MATCH_MIN_FIRST()]};  | 
| 
241
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return {rule_type => 'MULTIPLE', elements => [$_[0]->{element},$min,$max]}  | 
| 
243
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      })),  | 
| 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    min_max => A(qr/\*/,{min=>qr/\d+/},qr/\,/,{max=>qr/\d+/}),  | 
| 
245
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    use_min_first => qr/\?/,  | 
| 
246
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    optional => A( qr/\[/, 'some_white_space',  | 
| 
247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'element', 'some_white_space', qr/\]/,  | 
| 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {  | 
| 
249
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return {rule_type => 'OPTIONAL', elements => [$_[0]->{element}]}  | 
| 
250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      })),  | 
| 
251
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    quote_sub_rule => A( O(A(qr/q/i, qr/[^\w\s]/), qr/(\"|\')/), 'leaf_info',  | 
| 
252
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {my $li = $_[0]->{leaf_info}; substr($li, -1) = '';  | 
| 
253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       $li =~ s/(\W)/\\$1/g;  | 
| 
254
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return L(qr/$li/)})),  | 
| 
255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    quote => A( O(A(qr/q/i, qr/[^\w\s]/,), qr/(\"|\')/), 'leaf_info',  | 
| 
256
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {my $li = $_[0]->{leaf_info}; substr($li, -1) = '';  | 
| 
257
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       $li =~ s/(\W)/\\$1/g;  | 
| 
258
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return {rule_type => 'LEAF', elements => [qr/$li/]}})),  | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    leaf_sub_rule => A( qr/qr/i, qr/[^\w\s]/, 'leaf_info',  | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {my $li = $_[0]->{leaf_info}; substr($li, -1) = '';  | 
| 
261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return L(qr/$li/)})),  | 
| 
262
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    leaf => A( qr/qr/, qr/[^\w\s]/, 'leaf_info',  | 
| 
263
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Z({modifiers=>qr/\w+/}),  | 
| 
264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {my $li = $_[0]->{leaf_info}; substr($li, -1) = '';  | 
| 
265
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if (defined $_[0]->{modifiers}) {  | 
| 
266
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          $li = '(?' . $_[0]->{modifiers}. ')'.$li  | 
| 
267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return {rule_type => 'LEAF', elements => [qr/$li/]}})),  | 
| 
269
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    leaf_info => L(PF(  | 
| 
270
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sub {my $parameters = shift;  | 
| 
271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $in_ref = $parameters->{parse_this_ref};  | 
| 
272
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $pos = $parameters->{current_position};  | 
| 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $previous = substr($$in_ref, $pos-1, 1);  | 
| 
274
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       pos $$in_ref = $pos;  | 
| 
275
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if ($$in_ref =~ /\G([^$previous]+$previous)/) {  | 
| 
276
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return 1, $1, length($1);  | 
| 
277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
278
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       else {  | 
| 
279
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return 0;  | 
| 
280
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    )),  | 
| 
283
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    pf_pb_subrule => A('parse_forward',  | 
| 
284
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Z(A('some_white_space', 'parse_backtrack')),  | 
| 
285
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E (sub {  | 
| 
286
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        if ($_[0]->{parse_backtrack}) {  | 
| 
287
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          return L(PF($_[0]->{parse_forward}),  | 
| 
288
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
            PB($_[0]->{parse_backtrack}));  | 
| 
289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           };  | 
| 
290
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        return L(PF($_[0]->{parse_forward}));  | 
| 
291
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      }  | 
| 
292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    )),  | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    pf_pb => A('parse_forward', Z(A('some_white_space', 'parse_backtrack')),  | 
| 
294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      E(sub {  | 
| 
295
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      if ($_[0]->{parse_backtrack}) {  | 
| 
296
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        return {rule_type => 'LEAF', elements => [  | 
| 
297
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          PF($_[0]->{parse_forward}),  | 
| 
298
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          PB($_[0]->{parse_backtrack}),  | 
| 
299
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ]};  | 
| 
300
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
301
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return {rule_type => 'LEAF', elements => [  | 
| 
302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         PF($_[0]->{parse_forward}),  | 
| 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        ]};  | 
| 
304
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    })),  | 
| 
305
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    quote_sub_rule => A( O(A(qr/q/i, qr/[^\w\s]/), qr/(\"|\')/), 'leaf_info',  | 
| 
306
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {my $li = $_[0]->{leaf_info}; substr($li, -1) = '';  | 
| 
307
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       $li =~ s/(\W)/\\$1/g;  | 
| 
308
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return L(qr/$li/)})),  | 
| 
309
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    quote => A( O(A(qr/q/i, qr/[^\w\s]/,), qr/(\"|\')/), 'leaf_info',  | 
| 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {my $li = $_[0]->{leaf_info}; substr($li, -1) = '';  | 
| 
311
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       $li =~ s/(\W)/\\$1/g;  | 
| 
312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return {rule_type => 'LEAF', elements => [qr/$li/]}})),  | 
| 
313
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    parse_backtrack => A( qr/B[^\w\s]/, 'sub_routine',  | 
| 
314
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {  | 
| 
315
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        my $routine = eval $_[0]->{sub_routine}->{the_sub};  | 
| 
316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        if ($@) {croak $@};  | 
| 
317
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        return $routine;})  | 
| 
318
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    ),  | 
| 
319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    parse_forward => A( qr/F[^\w\s]/, 'sub_routine',  | 
| 
320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {  | 
| 
321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        my $routine = eval $_[0]->{sub_routine}->{the_sub};  | 
| 
322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        if ($@) {croak $@};  | 
| 
323
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        return $routine;})  | 
| 
324
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    ),  | 
| 
325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    eval_subroutine => A( qr/S[^\w\s]/, 'sub_routine',  | 
| 
326
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {return {'sub' => SE($_[0]->{'sub_routine'}->{the_sub},  | 
| 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      '_matched_string')}})  | 
| 
328
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    ),  | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    sub_routine => L(PARSE_FORWARD(  | 
| 
330
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sub {my $parameters = shift;  | 
| 
331
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $in_ref = $parameters->{parse_this_ref};  | 
| 
332
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $pos = $parameters->{current_position};  | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $previous = substr($$in_ref, $pos-1, 1);  | 
| 
334
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $previous2 = substr($$in_ref, $pos-2, 1);  | 
| 
335
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       pos $$in_ref = $pos;  | 
| 
336
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $opposite;  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if ($previous eq '{') {$opposite = '}'};  | 
| 
338
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if ($previous eq '[') {$opposite = ']'};  | 
| 
339
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if (!defined $opposite) {return 0}  | 
| 
340
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if ($$in_ref =~ /\G(.*?$opposite($previous2))/s) {  | 
| 
341
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return 1, $1, length($1);  | 
| 
342
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       else {  | 
| 
344
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return 0;  | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }),  | 
| 
347
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     E(sub {  | 
| 
348
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        my $subroutine = shift;  | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        substr($subroutine, -2) = '';  | 
| 
350
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        return {the_sub => $subroutine};  | 
| 
351
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      }  | 
| 
352
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    ))  | 
| 
353
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
354
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
355
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $ebnf_parser = new Parse::Stallion(\%ebnf_rules);  | 
| 
356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 foreach my $mn (keys %{$ebnf_parser->{rule}}) {  | 
| 
357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   if (!$ebnf_parser->{rule}->{$mn}->{rule_type}) {  | 
| 
358
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     warn "name generated $mn\n";  | 
| 
359
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
360
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
361
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
362
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
 
 | 
69
 | 
 use Parse::Stallion::EBNF;  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1292
 | 
    | 
| 
363
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $ebnf_form = ebnf Parse::Stallion::EBNF($ebnf_parser);  | 
| 
364
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
365
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub ebnf_new {  | 
| 
366
 | 
26
 | 
 
 | 
 
 | 
  
26
  
 | 
  
0
  
 | 
18417
 | 
   my $type = shift;  | 
| 
367
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
61
 | 
   my $rules_string = shift;  | 
| 
368
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #print STDERR "rule string is $rules_string\n";  | 
| 
369
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  my @pt;  | 
| 
370
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
   my $rules_out = eval {$ebnf_parser->parse_and_evaluate(  | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
113
 | 
    | 
| 
371
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $rules_string  | 
| 
372
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #    , {parse_trace => \@pt}  | 
| 
373
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    )};  | 
| 
374
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #use Data::Dumper;print STDERR "pt is ".Dumper(\@pt)."\n";  | 
| 
375
 | 
26
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
368
 | 
   if ($@) {croak "\nUnable to create parser due to the following:\n$@\n"};  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
183
 | 
    | 
| 
376
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #use Data::Dumper;print STDERR "ro is ".Dumper($rules_out)."\n";  | 
| 
377
 | 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
51
 | 
   my %rules;  | 
| 
378
 | 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
66
 | 
   foreach my $rule (@$rules_out) {  | 
| 
379
 | 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
152
 | 
     my $rule_name = $rule->{rule_name};  | 
| 
380
 | 
72
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
198
 | 
     if ($rules{$rule_name}) {  | 
| 
381
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
229
 | 
       croak "Unable to create parse: Duplicate rule name $rule_name\n";  | 
| 
382
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
383
 | 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
216
 | 
     $rules{$rule_name} = $rule->{rule_definition};  | 
| 
384
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
385
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #use Data::Dumper;print STDERR "therules is ".Dumper(\%rules)."\n";  | 
| 
386
 | 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
284
 | 
   my $new_parser = new Parse::Stallion(\%rules, {separator => '.'});  | 
| 
387
 | 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
312
 | 
   return $new_parser;  | 
| 
388
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
390
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
391
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
392
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |