File Coverage

blib/lib/Parse/Stallion/RD.pm
Criterion Covered Total %
statement 39 390 10.0
branch 0 84 0.0
condition 0 57 0.0
subroutine 13 37 35.1
pod 0 9 0.0
total 52 577 9.0


line stmt bran cond sub pod time code
1             #Copyright 2009 Arthur S Goldstein
2              
3             # Since there are other features one can implement, most debugging code
4             # has been left in.
5              
6             # test for could not parse beyond
7              
8             # starting line number argument of the start rule
9              
10             #use extract_quotelike for mtoken (and token?)
11              
12             #up_to, up_from = = 1 right op, left op, what else there is..
13              
14             package Parse::Stallion::RD::Dummy;
15              
16             package Parse::Stallion::RD::Thisline;
17 2     2   29675 use Parse::Stallion;
  2         8  
  2         649  
18             require Tie::Scalar;
19             our @ISA = (Tie::StdScalar);
20             sub FETCH {
21 0     0     my ($loc) = LOCATION($Parse::Stallion::RD::__parse_this_ref,
22             $Parse::Stallion::RD::__previous_position);
23 0           return $loc;
24             }
25              
26             package Parse::Stallion::RD::Text;
27 2     2   16 use Parse::Stallion;
  2         4  
  2         708  
28             require Tie::Scalar;
29             our @ISA = (Tie::StdScalar);
30             sub FETCH {
31 0     0     my $ptr = $Parse::Stallion::RD::__parse_this_ref;
32 0   0       my $position = $Parse::Stallion::RD::__current_position || 0;
33 0           my $to_return = substr($$ptr, $position);
34 0           return $to_return;
35             }
36             sub STORE {
37 0     0     my $self = shift;
38 0           my $store = shift;
39 0   0       my $position = $Parse::Stallion::RD::__current_position || 0;
40 0           substr(${$Parse::Stallion::RD::__parse_this_ref},
  0            
41             $position) = $store;
42             }
43              
44             package Parse::Stallion::RD::Itempos;
45 2     2   12 use Parse::Stallion;
  2         14  
  2         1737  
46             require Tie::Array;
47             our @ISA = (Tie::StdArray);
48             sub FETCH {
49 0     0     my $self = shift;
50 0           my $place = shift;
51 0           my $parent = $Parse::Stallion::RD::__parent;
52 0           my $item_node = $parent->{children}->[$place];
53 0           my $thisparser = $Parse::Stallion::RD::__thisparser;
54 0           my $this_parser = $thisparser->{parser};
55 0           my $is_leaf = $this_parser->{rule}->{$item_node->{name}}->{leaf_rule};
56 0           my $to_return = {};
57 0           my $ptr = $Parse::Stallion::RD::__parse_this_ref;
58              
59 0           my $from;
60 0 0         if ($is_leaf) {
61 0           $from = $item_node->{position_when_completed} -
62             length($item_node->{parse_match});
63             }
64             else {
65 0           $from = $item_node->{position_when_entered};
66             }
67              
68 0           ($to_return->{line}->{from},
69             $to_return->{column}->{from}) = LOCATION(
70             $ptr,
71             $to_return->{offset}->{from} = $from);
72 0           ($to_return->{line}->{to},
73             $to_return->{column}->{to}) = LOCATION(
74             $ptr,
75             $to_return->{offset}->{to} =
76             $item_node->{position_when_completed});
77              
78 0           return $to_return;
79             }
80              
81             package Parse::Stallion::RD;
82             # Read in grammars similar to those used for Parse::RecDescent
83             our @ISA = qw { Parse::Stallion::RD::Dummy }; #to match test case of Parse::RecDescent
84             local $::D = $::D; #not used here
85             local $::RD_HINT = $::RD_HINT; #not used here
86             local $::ERROR = $::ERROR; #not used here
87             local $::RD_ERRORS = $::RD_ERRORS; #not used here
88             local $::RD_WARN = $::RD_WARN; #not used here
89             local $::RD_TRACE = $::RD_TRACE; #not used here
90             local $::RD_CHECK = $::RD_CHECK; #not used here
91 2     2   15 use Carp;
  2         6  
  2         153  
92 2     2   13 use strict;
  2         4  
  2         95  
93 2     2   15 use warnings;
  2         5  
  2         63  
94 2     2   11 use Parse::Stallion;
  2         4  
  2         448  
95 2     2   1321 use Text::Balanced qw (extract_codeblock extract_bracketed);
  2         20188  
  2         25575  
96             our $VERSION='0.41'; #unchanging
97             our $skip = qr/\s*/; #prev
98             our $__default_skip; #prev?
99             our $commit; #prev
100             our @__skip; #prev
101             our $__thisparser; #prev
102             our %__rulevar; # creation
103             our $__error_message; #prev
104             our @__delay; #prev
105             our $__trace; #not important?
106             our $__parent; #mctr
107             our $__rule_has_commit; #prev
108             our $__rule_has_error; #prev
109             our $__previous_position; #tied from mctr
110             our $__current_position; #tied and mctr
111             our $__parse_this_ref; #mctr and prev
112             our $__max_steps; #not important
113             our $__rule_info; #prev
114             our $__replace_mode; # creation
115             our %__max_replace; # creation
116             our $__replace_level; # creation
117             our $__current_package_number = 0; # creation
118             our $__current_package_name; # creation
119             our $__sub_count = 0; # creation
120             our @__package_list; # creation
121             our $__package_text; # creation
122             our %__package_temp_names; # creation
123             our %__package_subs; # creation
124             our @__package_sub_names; # creation
125             our @arg; #prev
126             our %arg; #prev
127             tie our $thisline, "Parse::Stallion::RD::Thisline";
128             tie our $text, "Parse::Stallion::RD::Text";
129             tie our @itempos, "Parse::Stallion::RD::Itempos";
130              
131             sub compute_node_value {
132 0     0 0   my $node_with_value = shift;
133 0           my $item_value = $node_with_value->{parse_match};
134 0 0         if (defined $item_value) {return $item_value}
  0            
135 0   0       my $item_type =
136             $__rule_info->{$node_with_value->{name}}->{rule_type} || "";
137 0 0 0       if ($item_type eq "straight") {
    0          
    0          
    0          
    0          
    0          
138 0           $item_value = [];
139 0 0         if ($node_with_value->{child_count}) {
140 0           foreach my $node_child (@{$node_with_value->{children}}) {
  0            
141 0           push @{$item_value}, $node_child->{parse_match};
  0            
142             }
143             }
144             }
145             elsif ($item_type eq "straight_separator" ||
146             $item_type eq "leftop_two") {
147 0           $item_value = [$node_with_value->{children}->[0]->{parse_match}];
148 0           my $other_children = $node_with_value->{children}->[1];
149 0           foreach my $child (@{$other_children->{children}}) {
  0            
150 0           push @$item_value,
151             $child->{children}->[1]->{parse_match};
152             }
153             }
154             elsif ($item_type eq "leftop_one") {
155 0           $item_value = [$node_with_value->{children}->[0]->{parse_match}];
156 0           my $other_children = $node_with_value->{children}->[1];
157 0           foreach my $other_child (@{$other_children->{children}}) {
  0            
158 0           push @$item_value, $other_child->{children}->[0]->{parse_match};
159 0           push @$item_value, $other_child->{children}->[1]->{parse_match};
160             }
161             }
162             elsif ($item_type eq "rightop_one") {
163 0           my $other_children = $node_with_value->{children}->[0];
164 0           foreach my $other_child (@{$other_children->{children}}) {
  0            
165 0           push @$item_value, $other_child->{children}->[0]->{parse_match};
166 0           push @$item_value, $other_child->{children}->[1]->{parse_match};
167             }
168 0           push @$item_value,
169             $node_with_value->{children}->[1]->{parse_match};
170             }
171             elsif ($item_type eq "rightop_two") {
172 0           my $other_children = $node_with_value->{children}->[0];
173 0           foreach my $other_child (@{$other_children->{children}}) {
  0            
174 0           push @$item_value, $other_child->{children}->[0]->{parse_match};
175             }
176 0           push @$item_value,
177             $node_with_value->{children}->[1]->{parse_match};
178             }
179             elsif ($item_type eq "straight_z_separator") {
180 0           my $z_node = $node_with_value->{children}->[0];
181 0 0         if ($z_node) {
182 0           $item_value = [];
183 0           push @$item_value, $z_node->{children}->[0]->{parse_match};
184 0           foreach my $child (@{$z_node->{children}->[1]->{children}}) {
  0            
185 0           push @$item_value,
186             $child->{children}->[1]->{parse_match};
187             }
188             }
189             }
190 0           $node_with_value->{parse_match} = $item_value;
191 0           return $item_value;
192             }
193              
194             sub mctr {
195 0     0 0   my $code = shift;
196 0           my $__current_rule = shift;
197             # my $sub_means_grandparent = shift;
198 0           my $get_parent_code;
199             # if ($sub_means_grandparent) {
200             # $get_parent_code = '$__parent = $_[0]->{parent_node}->{parent_node};';
201             # }
202             # else {
203             # $get_parent_code = '$__parent = $_[0]->{parent_node};';
204             # }
205             # my $safe_code = $code;
206             # $safe_code =~ s/\'//g;
207             # $safe_code =~ s/\"//g;
208             # $safe_code =~ s/\$//g;
209 0           my $sub_text = "
210             sub $__current_package_name\_sub".$__sub_count.' {
211             #delete $_[0]->{parser};use Data::Dumper;print "actode in ".Dumper(\@_)."\n";
212             $__parent = $_[0]->{parent_node};
213             my $__subparent = $__parent;
214             #print "sbpsteps ".$__subparent->{steps}."\n";
215             #print "keys of p ".join("..",keys %{$__parent})."\n";
216             if ($__parent->{use_grandparent}) {
217             #print "set uggg\n";
218             $__parent = $__parent->{parent_node};
219             }
220             $__current_position = $_[0]->{current_position};
221             #print "set cp to $__current_position\n";
222             my $return;
223             my $__updated_position;
224             $__previous_position = $__parent->{position_when_entered};
225             my $thisparser = $__thisparser; # used by RecDescent
226             $__parse_this_ref = $_[0]->{parse_this_ref};
227             my $child_number = 1;
228             my @item = ("'.$__current_rule.'");
229             my %item = (__RULE__ => "'.$__current_rule.'");
230             while ($child_number <= $#{$__parent->{children}}) {
231             my $node_with_value = $__parent->{children}->[$child_number];
232             my $item_name = $node_with_value->{alias} ||
233             $__rule_info->{$node_with_value->{name}}->{rd_name} || "";
234             my $item_value = Parse::Stallion::RD::compute_node_value($node_with_value);
235             $child_number++;
236             if ($item_name ne "") {
237             push @item, $item_value;
238             $item{$item_name} = $item_value;
239             }
240             }
241             #use Data::Dumper;print "item is ".Dumper(\@item)."\n";
242             #SPE_CIAL '.$__current_rule.' SPEC_IAL
243             my $match = do {'. $code.'};
244             if (defined $return) {$match = $return}
245             if (!defined $match) { return 0; }
246             if (defined $__updated_position) {
247             return 1, $match, $__updated_position;
248             }
249             return 1, $match;}';
250             #print "subtext is $sub_text\n";
251 0           push @__package_list, $sub_text;
252 0     0 0   sub k{my $t; return sub {$t}}; #force perl to generate different subs
  0     0      
  0            
253 0           my $return_sub = k;
254             #print "return sub is $return_sub\n";
255 0           $__package_temp_names{$return_sub} =
256             $__current_package_name.'_sub'.$__sub_count;
257             # eval $sub_text;
258             # if ($@) {print "err $@";croak "Error is $@\n"};
259             # my $mcsub;
260             # eval "\$mcsub = \\\&{".$__current_package_name.'::sub'.$__sub_count."}";
261             # if ($@) {print "krr $@";croak "Error is $@\n"};
262 0           $__sub_count++;
263             #print "mct $__mct Error is $@\n";
264 0           return $return_sub;
265             }
266              
267             my $move_to_parent = L(PF(
268             sub {
269             my $parameters = shift;
270             #use Data::Dumper; print "mtp params ".Dumper($parameters)."\n";
271             my $parent_node = $parameters->{parent_node};
272             my $previous_node_count = $parent_node->{child_count} - 1;
273             my $previous_node = $parent_node->{children}->[$previous_node_count];
274             my $value = compute_node_value($previous_node);
275             $parent_node->{parse_match} = $value;
276             return 1;
277             }), LEAF_DISPLAY('move to parent')
278             );
279             our $__counts = [];
280             our $__current_rule_count = 0;
281             #print "set orig\n";
282             #print "done set orig\n";
283             our $__autotree;
284             our $__autotree_namespace;
285             our $__orig_autotreeterminal = 'bless {__VALUE__=>$item[1]}, XX$item[0]';
286             our $__orig_autotreenonterminal = 'bless \%item, XX$item[0]';
287             our $__autotreeterminal;
288             our $__autotreenonterminal;
289              
290             my $__start_rule = L(PF(
291             sub {
292             my $parameters = shift;
293             $parameters->{parent_node}->{previous_commit} = $commit;
294             unshift @__skip, $skip = $__default_skip;
295             $commit = 0;
296             return 1;
297             }),
298             PB( sub {
299             my $parent = $_[0]->{parent_node};
300             pop @__skip;
301             $skip = $__skip[0];
302             #use Data::Dumper;print "in sr pn e ".Dumper($parent->{error_messages})."\n";
303             $commit = $parent->{previous_commit};
304             if ($parent->{error_messages} && !($parent->{completed})) {
305             $__error_message .= join("\n", @{$parent->{error_messages}})."\n";
306             }
307             return 0;
308             }
309             ), LEAF_DISPLAY('start rule'));
310              
311             my $__end_rule = L(PB(
312             sub {
313             my $parent = $_[0]->{parent_node};
314             # my $parent = $current_node->{parent};
315             unshift @__skip, $skip = $parent->{skip};
316             $commit = $parent->{commit_on_exit};
317             return 0;
318             }),
319             PF( sub {
320             #delete $_[0]->{parser};use Data::Dumper;print "end rule arg ".Dumper(\@_)."\n";
321             my $parent_node = $_[0]->{parent_node};
322             $parent_node->{commit_on_exit} = $commit;
323             $parent_node->{completed} = 1;
324             $commit = $parent_node->{previous_commit};
325             my $parent_last_child = $parent_node->{child_count}-1;
326             my $previous_node = $parent_node->{children}->[$parent_last_child];
327             my $previous_last_child = $previous_node->{child_count}-1;
328             my $pre_previous_node = $previous_node->{children}->[$previous_last_child];
329             my $last_previous_node_count = $pre_previous_node->{child_count}-1;
330             my $last_previous_node =
331             $pre_previous_node->{children}->[$last_previous_node_count];
332             my $value = compute_node_value($last_previous_node);
333             $parent_node->{parse_match} = $value;
334             $parent_node->{skip} = shift @__skip;
335             $skip = $__skip[0];
336             return 1;
337             }
338             ), LEAF_DISPLAY('end rule'));
339              
340             my $__check_commit = L(PF(
341             sub {
342             #print "checking commit which is $commit\n";
343             if ($commit) {return 0;}
344             return 1;
345             }
346             ), LEAF_DISPLAY('check commit'));
347              
348             sub __rule_def {
349 0     0     return $_[0]->{the_productions}->{''};}
350             sub __xrule_def {
351 0     0     return $_[0]->{x};}
352             my $__current_rule;
353             my $__look_ahead_count=0;
354             our $any_deferred;
355             our @other_rules;
356             my %rd_rules = (
357             rd_rule_list => A(M(O(qr/\s*/,'comment','initial_actions', 'autotree')),
358             M(A('rule',A(M(O(qr/\s*/,'comment'))))),
359             E(sub {return $_[0]->{rule};})),
360             rule =>
361             A('set_rule_name', qr/\s*\:\s*/, M(O(qr/\s*/,'comment')),
362             Z(A('rule_def', qr/\s*\n/)),
363             E(sub {
364             if ($__replace_mode) {
365             $__max_replace{$_[0]->{set_rule_name}} = $__replace_level;
366             }
367             if (!(defined $_[0]->{rule_def})) {
368             $_[0]->{rule_def} = [[{item_type => 'token',
369             operation => qr//, name => 'dummy'}]];
370             }
371             return {rule_name => $_[0]->{set_rule_name},
372             replace_level => $__replace_level,
373             rule_definition => $_[0]->{rule_def}};})),
374             rule_def => A('production', M(A(qr/\s*\|\s*/, 'production')),
375             E(sub {my $in = shift; return $in->{production};}
376             )),
377             comment => O(qr/\s*\#.*?\n/,{sr=>qr/\s*\*STARTREPLACE\n/},
378             {er=>qr/\s*\*ENDREPLACE\n/},
379             E(sub {if ($_[0]->{sr}) {$__replace_mode = 1; $__replace_level++;
380             print "start replace\n"}
381             elsif ($_[0]->{er}) {$__replace_mode = 0; print "end replace\n"}})),
382             set_counts => L(PF(sub {return 1;}),
383             E(sub {unshift @$__counts, {}})),
384             production => A('set_counts', 'item', M(A(qr/\s/,
385             M(O(qr/\s*/, 'comment')),
386             'item')),
387             Z('comment'),
388             E(sub {my $in = shift;
389             #use Data::Dumper; print "production in shift reveals ".Dumper($in);
390             return $in->{item};
391             })),
392             resync => O(qr/\/, A(qr/\
393             E( sub {
394             my $pattern;
395             if (defined $_[0]->{def_perl_code}) {
396             $pattern = $_[0]->{def_perl_code};
397             $pattern =~ s/^.//;
398             $pattern =~ s/.$//;
399             }
400             else {
401             $pattern = '/[^n]*\n/';
402             }
403             substr($pattern, 1, 0) = '\G';
404             my $regex = eval 'qr'.$pattern;
405             if ($@) {print "ResyncGex is $@"};
406             my $sub = sub {
407             my $current_position = $_[0]->{current_position};
408             my $inref = $_[0]->{parse_this_ref};
409             pos $$inref = $current_position;
410             $$inref =~ /\G$skip/cg;
411             if ($$inref =~ /($regex)/cg) {
412             return 1, 0, pos $$inref;
413             }
414             #print "tdid not match on $regex at ".$_[0]->{current_position}."\n";
415             return 0;
416             };
417             my $count = ++$__counts->[0]->{directive}->{$__current_rule};
418             my $latest_name = '__DIRECTIVE'.$count.'__';
419             return {name => $latest_name,
420             operation => {$latest_name => L(PF($sub),
421             LEAF_DISPLAY('resync '.$pattern)
422             ,RULE_INFO({rule_type => 'resync'}))}
423             };
424             })),
425             rulevar => A(qr/\
426             E( sub {
427             my $body = $_[0]->{def_perl_code};
428             $body =~ s/^.//;
429             $body =~ s/.$//;
430             if ($body =~ /^\s*local\s/) {
431             $__rulevar{$__current_rule} .= $body.";\n";
432             }
433             else {
434             $__rulevar{$__current_rule} .= 'my '.$body.";\n";
435             }
436             my $sub = sub { return 1;};
437             my $count = ++$__counts->[0]->{directive}->{$__current_rule};
438             my $latest_name = '__DIRECTIVE'.$count.'__';
439             return {name => $latest_name, operation => {$latest_name => L(PF($sub)
440             ,RULE_INFO({rule_type => 'rulevar'})
441             ,LEAF_DISPLAY('rulevar'))}};
442             })),
443             matchrule => A(qr/\
444             #need not be def_perl_code
445             E( sub {
446             my $body = $_[0]->{def_perl_code};
447             $body =~ s/^.//;
448             $body =~ s/.$//;
449             #print "mr body is $body\n";
450             my $code = '
451             if ($__subparent->{use_grandparent}) {
452             @arg = @{$__subparent->{previous_arg_list}};
453             %arg = %{$__subparent->{previous_arg_hash}};
454             #use Data::Dumper;print "sbarg now ".Dumper(\@arg)."\n";
455             }
456             my $subrule = '.$body.';
457             #print "mr subrule is $subrule\n";
458             #use Data::Dumper;print "mrparms is ".Dumper(\@_)."\n";
459             if ($__subparent->{use_grandparent}) {
460             @arg = @{$__subparent->{this_arg_list}};
461             %arg = %{$__subparent->{this_arg_hash}};
462             }
463             my $pi = {};
464             my $result = $_[0]->{the_parser}->parse_and_evaluate(
465             undef,
466             {start_rule=> $subrule, parse_info => $pi,
467             max_steps => $__max_steps || 1000000,
468             parse_hash => $_[0],
469             parse_this_ref => $__parse_this_ref,
470             start_position => $__current_position});
471             #print "completed pande\n";
472             if ($pi->{parse_succeeded}) {
473             my $n_match = $pi->{tree}->{parse_match};
474             $__updated_position = $pi->{final_position};
475             #print "succeeded returning match of $n_match\n";
476             return 1, $n_match, $__updated_position;
477             }';
478             my $sub = mctr($code, $__current_rule);
479             my $count = ++$__counts->[0]->{directive}->{$__current_rule};
480             my $latest_name = '__DIRECTIVE'.$count.'__';
481             return {name => $latest_name,
482             operation => {$latest_name => L(PF($sub),
483             ,LEAF_DISPLAY('matchrule')
484             ,RULE_INFO({rule_type => 'matchrule'}))}
485             };
486             })),
487             reject => O(qr/\/, A(qr/\
488             E( sub {
489             my $condition = $_[0]->{def_perl_code};
490             my $code;
491             if ($condition) {
492             $condition =~ s/^.//;
493             $condition =~ s/.$//;
494             $code = "($condition)?undef:1";
495             }
496             else {
497             $code = 'undef';
498             }
499             #$code = 'print "helrejlo\n"; use Data::Dumper;print "text is $text\n";'.$code;
500             my $sub = mctr($code, $__current_rule);
501             my $count = ++$__counts->[0]->{directive}->{$__current_rule};
502             my $latest_name = '__DIRECTIVE'.$count.'__';
503             #print "error is $@\n";
504             #print "ln $latest_name sub is $sub\n";
505             my $dcode = $_[0]->{def_perl_code} || '';
506             return {name => $latest_name, operation => {$latest_name => L(PF($sub),
507             LEAF_DISPLAY('reject '.$dcode)
508             ,RULE_INFO({rule_type => 'reject'})
509             )}};
510             }
511             )),
512             commit => A( qr/\/,
513             E(sub {
514             my $count = ++$__counts->[0]->{directives}->{$__current_rule};
515             my $latest_name = '__DIRECTIVE'.$count.'__';
516             $__rule_has_commit->{$__current_rule} = 1;
517             my $sub = sub {$commit = 1; return 1;};
518             return {name => $latest_name, operation => {$latest_name => L(PF($sub)
519             ,RULE_INFO({rule_type => 'commit'})
520             ,LEAF_DISPLAY('commit'))}};
521             }
522             )),
523             uncommit => A( qr/\/,
524             E(sub {
525             my $count = ++$__counts->[0]->{directives}->{$__current_rule};
526             my $latest_name = '__DIRECTIVE'.$count.'__';
527             my $sub = sub { $commit = 0; return 1;};
528             return {name => $latest_name, operation => {$latest_name => L(PF($sub)
529             ,RULE_INFO({rule_type => 'uncommit'})
530             ,LEAF_DISPLAY('uncommit'))}};
531             }
532             )),
533             leftop => A(
534             qr/\
535             {item1=>'item'},
536             qr/\s*/,
537             {item2=>'item'},
538             qr/\s*/,
539             {item3=>'item'},
540             qr/\s*\>/,
541             Z(A(qr/\(/, 'repetition_cardinality', qr/\)/)),
542             ,E(sub {
543             my $parameters = shift;
544             my $secondary = shift;
545             my $item1 = $parameters->{item1};
546             my $item2 = $parameters->{item2};
547             my $item3 = $parameters->{item3};
548             my $up_from = $parameters->{repetition_cardinality}->{low} || 0;
549             my $up_to = $parameters->{repetition_cardinality}->{high} || 0;
550             my $count = ++$__counts->[0]->{directives}->{$__current_rule};
551             my $latest_name = '__DIRECTIVE'.$count.'__';
552             my $nv;
553             my $val;
554             #print "cr $__current_rule litem 2 type is ".$item2->{item_type}."\n";
555             if ($up_to == 1) {
556             if ($up_from == 0) {
557             $val = {$latest_name => A(Z($item1->{operation}),
558             L(PF(sub {
559             my $parent = $_[0]->{parent_node};
560             my $fc = $parent->{children}->[0];
561             if ($fc->{child_count}) {
562             my $ffc = $fc->{children}->[0];
563             $parent->{parse_match} = [$ffc->{parse_match}];
564             }
565             return 1;
566             }))
567             )};
568             }
569             else {
570             $val = {$latest_name => A(M($item1->{operation},1,1),
571             L(PF(sub {
572             my $parent = $_[0]->{parent_node};
573             my $fc = $parent->{children}->[0];
574             if ($fc->{child_count}) {
575             my $ffc = $fc->{children}->[0];
576             $parent->{parse_match} = [$ffc->{parse_match}];
577             }
578             return 1;
579             }))
580             )};
581             }
582             }
583             else {
584             if ($up_to) {$up_to--};
585             if ($up_from) {$up_from--}; #fails on 0?
586             if ($item2->{item_type} eq 'mtoken' ||
587             $item2->{item_type} eq 'token' ||
588             $item2->{item_type} eq 'subrule' ||
589             $item2->{item_type} eq 'rule_name') {
590             $val = {$latest_name => A($item1->{operation},
591             M(A($item2->{operation},
592             $item3->{operation} ), $up_from, $up_to)
593             ,RULE_INFO({rule_type => 'leftop_one'})
594             , MATCH_ONCE()
595             )};
596             }
597             else {
598             $val = {$latest_name => A($item1->{operation},
599             M(A($item2->{operation},
600             $item3->{operation}), $up_from, $up_to)
601             ,RULE_INFO({rule_type => 'leftop_two'})
602             , MATCH_ONCE())};
603             }
604             }
605             #use Data::Dumper;print "leftope valpar ".Dumper($parameters)."\n";
606             #print "nv is ".Dumper($nv)."\n";
607             return {name => $latest_name, operation => $val};
608             })
609             ),
610             rightop => A( qr/\
611             {item1=>'item'},
612             qr/\s*/,
613             {item2=>'item'},
614             qr/\s*/,
615             {item3=>'item'},
616             qr/\s*\>/,
617             Z(A(qr/\(/, 'repetition_cardinality', qr/\)/)),
618             ,E(sub {
619             my $parameters = shift;
620             my $secondary = shift;
621             my $item1 = $parameters->{item1};
622             my $item2 = $parameters->{item2};
623             my $item3 = $parameters->{item3};
624             my $up_from = $parameters->{repetition_cardinality}->{low} || 0;
625             my $up_to = $parameters->{repetition_cardinality}->{high} || 0;
626             my $count = ++$__counts->[0]->{directives}->{$__current_rule};
627             my $latest_name = '__DIRECTIVE'.$count.'__';
628             my $nv;
629             my $val;
630             #print "item 2 type is ".$item2->{item_type}."\n";
631             my $rule_type;
632             if ($item2->{item_type} eq 'mtoken' ||
633             $item2->{item_type} eq 'token' ||
634             $item2->{item_type} eq 'subrule' ||
635             $item2->{item_type} eq 'rule_name') {
636             $rule_type = 'rightop_one';
637             }
638             else {
639             $rule_type = 'rightop_two';
640             }
641             if ($up_to == 1) { #?#
642             if ($up_from == 0) {
643             $val = {$latest_name => A(Z($item3->{operation}),
644             L(PF(sub {
645             my $parent = $_[0]->{parent_node};
646             my $fc = $parent->{children}->[0];
647             if ($fc->{child_count}) {
648             my $ffc = $fc->{children}->[0];
649             $parent->{parse_match} = [$ffc->{parse_match}];
650             }
651             return 1;
652             }))
653             )};
654             }
655             else {
656             $val = {$latest_name => A(M($item3->{operation},1,1),
657             L(PF(sub {
658             my $parent = $_[0]->{parent_node};
659             my $fc = $parent->{children}->[0];
660             if ($fc->{child_count}) {
661             my $ffc = $fc->{children}->[0];
662             $parent->{parse_match} = [$ffc->{parse_match}];
663             }
664             return 1;
665             }))
666             )};
667             }
668             }
669             else {
670             if ($up_to) {$up_to--};
671             if ($up_from) {$up_from--}; #fails on 1?
672             $val = {$latest_name => A(M(A($item1->{operation},
673             $item2->{operation}), $up_from, $up_to), $item3->{operation}
674             ,RULE_INFO({rule_type => $rule_type})
675             , MATCH_ONCE())};
676             }
677             #use Data::Dumper;print "rightope valpar ".Dumper($parameters)."\n";
678             #print "nv is ".Dumper($nv)."\n";
679             return {name => $latest_name, operation => $val};
680             })
681             ),
682             defer => A(qr/\
683             E( sub { my $parameters = shift;
684             $any_deferred = 1;
685             my $code = $parameters->{def_perl_code};
686             $code =~ s/^.//;
687             $code =~ s/.$//;
688             my $count = ++$__counts->[0]->{directives}->{$__current_rule};
689             my $latest_name = '__DIRECTIVE'.$count.'__';
690             my $cr = $__current_rule;
691             my $sub = mctr($code, $cr);
692             push @__package_sub_names, $sub;
693             my $leaf = {$latest_name => L(PF(sub {
694             #use Data::Dumper;print "defer params are ".Dumper(\@_);
695             my $parent_node = $_[0]->{parent_node};
696             my $stored_params = {current_position => $_[0]->{current_position},
697             parent_node => $parent_node,
698             parse_this_ref => $_[0]->{parse_this_ref}};
699             #print "storing for sub $sub\n";
700             push @__delay, {sub => $__package_subs{$sub},
701             parameters => $stored_params};
702             return 1, scalar(@__delay);}
703             ),
704             PB(sub {
705             pop @__delay;
706             return 0;
707             }
708             )
709             ,LEAF_DISPLAY('defer '.$code)
710             ,RULE_INFO({rule_type => 'deferred action'})
711             )};
712             return {name => $latest_name, operation => $leaf };
713             })),
714             def_perl_code => L(PF(
715             sub { my $parameters = shift;
716             my $in_ref = $parameters->{parse_this_ref};
717             my $pos = $parameters->{current_position};
718             my $find_code = substr($$in_ref, $pos);
719             if (my $code = Text::Balanced::extract_codeblock('<'.$find_code,'<>')) {
720             return 1, $code, $pos + length($code) - 1;
721             }
722             return 0;
723             })),
724             autotree => O(qr/\/,A(qr/\qr/\w+/},qr/\>/),
725             E( sub {$__autotree=1;
726             $__autotreeterminal = $__orig_autotreeterminal;
727             $__autotreenonterminal = $__orig_autotreenonterminal;
728             if ($_[0]->{ns}) {
729             $__autotreeterminal =~ s/XX/$ns::/;
730             $__autotreenonterminal =~ s/XX/$ns::/;
731             }
732             else {
733             $__autotreeterminal =~ s/XX//;
734             $__autotreenonterminal =~ s/XX//;
735             }
736             })),
737             initial_actions => M(A({actions => L(PF(
738             sub {my $parameters = shift;
739             my $in_ref = $parameters->{parse_this_ref};
740             my $pos = $parameters->{current_position};
741             if (substr($$in_ref, $pos, 1) eq '{') { # '}'
742             my $find_code = substr($$in_ref, $pos);
743             if (my $code = Text::Balanced::extract_codeblock($find_code)) {
744             return 1, $code, $pos + length($code);
745             }
746             }
747             return 0;
748             }))}, qr/\s*/),
749             E( sub {
750             my $actions = $_[0]->{actions};
751             my $the_code;
752             foreach my $code (@$actions) {
753             $code =~ s/^\s*.//;
754             $code =~ s/.\s*$//;
755             $the_code .= $code.";\n";
756             }
757             if ($the_code) {
758             $__package_text .= "$the_code\n\n";
759             # my $np = "package $__current_package_name;
760             # $the_code";
761             #print "np is $np\n";
762             # eval $np;
763             # my $sub = $init1a.$the_code.$init2;
764             # $sub = $the_code.';'.$init1a.$init2;
765             #print "iasub is $sub\n";
766             # my $ns = eval $sub;
767             #print "mct is $__mct\n";
768             # $__mct = &{$ns}();
769             #print "mct now is $__mct\n";
770             }
771             })),
772             action => L(PF(
773             sub {my $parameters = shift;
774             my $in_ref = $parameters->{parse_this_ref};
775             my $pos = $parameters->{current_position};
776             if (substr($$in_ref, $pos, 1) eq '{') { # '}'
777             my $find_code = substr($$in_ref, $pos);
778             if (my $code = Text::Balanced::extract_codeblock($find_code)) {
779             return 1, $code, $pos + length($code);
780             }
781             }
782             return 0;
783             }),
784             E( sub {
785             my $code = shift;
786             my $sub = mctr($code, $__current_rule);
787             my $count = ++$__counts->[0]->{actions}->{$__current_rule};
788             my $latest_name = '__ACTION'.$count.'__';
789             #print "error is $@\n";
790             #print "ln $latest_name sub is $sub\n";
791             return {name => $latest_name, operation => {$latest_name => L(PF($sub),
792             PB(sub {shift; my $parameters = shift;
793             $parameters->{parentt_node}->{parse_match} = undef}),
794             ,RULE_INFO({rule_type => 'action'})
795             ,LEAF_DISPLAY("$latest_name: $code"))}};
796             })),
797             subrule => A(qr/\(\s*/, 'rule_def', qr/\s*\)/,
798             E( sub {
799             my $new_rule = $__current_rule.':'.$__current_rule_count++;
800             #use Data::Dumper;print "new rule $new_rule def is ".Dumper($_[0]->{rule_def})."\n";
801             push @other_rules,
802             {rule_name => $new_rule,
803             rule_definition => $_[0]->{rule_def}
804             };
805             return {name => $new_rule, operation => $new_rule}
806             })),
807             def_bracket => L(PF(
808             sub { my $parameters = shift;
809             my $in_ref = $parameters->{parse_this_ref};
810             my $pos = $parameters->{current_position};
811             my $find_bracket = substr($$in_ref, $pos);
812             if (my $bracketed =
813             Text::Balanced::extract_bracketed('['.$find_bracket,'[]')) {
814             return 1, $bracketed, $pos + length($bracketed) - 1;
815             }
816             return 0;
817             })),
818             argument_list => A(qr/\[/, 'def_bracket',
819             E(sub {return $_[0]->{'def_bracket'}})),
820             item => A({the_item=>O('token', 'rule_name', 'mtoken', 'dquoted_string',
821             'squoted_string', 'action', 'look_ahead', 'leftop', 'rightop',
822             'skip', 'matchrule', 'rulevar', 'resync', 'perl_quotelike',
823             'subrule', 'reject', 'commit', 'uncommit', 'error', 'defer')},
824             Z('argument_list'),
825             Z('repetition'),
826             E(sub {my $in = shift;
827             #use Data::Dumper;print "iteminis ".Dumper($in)."\n";
828             my %to_return;
829             my ($item) = keys %{$in->{the_item}};
830             $to_return{name} = $in->{the_item}->{$item}->{name};
831             $to_return{error_text} = $in->{the_item}->{$item}->{error_text};
832             $to_return{item_type} = $item;
833             my $operation = $in->{the_item}->{$item}->{operation};
834             if ($in->{argument_list}) {
835             #print "al is ".$in->{argument_list}."\n";
836             my $code = '
837             $__subparent->{previous_arg_list} = [@arg];
838             $__subparent->{previous_arg_hash} = {%arg};
839             my $__arg_list = '.$in->{argument_list}.';
840             #use Data::Dumper;print "argument list is ".Dumper(\@arg)."\n";
841             #use Data::Dumper;print "argument hash is ".Dumper(\%arg)."\n";
842             #use Data::Dumper;print "argument list set arg to ".Dumper($__arg_list)."\n";
843             #print "sinsteps ".$__subparent->{steps}."\n";
844             @arg = @{$__arg_list};
845             if ($#arg % 2) {
846             #print "mod 2\n";
847             %arg = @arg;
848             }
849             else {
850             #print "monotd 2\n";
851             %arg = (@arg, undef);
852             }
853             #use Data::Dumper;print "arguNent list is ".Dumper(\@arg)."\n";
854             #use Data::Dumper;print "arguNent hash is ".Dumper(\%arg)."\n";
855             my $__arg_hash = {%arg};
856             $__subparent->{this_arg_list} = $__arg_list;
857             $__subparent->{this_arg_hash} = $__arg_hash;
858             $__subparent->{use_grandparent} = 1;
859             ';
860             my $sub = mctr($code, $__current_rule, 1);
861             my $pb_sub = sub {
862             #print "backtracking on pb arg\n";
863             my $__arg_list = $_[0]->{parent_node}->{previous_arg_list};
864             my $__arg_hash = $_[0]->{parent_node}->{previous_arg_hash};
865             @arg = @{$__arg_list};
866             %arg = %{$__arg_hash};
867             #use Data::Dumper;print "arguMent list is ".Dumper(\@arg)."\n";
868             #use Data::Dumper;print "arguMent hash is ".Dumper(\%arg)."\n";
869             return 0;
870             };
871             my $done_sub = sub {
872             #print "completing on p arg\n";
873             my $__arg_list = $_[0]->{parent_node}->{previous_arg_list};
874             my $__arg_hash = $_[0]->{parent_node}->{previous_arg_hash};
875             @arg = @{$__arg_list};
876             %arg = %{$__arg_hash};
877             #use Data::Dumper;print "argulMent list is ".Dumper(\@arg)."\n";
878             #use Data::Dumper;print "argulMent hash is ".Dumper(\%arg)."\n";
879             my $value_to_return =
880             $_[0]->{parent_node}->{children}->[1]->{parse_match};
881             $_[0]->{parent_node}->{parse_match} = $value_to_return;
882             return 1;
883             };
884             my $done_pb_sub = sub {
885             #print "completing but backing on pb arg\n";
886             my $__arg_list = $_[0]->{parent_node}->{this_arg_list};
887             my $__arg_hash = $_[0]->{parent_node}->{this_arg_hash};
888             @arg = @{$__arg_list};
889             %arg = %{$__arg_hash};
890             #use Data::Dumper;print "arguxMent list is ".Dumper(\@arg)."\n";
891             #use Data::Dumper;print "arguxMent hash is ".Dumper(\%arg)."\n";
892             return 0;
893             };
894             $operation = A(L(PF($sub), PB($pb_sub)), $operation,
895             L(PF($done_sub), PB($done_pb_sub)));
896             }
897             if (defined $in->{repetition}) {
898             $to_return{name} .= $in->{repetition}->{name_extra};
899             $to_return{item_type} = 'leftop';
900             my $up_from = $in->{repetition}->{cardinality}->{low} || 0;
901             my $up_to = $in->{repetition}->{cardinality}->{high} || 0;
902             if ((my $separator = $in->{repetition}->{separator})
903             && ($up_to != 1)) {
904             if ($up_to) {
905             $up_to--;
906             }
907             if ($up_from) {
908             $to_return{operation} = {$to_return{name} => A($operation,
909             M(A($separator->{operation}, $operation),
910             $up_from-1, $up_to)
911             ,RULE_INFO({ rule_type => 'straight_separator'})
912             , MATCH_ONCE())};
913             }
914             else {
915             $to_return{operation} = {$to_return{name} => Z(A($operation,
916             M(A($separator->{operation}, $operation),
917             0, $up_to))
918             ,RULE_INFO({rule_type => 'straight_z_separator'})
919             , MATCH_ONCE())};
920             }
921             }
922             else {
923             #print "has repetition ptgp\n";
924             $to_return{operation} = {$to_return{name} =>
925             M($operation, $up_from, $up_to
926             ,RULE_INFO({rule_type => 'straight'})
927             , MATCH_ONCE())};
928             }
929             }
930             else {
931             $to_return{operation} = $operation;
932             }
933             #use Data::Dumper;print "item $item itemin is ".Dumper($in)."\n";
934             #use Data::Dumper;print "toreturning ".Dumper(\%to_return)."\n";
935             return \%to_return;
936             })),
937             look_ahead => A(qr/\.\.\./, Z({not=>qr/\!/}), 'item',
938             E(sub {
939             #use Data::Dumper;print "lookahed e val parms are ".Dumper(\@_)."\n";
940             my $item = $_[0]->{item};
941             my $new_rule;
942             if (ref $item->{operation} eq '') {
943             $new_rule = $item->{operation};
944             }
945             else {
946             $new_rule = $__current_rule.':'.$__current_rule_count++;
947             push @other_rules,
948             {rule_name => $new_rule,
949             rule_definition => [[$item]]
950             };
951             }
952             #print "name set up is $new_rule\n";
953             #use Data::Dumper;print "other rules now ".Dumper(\@other_rules)."\n";
954             my $la_sub;
955             if ($_[0]->{not}) {
956             $la_sub = sub {
957             #use Data::Dumper;print "la parms (not) are ".Dumper(\@_)."\n";
958             my $current_position = $_[0]->{current_position};
959             #print "new rule of la is $new_rule p $parser rt is $remaining_text\n";
960             my $pi = {};
961             #use Data::Dumper;print Dumper($__thisparser);exit;
962             my $result = $_[0]->{the_parser}->parse_and_evaluate(
963             undef,
964             {start_rule=> $new_rule, parse_info => $pi,
965             max_steps => $__max_steps || 1000000,
966             parse_this_ref => $_[0]->{parse_this_ref},
967             parse_hash => $_[0],
968             start_position => $current_position});
969             #use Data::Dumper;print "pi is ".Dumper($pi)."\n";
970             if ($pi->{parse_succeeded}) {
971             return 0;
972             }
973             else {
974             return 1, $pi->{tree}->{parse_match};
975             }
976             };
977             }
978             else {
979             $la_sub = sub {
980             my $ref = $_[0]->{parse_this_ref};
981             my $current_position = $_[0]->{current_position};
982             #use Data::Dumper;print "la parms (not) are ".Dumper(\@_)."\n";
983             # my $parser = $_[0]->{parser};
984             my $pi = {};
985             my $result = $_[0]->{the_parser}->parse_and_evaluate(
986             undef,
987             {start_rule=> $new_rule, parse_info => $pi,
988             max_steps => $__max_steps || 1000000,
989             parse_hash => $_[0],
990             parse_this_ref => $_[0]->{parse_this_ref},
991             start_position => $current_position});
992             #use Data::Dumper;print "pinow is ".Dumper($pi)."\n";
993             if ($pi->{parse_succeeded}) {
994             return 1, $pi->{tree}->{parse_match};
995             }
996             else {
997             return 0;
998             }
999             };
1000             }
1001             return {name => $item->{name}, operation => {$item->{name} => L(
1002             PF($la_sub),
1003             LEAF_DISPLAY('look ahead on:'.$item->{name})
1004             ,RULE_INFO({ rule_type => 'look_ahead'})
1005             )}};
1006             }
1007             )),
1008             perl_quotelike => L(qr/\/,
1009             E( sub {
1010             my $code = '
1011             my $s = substr($$__parse_this_ref, $__current_position);
1012             my ($m, $text, undef, @res) =
1013             Text::Balanced::extract_quotelike($s, $skip);
1014             $__updated_position = $__current_position + length($m);
1015             $m ? \@res : undef;
1016             ';
1017             my $sub = mctr($code, $__current_rule);
1018             my $count = ++$__counts->[0]->{directive}->{$__current_rule};
1019             my $latest_name = '__DIRECTIVE'.$count.'__';
1020             return {name => $latest_name,
1021             operation => {$latest_name => L(PF($sub),
1022             LEAF_DISPLAY('
1023             ,RULE_INFO({rule_type => 'perl_quotelike'}))}
1024             ,error_text => ''};
1025             })),
1026             skip => L(qr/(\]*)?\>)/, E( sub {
1027             my $skip_string = shift;
1028             $skip_string =~ qr/(\]*)?\>)/;
1029             my $the_skip = $2;
1030             my $count = ++$__counts->[0]->{directives}->{$__current_rule};
1031             my $latest_name = '__DIRECTIVE'.$count.'__';
1032             my $code = 'my $to_match = '.$the_skip.';
1033             my $previous = $__skip[0];
1034             $skip = qr/$to_match/;
1035             $__skip[0] = $skip;
1036             pos $$__parse_this_ref = $__current_position;
1037             $previous;
1038             ';
1039             my $sub = mctr($code, $__current_rule);
1040             my $subb = sub {
1041             # my $current_node = $_[0]->{current_node};
1042             my $parse_match = $_[0]->{parse_match};
1043             $__skip[0] = $parse_match;
1044             $skip = $parse_match;
1045             #print "skip nnow $skip\n";
1046             return;
1047             };
1048             return {name => $latest_name, operation => {$latest_name =>
1049             L(PF($sub),PB($subb),
1050             ,RULE_INFO({rule_type => 'skip directive'}),
1051             LEAF_DISPLAY("skip to be $the_skip"))}};
1052             })),
1053             error => L(qr/(\]*)?\>)/, E( sub {
1054             my $error_string = shift;
1055             my $parameters = shift;
1056             $error_string =~ /\]*))?\>/;
1057             my $only_on_commit = $1;
1058             my $message = $3;
1059             my $the_rule = $__current_rule;
1060             $__rule_has_error->{$__current_rule} = 1;
1061             my $the_message = $message || '';
1062             return {name => 'error', operation => {'error' => L(PF(
1063             sub {
1064             my $parameters = shift;
1065             my $parent_node = $parameters->{parent_node};
1066             my $grand_parent = $parent_node->{parent};
1067             my $great_grand_parent = $grand_parent->{parent};
1068             if ($only_on_commit && !$commit) {
1069             return 1;
1070             }
1071             my $error_message;
1072             $__parse_this_ref = $parameters->{parse_this_ref};
1073             $__previous_position = $parameters->{current_position}; #sets $thisline
1074             my $error_start .=
1075             " ERROR (line $thisline): ";
1076             $error_message .=
1077             " ERROR (line $thisline): Invalid $the_rule: Was expecting ";
1078             if (defined $grand_parent->{first_max}) {
1079             $error_message .= $grand_parent->{first_max};
1080             my $fat = $grand_parent->{first_max_at};
1081             my $remaining_text = substr(${$parameters->{parse_this_ref}}, $fat);
1082             $remaining_text =~ s/^$skip//;
1083             if (length($remaining_text) > 0) {
1084             $error_message .= " but found \"$remaining_text\" instead";
1085             }
1086             else {
1087             $error_message .= " not found";
1088             }
1089             }
1090             else {
1091             my @productions = @{$grand_parent->{productions}};
1092             pop @productions;
1093             $error_message .= join (", or ",@productions);
1094             }
1095             if ($message) {
1096             #print "using $error_start and $message\n";
1097             unshift @{$great_grand_parent->{error_messages}}, $error_start.$message;
1098             }
1099             else {
1100             #print "using $error_message only \n";
1101             unshift @{$great_grand_parent->{error_messages}}, $error_message;
1102             }
1103             return 0;
1104             })
1105             ,RULE_INFO({rule_type => 'error directive'})
1106             , LEAF_DISPLAY("error $the_message"))}};
1107             })),
1108             set_rule_name => A('rule_name', E(sub {
1109             $__current_rule = $_[0]->{rule_name}->{name};
1110             return $__current_rule;
1111             })),
1112             rule_name => L(qr/\w+/,
1113             E(sub {
1114             #use Data::Dumper;print "rulnam ".Dumper(\@_);
1115             my $rule_name = $_[0];
1116             return {name => $_[0], operation => {$_[0] => $_[0]}};
1117             })),
1118             mtoken => O(qr/m(\([^()]*\))[cgimsox]*/, qr/m(\{[^{}]*\})[cgimsox]*/,
1119             qr/m(\#[^#]*\#)[cgimsox]*/,
1120             qr/m(\|[^|]*\|)[cgimsox]*/,
1121             #should really use extract_quotelike
1122             E(sub {my $token = $_[0]->{''};
1123             #use Data::Dumper;print "got mttok ".Dumper($token)."\n";
1124             my $count = ++$__counts->[0]->{patterns}->{$__current_rule};
1125             my $latest_name = '__PATTERN'.$count.'__';
1126             my $et = $token;
1127             substr($token, 1, 0) = '\G';
1128             my $regex = eval 'qr'.$token;
1129             if ($@) {croak "Unable to handle mtoken $token\n"}
1130             my $sub = sub {
1131             my $current_position = $_[0]->{current_position};
1132             my $inref = $_[0]->{parse_this_ref};
1133             pos $$inref = $current_position;
1134             $$inref =~ /\G$skip/cg;
1135             if ($$inref =~ /($regex)/cg) {
1136             my $to_match = $1;
1137             #print "to match is $to_match\n";
1138             return 1, $to_match, pos $$inref;
1139             }
1140             #print "did not match on $regex at ".$_[0]->{current_position}."\n";
1141             return 0;
1142             };
1143             return {name => $latest_name,
1144             operation => {$latest_name => L(PF($sub),LEAF_DISPLAY($et)
1145             ,RULE_INFO({rule_type => 'mtoken'}))}
1146             ,error_text => $et};
1147             })),
1148             token => L(qr{\G\s*(/(\\\/|[^/])*/([cgimsox]*))}s,
1149             E(sub {my $token = shift;
1150             #print "got t $token\n";
1151             my $count = ++$__counts->[0]->{patterns}->{$__current_rule};
1152             my $latest_name = '__PATTERN'.$count.'__';
1153             my $et = $token;
1154             substr($token, 1, 0) = '\G(';
1155             $token =~ s-(.*)\/-$1)/-s;
1156             #print "have t $token\n";
1157             my $regex = eval 'qr'.$token;
1158             if ($@) {croak "unable to handle token $token\n"}
1159             #print "regex is $regex\n";
1160             my $sub = sub {
1161             my $current_position = $_[0]->{current_position};
1162             my $inref = $_[0]->{parse_this_ref};
1163             pos $$inref = $current_position;
1164             $$inref =~ /\G$skip/cg;
1165             if ($$inref =~ /($regex)/cg) {
1166             my $to_match = $1;
1167             #print "tto match is $to_match\n";
1168             return 1, $to_match, pos $$inref;
1169             }
1170             #print "tdid not match on $regex at ".$_[0]->{current_position}."\n";
1171             return 0;
1172             };
1173             return {name => $latest_name,
1174             operation => {$latest_name => L(PF($sub),LEAF_DISPLAY($et)
1175             ,RULE_INFO({rule_type => 'token'}))}
1176             ,error_text => $et};
1177             })),
1178             dquoted_string => L(qr/\"[^"]*\"/,
1179             E( sub {
1180             #use Data::Dumper;print "dqparamas are ".Dumper(\@_)."\n";
1181             my $qs = shift;
1182             my $code = '
1183             my $to_match = '.$qs.';
1184             my $l = length($to_match);
1185             my $result;
1186             pos $$__parse_this_ref = $__current_position;
1187             $$__parse_this_ref =~ /\G$skip/cg;
1188             my $current_position = pos $$__parse_this_ref;
1189             if (substr($$__parse_this_ref, $current_position, $l)
1190             eq $to_match) {
1191             $__updated_position = $current_position + $l;
1192             $result = $to_match;
1193             }
1194             $result;
1195             ';
1196             my $sub = mctr($code, $__current_rule);
1197             my $count = ++$__counts->[0]->{strings}->{$__current_rule};
1198             my $latest_name = '__STRING'.$count.'__';
1199             #print "dqerror is $@\n";
1200             #print "ln $latest_name sub is $sub\n";
1201             return {name => $latest_name,
1202             operation => {$latest_name => L(PF($sub),LEAF_DISPLAY('"'.$qs.'"')
1203             ,RULE_INFO({rule_type => 'dquote'}))}
1204             ,error_text => '"'.$qs.'"'};
1205             })),
1206             squoted_string => L(qr/\'[^']*\'/,
1207             E( sub {
1208             #use Data::Dumper;print "sqparamas are ".Dumper(\@_)."\n";
1209             my $qs = shift;
1210             my $to_match = substr($qs, 1, -1);
1211             my $l = length($to_match);
1212             # my $rule_name = $__current_rule;
1213             my $sub = sub {
1214             #delete $_[0]->{parser};use Data::Dumper;print "sqtode in ".Dumper(\@_)."\n";
1215             my $inref = $_[0]->{parse_this_ref};
1216             my $current_position = $_[0]->{current_position};
1217             pos $$inref = $current_position;
1218             #print "check squote 1cp $current_position\n";
1219             $$inref =~ /\G$skip/cg;
1220             $current_position = pos $$inref;
1221             #print "check squote cp $current_position and l is $l and tm $to_match\n";
1222             if (substr($$inref, $current_position, $l)
1223             eq $to_match) {
1224             return 1, $to_match, $current_position + $l;
1225             }
1226             #print "returning no match\n";
1227             return 0;
1228             };
1229             my $count = ++$__counts->[0]->{strings}->{$__current_rule};
1230             my $latest_name = '__STRING'.$count.'__';
1231             #print "sqerror is $@\n";
1232             #print "ln $latest_name sub is $sub\n";
1233             return {name => $latest_name,
1234             operation => {$latest_name => L(PF($sub),LEAF_DISPLAY($qs)
1235             ,RULE_INFO({rule_type => 'squote'}))}
1236             ,error_text => $qs};
1237             })),
1238             repetition => A(qr/\(/, 'repetition_cardinality', Z(A(qr/\s\s*/,
1239             {separator => 'item'})), qr/\)/, E(
1240             sub {my $in = shift;
1241             #use Data::Dumper;print "rep in is ".Dumper($in);
1242             my $others = shift;
1243             my $current_node = $others->{current_node};
1244             #use Data::Dumper; print "others is ".Dumper($others)."\n";
1245             my $string_match = substr(${$others->{parse_this_ref}},
1246             $current_node->{position_when_entered},
1247             ($current_node->{position_when_completed} -
1248             $current_node->{position_when_entered}));
1249             # my $name_extra = '('. $string_match.')';
1250             my $rx = '';
1251             return {separator => $in->{separator},
1252             cardinality => $in->{repetition_cardinality},
1253             name_extra => $string_match};
1254             })),
1255             repetition_cardinality => O({'qm'=>qr/\?/}, {'sqm' => qr/s\?/},
1256             {'s'=>qr/s/}, {'nm'=>qr/((\d+)\.\.(\d+))/}, {'m0' => qr/(\.\.(\d+))/},
1257             {'n0'=> qr/((\d+)\.\.)/},{'nn'=>qr/(\d+)/}, E(
1258             sub {
1259             my $in = shift;
1260             #use Data::Dumper;print "rp is ".Dumper(\$in)."\n";
1261             if ($in->{qm}) {
1262             return {low=> 0, high => 1}
1263             }
1264             if ($in->{sqm}) {
1265             return {low=> 0, high => 0}
1266             }
1267             if ($in->{s}) {
1268             return {low=> 1, high => 0}
1269             }
1270             if (defined $in->{nm}) {
1271             my ($low, $high);
1272             $in->{nm} =~ /(\d+)\.\.(\d+)/;
1273             if ($1 > $2) {
1274             $low = $2;
1275             $high = $1;
1276             }
1277             else {
1278             $low = $1;
1279             $high = $2;
1280             }
1281             #print "low is $low and high is $high\n";
1282             return {low=> $low, high => $high}
1283             }
1284             if (defined $in->{m0}) {
1285             $in->{m0} =~ /\.\.(\d+)/;
1286             return {low=> 1, high => $1}
1287             }
1288             if (defined $in->{n0}) {
1289             $in->{n0} =~ /(\d+)\.\./;
1290             return {low=> $1, high => 0}
1291             }
1292             if (defined $in->{nn}) {
1293             $in->{nn} =~ /(\d+)/;
1294             return {low=> $1, high => $1}
1295             }
1296             })),
1297             );
1298              
1299             our $rd_parser = new Parse::Stallion(\%rd_rules);
1300             #use Data::Dumper;print Dumper($rd_parser)."\nis rd parser\n";
1301              
1302              
1303             sub pre_production {
1304 0     0 0   my $parameters = shift;
1305 0           my $error_text = $parameters->{error_text};
1306 0           my $name = $parameters->{name};
1307             my $pf_sub = sub {
1308 0     0     my $parameters = shift;
1309 0           my $parent_node = $parameters->{parent_node};
1310 0           my $grand_parent = $parent_node->{parent};
1311 0           push @{$grand_parent->{productions}}, $error_text;
  0            
1312 0           return 1;
1313 0           };
1314 0           return L(PF($pf_sub),LEAF_DISPLAY("pre rule name $name and et $error_text"));
1315             }
1316              
1317             sub skipsub {
1318 0     0 0   my $parameters = shift;
1319 0           my $node_name = $parameters->{node_name};
1320 0           my $error_text = $parameters->{error_text};
1321             my $pf_sub = sub {
1322             #delete $_[0]->{parser};use Data::Dumper;print "skipsub pfparameters are ".Dumper(\@_)."\n";
1323 0     0     my $parameters = shift;
1324 0           my $parent_node = $parameters->{parent_node};
1325 0           my $previous_node =
1326 0           $parent_node->{children}->[$#{$parent_node->{children}}];
1327 0           my $previous_node_value = $previous_node->{parse_match};
1328             #use Data::Dumper;print "in skipsub pnv is ".Dumper($previous_node_value)."\n";
1329             #print " skipsubnode name $node_name and et $error_text\n";
1330 0           my $current_value;
1331 0           return 1, $current_value;
1332 0           };
1333             my $pb_sub = sub {
1334 0     0     my $parameters = shift;
1335 0           my $parent_node = $parameters->{parent_node};
1336 0           my $grand_parent = $parent_node->{parent};
1337 0 0         if (!(defined $grand_parent->{first_max})) {
1338 0           $grand_parent->{first_max} = $error_text;
1339 0           $grand_parent->{first_max_at} = $parameters->{current_position};
1340             }
1341 0           return;
1342 0           };
1343 0   0       $error_text = $error_text || '';
1344 0           return {'' => L(PF($pf_sub), PB($pb_sub),
1345             LEAF_DISPLAY("skip $node_name followed by $error_text"))};
1346             }
1347              
1348             sub error_name {
1349 0     0 0   return s/\_/ /g;
1350             }
1351              
1352             sub __rd_new {
1353 0     0     my $type = shift;
1354 0           my $rules_string = shift;
1355 0           my $trace = shift;
1356             #print "rule string is $rules_string\n";
1357 0           my @pt;
1358 0           my $parse_info = {};
1359 0           my $rules_out;
1360 0           $__autotree = 0;
1361 0           $__replace_mode = 0;
1362 0           $__replace_level = 0;
1363 0           %__max_replace=();
1364 0           $__current_package_name = 'rd_package_'.$__current_package_number++;
1365 0           $__package_text = "{
1366             our \@arg;
1367             our \%arg;
1368             *arg = *Parse::Stallion::RD::arg;
1369             ";
1370 0           @__package_list = ();
1371 0           %__rulevar = ();
1372 0           @other_rules = ();
1373 0           $any_deferred = 0;
1374 0 0         if ($trace) {
1375 0           my $rules_out = eval {$rd_parser->parse_and_evaluate(
  0            
1376             $rules_string, {parse_info=>$parse_info
1377             , parse_trace => \@pt, no_evaluation => 1
1378             }
1379             )};
1380 2     2   2617 use Data::Dumper;print " pt ".Dumper(\@pt);
  2         15032  
  2         265  
  0            
1381 0 0         if ($@) {
1382 2     2   21 use Data::Dumper;print "$@ tracefailurefailure pt ".Dumper(\@pt);
  2         4  
  2         241  
  0            
1383             }
1384             }
1385             else {
1386 0           $rules_out = eval {$rd_parser->parse_and_evaluate(
  0            
1387             $rules_string, {parse_info=>$parse_info, no_evaluation => 1
1388             # , parse_trace => \@pt
1389             }
1390             )};
1391 0 0         if ($@) {
1392 2     2   13 use Data::Dumper;print "$@ failurefailure pt ".Dumper(\@pt);
  2         3  
  2         5487  
  0            
1393             }
1394             }
1395             #use Data::Dumper;print "pqt is ".Dumper(\@pt)."\n";
1396             #delete $parse_info->{bottom_up_left_to_right};
1397             #use Data::Dumper;print "pi is ".Dumper($parse_info)."\n";
1398             # if ($@) {croak "\nUnable to create parser due to the following:\n$@\n"};
1399 0 0         if (!$parse_info->{parse_succeeded}) {
1400 0           my ($max_line, $max_line_position) =
1401             LOCATION(\$rules_string, $parse_info->{maximum_position});
1402 0           croak(
1403             "Unable to parse beyond line $max_line, position: $max_line_position");
1404             }
1405             #use Data::Dumper;print "ro is ".Dumper($rules_out)."\n";
1406 0           my %raw_rules;
1407 0           foreach my $rule (@$rules_out, @other_rules) {
1408 0           my $rule_name = $rule->{rule_name};
1409 0 0 0       if (!((defined $__max_replace{$rule_name}) &&
1410             ($rule->{replace_level} < $__max_replace{$rule_name}))) {
1411 0           push @{$raw_rules{$rule_name}}, @{$rule->{rule_definition}};
  0            
  0            
1412             }
1413             }
1414 0           my %other_rule;
1415 0           foreach my $rule (@other_rules) {
1416 0           $other_rule{$rule->{rule_name}}=1;
1417             }
1418 0           my %rule_productions;
1419             my $some_rule;
1420 0           foreach my $rule (keys %raw_rules) {
1421             #print "rule is $rule\n";
1422 0           $some_rule = $rule;
1423 0           my @o_args;
1424             my $single_o_arg;
1425 0           my $single_operation;
1426 0           my $not_first_production = 0;
1427 0           my $item_count;
1428 0           PRODUCTION: foreach my $production (@{$raw_rules{$rule}}) {
  0            
1429 0 0         if ($production->[0]->{item_type} eq 'rulevar') {
1430 0           next PRODUCTION;
1431             }
1432 0 0 0       if ($::RD_AUTOACTION &&
  0 0 0        
1433             # !$other_rule{$rule} &&
1434 0           ($production->[$#{$production}]->{item_type} ne 'action')) {
1435 0           my $sub = mctr($::RD_AUTOACTION, $rule);
1436 0           my $count = ++$__counts->[0]->{actions}->{$rule};
1437 0           my $latest_name = '__ACTION'.$count.'__';
1438 0           push @{$production}, {item_type => 'action', name => $latest_name,
  0            
1439             operation => {$latest_name => L(PF($sub),
1440             LEAF_DISPLAY($::RD_AUTOACTION)
1441             ,RULE_INFO({rule_type => 'action'})
1442             )}};
1443             }
1444             elsif ($__autotree &&
1445             ($production->[$#{$production}]->{item_type} ne 'action')) {
1446 0 0 0       if (($#{$production} == 0) && (
  0   0        
1447             ($production->[0]->{item_type} eq 'mtoken') ||
1448             ($production->[0]->{item_type} eq 'token') ||
1449             ($production->[0]->{item_type} eq 'squoted_string') ||
1450             ($production->[0]->{item_type} eq 'dquoted_string')
1451             )) {
1452 0           my $sub = mctr($__autotreeterminal, $rule);
1453 0           my $count = ++$__counts->[0]->{actions}->{$rule};
1454 0           my $latest_name = '__ACTION'.$count.'__';
1455 0           push @{$production}, {item_type => 'action', name => $latest_name,
  0            
1456             operation => {$latest_name => L(PF($sub),
1457             LEAF_DISPLAY($__autotreeterminal)
1458             ,RULE_INFO({rule_type => 'action'})
1459             )}};
1460             }
1461             else {
1462 0           my $sub = mctr($__autotreenonterminal, $rule);
1463 0           my $count = ++$__counts->[0]->{actions}->{$rule};
1464 0           my $latest_name = '__ACTION'.$count.'__';
1465 0           push @{$production}, {item_type => 'action', name => $latest_name,
  0            
1466             operation => {$latest_name => L(PF($sub),
1467             LEAF_DISPLAY($__autotreenonterminal)
1468             ,RULE_INFO({rule_type => 'action'})
1469             )}};
1470             }
1471             }
1472 0           my @a_args;
1473 0           $item_count = scalar @{$production};
  0            
1474 0           foreach my $i (0..$#{$production}-1) {
  0            
1475 0           my $item = $production->[$i];
1476 0           push @a_args, $item->{operation};
1477 0 0         if ($__rule_has_error->{$rule}) {
1478 0           my $next_item = $production->[$i+1];
1479 0           my $error_text;
1480 0 0         if (defined $next_item->{error_text}) {
1481 0           $error_text = $next_item->{error_text};
1482             }
1483             else {
1484 0           $error_text = $next_item->{name};
1485 0           $error_text =~ s/\_/ /g;
1486             }
1487 0           push @a_args, skipsub({node_name=>$item->{name},
1488             error_text => $error_text});
1489             }
1490             }
1491 0           my $last_item = $production->[$#{$production}];
  0            
1492             #use Data::Dumper; print "last item is ".Dumper($last_item)."\n";
1493 0 0 0       if ($last_item->{item_type} eq 'token' ||
      0        
1494             $last_item->{item_type} eq 'squoted_string' ||
1495             # $last_item->{item_type} eq 'rule_name' ||
1496             $last_item->{item_type} eq 'mtoken') {
1497 0           ($single_operation) = values %{$last_item->{operation}};
  0            
1498             }
1499 0           push @a_args, $last_item->{operation};
1500             # if ($__rule_has_error->{$rule}) {
1501             # push @a_args, skipsub({node_name=>$last_item->{name}});
1502             # }
1503 0           my $first_item = $production->[0];
1504 0   0       unshift @a_args,
1505             pre_production({error_text => $first_item->{error_text} ||
1506             $first_item->{name}, name => $rule});
1507 0 0 0       if ($__rule_has_commit->{$rule} && $first_item->{item_type} ne 'error' &&
      0        
      0        
1508             $first_item->{item_type} ne 'uncommit' && $not_first_production) {
1509 0           unshift @a_args, $__check_commit;
1510             }
1511 0           push @o_args, A(@a_args, MATCH_ONCE());
1512 0           $single_o_arg = A(@a_args, $move_to_parent,
1513             RULE_INFO({rule_type => 'rule'}), MATCH_ONCE());
1514 0           $not_first_production = 1;
1515             }
1516 0 0         if ($#o_args > 0) {
1517 0           $rule_productions{$rule} = A($__start_rule, O(@o_args),
1518             $__end_rule, RULE_INFO({rule_type => 'rule'}),
1519             MATCH_ONCE());
1520             }
1521             else {
1522 0 0 0       if ($single_operation && $item_count == 1 && !($other_rule{$rule})) {
      0        
1523 0           $rule_productions{$rule} = $single_operation;
1524             }
1525             else {
1526 0           $rule_productions{$rule} = $single_o_arg;
1527             }
1528             }
1529             }
1530             #use Data::Dumper;print "therules is ".Dumper(\%rule_productions)."\n";
1531 0     0     my $new_parser = eval {new Parse::Stallion(\%rule_productions,
  0            
1532             {separator => '.', final_position_routine => sub {return $_[1]},
1533 0           traversal_only => 1, fast_move_back => !$any_deferred,
1534             unreachable_rules_allowed => 1}
1535             )};
1536 0 0         if ($@ =~ /No valid start rule/) {
1537 0     0     $new_parser = eval {new Parse::Stallion(\%rule_productions,
  0            
1538             {separator => '.', final_position_routine => sub {return $_[1]},
1539 0           traversal_only => 1, fast_move_back => !$any_deferred,
1540             start_rule => $some_rule,
1541             unreachable_rules_allowed => 1}
1542             )};
1543             }
1544 0 0         if ($@) {print "errff $@";croak $@}
  0            
  0            
1545 0           $__package_text .= join("", @__package_list).'}';
1546 0           foreach my $rule (keys %__rulevar) {
1547 0           $__package_text =~ s/\#SPE_CIAL $rule SPEC_IAL/$__rulevar{$rule}/g;
1548             #print "after $rule package_text now $__package_text\n";
1549             }
1550             #print "pt is $__package_text\n";
1551 0           eval $__package_text; #for lexicals in the name space to work
1552 0 0         if ($@) {print "package text error $@"; croak $@}
  0            
  0            
1553 0           my $parser_rules = $new_parser->{rule};
1554 0           foreach my $parse_rule_key (keys %{$parser_rules}) {
  0            
1555 0           my $parse_rule = $parser_rules->{$parse_rule_key};
1556             #use Data::Dumper;print "looking at ".Dumper($parse_rule)."\n";
1557 0 0         if (defined $parse_rule->{parse_forward}) {
1558 0 0         if ($__package_temp_names{$parse_rule->{parse_forward}}) {
1559 0           my $new_sub = "\\\&".
1560             $__package_temp_names{$parse_rule->{parse_forward}};
1561             #print "new sub is $new_sub\n";
1562 0           $parse_rule->{parse_forward} =
1563             eval $new_sub;
1564 0 0         if ($@) {print "error on ptm $@";croak $@};
  0            
  0            
1565             #print "updated pf\n";
1566             }
1567             }
1568             }
1569             #print "count delay\n";
1570 0           while (my $subname = pop @__package_sub_names) {
1571 0           my $new_sub = "\\\&". $__package_temp_names{$subname};
1572             #print "nsp is $new_sub\n";
1573 0           $__package_subs{$subname} = eval $new_sub;
1574 0 0         if ($@) {print "deneror on ptm $@";croak $@};
  0            
  0            
1575             }
1576             #use Parse::Stallion::EBNF;
1577             #print ebnf Parse::Stallion::EBNF($new_parser)."\n";
1578 0           return $new_parser;
1579             }
1580              
1581             sub new {
1582 0     0 0   my $type = shift;
1583 0           my $grammar = shift;
1584 0           my $trace = shift;
1585 0   0       my $class = ref($type) || $type;
1586 0           my $parsing_info = {};
1587 0           $parsing_info->{parser} = __rd_new($type, $grammar, $trace);
1588 0           $parsing_info->{grammar_text} = $grammar;
1589 0           $parsing_info->{namespace} = "Parse::Stallion::RD";
1590 0           return bless $parsing_info, $class;
1591             }
1592              
1593             sub Extend {
1594 0     0 0   my $self = shift;
1595 0           my $string = shift;
1596 0           my $current_grammar = $self->{grammar_text} .= "\n\n$string\n";
1597             #print "doing extend on $current_grammar\n";
1598 0           my $new_parser = __rd_new($self, $current_grammar);
1599 0           foreach my $npk (keys %{$new_parser}) {
  0            
1600 0 0         if (ref $new_parser->{$npk} eq 'HASH') {
1601 0           foreach my $npkk (keys %{$new_parser->{$npk}}) {
  0            
1602 0           $self->{parser}->{$npk}->{$npkk} = $new_parser->{$npk}->{$npkk};
1603             }
1604             }
1605             else {
1606 0           $self->{parser}->{$npk} = $new_parser->{$npk};
1607             }
1608             }
1609             #print "finished extend\n";
1610             }
1611              
1612             sub EBNF {
1613 0     0 0   my $self = shift;
1614 2     2   1746 use Parse::Stallion::EBNF;
  2         8  
  2         2322  
1615 0           my $out = ebnf Parse::Stallion::EBNF $self->{parser};
1616 0           return $out;
1617             }
1618              
1619             sub AUTOLOAD {
1620 0     0     our $AUTOLOAD;
1621 0           my $self = shift;
1622 0           my $string = shift;
1623 0           my $starting_line_number = shift; #ignored for now
1624 0           my @previous_arg = @arg;
1625 0           my %previous_arg = %arg;
1626 0           @arg = @_;
1627 0 0         if ($#arg % 2) {
1628             #print "imod 2\n";
1629 0           %arg = @arg;
1630             }
1631             else {
1632             #print "imonotd 2\n";
1633 0           %arg = (@arg, undef);
1634             }
1635 0           my $reference;
1636 0 0         if (ref $string) {
1637 0           $reference = $string;
1638 0           $string = $$string;
1639             }
1640 0           my $start_position = pos $string;
1641 0           my @previous_skip = @__skip;
1642 0           @__skip=();
1643 0           my $previous_default_skip = $__default_skip;
1644 0           push @__skip, $__default_skip = $skip;
1645 0           my $previous_error_message = $__error_message;
1646 0           $__error_message = '';
1647 0           my $start_rule = $AUTOLOAD;
1648             #print "start rule is $start_rule\n";
1649             #print "found mct\n";
1650 0           my @previous_delay = @__delay;
1651 0           my $previous_rule_has_commit = $__rule_has_commit;
1652 0           my $previous_rule_has_error = $__rule_has_error;
1653 0           @__delay = ();
1654 0           $__rule_has_commit = {};
1655 0           $__rule_has_error = {};
1656 0           $start_rule =~ s/.*:://;
1657 0           my $previous_commit = $commit;
1658 0           $commit = 0;
1659 0           my $previous_parser = $__thisparser;
1660 0           $__thisparser = $self;
1661             #print "tpsslf set to $__thisparser\n";
1662 0           my $pi = {};
1663             #print "String is $string\n";
1664 0           my @pt;
1665             my $results;
1666 0           my $previous_rule_info = $__rule_info;
1667 0           my $previous_parse_this_ref = $__parse_this_ref;
1668 0           $__rule_info = $self->{parser}->rule_info_hash_ref;
1669 0 0         if ($__trace) {
1670 0   0       eval {$results = $self->{parser}->parse_and_evaluate($string,
  0            
1671             {start_rule => $start_rule, parse_info => $pi
1672             ,max_steps => $__max_steps || 1000000
1673             , start_position => $start_position
1674             ,parse_hash =>
1675             {
1676             the_parser => $self->{parser}
1677             }
1678             , parse_trace=>\@pt
1679             });
1680 0           foreach my $action (@__delay) {
1681 0           &{$action->{sub}}($action->{parameters});
  0            
1682             }
1683             };
1684             #use Data::Dumper; print "bigtracept ".Dumper(\@pt)."\n";
1685             }
1686             else {
1687 0   0       eval {$results = $self->{parser}->parse_and_evaluate($string,
  0            
1688             {start_rule => $start_rule, parse_info => $pi
1689             ,parse_hash =>
1690             {
1691             the_parser => $self->{parser}
1692             }
1693             ,max_steps => $__max_steps || 1000000
1694             , start_position => $start_position
1695             # , parse_trace=>\@pt
1696             });
1697             #print "done with er\n";
1698 0           foreach my $action (@__delay) {
1699 0           &{$action->{sub}}($action->{parameters});
  0            
1700             }
1701             };
1702             }
1703 0           $__thisparser = $previous_parser;
1704 0           @arg = @previous_arg;
1705 0           %arg = %previous_arg;
1706 0           @__skip = @previous_skip;
1707 0           @__delay = @previous_delay;
1708 0           $__rule_has_commit = $previous_rule_has_commit;
1709 0           $__rule_has_error = $previous_rule_has_error;
1710 0           $__rule_info = $previous_rule_info;
1711 0           $__default_skip = $previous_default_skip;
1712 0           $commit = $previous_commit;
1713 0           $__parse_this_ref = $previous_parse_this_ref;
1714             #use Data::Dumper; print "pt ".Dumper(\@pt)."\n";
1715 0 0         if (defined $__default_skip) {
1716 0           $skip = $__default_skip;
1717             }
1718 0 0         if ($@) {
1719             #print "em $@\n";
1720             #use Data::Dumper; print "pt ".Dumper(\@pt)."\n";
1721 0           croak $@}
1722             #use Data::Dumper;print "resulsts are ".Dumper($results)."\n";
1723             #use Data::Dumper;print "pi is ".Dumper($pi)."\n";
1724 0 0         if ($pi->{parse_succeeded}) {
1725 0 0         if ($reference) {
1726 0           substr($$reference, 0, $pi->{final_position}) = '';
1727             }
1728             #print "pi is $pi returning ";
1729             #print $pi->{tree}->{parse_match};
1730             #print "\n";
1731 0           return $pi->{tree}->{parse_match};
1732             }
1733             else {
1734 0 0         if (length($__error_message) > 0) {print STDERR $__error_message}
  0            
1735 0           return undef;
1736             }
1737 0           $__error_message = $previous_error_message;
1738             }
1739              
1740 0     0     sub DESTROY {
1741             }
1742              
1743             package main;
1744              
1745 2     2   32 use vars qw ( $RD_ERRORS $RD_WARN $RD_HINT $RD_TRACE $RD_CHECK );
  2         4  
  2         502  
1746             $::RD_CHECK = 1;
1747             $::RD_ERRORS = 1;
1748             $::RD_WARN = 3;
1749              
1750             1;
1751              
1752             __END__