File Coverage

blib/lib/Hash/Weighted/Categorize/Parser.pm
Criterion Covered Total %
statement 246 1444 17.0
branch 66 690 9.5
condition 6 189 3.1
subroutine 47 180 26.1
pod 0 2 0.0
total 365 2505 14.5


line stmt bran cond sub pod time code
1             ########################################################################################
2             #
3             # This file was generated using Parse::Eyapp version 1.182.
4             #
5             # (c) Parse::Yapp Copyright 1998-2001 Francois Desarmenien.
6             # (c) Parse::Eyapp Copyright 2006-2008 Casiano Rodriguez-Leon. Universidad de La Laguna.
7             # Don't edit this file, use source file 'lib/Hash/Weighted/Categorize/Parser.eyp' instead.
8             #
9             # ANY CHANGE MADE HERE WILL BE LOST !
10             #
11             ########################################################################################
12             package Hash::Weighted::Categorize::Parser;
13             {
14             $Hash::Weighted::Categorize::Parser::VERSION = '0.002';
15             }
16 1     1   5 use strict;
  1         1  
  1         774  
17              
18             push @Hash::Weighted::Categorize::Parser::ISA, 'Parse::Eyapp::Driver';
19              
20              
21              
22             # Loading Parse::Eyapp::Driver
23             BEGIN {
24 1 50   1   15 unless (Parse::Eyapp::Driver->can('YYParse')) {
25             eval << 'MODULE_Parse_Eyapp_Driver'
26             #
27             # Module Parse::Eyapp::Driver
28             #
29             # This module is part of the Parse::Eyapp package available on your
30             # nearest CPAN
31             #
32             # This module is based on Francois Desarmenien Parse::Yapp module
33             # (c) Parse::Yapp Copyright 1998-2001 Francois Desarmenien, all rights reserved.
34             # (c) Parse::Eyapp Copyright 2006-2010 Casiano Rodriguez-Leon, all rights reserved.
35              
36             our $SVNREVISION = '$Rev: 2399M $';
37             our $SVNDATE = '$Date: 2009-01-06 12:28:04 +0000 (mar, 06 ene 2009) $';
38              
39             package Parse::Eyapp::Driver;
40              
41             require 5.006;
42              
43             use strict;
44              
45             our ( $VERSION, $COMPATIBLE, $FILENAME );
46              
47              
48             # $VERSION is also in Parse/Eyapp.pm
49             $VERSION = "1.182";
50             $COMPATIBLE = '0.07';
51             $FILENAME =__FILE__;
52              
53             use Carp;
54             use Scalar::Util qw{blessed reftype looks_like_number};
55              
56             use Getopt::Long;
57              
58             #Known parameters, all starting with YY (leading YY will be discarded)
59             my (%params)=(YYLEX => 'CODE', 'YYERROR' => 'CODE', YYVERSION => '',
60             YYRULES => 'ARRAY', YYSTATES => 'ARRAY', YYDEBUG => '',
61             # added by Casiano
62             #YYPREFIX => '', # Not allowed at YYParse time but in new
63             YYFILENAME => '',
64             YYBYPASS => '',
65             YYGRAMMAR => 'ARRAY',
66             YYTERMS => 'HASH',
67             YYBUILDINGTREE => '',
68             YYACCESSORS => 'HASH',
69             YYCONFLICTHANDLERS => 'HASH',
70             YYSTATECONFLICT => 'HASH',
71             YYLABELS => 'HASH',
72             );
73             my (%newparams) = (%params, YYPREFIX => '',);
74              
75             #Mandatory parameters
76             my (@params)=('LEX','RULES','STATES');
77              
78             sub new {
79             my($class)=shift;
80              
81             my($errst,$nberr,$token,$value,$check,$dotpos);
82              
83             my($self)={
84             ERRST => \$errst,
85             NBERR => \$nberr,
86             TOKEN => \$token,
87             VALUE => \$value,
88             DOTPOS => \$dotpos,
89             STACK => [],
90             DEBUG => 0,
91             PREFIX => "",
92             CHECK => \$check,
93             };
94              
95             _CheckParams( [], \%newparams, \@_, $self );
96              
97             exists($$self{VERSION})
98             and $$self{VERSION} < $COMPATIBLE
99             and croak "Eyapp driver version $VERSION ".
100             "incompatible with version $$self{VERSION}:\n".
101             "Please recompile parser module.";
102              
103             ref($class)
104             and $class=ref($class);
105              
106             unless($self->{ERROR}) {
107             $self->{ERROR} = $class->error;
108             $self->{ERROR} = \&_Error unless ($self->{ERROR});
109             }
110              
111             unless ($self->{LEX}) {
112             $self->{LEX} = $class->YYLexer;
113             @params = ('RULES','STATES');
114             }
115              
116             my $parser = bless($self,$class);
117              
118             $parser;
119             }
120              
121             sub YYParse {
122             my($self)=shift;
123             my($retval);
124              
125             _CheckParams( \@params, \%params, \@_, $self );
126              
127             unless($self->{ERROR}) {
128             $self->{ERROR} = $self->error;
129             $self->{ERROR} = \&_Error unless ($self->{ERROR});
130             }
131              
132             unless($self->{LEX}) {
133             $self->{LEX} = $self->YYLexer;
134             croak "Missing parameter 'yylex' " unless $self->{LEX} && reftype($self->{LEX}) eq 'CODE';
135             }
136              
137             if($$self{DEBUG}) {
138             _DBLoad();
139             $retval = eval '$self->_DBParse()';#Do not create stab entry on compile
140             $@ and die $@;
141             }
142             else {
143             $retval = $self->_Parse();
144             }
145             return $retval;
146             }
147              
148             sub YYData {
149             my($self)=shift;
150              
151             exists($$self{USER})
152             or $$self{USER}={};
153              
154             $$self{USER};
155            
156             }
157              
158             sub YYErrok {
159             my($self)=shift;
160              
161             ${$$self{ERRST}}=0;
162             undef;
163             }
164              
165             sub YYNberr {
166             my($self)=shift;
167              
168             ${$$self{NBERR}};
169             }
170              
171             sub YYRecovering {
172             my($self)=shift;
173              
174             ${$$self{ERRST}} != 0;
175             }
176              
177             sub YYAbort {
178             my($self)=shift;
179              
180             ${$$self{CHECK}}='ABORT';
181             undef;
182             }
183              
184             sub YYAccept {
185             my($self)=shift;
186              
187             ${$$self{CHECK}}='ACCEPT';
188             undef;
189             }
190              
191             # Used to set that we are in "error recovery" state
192             sub YYError {
193             my($self)=shift;
194              
195             ${$$self{CHECK}}='ERROR';
196             undef;
197             }
198              
199             sub YYSemval {
200             my($self)=shift;
201             my($index)= $_[0] - ${$$self{DOTPOS}} - 1;
202              
203             $index < 0
204             and -$index <= @{$$self{STACK}}
205             and return $$self{STACK}[$index][1];
206              
207             undef; #Invalid index
208             }
209              
210             ### Casiano methods
211              
212             sub YYRule {
213             # returns the list of rules
214             # counting the super rule as rule 0
215             my $self = shift;
216             my $index = shift;
217              
218             if ($index) {
219             $index = $self->YYIndex($index) unless (looks_like_number($index));
220             return wantarray? @{$self->{RULES}[$index]} : $self->{RULES}[$index]
221             }
222              
223             return wantarray? @{$self->{RULES}} : $self->{RULES}
224             }
225              
226             # YYState returns the list of states. Each state is an anonymous hash
227             # DB<4> x $parser->YYState(2)
228             # 0 HASH(0xfa7120)
229             # 'ACTIONS' => HASH(0xfa70f0) # token => state
230             # ':' => '-7'
231             # 'DEFAULT' => '-6'
232             # There are three keys: ACTIONS, GOTOS and DEFAULT
233             # DB<7> x $parser->YYState(13)
234             # 0 HASH(0xfa8b50)
235             # 'ACTIONS' => HASH(0xfa7530)
236             # 'VAR' => 17
237             # 'GOTOS' => HASH(0xfa8b20)
238             # 'type' => 19
239             sub YYState {
240             my $self = shift;
241             my $index = shift;
242              
243             if ($index) {
244             # Comes from the stack: a pair [state number, attribute]
245             $index = $index->[0] if 'ARRAY' eq reftype($index);
246             die "YYState error. Expecting a number, found <$index>" unless (looks_like_number($index));
247             return $self->{STATES}[$index]
248             }
249              
250             return $self->{STATES}
251             }
252              
253             sub YYGoto {
254             my ($self, $state, $symbol) = @_;
255            
256             my $stateLRactions = $self->YYState($state);
257              
258             $stateLRactions->{GOTOS}{$symbol};
259             }
260              
261             sub YYRHSLength {
262             my $self = shift;
263             # If no production index is given, is the production begin used in the current reduction
264             my $index = shift || $self->YYRuleindex;
265              
266             # If the production was given by its name, compute its index
267             $index = $self->YYIndex($index) unless looks_like_number($index);
268            
269             return unless looks_like_number($index);
270              
271             my $currentprod = $self->YYRule($index);
272              
273             $currentprod->[1] if reftype($currentprod);
274             }
275              
276             # To be used in a semantic action, when reducing ...
277             # It gives the next state after reduction
278             sub YYNextState {
279             my $self = shift;
280              
281             my $lhs = $self->YYLhs;
282              
283             if ($lhs) { # reduce
284             my $length = $self->YYRHSLength;
285              
286             my $state = $self->YYTopState($length);
287             #print "state = $$state[0]\n";
288             $self->YYGoto($state, $lhs);
289             }
290             else { # shift: a token must be provided as argument
291             my $token = shift;
292            
293             my $state = $self->YYTopState;
294             $self->YYGetLRAction($state, $token);
295             }
296             }
297              
298             # TODO: make it work with a list of indices ...
299             sub YYGrammar {
300             my $self = shift;
301             my $index = shift;
302              
303             if ($index) {
304             $index = $self->YYIndex($index) unless (looks_like_number($index));
305             return wantarray? @{$self->{GRAMMAR}[$index]} : $self->{GRAMMAR}[$index]
306             }
307             return wantarray? @{$self->{GRAMMAR}} : $self->{GRAMMAR}
308             }
309              
310             # Return the list of production names
311             sub YYNames {
312             my $self = shift;
313              
314             my @names = map { $_->[0] } @{$self->{GRAMMAR}};
315              
316             return wantarray? @names : \@names;
317             }
318              
319             # Return the hash of indices for each production name
320             # Initializes the INDICES attribute of the parser
321             # Returns the index of the production rule with name $name
322             sub YYIndex {
323             my $self = shift;
324              
325             if (@_) {
326             my @indices = map { $self->{LABELS}{$_} } @_;
327             return wantarray? @indices : $indices[0];
328             }
329             return wantarray? %{$self->{LABELS}} : $self->{LABELS};
330              
331             }
332              
333             sub YYTopState {
334             my $self = shift;
335             my $length = shift || 0;
336              
337             $length = -$length unless $length <= 0;
338             $length--;
339              
340             $_[1] and $self->{STACK}[$length] = $_[1];
341             $self->{STACK}[$length];
342             }
343              
344             sub YYStack {
345             my $self = shift;
346              
347             return $self->{STACK};
348             }
349              
350             # To dynamically set syntactic actions
351             # Change it to state, token, action
352             # it is more natural
353             sub YYSetLRAction {
354             my ($self, $state, $token, $action) = @_;
355              
356             die "YYLRAction: Provide a state " unless defined($state);
357              
358             # Action can be given using the name of the production
359             $action = -$self->YYIndex($action) unless looks_like_number($action);
360             $token = [ $token ] unless ref($token);
361             for (@$token) {
362             $self->{STATES}[$state]{ACTIONS}{$_} = $action;
363             }
364             }
365              
366             sub YYRestoreLRAction {
367             my $self = shift;
368             my $conflictname = shift;
369             my @tokens = @_;
370              
371             for (@tokens) {
372             my ($conflictstate, $action) = @{$self->{CONFLICT}{$conflictname}{$_}};
373             $self->{STATES}[$conflictstate]{ACTIONS}{$_} = $action;
374             }
375             }
376              
377             # Fools the lexer to get a new token
378             # without modifying the parsing position (pos)
379             # Warning, warning! this and YYLookaheads assume
380             # that the input comes from the string
381             # referenced by $self->input.
382             # It will not work for a stream
383             sub YYLookahead {
384             my $self = shift;
385              
386             my $pos = pos(${$self->input});
387             my ($nextToken, $val) = $self->YYLexer->($self);
388             # restore pos
389             pos(${$self->input}) = $pos;
390             return $nextToken;
391             }
392              
393             # Fools the lexer to get $spec new tokens
394             sub YYLookaheads {
395             my $self = shift;
396             my $spec = shift || 1; # a number
397              
398             my $pos = pos(${$self->input});
399             my @r; # list of lookahead tokens
400              
401             my ($t, $v);
402             if (looks_like_number($spec)) {
403             for my $i (1..$spec) {
404             ($t, $v) = $self->YYLexer->($self);
405             push @r, $t;
406             last if $t eq '';
407             }
408             }
409             else { # if string
410             do {
411             ($t, $v) = $self->YYLexer->($self);
412             push @r, $t;
413             } while ($t ne $spec && $t ne '');
414             }
415              
416             # restore pos
417             pos(${$self->input}) = $pos;
418              
419             return @r;
420             }
421              
422              
423             # more parameters: debug, etc, ...
424             #sub YYNestedParse {
425             sub YYPreParse {
426             my $self = shift;
427             my $parser = shift;
428             my $file = shift() || $parser;
429              
430             # Check for errors!
431             eval "require $file";
432            
433             # optimize to state variable for 5.10
434             my $rp = $parser->new( yyerror => sub {});
435              
436             my $pos = pos(${$self->input});
437             my $rpos = $self->{POS};
438              
439             #print "pos = $pos\n";
440             $rp->input($self->input);
441             pos(${$rp->input}) = $rpos;
442              
443             my $t = $rp->Run(@_);
444             my $ne = $rp->YYNberr;
445              
446             #print "After nested parsing\n";
447              
448             pos(${$self->input}) = $pos;
449              
450             return (wantarray ? ($t, !$ne) : !$ne);
451             }
452              
453             sub YYNestedParse {
454             my $self = shift;
455             my $parser = shift;
456             my $conflictName = shift;
457              
458             $conflictName = $self->YYLhs unless $conflictName;
459              
460             my ($t, $ok) = $self->YYPreParse($parser, @_);
461              
462             $self->{CONFLICTHANDLERS}{$conflictName}{".".$parser} = [$ok, $t];
463              
464             return $ok;
465             }
466              
467             sub YYNestedRegexp {
468             my $self = shift;
469             my $regexp = shift;
470             my $conflictName = $self->YYLhs;
471              
472             my $ok = $_ =~ /$regexp/gc;
473              
474             $self->{CONFLICTHANDLERS}{$conflictName}{'..regexp'} = [$ok, undef];
475              
476             return $ok;
477             }
478              
479             sub YYIs {
480             my $self = shift;
481             # this is ungly and dangeorus. Don't use the dot. Change it!
482             my $syntaxVariable = '.'.(shift());
483             my $conflictName = $self->YYLhs;
484             my $v = $self->{CONFLICTHANDLERS}{$conflictName};
485              
486             $v->{$syntaxVariable}[0] = shift if @_;
487             return $v->{$syntaxVariable}[0];
488             }
489              
490              
491             sub YYVal {
492             my $self = shift;
493             # this is ungly and dangeorus. Don't use the dot. Change it!
494             my $syntaxVariable = '.'.(shift());
495             my $conflictName = $self->YYLhs;
496             my $v = $self->{CONFLICTHANDLERS}{$conflictName};
497              
498             $v->{$syntaxVariable}[1] = shift if @_;
499             return $v->{$syntaxVariable}[1];
500             }
501              
502             #x $self->{CONFLICTHANDLERS}
503             #0 HASH(0x100b306c0)
504             # 'rangeORenum' => HASH(0x100b30660)
505             # 'explorerline' => 12
506             # 'line' => 5
507             # 'production' => HASH(0x100b30580)
508             # '-13' => ARRAY(0x100b30520)
509             # 0 1 <------- mark: conflictive position in the rhs
510             # '-5' => ARRAY(0x100b30550)
511             # 0 1 <------- mark: conflictive position in the rhs
512             # 'states' => ARRAY(0x100b30630)
513             # 0 HASH(0x100b30600)
514             # 25 => ARRAY(0x100b305c0)
515             # 0 '\',\''
516             # 1 '\')\''
517             sub YYSetReduceXXXXX {
518             my $self = shift;
519             my $action = pop;
520             my $token = shift;
521            
522              
523             croak "YYSetReduce error: specify a production" unless defined($action);
524              
525             # Conflict state
526             my $conflictstate = $self->YYNextState();
527              
528             my $conflictName = $self->YYLhs;
529              
530             #$self->{CONFLICTHANDLERS}{conflictName}{states}
531             # is a hash
532             # statenumber => [ tokens, '\'-\'' ]
533             my $cS = $self->{CONFLICTHANDLERS}{$conflictName}{states};
534             my @conflictStates = $cS ? @$cS : ();
535              
536             # Perform the action to change the LALR tables only if the next state
537             # is listed as a conflictstate
538             my ($cs) = (grep { exists $_->{$conflictstate}} @conflictStates);
539             return unless $cs;
540              
541             # Action can be given using the name of the production
542             unless (looks_like_number($action)) {
543             my $actionnum = $self->{LABELS}{$action};
544             unless (looks_like_number($actionnum)) {
545             croak "YYSetReduce error: can't find production '$action'. Did you forget to name it?";
546             }
547             $action = -$actionnum;
548             }
549              
550             $token = $cs->{$conflictstate} unless defined($token);
551             $token = [ $token ] unless ref($token);
552             for (@$token) {
553             # save if shift
554             if (exists($self->{STATES}[$conflictstate]{ACTIONS}) and $self->{STATES}[$conflictstate]{ACTIONS}{$_} >= 0) {
555             $self->{CONFLICT}{$conflictName}{$_} = [ $conflictstate, $self->{STATES}[$conflictstate]{ACTIONS}{$_} ];
556             }
557             $self->{STATES}[$conflictstate]{ACTIONS}{$_} = $action;
558             }
559             }
560              
561             sub YYSetReduce {
562             my $self = shift;
563             my $action = pop;
564             my $token = shift;
565            
566              
567             croak "YYSetReduce error: specify a production" unless defined($action);
568              
569             my $conflictName = $self->YYLhs;
570              
571             #$self->{CONFLICTHANDLERS}{conflictName}{states}
572             # is a hash
573             # statenumber => [ tokens, '\'-\'' ]
574             my $cS = $self->{CONFLICTHANDLERS}{$conflictName}{states};
575             my @conflictStates = $cS ? @$cS : ();
576            
577             return unless @conflictStates;
578              
579             # Conflict state
580             my $cs = $conflictStates[0];
581              
582              
583             my ($conflictstate) = keys %{$cs};
584              
585             # Action can be given using the name of the production
586             unless (looks_like_number($action)) {
587             my $actionnum = $self->{LABELS}{$action};
588             unless (looks_like_number($actionnum)) {
589             croak "YYSetReduce error: can't find production '$action'. Did you forget to name it?";
590             }
591             $action = -$actionnum;
592             }
593              
594             $token = $cs->{$conflictstate} unless defined($token);
595             $token = [ $token ] unless ref($token);
596             for (@$token) {
597             # save if shift
598             if (exists($self->{STATES}[$conflictstate]{ACTIONS}) and $self->{STATES}[$conflictstate]{ACTIONS}{$_} >= 0) {
599             $self->{CONFLICT}{$conflictName}{$_} = [ $conflictstate, $self->{STATES}[$conflictstate]{ACTIONS}{$_} ];
600             }
601             $self->{STATES}[$conflictstate]{ACTIONS}{$_} = $action;
602             }
603             }
604              
605             sub YYSetShift {
606             my ($self, $token) = @_;
607              
608             # my ($self, $token, $action) = @_;
609             # $action is syntactic sugar ...
610              
611              
612             my $conflictName = $self->YYLhs;
613              
614             my $cS = $self->{CONFLICTHANDLERS}{$conflictName}{states};
615             my @conflictStates = $cS ? @$cS : ();
616            
617             return unless @conflictStates;
618              
619             my $cs = $conflictStates[0];
620              
621             my ($conflictstate) = keys %{$cs};
622              
623             $token = $cs->{$conflictstate} unless defined($token);
624             $token = [ $token ] unless ref($token);
625              
626             for (@$token) {
627             if (defined($self->{CONFLICT}{$conflictName}{$_})) {
628             my ($conflictstate2, $action) = @{$self->{CONFLICT}{$conflictName}{$_}};
629             # assert($conflictstate == $conflictstate2)
630              
631             $self->{STATES}[$conflictstate]{ACTIONS}{$_} = $self->{CONFLICT}{$conflictName}{$_}[1];
632             }
633             else {
634             #croak "YYSetShift error. No shift action found";
635             # shift is the default ... hope to be lucky!
636             }
637             }
638             }
639              
640              
641             # if is reduce ...
642             # x $self->{CONFLICTHANDLERS}{$conflictName}{production}{$action} $action is a number
643             #0 ARRAY(0x100b3f930)
644             # 0 2
645             # has the position in the item, starting at 0
646             # DB<19> x $self->YYRHSLength(4)
647             # 0 3
648             # if pos is length -1 then is reduce otherwise is shift
649              
650              
651             # It does YYSetReduce or YYSetshift according to the
652             # decision variable
653             # I need to know the kind of conflict that there is
654             # shift-reduce or reduce-reduce
655             sub YYIf {
656             my $self = shift;
657             my $syntaxVariable = shift;
658              
659             if ($self->YYIs($syntaxVariable)) {
660             if ($_[0] eq 'shift') {
661             $self->YYSetShift(@_);
662             }
663             else {
664             $self->YYSetReduce($_[0]);
665             }
666             }
667             else {
668             if ($_[1] eq 'shift') {
669             $self->YYSetShift(@_);
670             }
671             else {
672             $self->YYSetReduce($_[1]);
673             }
674             }
675             $self->YYIs($syntaxVariable, 0);
676             }
677              
678             sub YYGetLRAction {
679             my ($self, $state, $token) = @_;
680              
681             $state = $state->[0] if reftype($state) && (reftype($state) eq 'ARRAY');
682             my $stateentry = $self->{STATES}[$state];
683              
684             if (defined($token)) {
685             return $stateentry->{ACTIONS}{$token} if exists $stateentry->{ACTIONS}{$token};
686             }
687              
688             return $stateentry->{DEFAULT} if exists $stateentry->{DEFAULT};
689              
690             return;
691             }
692              
693             # to dynamically set semantic actions
694             sub YYAction {
695             my $self = shift;
696             my $index = shift;
697             my $newaction = shift;
698              
699             croak "YYAction error: Expecting an index" unless $index;
700              
701             # If $index is the production 'name' find the actual index
702             $index = $self->YYIndex($index) unless looks_like_number($index);
703             my $rule = $self->{RULES}->[$index];
704             $rule->[2] = $newaction if $newaction && (reftype($newaction) eq 'CODE');
705              
706             return $rule->[2];
707             }
708              
709             sub YYSetaction {
710             my $self = shift;
711             my %newaction = @_;
712              
713             for my $n (keys(%newaction)) {
714             my $m = looks_like_number($n) ? $n : $self->YYIndex($n);
715             my $rule = $self->{RULES}->[$m];
716             $rule->[2] = $newaction{$n} if ($newaction{$n} && (reftype($newaction{$n}) eq 'CODE'));
717             }
718             }
719              
720             #sub YYDebugtree {
721             # my ($self, $i, $e) = @_;
722             #
723             # my ($name, $lhs, $rhs) = @$e;
724             # my @rhs = @$rhs;
725             #
726             # return if $name =~ /_SUPERSTART/;
727             # $name = $lhs."::"."@rhs";
728             # $name =~ s/\W/_/g;
729             # return $name;
730             #}
731             #
732             #sub YYSetnames {
733             # my $self = shift;
734             # my $newname = shift || \&YYDebugtree;
735             #
736             # die "YYSetnames error. Exected a CODE reference found <$newname>"
737             # unless $newname && (reftype($newname) eq 'CODE');
738             #
739             # my $i = 0;
740             # for my $e (@{$self->{GRAMMAR}}) {
741             # my $nn= $newname->($self, $i, $e);
742             # $e->[0] = $nn if defined($nn);
743             # $i++;
744             # }
745             #}
746              
747             sub YYLhs {
748             # returns the syntax variable on
749             # the left hand side of the current production
750             my $self = shift;
751              
752             return $self->{CURRENT_LHS}
753             }
754              
755             sub YYRuleindex {
756             # returns the index of the rule
757             # counting the super rule as rule 0
758             my $self = shift;
759              
760             return $self->{CURRENT_RULE}
761             }
762              
763             sub YYRightside {
764             # returns the rule
765             # counting the super rule as rule 0
766             my $self = shift;
767             my $index = shift || $self->{CURRENT_RULE};
768             $index = $self->YYIndex($index) unless looks_like_number($index);
769              
770             return @{$self->{GRAMMAR}->[$index]->[2]};
771             }
772              
773             sub YYTerms {
774             my $self = shift;
775              
776             return $self->{TERMS};
777             }
778              
779              
780             sub YYIsterm {
781             my $self = shift;
782             my $symbol = shift;
783              
784             return exists ($self->{TERMS}->{$symbol});
785             }
786              
787             sub YYIssemantic {
788             my $self = shift;
789             my $symbol = shift;
790              
791             return 0 unless exists($self->{TERMS}{$symbol});
792             $self->{TERMS}{$symbol}{ISSEMANTIC} = shift if @_;
793             return ($self->{TERMS}{$symbol}{ISSEMANTIC});
794             }
795              
796             sub YYName {
797             my $self = shift;
798              
799             my $current_rule = $self->{GRAMMAR}->[$self->{CURRENT_RULE}];
800             $current_rule->[0] = shift if @_;
801             return $current_rule->[0];
802             }
803              
804             sub YYPrefix {
805             my $self = shift;
806              
807             $self->{PREFIX} = $_[0] if @_;
808             $self->{PREFIX};
809             }
810              
811             sub YYAccessors {
812             my $self = shift;
813              
814             $self->{ACCESSORS}
815             }
816              
817             # name of the file containing
818             # the source grammar
819             sub YYFilename {
820             my $self = shift;
821              
822             $self->{FILENAME} = $_[0] if @_;
823             $self->{FILENAME};
824             }
825              
826             sub YYBypass {
827             my $self = shift;
828              
829             $self->{BYPASS} = $_[0] if @_;
830             $self->{BYPASS};
831             }
832              
833             sub YYBypassrule {
834             my $self = shift;
835              
836             $self->{GRAMMAR}->[$self->{CURRENT_RULE}][3] = $_[0] if @_;
837             return $self->{GRAMMAR}->[$self->{CURRENT_RULE}][3];
838             }
839              
840             sub YYFirstline {
841             my $self = shift;
842              
843             $self->{FIRSTLINE} = $_[0] if @_;
844             $self->{FIRSTLINE};
845             }
846              
847             # Used as default action when writing a reusable grammar.
848             # See files examples/recycle/NoacInh.eyp
849             # and examples/recycle/icalcu_and_ipost.pl
850             # in the Parse::Eyapp distribution
851             sub YYDelegateaction {
852             my $self = shift;
853              
854             my $action = $self->YYName;
855            
856             $self->$action(@_);
857             }
858              
859             # Influences the behavior of YYActionforT_X1X2
860             # YYActionforT_single and YYActionforT_empty
861             # If true these methods will build simple lists of attributes
862             # for the lists operators X*, X+ and X? and parenthesis (X Y)
863             # Otherwise the classic node construction for the
864             # syntax tree is used
865             sub YYBuildingTree {
866             my $self = shift;
867              
868             $self->{BUILDINGTREE} = $_[0] if @_;
869             $self->{BUILDINGTREE};
870             }
871              
872             sub BeANode {
873             my $class = shift;
874              
875             no strict 'refs';
876             push @{$class."::ISA"}, "Parse::Eyapp::Node" unless $class->isa("Parse::Eyapp::Node");
877             }
878              
879             #sub BeATranslationScheme {
880             # my $class = shift;
881             #
882             # no strict 'refs';
883             # push @{$class."::ISA"}, "Parse::Eyapp::TranslationScheme" unless $class->isa("Parse::Eyapp::TranslationScheme");
884             #}
885              
886             {
887             my $attr = sub {
888             $_[0]{attr} = $_[1] if @_ > 1;
889             $_[0]{attr}
890             };
891              
892             sub make_node_classes {
893             my $self = shift;
894             my $prefix = $self->YYPrefix() || '';
895              
896             { no strict 'refs';
897             *{$prefix."TERMINAL::attr"} = $attr;
898             }
899              
900             for (@_) {
901             my ($class) = split /:/, $_;
902             BeANode("$prefix$class");
903             }
904              
905             my $accessors = $self->YYAccessors();
906             for (keys %$accessors) {
907             my $position = $accessors->{$_};
908             no strict 'refs';
909             *{$prefix.$_} = sub {
910             my $self = shift;
911              
912             return $self->child($position, @_)
913             }
914             } # for
915             }
916             }
917              
918             ####################################################################
919             # Usage : ????
920             # Purpose : Responsible for the %tree directive
921             # On each production the default action becomes:
922             # sub { goto &Parse::Eyapp::Driver::YYBuildAST }
923             #
924             # Returns : ????
925             # Parameters : ????
926             # Throws : no exceptions
927             # Comments : none
928             # See Also : n/a
929             # To Do : many things: Optimize this!!!!
930             sub YYBuildAST {
931             my $self = shift;
932             my $PREFIX = $self->YYPrefix();
933             my @right = $self->YYRightside(); # Symbols on the right hand side of the production
934             my $lhs = $self->YYLhs;
935             my $fullname = $self->YYName();
936             my ($name) = split /:/, $fullname;
937             my $bypass = $self->YYBypassrule; # Boolean: shall we do bypassing of lonely nodes?
938             my $class = "$PREFIX$name";
939             my @children;
940              
941             my $node = bless {}, $class;
942              
943             for(my $i = 0; $i < @right; $i++) {
944             local $_ = $right[$i]; # The symbol
945             my $ch = $_[$i]; # The attribute/reference
946              
947             # is $ch already a Parse::Eyapp::Node. May be a terminal and a syntax variable share the same name?
948             unless (UNIVERSAL::isa($ch, 'Parse::Eyapp::Node')) {
949             if ($self->YYIssemantic($_)) {
950             my $class = $PREFIX.'TERMINAL';
951             my $node = bless { token => $_, attr => $ch, children => [] }, $class;
952             push @children, $node;
953             next;
954             }
955              
956             if ($self->YYIsterm($_)) {
957             TERMINAL::save_attributes($ch, $node) if UNIVERSAL::can($PREFIX."TERMINAL", "save_attributes");
958             next;
959             }
960             }
961              
962             if (UNIVERSAL::isa($ch, $PREFIX."_PAREN")) { # Warning: weak code!!!
963             push @children, @{$ch->{children}};
964             next;
965             }
966              
967             # If it is an intermediate semantic action skip it
968             next if $_ =~ qr{@}; # intermediate rule
969             next unless ref($ch);
970             push @children, $ch;
971             }
972              
973            
974             if ($bypass and @children == 1) {
975             $node = $children[0];
976              
977             my $childisterminal = ref($node) =~ /TERMINAL$/;
978             # Re-bless unless is "an automatically named node", but the characterization of this is
979             bless $node, $class unless $name =~ /${lhs}_\d+$/; # lazy, weak (and wicked).
980              
981            
982             my $finalclass = ref($node);
983             $childisterminal and !$finalclass->isa($PREFIX.'TERMINAL')
984             and do {
985             no strict 'refs';
986             push @{$finalclass."::ISA"}, $PREFIX.'TERMINAL'
987             };
988              
989             return $node;
990             }
991             $node->{children} = \@children;
992             return $node;
993             }
994              
995             sub YYBuildTS {
996             my $self = shift;
997             my $PREFIX = $self->YYPrefix();
998             my @right = $self->YYRightside(); # Symbols on the right hand side of the production
999             my $lhs = $self->YYLhs;
1000             my $fullname = $self->YYName();
1001             my ($name) = split /:/, $fullname;
1002             my $class;
1003             my @children;
1004              
1005             for(my $i = 0; $i < @right; $i++) {
1006             local $_ = $right[$i]; # The symbol
1007             my $ch = $_[$i]; # The attribute/reference
1008              
1009             if ($self->YYIsterm($_)) {
1010             $class = $PREFIX.'TERMINAL';
1011             push @children, bless { token => $_, attr => $ch, children => [] }, $class;
1012             next;
1013             }
1014              
1015             if (UNIVERSAL::isa($ch, $PREFIX."_PAREN")) { # Warning: weak code!!!
1016             push @children, @{$ch->{children}};
1017             next;
1018             }
1019              
1020             # Substitute intermediate code node _CODE(CODE()) by CODE()
1021             if (UNIVERSAL::isa($ch, $PREFIX."_CODE")) { # Warning: weak code!!!
1022             push @children, $ch->child(0);
1023             next;
1024             }
1025              
1026             next unless ref($ch);
1027             push @children, $ch;
1028             }
1029              
1030             if (unpack('A1',$lhs) eq '@') { # class has to be _CODE check
1031             $lhs =~ /^\@[0-9]+\-([0-9]+)$/
1032             or croak "In line rule name '$lhs' ill formed: report it as a BUG.\n";
1033             my $dotpos = $1;
1034            
1035             croak "Fatal error building metatree when processing $lhs -> @right"
1036             unless exists($_[$dotpos]) and UNIVERSAL::isa($_[$dotpos], 'CODE') ;
1037             push @children, $_[$dotpos];
1038             }
1039             else {
1040             my $code = $_[@right];
1041             if (UNIVERSAL::isa($code, 'CODE')) {
1042             push @children, $code;
1043             }
1044             else {
1045             croak "Fatal error building translation scheme. Code or undef expected" if (defined($code));
1046             }
1047             }
1048              
1049             $class = "$PREFIX$name";
1050             my $node = bless { children => \@children }, $class;
1051             $node;
1052             }
1053              
1054             sub YYActionforT_TX1X2_tree {
1055             my $self = shift;
1056             my $head = shift;
1057             my $PREFIX = $self->YYPrefix();
1058             my @right = $self->YYRightside();
1059             my $class;
1060              
1061             for(my $i = 1; $i < @right; $i++) {
1062             local $_ = $right[$i];
1063             my $ch = $_[$i-1];
1064             if ($self->YYIssemantic($_)) {
1065             $class = $PREFIX.'TERMINAL';
1066             push @{$head->{children}}, bless { token => $_, attr => $ch, children => [] }, $class;
1067            
1068             next;
1069             }
1070             next if $self->YYIsterm($_);
1071             if (ref($ch) eq $PREFIX."_PAREN") { # Warning: weak code!!!
1072             push @{$head->{children}}, @{$ch->{children}};
1073             next;
1074             }
1075             next unless ref($ch);
1076             push @{$head->{children}}, $ch;
1077             }
1078              
1079             return $head;
1080             }
1081              
1082             # For * and + lists
1083             # S2 -> S2 X { push @$_[1] the node associated with X; $_[1] }
1084             # S2 -> /* empty */ { a node with empty children }
1085             sub YYActionforT_TX1X2 {
1086             goto &YYActionforT_TX1X2_tree if $_[0]->YYBuildingTree;
1087              
1088             my $self = shift;
1089             my $head = shift;
1090              
1091             push @$head, @_;
1092             return $head;
1093             }
1094              
1095             sub YYActionforParenthesis {
1096             goto &YYBuildAST if $_[0]->YYBuildingTree;
1097              
1098             my $self = shift;
1099              
1100             return [ @_ ];
1101             }
1102              
1103              
1104             sub YYActionforT_empty_tree {
1105             my $self = shift;
1106             my $PREFIX = $self->YYPrefix();
1107             my $name = $self->YYName();
1108              
1109             # Allow use of %name
1110             my $class = $PREFIX.$name;
1111             my $node = bless { children => [] }, $class;
1112             #BeANode($class);
1113             $node;
1114             }
1115              
1116             sub YYActionforT_empty {
1117             goto &YYActionforT_empty_tree if $_[0]->YYBuildingTree;
1118              
1119             [];
1120             }
1121              
1122             sub YYActionforT_single_tree {
1123             my $self = shift;
1124             my $PREFIX = $self->YYPrefix();
1125             my $name = $self->YYName();
1126             my @right = $self->YYRightside();
1127             my $class;
1128              
1129             # Allow use of %name
1130             my @t;
1131             for(my $i = 0; $i < @right; $i++) {
1132             local $_ = $right[$i];
1133             my $ch = $_[$i];
1134             if ($self->YYIssemantic($_)) {
1135             $class = $PREFIX.'TERMINAL';
1136             push @t, bless { token => $_, attr => $ch, children => [] }, $class;
1137             #BeANode($class);
1138             next;
1139             }
1140             next if $self->YYIsterm($_);
1141             if (ref($ch) eq $PREFIX."_PAREN") { # Warning: weak code!!!
1142             push @t, @{$ch->{children}};
1143             next;
1144             }
1145             next unless ref($ch);
1146             push @t, $ch;
1147             }
1148             $class = $PREFIX.$name;
1149             my $node = bless { children => \@t }, $class;
1150             #BeANode($class);
1151             $node;
1152             }
1153              
1154             sub YYActionforT_single {
1155             goto &YYActionforT_single_tree if $_[0]->YYBuildingTree;
1156              
1157             my $self = shift;
1158             [ @_ ];
1159             }
1160              
1161             ### end Casiano methods
1162              
1163             sub YYCurtok {
1164             my($self)=shift;
1165              
1166             @_
1167             and ${$$self{TOKEN}}=$_[0];
1168             ${$$self{TOKEN}};
1169             }
1170              
1171             sub YYCurval {
1172             my($self)=shift;
1173              
1174             @_
1175             and ${$$self{VALUE}}=$_[0];
1176             ${$$self{VALUE}};
1177             }
1178              
1179             {
1180             sub YYSimStack {
1181             my $self = shift;
1182             my $stack = shift;
1183             my @reduce = @_;
1184             my @expected;
1185              
1186             for my $index (@reduce) {
1187             my ($lhs, $length) = @{$self->{RULES}[-$index]};
1188             if (@$stack > $length) {
1189             my @auxstack = @$stack;
1190             splice @auxstack, -$length if $length;
1191              
1192             my $state = $auxstack[-1]->[0];
1193             my $nextstate = $self->{STATES}[$state]{GOTOS}{$lhs};
1194             if (defined($nextstate)) {
1195             push @auxstack, [$nextstate, undef];
1196             push @expected, $self->YYExpected(\@auxstack);
1197             }
1198             }
1199             # else something went wrong!!! See Frank Leray report
1200             }
1201              
1202             return map { $_ => 1 } @expected;
1203             }
1204              
1205             sub YYExpected {
1206             my($self)=shift;
1207             my $stack = shift;
1208              
1209             # The state in the top of the stack
1210             my $state = $self->{STATES}[$stack->[-1][0]];
1211              
1212             my %actions;
1213             %actions = %{$state->{ACTIONS}} if exists $state->{ACTIONS};
1214              
1215             # The keys of %reduction are the -production numbers
1216             # Use hashes and not lists to guarantee that no tokens are repeated
1217             my (%expected, %reduce);
1218             for (keys(%actions)) {
1219             if ($actions{$_} > 0) { # shift
1220             $expected{$_} = 1;
1221             next;
1222             }
1223             $reduce{$actions{$_}} = 1;
1224             }
1225             $reduce{$state->{DEFAULT}} = 1 if exists($state->{DEFAULT});
1226              
1227             if (keys %reduce) {
1228             %expected = (%expected, $self->YYSimStack($stack, keys %reduce));
1229             }
1230            
1231             return keys %expected;
1232             }
1233              
1234             sub YYExpect {
1235             my $self = shift;
1236             $self->YYExpected($self->{STACK}, @_);
1237             }
1238             }
1239              
1240             # $self->expects($token) : returns true if the token is among the expected ones
1241             sub expects {
1242             my $self = shift;
1243             my $token = shift;
1244              
1245             my @expected = $self->YYExpect;
1246             return grep { $_ eq $token } @expected;
1247             }
1248              
1249             BEGIN {
1250             *YYExpects = \&expects;
1251             }
1252              
1253             # Set/Get a static/class attribute for $class
1254             # Searches the $class ancestor tree for an ancestor
1255             # having defined such attribute. If found, that value is returned
1256             sub static_attribute {
1257             my $class = shift;
1258             $class = ref($class) if ref($class);
1259             my $attributename = shift;
1260              
1261             # class/static method
1262             no strict 'refs';
1263             my $classlexer;
1264             my $classname = $classlexer = $class.'::'.$attributename;
1265             if (@_) {
1266             ${$classlexer} = shift;
1267             }
1268              
1269             return ${$classlexer} if defined($$classlexer);
1270            
1271             # Traverse the inheritance tree for a defined
1272             # version of the attribute
1273             my @classes = @{$class.'::ISA'};
1274             my %classes = map { $_ => undef } @classes;
1275             while (@classes) {
1276             my $c = shift @classes || return;
1277             $classlexer = $c.'::'.$attributename;
1278             if (defined($$classlexer)) {
1279             $$classname = $$classlexer;
1280             return $$classlexer;
1281             }
1282             # push those that aren't already there
1283             push @classes, grep { !exists $classes{$_} } @{$c.'::ISA'};
1284             }
1285             return undef;
1286             }
1287              
1288             sub YYEndOfInput {
1289             my $self = shift;
1290              
1291             for (${$self->input}) {
1292             return !defined($_) || ($_ eq '') || (defined(pos($_)) && (pos($_) >= length($_)));
1293             }
1294             }
1295              
1296             #################
1297             # Private stuff #
1298             #################
1299              
1300              
1301             sub _CheckParams {
1302             my ($mandatory,$checklist,$inarray,$outhash)=@_;
1303             my ($prm,$value);
1304             my ($prmlst)={};
1305              
1306             while(($prm,$value)=splice(@$inarray,0,2)) {
1307             $prm=uc($prm);
1308             exists($$checklist{$prm})
1309             or croak("Unknown parameter '$prm'");
1310             ref($value) eq $$checklist{$prm}
1311             or croak("Invalid value for parameter '$prm'");
1312             $prm=unpack('@2A*',$prm);
1313             $$outhash{$prm}=$value;
1314             }
1315             for (@$mandatory) {
1316             exists($$outhash{$_})
1317             or croak("Missing mandatory parameter '".lc($_)."'");
1318             }
1319             }
1320              
1321             #################### TailSupport ######################
1322             sub line {
1323             my $self = shift;
1324              
1325             if (ref($self)) {
1326             $self->{TOKENLINE} = shift if @_;
1327              
1328             return $self->static_attribute('TOKENLINE', @_,) unless defined($self->{TOKENLINE}); # class/static method
1329             return $self->{TOKENLINE};
1330             }
1331             else { # class/static method
1332             return $self->static_attribute('TOKENLINE', @_,); # class/static method
1333             }
1334             }
1335              
1336             # attribute to count the lines
1337             sub tokenline {
1338             my $self = shift;
1339              
1340             if (ref($self)) {
1341             $self->{TOKENLINE} += shift if @_;
1342              
1343             return $self->static_attribute('TOKENLINE', @_,) unless defined($self->{TOKENLINE}); # class/static method
1344             return $self->{TOKENLINE};
1345             }
1346             else { # class/static method
1347             return $self->static_attribute('TOKENLINE', @_,); # class/static method
1348             }
1349             }
1350              
1351             our $ERROR = \&_Error;
1352             sub error {
1353             my $self = shift;
1354              
1355             if (ref $self) { # instance method
1356             $self->{ERROR} = shift if @_;
1357              
1358             return $self->static_attribute('ERROR', @_,) unless defined($self->{ERROR}); # class/static method
1359             return $self->{ERROR};
1360             }
1361             else { # class/static method
1362             return $self->static_attribute('ERROR', @_,); # class/static method
1363             }
1364             }
1365              
1366             # attribute with the input
1367             # is a reference to the actual input
1368             # slurp_file.
1369             # Parameters: object or class, filename, prompt messagge, mode (interactive or not: undef or "\n")
1370             *YYSlurpFile = \&slurp_file;
1371             sub slurp_file {
1372             my $self = shift;
1373             my $fn = shift;
1374             my $f;
1375              
1376             my $mode = undef;
1377             if ($fn && -r $fn) {
1378             open $f, $fn or die "Can't find file '$fn'!\n";
1379             }
1380             else {
1381             $f = \*STDIN;
1382             my $msg = $self->YYPrompt();
1383             $mode = shift;
1384             print($msg) if $msg;
1385             }
1386             $self->YYInputFile($f);
1387              
1388             local $/ = $mode;
1389             my $input = <$f>;
1390              
1391             if (ref($self)) { # called as object method
1392             $self->input(\$input);
1393             }
1394             else { # class/static method
1395             my $classinput = $self.'::input';
1396             ${$classinput}->input(\$input);
1397             }
1398             }
1399              
1400             our $INPUT = \undef;
1401             *Parse::Eyapp::Driver::YYInput = \&input;
1402             sub input {
1403             my $self = shift;
1404              
1405             $self->line(1) if @_; # used as setter
1406             if (ref $self) { # instance method
1407             if (@_) {
1408             if (ref $_[0]) {
1409             $self->{INPUT} = shift;
1410             }
1411             else {
1412             my $input = shift;
1413             $self->{INPUT} = \$input;
1414             }
1415             }
1416              
1417             return $self->static_attribute('INPUT', @_,) unless defined($self->{INPUT}); # class/static method
1418             return $self->{INPUT};
1419             }
1420             else { # class/static method
1421             return $self->static_attribute('INPUT', @_,); # class/static method
1422             }
1423             }
1424             *YYInput = \&input; # alias
1425              
1426             # Opened file used to get the input
1427             # static and instance method
1428             our $INPUTFILE = \*STDIN;
1429             sub YYInputFile {
1430             my $self = shift;
1431              
1432             if (ref($self)) { # object method
1433             my $file = shift;
1434             if ($file) { # setter
1435             $self->{INPUTFILE} = $file;
1436             }
1437            
1438             return $self->static_attribute('INPUTFILE', @_,) unless defined($self->{INPUTFILE}); # class/static method
1439             return $self->{INPUTFILE};
1440             }
1441             else { # static
1442             return $self->static_attribute('INPUTFILE', @_,); # class/static method
1443             }
1444             }
1445              
1446              
1447             our $PROMPT;
1448             sub YYPrompt {
1449             my $self = shift;
1450              
1451             if (ref($self)) { # object method
1452             my $prompt = shift;
1453             if ($prompt) { # setter
1454             $self->{PROMPT} = $prompt;
1455             }
1456            
1457             return $self->static_attribute('PROMPT', @_,) unless defined($self->{PROMPT}); # class/static method
1458             return $self->{PROMPT};
1459             }
1460             else { # static
1461             return $self->static_attribute('PROMPT', @_,); # class/static method
1462             }
1463             }
1464              
1465             # args: parser, debug and optionally the input or a reference to the input
1466             sub Run {
1467             my ($self) = shift;
1468             my $yydebug = shift;
1469            
1470             if (defined($_[0])) {
1471             if (ref($_[0])) { # if arg is a reference
1472             $self->input(shift());
1473             }
1474             else { # arg isn't a ref: make a copy
1475             my $x = shift();
1476             $self->input(\$x);
1477             }
1478             }
1479             croak "Provide some input for parsing" unless ($self->input && defined(${$self->input()}));
1480             return $self->YYParse(
1481             #yylex => $self->lexer(),
1482             #yyerror => $self->error(),
1483             yydebug => $yydebug, # 0xF
1484             );
1485             }
1486             *Parse::Eyapp::Driver::YYRun = \&run;
1487              
1488             # args: class, prompt, file, optionally input (ref or not)
1489             # return the abstract syntax tree (or whatever was returned by the parser)
1490             *Parse::Eyapp::Driver::YYMain = \&main;
1491             sub main {
1492             my $package = shift;
1493             my $prompt = shift;
1494              
1495             my $debug = 0;
1496             my $file = '';
1497             my $showtree = 0;
1498             my $TERMINALinfo;
1499             my $help;
1500             my $slurp;
1501             my $inputfromfile = 1;
1502             my $commandinput = '';
1503             my $quotedcommandinput = '';
1504             my $yaml = 0;
1505             my $dot = 0;
1506              
1507             my $result = GetOptions (
1508             "debug!" => \$debug, # sets yydebug on
1509             "file=s" => \$file, # read input from that file
1510             "commandinput=s" => \$commandinput, # read input from command line arg
1511             "tree!" => \$showtree, # prints $tree->str
1512             "info" => \$TERMINALinfo, # prints $tree->str and provides default TERMINAL::info
1513             "help" => \$help, # shows SYNOPSIS section from the script pod
1514             "slurp!" => \$slurp, # read until EOF or CR is reached
1515             "argfile!" => \$inputfromfile, # take input string from @_
1516             "yaml" => \$yaml, # dumps YAML for $tree: YAML must be installed
1517             "dot=s" => \$dot, # dumps YAML for $tree: YAML must be installed
1518             "margin=i" => \$Parse::Eyapp::Node::INDENT,
1519             );
1520              
1521             $package->_help() if $help;
1522              
1523             $debug = 0x1F if $debug;
1524             $file = shift if !$file && @ARGV; # file is taken from the @ARGV unless already defined
1525             $slurp = "\n" if defined($slurp);
1526              
1527             my $parser = $package->new();
1528             $parser->YYPrompt($prompt) if defined($prompt);
1529              
1530             if ($commandinput) {
1531             $parser->input(\$commandinput);
1532             }
1533             elsif ($inputfromfile) {
1534             $parser->slurp_file( $file, $slurp);
1535             }
1536             else { # input must be a string argument
1537             croak "No input provided for parsing! " unless defined($_[0]);
1538             if (ref($_[0])) {
1539             $parser->input(shift());
1540             }
1541             else {
1542             my $x = shift();
1543             $parser->input(\$x);
1544             }
1545             }
1546              
1547             if (defined($TERMINALinfo)) {
1548             my $prefix = ($parser->YYPrefix || '');
1549             no strict 'refs';
1550             *{$prefix.'TERMINAL::info'} = sub {
1551             (ref($_[0]->attr) eq 'ARRAY')? $_[0]->attr->[0] : $_[0]->attr
1552             };
1553             }
1554              
1555             my $tree = $parser->Run( $debug, @_ );
1556              
1557             if (my $ne = $parser->YYNberr > 0) {
1558             print "There were $ne errors during parsing\n";
1559             return undef;
1560             }
1561             else {
1562             if ($showtree) {
1563             if ($tree && blessed $tree && $tree->isa('Parse::Eyapp::Node')) {
1564              
1565             print $tree->str()."\n";
1566             }
1567             elsif ($tree && ref $tree) {
1568             require Data::Dumper;
1569             print Data::Dumper::Dumper($tree)."\n";
1570             }
1571             elsif (defined($tree)) {
1572             print "$tree\n";
1573             }
1574             }
1575             if ($yaml && ref($tree)) {
1576             eval {
1577             require YAML;
1578             };
1579             if ($@) {
1580             print "You must install 'YAML' to use this option\n";
1581             }
1582             else {
1583             YAML->import;
1584             print Dump($tree);
1585             }
1586             }
1587             if ($dot && blessed($tree)) {
1588             my ($sfile, $extension) = $dot =~ /^(.*)\.([^.]*)$/;
1589             $extension = 'png' unless (defined($extension) and $tree->can($extension));
1590             ($sfile) = $file =~ m{(.*[^.])} if !defined($sfile) and defined($file);
1591             $tree->$extension($sfile);
1592             }
1593              
1594             return $tree
1595             }
1596             }
1597              
1598             sub _help {
1599             my $package = shift;
1600              
1601             print << 'AYUDA';
1602             Available options:
1603             --debug sets yydebug on
1604             --nodebug sets yydebug off
1605             --file filepath read input from filepath
1606             --commandinput string read input from string
1607             --tree prints $tree->str
1608             --notree does not print $tree->str
1609             --info When printing $tree->str shows the value of TERMINALs
1610             --help shows this help
1611             --slurp read until EOF reached
1612             --noslurp read until CR is reached
1613             --argfile main() will take the input string from its @_
1614             --noargfile main() will not take the input string from its @_
1615             --yaml dumps YAML for $tree: YAML module must be installed
1616             --margin=i controls the indentation of $tree->str (i.e. $Parse::Eyapp::Node::INDENT)
1617             --dot format produces a .dot and .format file (png,jpg,bmp, etc.)
1618             AYUDA
1619              
1620             $package->help() if ($package & $package->can("help"));
1621              
1622             exit(0);
1623             }
1624              
1625             # Generic error handler
1626             # Convention adopted: if the attribute of a token is an object
1627             # assume it has 'line' and 'str' methods. Otherwise, if it
1628             # is an array, follows the convention [ str, line, ...]
1629             # otherwise is just an string representing the value of the token
1630             sub _Error {
1631             my $parser = shift;
1632              
1633             my $yydata = $parser->YYData;
1634              
1635             exists $yydata->{ERRMSG}
1636             and do {
1637             warn $yydata->{ERRMSG};
1638             delete $yydata->{ERRMSG};
1639             return;
1640             };
1641              
1642             my ($attr)=$parser->YYCurval;
1643              
1644             my $stoken = '';
1645              
1646             if (blessed($attr) && $attr->can('str')) {
1647             $stoken = " near '".$attr->str."'"
1648             }
1649             elsif (ref($attr) eq 'ARRAY') {
1650             $stoken = " near '".$attr->[0]."'";
1651             }
1652             else {
1653             if ($attr) {
1654             $stoken = " near '$attr'";
1655             }
1656             else {
1657             $stoken = " near end of input";
1658             }
1659             }
1660              
1661             my @expected = map { ($_ ne '')? "'$_'" : q{'end of input'}} $parser->YYExpect();
1662             my $expected = '';
1663             if (@expected) {
1664             $expected = (@expected >1) ? "Expected one of these terminals: @expected"
1665             : "Expected terminal: @expected"
1666             }
1667              
1668             my $tline = '';
1669             if (blessed($attr) && $attr->can('line')) {
1670             $tline = " (line number ".$attr->line.")"
1671             }
1672             elsif (ref($attr) eq 'ARRAY') {
1673             $tline = " (line number ".$attr->[1].")";
1674             }
1675             else {
1676             # May be the parser object knows the line number ?
1677             my $lineno = $parser->line;
1678             $tline = " (line number $lineno)" if $lineno > 1;
1679             }
1680              
1681             local $" = ', ';
1682             warn << "ERRMSG";
1683              
1684             Syntax error$stoken$tline.
1685             $expected
1686             ERRMSG
1687             };
1688              
1689             ################ end TailSupport #####################
1690              
1691             sub _DBLoad {
1692              
1693             #Already loaded ?
1694             __PACKAGE__->can('_DBParse') and return;
1695            
1696             my($fname)=__FILE__;
1697             my(@drv);
1698             local $/ = "\n";
1699             if (open(DRV,"<$fname")) {
1700             local $_;
1701             while() {
1702             #/^\s*sub\s+_Parse\s*{\s*$/ .. /^\s*}\s*#\s*_Parse\s*$/ and do {
1703             /^my\s+\$lex;##!!##$/ .. /^\s*}\s*#\s*_Parse\s*$/ and do {
1704             s/^#DBG>//;
1705             push(@drv,$_);
1706             }
1707             }
1708             close(DRV);
1709              
1710             $drv[1]=~s/_P/_DBP/;
1711             eval join('',@drv);
1712             }
1713             else {
1714             # TODO: debugging for standalone modules isn't supported yet
1715             *Parse::Eyapp::Driver::_DBParse = \&_Parse;
1716             }
1717             }
1718              
1719             ### Receives an index for the parsing stack: -1 is the top
1720             ### Returns the symbol associated with the state $index
1721             sub YYSymbol {
1722             my $self = shift;
1723             my $index = shift;
1724            
1725             return $self->{STACK}[$index][2];
1726             }
1727              
1728             # # YYSymbolStack(0,-k) string with symbols from 0 to last-k
1729             # # YYSymbolStack(-k-2,-k) string with symbols from last-k-2 to last-k
1730             # # YYSymbolStack(-k-2,-k, filter) string with symbols from last-k-2 to last-k that match with filter
1731             # # YYSymbolStack('SYMBOL',-k, filter) string with symbols from the last occurrence of SYMBOL to last-k
1732             # # where filter can be code, regexp or string
1733             # sub YYSymbolStack {
1734             # my $self = shift;
1735             # my ($a, $b, $filter) = @_;
1736             #
1737             # # $b must be negative
1738             # croak "Error: Second index in YYSymbolStack must be negative\n" unless $b < 0;
1739             #
1740             # my $stack = $self->{STACK};
1741             # my $bottom = -@{$stack};
1742             # unless (looks_like_number($a)) {
1743             # # $a is a string: search from the top to the bottom for $a. Return empty list if not found
1744             # # $b must be a negative number
1745             # # $b must be a negative number
1746             # my $p = $b;
1747             # while ($p >= $bottom) {
1748             # last if (defined($stack->[$p][2]) && ($stack->[$p][2] eq $a));
1749             # $p--;
1750             # }
1751             # return () if $p < $bottom;
1752             # $a = $p;
1753             # }
1754             # # If positive, $a is an offset from the bottom of the stack
1755             # $a = $bottom+$a if $a >= 0;
1756             #
1757             # my @a = map { $self->YYSymbol($_) or '' } $a..$b;
1758             #
1759             # return @a unless defined $filter; # no filter
1760             # return (grep { $filter->{$_} } @a) if reftype($filter) && (reftype($filter) eq 'CODE'); # sub
1761             # return (grep /$filter/, @a) if reftype($filter) && (reftype($filter) eq 'SCALAR'); # regexp
1762             # return (grep { $_ eq $filter } @a); # string
1763             # }
1764              
1765             #Note that for loading debugging version of the driver,
1766             #this file will be parsed from 'sub _Parse' up to '}#_Parse' inclusive.
1767             #So, DO NOT remove comment at end of sub !!!
1768             my $lex;##!!##
1769             sub _Parse {
1770             my($self)=shift;
1771              
1772             #my $lex = $self->{LEX};
1773              
1774             my($rules,$states,$error)
1775             = @$self{ 'RULES', 'STATES', 'ERROR' };
1776             my($errstatus,$nberror,$token,$value,$stack,$check,$dotpos)
1777             = @$self{ 'ERRST', 'NBERR', 'TOKEN', 'VALUE', 'STACK', 'CHECK', 'DOTPOS' };
1778              
1779             my %conflictiveStates = %{$self->{STATECONFLICT}};
1780             #DBG> my($debug)=$$self{DEBUG};
1781             #DBG> my($dbgerror)=0;
1782              
1783             #DBG> my($ShowCurToken) = sub {
1784             #DBG> my($tok)='>';
1785             #DBG> for (split('',$$token)) {
1786             #DBG> $tok.= (ord($_) < 32 or ord($_) > 126)
1787             #DBG> ? sprintf('<%02X>',ord($_))
1788             #DBG> : $_;
1789             #DBG> }
1790             #DBG> $tok.='<';
1791             #DBG> };
1792              
1793             $$errstatus=0;
1794             $$nberror=0;
1795             ($$token,$$value)=(undef,undef);
1796             @$stack=( [ 0, undef, ] );
1797             #DBG> push(@{$stack->[-1]}, undef);
1798             #@$stack=( [ 0, undef, undef ] );
1799             $$check='';
1800              
1801             while(1) {
1802             my($actions,$act,$stateno);
1803              
1804             $self->{POS} = pos(${$self->input()});
1805             $stateno=$$stack[-1][0];
1806             if (exists($conflictiveStates{$stateno})) {
1807             #warn "Conflictive state $stateno managed by conflict handler '$conflictiveStates{$stateno}{name}'\n"
1808             for my $h (@{$conflictiveStates{$stateno}}) {
1809             $self->{CURRENT_LHS} = $h->{name};
1810             $h->{codeh}($self);
1811             }
1812             }
1813              
1814             # check if the state is a conflictive one,
1815             # if so, execute its conflict handlers
1816             $actions=$$states[$stateno];
1817              
1818             #DBG> print STDERR ('-' x 40),"\n";
1819             #DBG> $debug & 0x2
1820             #DBG> and print STDERR "In state $stateno:\n";
1821             #DBG> $debug & 0x08
1822             #DBG> and print STDERR "Stack: ".
1823             #DBG> join('->',map { defined($$_[2])? "'$$_[2]'->".$$_[0] : $$_[0] } @$stack).
1824             #DBG> "\n";
1825              
1826              
1827             if (exists($$actions{ACTIONS})) {
1828              
1829             defined($$token)
1830             or do {
1831             ($$token,$$value)=$self->{LEX}->($self); # original line
1832             #($$token,$$value)=$self->$lex; # to make it a method call
1833             #($$token,$$value) = $self->{LEX}->($self); # sensitive to the lexer changes
1834             #DBG> $debug & 0x01
1835             #DBG> and do {
1836             #DBG> print STDERR "Need token. Got ".&$ShowCurToken."\n";
1837             #DBG> };
1838             };
1839              
1840             $act= exists($$actions{ACTIONS}{$$token})
1841             ? $$actions{ACTIONS}{$$token}
1842             : exists($$actions{DEFAULT})
1843             ? $$actions{DEFAULT}
1844             : undef;
1845             }
1846             else {
1847             $act=$$actions{DEFAULT};
1848             #DBG> $debug & 0x01
1849             #DBG> and print STDERR "Don't need token.\n";
1850             }
1851              
1852             defined($act)
1853             and do {
1854              
1855             $act > 0
1856             and do { #shift
1857              
1858             #DBG> $debug & 0x04
1859             #DBG> and print STDERR "Shift and go to state $act.\n";
1860              
1861             $$errstatus
1862             and do {
1863             --$$errstatus;
1864              
1865             #DBG> $debug & 0x10
1866             #DBG> and $dbgerror
1867             #DBG> and $$errstatus == 0
1868             #DBG> and do {
1869             #DBG> print STDERR "**End of Error recovery.\n";
1870             #DBG> $dbgerror=0;
1871             #DBG> };
1872             };
1873              
1874              
1875             push(@$stack,[ $act, $$value ]);
1876             #DBG> push(@{$stack->[-1]},$$token);
1877              
1878             defined($$token) and ($$token ne '') #Don't eat the eof
1879             and $$token=$$value=undef;
1880             next;
1881             };
1882              
1883             #reduce
1884             my($lhs,$len,$code,@sempar,$semval);
1885             ($lhs,$len,$code)=@{$$rules[-$act]};
1886              
1887             #DBG> $debug & 0x04
1888             #DBG> and $act
1889             #DBG> #and print STDERR "Reduce using rule ".-$act." ($lhs,$len): "; # old Parse::Yapp line
1890             #DBG> and do { my @rhs = @{$self->{GRAMMAR}->[-$act]->[2]};
1891             #DBG> @rhs = ( '/* empty */' ) unless @rhs;
1892             #DBG> my $rhs = "@rhs";
1893             #DBG> $rhs = substr($rhs, 0, 30).'...' if length($rhs) > 30; # chomp if too large
1894             #DBG> print STDERR "Reduce using rule ".-$act." ($lhs --> $rhs): ";
1895             #DBG> };
1896              
1897             $act
1898             or $self->YYAccept();
1899              
1900             $$dotpos=$len;
1901              
1902             unpack('A1',$lhs) eq '@' #In line rule
1903             and do {
1904             $lhs =~ /^\@[0-9]+\-([0-9]+)$/
1905             or die "In line rule name '$lhs' ill formed: ".
1906             "report it as a BUG.\n";
1907             $$dotpos = $1;
1908             };
1909              
1910             @sempar = $$dotpos
1911             ? map { $$_[1] } @$stack[ -$$dotpos .. -1 ]
1912             : ();
1913              
1914             $self->{CURRENT_LHS} = $lhs;
1915             $self->{CURRENT_RULE} = -$act; # count the super-rule?
1916             $semval = $code ? $self->$code( @sempar )
1917             : @sempar ? $sempar[0] : undef;
1918              
1919             splice(@$stack,-$len,$len);
1920              
1921             $$check eq 'ACCEPT'
1922             and do {
1923              
1924             #DBG> $debug & 0x04
1925             #DBG> and print STDERR "Accept.\n";
1926              
1927             return($semval);
1928             };
1929              
1930             $$check eq 'ABORT'
1931             and do {
1932              
1933             #DBG> $debug & 0x04
1934             #DBG> and print STDERR "Abort.\n";
1935              
1936             return(undef);
1937              
1938             };
1939              
1940             #DBG> $debug & 0x04
1941             #DBG> and print STDERR "Back to state $$stack[-1][0], then ";
1942              
1943             $$check eq 'ERROR'
1944             or do {
1945             #DBG> $debug & 0x04
1946             #DBG> and print STDERR
1947             #DBG> "go to state $$states[$$stack[-1][0]]{GOTOS}{$lhs}.\n";
1948              
1949             #DBG> $debug & 0x10
1950             #DBG> and $dbgerror
1951             #DBG> and $$errstatus == 0
1952             #DBG> and do {
1953             #DBG> print STDERR "**End of Error recovery.\n";
1954             #DBG> $dbgerror=0;
1955             #DBG> };
1956              
1957             push(@$stack,
1958             [ $$states[$$stack[-1][0]]{GOTOS}{$lhs}, $semval, ]);
1959             #[ $$states[$$stack[-1][0]]{GOTOS}{$lhs}, $semval, $lhs ]);
1960             #DBG> push(@{$stack->[-1]},$lhs);
1961             $$check='';
1962             $self->{CURRENT_LHS} = undef;
1963             next;
1964             };
1965              
1966             #DBG> $debug & 0x04
1967             #DBG> and print STDERR "Forced Error recovery.\n";
1968              
1969             $$check='';
1970              
1971             };
1972              
1973             #Error
1974             $$errstatus
1975             or do {
1976              
1977             $$errstatus = 1;
1978             &$error($self);
1979             $$errstatus # if 0, then YYErrok has been called
1980             or next; # so continue parsing
1981              
1982             #DBG> $debug & 0x10
1983             #DBG> and do {
1984             #DBG> print STDERR "**Entering Error recovery.\n";
1985             #DBG> {
1986             #DBG> local $" = ", ";
1987             #DBG> my @expect = map { ">$_<" } $self->YYExpect();
1988             #DBG> print STDERR "Expecting one of: @expect\n";
1989             #DBG> };
1990             #DBG> ++$dbgerror;
1991             #DBG> };
1992              
1993             ++$$nberror;
1994              
1995             };
1996              
1997             $$errstatus == 3 #The next token is not valid: discard it
1998             and do {
1999             $$token eq '' # End of input: no hope
2000             and do {
2001             #DBG> $debug & 0x10
2002             #DBG> and print STDERR "**At eof: aborting.\n";
2003             return(undef);
2004             };
2005              
2006             #DBG> $debug & 0x10
2007             #DBG> and print STDERR "**Discard invalid token ".&$ShowCurToken.".\n";
2008              
2009             $$token=$$value=undef;
2010             };
2011              
2012             $$errstatus=3;
2013              
2014             while( @$stack
2015             and ( not exists($$states[$$stack[-1][0]]{ACTIONS})
2016             or not exists($$states[$$stack[-1][0]]{ACTIONS}{error})
2017             or $$states[$$stack[-1][0]]{ACTIONS}{error} <= 0)) {
2018              
2019             #DBG> $debug & 0x10
2020             #DBG> and print STDERR "**Pop state $$stack[-1][0].\n";
2021              
2022             pop(@$stack);
2023             }
2024              
2025             @$stack
2026             or do {
2027              
2028             #DBG> $debug & 0x10
2029             #DBG> and print STDERR "**No state left on stack: aborting.\n";
2030              
2031             return(undef);
2032             };
2033              
2034             #shift the error token
2035              
2036             #DBG> $debug & 0x10
2037             #DBG> and print STDERR "**Shift \$error token and go to state ".
2038             #DBG> $$states[$$stack[-1][0]]{ACTIONS}{error}.
2039             #DBG> ".\n";
2040              
2041             push(@$stack, [ $$states[$$stack[-1][0]]{ACTIONS}{error}, undef, 'error' ]);
2042              
2043             }
2044              
2045             #never reached
2046             croak("Error in driver logic. Please, report it as a BUG");
2047              
2048             }#_Parse
2049             #DO NOT remove comment
2050              
2051             *Parse::Eyapp::Driver::lexer = \&Parse::Eyapp::Driver::YYLexer;
2052             sub YYLexer {
2053             my $self = shift;
2054              
2055             if (ref $self) { # instance method
2056             # The class attribute isn't changed, only the instance
2057             $self->{LEX} = shift if @_;
2058              
2059             return $self->static_attribute('LEX', @_,) unless defined($self->{LEX}); # class/static method
2060             return $self->{LEX};
2061             }
2062             else {
2063             return $self->static_attribute('LEX', @_,);
2064             }
2065             }
2066              
2067              
2068             1;
2069              
2070              
2071             MODULE_Parse_Eyapp_Driver
2072 1 50 33 1   137 }; # Unless Parse::Eyapp::Driver was loaded
  1 0 0 1   5  
  1 50 0 1   2  
  1 50 0 1   76  
  1 0 0 1   6  
  1 0 0 1   2  
  1 0 0 1   89  
  1 0 0 1   5  
  1 0 0 1   2  
  1 0 0 1   126  
  1 0 0 1   1250  
  1 0 0 20   15474  
  1 0 0 4   8  
  1 0 0 0   4462  
  1 0 0 4   2  
  1 0 0 1   170  
  1 0 0 0   5  
  1 0 0 0   11  
  1 0 0 0   129  
  1 0 0 0   5  
  1 0 66 0   1  
  1 0 0 0   595  
  1 0 0 0   6  
  1 0 0 0   2  
  1 0 0 0   1691  
  1 0 0 0   52  
  1 0 0 0   5  
  1 0 0 0   2  
  1 0 0 0   1937  
  1 0 0 0   7  
  1 0 0 0   2  
  1 0 0 0   2249  
  20 0 50 0   23  
  20 0 33 0   142  
  20 0 0 0   264  
  4 0 50 0   153  
  4 0   0   6  
  4 0   0   11  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  4 0   0   30  
  4 0   0   11  
  4 0   0   19  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  4 0   1   7  
  4 0   0   9  
  4 0   0   7  
  4 0   0   8  
  1 0   0   2  
  1 0   0   3  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   4   0  
  0 0   0   0  
  0 0   1   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 50   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 50   0   0  
  0 0   0   0  
  0 50   5   0  
  0 0   0   0  
  0 50   0   0  
  0 0   4   0  
  0 50   0   0  
  0 0   0   0  
  0 0   1   0  
  0 0   0   0  
  0 0   650   0  
  0 0   4   0  
  0 0   0   0  
  0 0   1   0  
  0 0   1   0  
  0 0   0   0  
  0 0   2   0  
  0 0   222   0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 50       0  
  0 50       0  
  0 50       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 50       0  
  0 100       0  
  0 50       0  
  0 100       0  
  0 100       0  
  0 50       0  
  0 100       0  
  0 100       0  
  0 100       0  
  0 0       0  
  0 50       0  
  0 100       0  
  0 50       0  
  0 100       0  
  0 100       0  
  0 50       0  
  0 50       0  
  0 50       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 50       0  
  0 100       0  
  0 50       0  
  0 100       0  
  0 50       0  
  0 50       0  
  0 50       0  
  0 50       0  
  0 50       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 50       0  
  0 50       0  
  0 50       0  
  0 50       0  
  0 50       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 50       0  
  0 50       0  
  0 100       0  
  0 50       0  
  0 50       0  
  0 50       0  
  0 50       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  1         2  
  1         5  
  0         0  
  0         0  
  0         0  
  1         11  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  4         7  
  4         7  
  4         55  
  4         15  
  0         0  
  0         0  
  4         12  
  0         0  
  0         0  
  4         10  
  0         0  
  0         0  
  0         0  
  4         18  
  4         35  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  1         2  
  1         4  
  1         29  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  5         17  
  5         9  
  5         14  
  5         221  
  17         30  
  17         49  
  17         49  
  17         46  
  17         72  
  5         17  
  8         34  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  4         44  
  4         13  
  4         15  
  4         5  
  4         15  
  4         7  
  4         5  
  4         7  
  4         23  
  4         10  
  4         4  
  416         443  
  416         365  
  416         781  
  416         2082  
  416         1136  
  0         0  
  0         0  
  0         0  
  0         0  
  416         491  
  416         782  
  324         708  
  222         608  
  324         1396  
  92         130  
  416         815  
  416         745  
  222         413  
  0         0  
  222         2552  
  222         1146  
  222         384  
  194         204  
  194         193  
  194         498  
  194         516  
  194         202  
  194         604  
  0         0  
  0         0  
  194         518  
  412         1106  
  194         356  
  194         245  
  194         595  
  194         450  
  194         458  
  4         21  
  190         336  
  0         0  
  190         367  
  190         701  
  190         262  
  190         244  
  190         465  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  1         3  
  1         5  
  0         0  
  0         0  
  0         0  
  1         9  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  650         984  
  650         1284  
  650         1211  
  650         1627  
  4         10  
  0         0  
  4         5  
  4         17  
  650         1775  
  650         1792  
  0         0  
  4         7  
  4         23  
  4         12  
  4         21  
  4         8  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  1         3  
  1         9  
  1         6  
  1         2  
  1         10  
  1         3  
  20         106  
  20         53  
  1         10  
  1         5  
  0         0  
  0         0  
  0         0  
  1         4  
  1         3  
  1         26  
  1         9  
  1         17  
  1         64  
  1         6  
  1         11  
  1         16  
  1         5  
  1         9  
  1         6  
  1         4  
  1         6  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  2         3  
  2         7  
  2         3  
  2         2  
  2         7  
  2         7  
  0         0  
  0         0  
  2         16  
  1         7  
  1         1  
  1         8  
  1         3  
  1         5  
  1         4  
  1         5  
  1         4  
  1         5  
  1         7  
  1         8  
  0         0  
  0         0  
  0         0  
  0         0  
  222         308  
  222         478  
  222         562  
  222         431  
  222         10531  
  0         0  
2073             } ########### End of BEGIN { load /home/book/perl5/lib/perl5/Parse/Eyapp/Driver.pm }
2074              
2075             # Loading Parse::Eyapp::Node
2076             BEGIN {
2077 1 50   1   23 unless (Parse::Eyapp::Node->can('m')) {
2078             eval << 'MODULE_Parse_Eyapp_Node'
2079             # (c) Parse::Eyapp Copyright 2006-2008 Casiano Rodriguez-Leon, all rights reserved.
2080             package Parse::Eyapp::Node;
2081             use strict;
2082             use Carp;
2083             no warnings 'recursion';use List::Util qw(first);
2084             use Data::Dumper;
2085              
2086             our $FILENAME=__FILE__;
2087              
2088             sub firstval(&@) {
2089             my $handler = shift;
2090            
2091             return (grep { $handler->($_) } @_)[0]
2092             }
2093              
2094             sub lastval(&@) {
2095             my $handler = shift;
2096            
2097             return (grep { $handler->($_) } @_)[-1]
2098             }
2099              
2100             ####################################################################
2101             # Usage :
2102             # line: %name PROG
2103             # exp <%name EXP + ';'>
2104             # { @{$lhs->{t}} = map { $_->{t}} ($lhs->child(0)->children()); }
2105             # ;
2106             # Returns : The array of children of the node. When the tree is a
2107             # translation scheme the CODE references are also included
2108             # Parameters : the node (method)
2109             # See Also : Children
2110              
2111             sub children {
2112             my $self = CORE::shift;
2113            
2114             return () unless UNIVERSAL::can($self, 'children');
2115             @{$self->{children}} = @_ if @_;
2116             @{$self->{children}}
2117             }
2118              
2119             ####################################################################
2120             # Usage : line: %name PROG
2121             # (exp) <%name EXP + ';'>
2122             # { @{$lhs->{t}} = map { $_->{t}} ($_[1]->Children()); }
2123             #
2124             # Returns : The true children of the node, excluding CODE CHILDREN
2125             # Parameters : The Node object
2126              
2127             sub Children {
2128             my $self = CORE::shift;
2129            
2130             return () unless UNIVERSAL::can($self, 'children');
2131              
2132             @{$self->{children}} = @_ if @_;
2133             grep { !UNIVERSAL::isa($_, 'CODE') } @{$self->{children}}
2134             }
2135              
2136             ####################################################################
2137             # Returns : Last non CODE child
2138             # Parameters : the node object
2139              
2140             sub Last_child {
2141             my $self = CORE::shift;
2142              
2143             return unless UNIVERSAL::can($self, 'children') and @{$self->{children}};
2144             my $i = -1;
2145             $i-- while defined($self->{children}->[$i]) and UNIVERSAL::isa($self->{children}->[$i], 'CODE');
2146             return $self->{children}->[$i];
2147             }
2148              
2149             sub last_child {
2150             my $self = CORE::shift;
2151              
2152             return unless UNIVERSAL::can($self, 'children') and @{$self->{children}};
2153             ${$self->{children}}[-1];
2154             }
2155              
2156             ####################################################################
2157             # Usage : $node->child($i)
2158             # my $transform = Parse::Eyapp::Treeregexp->new( STRING => q{
2159             # commutative_add: PLUS($x, ., $y, .)
2160             # => { my $t = $x; $_[0]->child(0, $y); $_[0]->child(2, $t)}
2161             # }
2162             # Purpose : Setter-getter to modify a specific child of a node
2163             # Returns : Child with index $i. Returns undef if the child does not exists
2164             # Parameters : Method: the node and the index of the child. The new value is used
2165             # as a setter.
2166             # Throws : Croaks if the index parameter is not provided
2167             sub child {
2168             my ($self, $index, $value) = @_;
2169            
2170             #croak "$self is not a Parse::Eyapp::Node" unless $self->isa('Parse::Eyapp::Node');
2171             return undef unless UNIVERSAL::can($self, 'child');
2172             croak "Index not provided" unless defined($index);
2173             $self->{children}[$index] = $value if defined($value);
2174             $self->{children}[$index];
2175             }
2176              
2177             sub descendant {
2178             my $self = shift;
2179             my $coord = shift;
2180              
2181             my @pos = split /\./, $coord;
2182             my $t = $self;
2183             my $x = shift(@pos); # discard the first empty dot
2184             for (@pos) {
2185             croak "Error computing descendant: $_ is not a number\n"
2186             unless m{\d+} and $_ < $t->children;
2187             $t = $t->child($_);
2188             }
2189             return $t;
2190             }
2191              
2192             ####################################################################
2193             # Usage : $node->s(@transformationlist);
2194             # Example : The following example simplifies arithmetic expressions
2195             # using method "s":
2196             # > cat Timeszero.trg
2197             # /* Operator "and" has higher priority than comma "," */
2198             # whatever_times_zero: TIMES(@b, NUM($x) and { $x->{attr} == 0 }) => { $_[0] = $NUM }
2199             #
2200             # > treereg Timeszero
2201             # > cat arrays.pl
2202             # !/usr/bin/perl -w
2203             # use strict;
2204             # use Rule6;
2205             # use Parse::Eyapp::Treeregexp;
2206             # use Timeszero;
2207             #
2208             # my $parser = new Rule6();
2209             # my $t = $parser->Run;
2210             # $t->s(@Timeszero::all);
2211             #
2212             #
2213             # Returns : Nothing
2214             # Parameters : The object (is a method) and the list of transformations to apply.
2215             # The list may be a list of Parse::Eyapp:YATW objects and/or CODE
2216             # references
2217             # Throws : No exceptions
2218             # Comments : The set of transformations is repeatedly applied to the node
2219             # until there are no changes.
2220             # The function may hang if the set of transformations
2221             # matches forever.
2222             # See Also : The "s" method for Parse::Eyapp::YATW objects
2223             # (i.e. transformation objects)
2224              
2225             sub s {
2226             my @patterns = @_[1..$#_];
2227              
2228             # Make them Parse::Eyapp:YATW objects if they are CODE references
2229             @patterns = map { ref($_) eq 'CODE'?
2230             Parse::Eyapp::YATW->new(
2231             PATTERN => $_,
2232             #PATTERN_ARGS => [],
2233             )
2234             :
2235             $_
2236             }
2237             @patterns;
2238             my $changes;
2239             do {
2240             $changes = 0;
2241             foreach (@patterns) {
2242             $_->{CHANGES} = 0;
2243             $_->s($_[0]);
2244             $changes += $_->{CHANGES};
2245             }
2246             } while ($changes);
2247             }
2248              
2249              
2250             ####################################################################
2251             # Usage : ????
2252             # Purpose : bud = Bottom Up Decoration: Decorates the tree with flowers :-)
2253             # The purpose is to decorate the AST with attributes during
2254             # the context-dependent analysis, mainly type-checking.
2255             # Returns : ????
2256             # Parameters : The transformations.
2257             # Throws : no exceptions
2258             # Comments : The tree is traversed bottom-up. The set of
2259             # transformations is applied to each node in the order
2260             # supplied by the user. As soon as one succeeds
2261             # no more transformations are applied.
2262             # See Also : n/a
2263             # To Do : Avoid closure. Save @patterns inside the object
2264             {
2265             my @patterns;
2266              
2267             sub bud {
2268             @patterns = @_[1..$#_];
2269              
2270             @patterns = map { ref($_) eq 'CODE'?
2271             Parse::Eyapp::YATW->new(
2272             PATTERN => $_,
2273             #PATTERN_ARGS => [],
2274             )
2275             :
2276             $_
2277             }
2278             @patterns;
2279             _bud($_[0], undef, undef);
2280             }
2281              
2282             sub _bud {
2283             my $node = $_[0];
2284             my $index = $_[2];
2285              
2286             # Is an odd leaf. Not actually a Parse::Eyapp::Node. Decorate it and leave
2287             if (!ref($node) or !UNIVERSAL::can($node, "children")) {
2288             for my $p (@patterns) {
2289             return if $p->pattern->(
2290             $_[0], # Node being visited
2291             $_[1], # Father of this node
2292             $index, # Index of this node in @Father->children
2293             $p, # The YATW pattern object
2294             );
2295             }
2296             };
2297              
2298             # Recursively decorate subtrees
2299             my $i = 0;
2300             for (@{$node->{children}}) {
2301             $_->_bud($_, $_[0], $i);
2302             $i++;
2303             }
2304              
2305             # Decorate the node
2306             #Change YATW object to be the first argument?
2307             for my $p (@patterns) {
2308             return if $p->pattern->($_[0], $_[1], $index, $p);
2309             }
2310             }
2311             } # closure for @patterns
2312              
2313             ####################################################################
2314             # Usage :
2315             # @t = Parse::Eyapp::Node->new( q{TIMES(NUM(TERMINAL), NUM(TERMINAL))},
2316             # sub {
2317             # our ($TIMES, @NUM, @TERMINAL);
2318             # $TIMES->{type} = "binary operation";
2319             # $NUM[0]->{type} = "int";
2320             # $NUM[1]->{type} = "float";
2321             # $TERMINAL[1]->{attr} = 3.5;
2322             # },
2323             # );
2324             # Purpose : Multi-Constructor
2325             # Returns : Array of pointers to the objects created
2326             # in scalar context a pointer to the first node
2327             # Parameters : The class plus the string description and attribute handler
2328              
2329             {
2330              
2331             my %cache;
2332              
2333             sub m_bless {
2334              
2335             my $key = join "",@_;
2336             my $class = shift;
2337             return $cache{$key} if exists $cache{$key};
2338              
2339             my $b = bless { children => \@_}, $class;
2340             $cache{$key} = $b;
2341              
2342             return $b;
2343             }
2344             }
2345              
2346             sub _bless {
2347             my $class = shift;
2348              
2349             my $b = bless { children => \@_ }, $class;
2350             return $b;
2351             }
2352              
2353             sub hexpand {
2354             my $class = CORE::shift;
2355              
2356             my $handler = CORE::pop if ref($_[-1]) eq 'CODE';
2357             my $n = m_bless(@_);
2358              
2359             my $newnodeclass = CORE::shift;
2360              
2361             no strict 'refs';
2362             push @{$newnodeclass."::ISA"}, 'Parse::Eyapp::Node' unless $newnodeclass->isa('Parse::Eyapp::Node');
2363              
2364             if (defined($handler) and UNIVERSAL::isa($handler, "CODE")) {
2365             $handler->($n);
2366             }
2367              
2368             $n;
2369             }
2370              
2371             sub hnew {
2372             my $blesser = \&m_bless;
2373              
2374             return _new($blesser, @_);
2375             }
2376              
2377             # Regexp for a full Perl identifier
2378             sub _new {
2379             my $blesser = CORE::shift;
2380             my $class = CORE::shift;
2381             local $_ = CORE::shift; # string: tree description
2382             my $handler = CORE::shift if ref($_[0]) eq 'CODE';
2383              
2384              
2385             my %classes;
2386             my $b;
2387             #TODO: Shall I receive a prefix?
2388              
2389             my (@stack, @index, @results, %results, @place, $open);
2390             #skip white spaces
2391             s{\A\s+}{};
2392             while ($_) {
2393             # If is a leaf is followed by parenthesis or comma or an ID
2394             s{\A([A-Za-z_][A-Za-z0-9_:]*)\s*([),])}
2395             {$1()$2} # ... then add an empty pair of parenthesis
2396             and do {
2397             next;
2398             };
2399              
2400             # If is a leaf is followed by an ID
2401             s{\A([A-Za-z_][A-Za-z0-9_:]*)\s+([A-Za-z_])}
2402             {$1()$2} # ... then add an empty pair of parenthesis
2403             and do {
2404             next;
2405             };
2406              
2407             # If is a leaf at the end
2408             s{\A([A-Za-z_][A-Za-z0-9_:]*)\s*$}
2409             {$1()} # ... then add an empty pair of parenthesis
2410             and do {
2411             $classes{$1} = 1;
2412             next;
2413             };
2414              
2415             # Is an identifier
2416             s{\A([A-Za-z_][A-Za-z0-9_:]*)}{}
2417             and do {
2418             $classes{$1} = 1;
2419             CORE::push @stack, $1;
2420             next;
2421             };
2422              
2423             # Open parenthesis: mark the position for when parenthesis closes
2424             s{\A[(]}{}
2425             and do {
2426             my $pos = scalar(@stack);
2427             CORE::push @index, $pos;
2428             $place[$pos] = $open++;
2429              
2430             # Warning! I don't know what I am doing
2431             next;
2432             };
2433              
2434             # Skip commas
2435             s{\A,}{} and next;
2436              
2437             # Closing parenthesis: time to build a node
2438             s{\A[)]}{} and do {
2439             croak "Syntax error! Closing parenthesis has no left partner!" unless @index;
2440             my $begin = pop @index; # check if empty!
2441             my @children = splice(@stack, $begin);
2442             my $class = pop @stack;
2443             croak "Syntax error! Any couple of parenthesis must be preceded by an identifier"
2444             unless (defined($class) and $class =~ m{^[a-zA-Z_][\w:]*$});
2445              
2446             $b = $blesser->($class, @children);
2447              
2448             CORE::push @stack, $b;
2449             $results[$place[$begin]] = $b;
2450             CORE::push @{$results{$class}}, $b;
2451             next;
2452             };
2453              
2454             last unless $_;
2455              
2456             #skip white spaces
2457             croak "Error building Parse::Eyapp::Node tree at '$_'." unless s{\A\s+}{};
2458             } # while
2459             croak "Syntax error! Open parenthesis has no right partner!" if @index;
2460             {
2461             no strict 'refs';
2462             for (keys(%classes)) {
2463             push @{$_."::ISA"}, 'Parse::Eyapp::Node' unless $_->isa('Parse::Eyapp::Node');
2464             }
2465             }
2466             if (defined($handler) and UNIVERSAL::isa($handler, "CODE")) {
2467             $handler->(@results);
2468             }
2469             return wantarray? @results : $b;
2470             }
2471              
2472             sub new {
2473             my $blesser = \&_bless;
2474              
2475             _new($blesser, @_);
2476             }
2477              
2478             ## Used by _subtree_list
2479             #sub compute_hierarchy {
2480             # my @results = @{shift()};
2481             #
2482             # # Compute the hierarchy
2483             # my $b;
2484             # my @r = @results;
2485             # while (@results) {
2486             # $b = pop @results;
2487             # my $d = $b->{depth};
2488             # my $f = lastval { $_->{depth} < $d} @results;
2489             #
2490             # $b->{father} = $f;
2491             # $b->{children} = [];
2492             # unshift @{$f->{children}}, $b;
2493             # }
2494             # $_->{father} = undef for @results;
2495             # bless $_, "Parse::Eyapp::Node::Match" for @r;
2496             # return @r;
2497             #}
2498              
2499             # Matches
2500              
2501             sub m {
2502             my $self = shift;
2503             my @patterns = @_ or croak "Expected a pattern!";
2504             croak "Error in method m of Parse::Eyapp::Node. Expected Parse::Eyapp:YATW patterns"
2505             unless $a = first { !UNIVERSAL::isa($_, "Parse::Eyapp:YATW") } @_;
2506              
2507             # array context: return all matches
2508             local $a = 0;
2509             my %index = map { ("$_", $a++) } @patterns;
2510             my @stack = (
2511             Parse::Eyapp::Node::Match->new(
2512             node => $self,
2513             depth => 0,
2514             dewey => "",
2515             patterns =>[]
2516             )
2517             );
2518             my @results;
2519             do {
2520             my $mn = CORE::shift(@stack);
2521             my %n = %$mn;
2522              
2523             # See what patterns do match the current $node
2524             for my $pattern (@patterns) {
2525             push @{$mn->{patterns}}, $index{$pattern} if $pattern->{PATTERN}($n{node});
2526             }
2527             my $dewey = $n{dewey};
2528             if (@{$mn->{patterns}}) {
2529             $mn->{family} = \@patterns;
2530              
2531             # Is at this time that I have to compute the father
2532             my $f = lastval { $dewey =~ m{^$_->{dewey}}} @results;
2533             $mn->{father} = $f;
2534             # ... and children
2535             push @{$f->{children}}, $mn if defined($f);
2536             CORE::push @results, $mn;
2537             }
2538             my $childdepth = $n{depth}+1;
2539             my $k = -1;
2540             CORE::unshift @stack,
2541             map
2542             {
2543             $k++;
2544             Parse::Eyapp::Node::Match->new(
2545             node => $_,
2546             depth => $childdepth,
2547             dewey => "$dewey.$k",
2548             patterns => []
2549             )
2550             } $n{node}->children();
2551             } while (@stack);
2552              
2553             wantarray? @results : $results[0];
2554             }
2555              
2556             #sub _subtree_scalar {
2557             # # scalar context: return iterator
2558             # my $self = CORE::shift;
2559             # my @patterns = @_ or croak "Expected a pattern!";
2560             #
2561             # # %index gives the index of $p in @patterns
2562             # local $a = 0;
2563             # my %index = map { ("$_", $a++) } @patterns;
2564             #
2565             # my @stack = ();
2566             # my $mn = { node => $self, depth => 0, patterns =>[] };
2567             # my @results = ();
2568             #
2569             # return sub {
2570             # do {
2571             # # See if current $node matches some patterns
2572             # my $d = $mn->{depth};
2573             # my $childdepth = $d+1;
2574             # # See what patterns do match the current $node
2575             # for my $pattern (@patterns) {
2576             # push @{$mn->{patterns}}, $index{$pattern} if $pattern->{PATTERN}($mn->{node});
2577             # }
2578             #
2579             # if (@{$mn->{patterns}}) { # matched
2580             # CORE::push @results, $mn;
2581             #
2582             # # Compute the hierarchy
2583             # my $f = lastval { $_->{depth} < $d} @results;
2584             # $mn->{father} = $f;
2585             # $mn->{children} = [];
2586             # $mn->{family} = \@patterns;
2587             # unshift @{$f->{children}}, $mn if defined($f);
2588             # bless $mn, "Parse::Eyapp::Node::Match";
2589             #
2590             # # push children in the stack
2591             # CORE::unshift @stack,
2592             # map { { node => $_, depth => $childdepth, patterns => [] } }
2593             # $mn->{node}->children();
2594             # $mn = CORE::shift(@stack);
2595             # return $results[-1];
2596             # }
2597             # # didn't match: push children in the stack
2598             # CORE::unshift @stack,
2599             # map { { node => $_, depth => $childdepth, patterns => [] } }
2600             # $mn->{node}->children();
2601             # $mn = CORE::shift(@stack);
2602             # } while ($mn); # May be the stack is empty now, but if $mn then there is a node to process
2603             # # reset iterator
2604             # my @stack = ();
2605             # my $mn = { node => $self, depth => 0, patterns =>[] };
2606             # return undef;
2607             # };
2608             #}
2609              
2610             # Factorize this!!!!!!!!!!!!!!
2611             #sub m {
2612             # goto &_subtree_list if (wantarray());
2613             # goto &_subtree_scalar;
2614             #}
2615              
2616             ####################################################################
2617             # Usage : $BLOCK->delete($ASSIGN)
2618             # $BLOCK->delete(2)
2619             # Purpose : deletes the specified child of the node
2620             # Returns : The deleted child
2621             # Parameters : The object plus the index or pointer to the child to be deleted
2622             # Throws : If the object can't do children or has no children
2623             # See Also : n/a
2624              
2625             sub delete {
2626             my $self = CORE::shift; # The tree object
2627             my $child = CORE::shift; # index or pointer
2628              
2629             croak "Parse::Eyapp::Node::delete error, node:\n"
2630             .Parse::Eyapp::Node::str($self)."\ndoes not have children"
2631             unless UNIVERSAL::can($self, 'children') and ($self->children()>0);
2632             if (ref($child)) {
2633             my $i = 0;
2634             for ($self->children()) {
2635             last if $_ == $child;
2636             $i++;
2637             }
2638             if ($i == $self->children()) {
2639             warn "Parse::Eyapp::Node::delete warning: node:\n".Parse::Eyapp::Node::str($self)
2640             ."\ndoes not have a child like:\n"
2641             .Parse::Eyapp::Node::str($child)
2642             ."\nThe node was not deleted!\n";
2643             return $child;
2644             }
2645             splice(@{$self->{children}}, $i, 1);
2646             return $child;
2647             }
2648             my $numchildren = $self->children();
2649             croak "Parse::Eyapp::Node::delete error: expected an index between 0 and ".
2650             ($numchildren-1).". Got $child" unless ($child =~ /\d+/ and $child < $numchildren);
2651             splice(@{$self->{children}}, $child, 1);
2652             return $child;
2653             }
2654              
2655             ####################################################################
2656             # Usage : $BLOCK->shift
2657             # Purpose : deletes the first child of the node
2658             # Returns : The deleted child
2659             # Parameters : The object
2660             # Throws : If the object can't do children
2661             # See Also : n/a
2662              
2663             sub shift {
2664             my $self = CORE::shift; # The tree object
2665              
2666             croak "Parse::Eyapp::Node::shift error, node:\n"
2667             .Parse::Eyapp::Node->str($self)."\ndoes not have children"
2668             unless UNIVERSAL::can($self, 'children');
2669              
2670             return CORE::shift(@{$self->{children}});
2671             }
2672              
2673             sub unshift {
2674             my $self = CORE::shift; # The tree object
2675             my $node = CORE::shift; # node to insert
2676              
2677             CORE::unshift @{$self->{children}}, $node;
2678             }
2679              
2680             sub push {
2681             my $self = CORE::shift; # The tree object
2682             #my $node = CORE::shift; # node to insert
2683              
2684             #CORE::push @{$self->{children}}, $node;
2685             CORE::push @{$self->{children}}, @_;
2686             }
2687              
2688             sub insert_before {
2689             my $self = CORE::shift; # The tree object
2690             my $child = CORE::shift; # index or pointer
2691             my $node = CORE::shift; # node to insert
2692              
2693             croak "Parse::Eyapp::Node::insert_before error, node:\n"
2694             .Parse::Eyapp::Node::str($self)."\ndoes not have children"
2695             unless UNIVERSAL::can($self, 'children') and ($self->children()>0);
2696              
2697             if (ref($child)) {
2698             my $i = 0;
2699             for ($self->children()) {
2700             last if $_ == $child;
2701             $i++;
2702             }
2703             if ($i == $self->children()) {
2704             warn "Parse::Eyapp::Node::insert_before warning: node:\n"
2705             .Parse::Eyapp::Node::str($self)
2706             ."\ndoes not have a child like:\n"
2707             .Parse::Eyapp::Node::str($child)."\nThe node was not inserted!\n";
2708             return $child;
2709             }
2710             splice(@{$self->{children}}, $i, 0, $node);
2711             return $node;
2712             }
2713             my $numchildren = $self->children();
2714             croak "Parse::Eyapp::Node::insert_before error: expected an index between 0 and ".
2715             ($numchildren-1).". Got $child" unless ($child =~ /\d+/ and $child < $numchildren);
2716             splice(@{$self->{children}}, $child, 0, $node);
2717             return $child;
2718             }
2719              
2720             sub insert_after {
2721             my $self = CORE::shift; # The tree object
2722             my $child = CORE::shift; # index or pointer
2723             my $node = CORE::shift; # node to insert
2724              
2725             croak "Parse::Eyapp::Node::insert_after error, node:\n"
2726             .Parse::Eyapp::Node::str($self)."\ndoes not have children"
2727             unless UNIVERSAL::can($self, 'children') and ($self->children()>0);
2728              
2729             if (ref($child)) {
2730             my $i = 0;
2731             for ($self->children()) {
2732             last if $_ == $child;
2733             $i++;
2734             }
2735             if ($i == $self->children()) {
2736             warn "Parse::Eyapp::Node::insert_after warning: node:\n"
2737             .Parse::Eyapp::Node::str($self).
2738             "\ndoes not have a child like:\n"
2739             .Parse::Eyapp::Node::str($child)."\nThe node was not inserted!\n";
2740             return $child;
2741             }
2742             splice(@{$self->{children}}, $i+1, 0, $node);
2743             return $node;
2744             }
2745             my $numchildren = $self->children();
2746             croak "Parse::Eyapp::Node::insert_after error: expected an index between 0 and ".
2747             ($numchildren-1).". Got $child" unless ($child =~ /\d+/ and $child < $numchildren);
2748             splice(@{$self->{children}}, $child+1, 0, $node);
2749             return $child;
2750             }
2751              
2752             { # $match closure
2753              
2754             my $match;
2755              
2756             sub clean_tree {
2757             $match = pop;
2758             croak "clean tree: a node and code reference expected" unless (ref($match) eq 'CODE') and (@_ > 0);
2759             $_[0]->_clean_tree();
2760             }
2761              
2762             sub _clean_tree {
2763             my @children;
2764            
2765             for ($_[0]->children()) {
2766             next if (!defined($_) or $match->($_));
2767            
2768             $_->_clean_tree();
2769             CORE::push @children, $_;
2770             }
2771             $_[0]->{children} = \@children; # Bad code
2772             }
2773             } # $match closure
2774              
2775             ####################################################################
2776             # Usage : $t->str
2777             # Returns : Returns a string describing the Parse::Eyapp::Node as a term
2778             # i.e., s.t. like: 'PROGRAM(FUNCTION(RETURN(TERMINAL,VAR(TERMINAL))))'
2779             our @PREFIXES = qw(Parse::Eyapp::Node::);
2780             our $INDENT = 0; # -1 new 0 = compact, 1 = indent, 2 = indent and include Types in closing parenthesis
2781             our $STRSEP = ',';
2782             our $DELIMITER = '[';
2783             our $FOOTNOTE_HEADER = "\n---------------------------\n";
2784             our $FOOTNOTE_SEP = ")\n";
2785             our $FOOTNOTE_LEFT = '^{';
2786             our $FOOTNOTE_RIGHT = '}';
2787             our $LINESEP = 4;
2788             our $CLASS_HANDLER = sub { type($_[0]) }; # What to print to identify the node
2789              
2790             my %match_del = (
2791             '[' => ']',
2792             '{' => '}',
2793             '(' => ')',
2794             '<' => '>'
2795             );
2796              
2797             my $pair;
2798             my $footnotes = '';
2799             my $footnote_label;
2800              
2801             sub str {
2802              
2803             my @terms;
2804              
2805             # Consume arg only if called as a class method Parse::Eyap::Node->str($node1, $node2, ...)
2806             CORE::shift unless ref($_[0]);
2807              
2808             for (@_) {
2809             $footnote_label = 0;
2810             $footnotes = '';
2811             # Set delimiters for semantic values
2812             if (defined($DELIMITER) and exists($match_del{$DELIMITER})) {
2813             $pair = $match_del{$DELIMITER};
2814             }
2815             else {
2816             $DELIMITER = $pair = '';
2817             }
2818             CORE::push @terms, _str($_).$footnotes;
2819             }
2820             return wantarray? @terms : $terms[0];
2821             }
2822              
2823             sub _str {
2824             my $self = CORE::shift; # root of the subtree
2825             my $indent = (CORE::shift or 0); # current depth in spaces " "
2826              
2827             my @children = Parse::Eyapp::Node::children($self);
2828             my @t;
2829              
2830             my $res;
2831             my $fn = $footnote_label;
2832             if ($INDENT >= 0 && UNIVERSAL::can($self, 'footnote')) {
2833             $res = $self->footnote;
2834             $footnotes .= $FOOTNOTE_HEADER.$footnote_label++.$FOOTNOTE_SEP.$res if $res;
2835             }
2836              
2837             # recursively visit nodes
2838             for (@children) {
2839             CORE::push @t, Parse::Eyapp::Node::_str($_, $indent+2) if defined($_);
2840             }
2841             local $" = $STRSEP;
2842             my $class = $CLASS_HANDLER->($self);
2843             $class =~ s/^$_// for @PREFIXES;
2844             my $information;
2845             $information = $self->info if ($INDENT >= 0 && UNIVERSAL::can($self, 'info'));
2846             $class .= $DELIMITER.$information.$pair if defined($information);
2847             if ($INDENT >= 0 && $res) {
2848             $class .= $FOOTNOTE_LEFT.$fn.$FOOTNOTE_RIGHT;
2849             }
2850              
2851             if ($INDENT > 0) {
2852             my $w = " "x$indent;
2853             $class = "\n$w$class";
2854             $class .= "(@t\n$w)" if @children;
2855             $class .= " # ".$CLASS_HANDLER->($self) if ($INDENT > 1) and ($class =~ tr/\n/\n/>$LINESEP);
2856             }
2857             else {
2858             $class .= "(@t)" if @children;
2859             }
2860             return $class;
2861             }
2862              
2863             sub _dot {
2864             my ($root, $number) = @_;
2865              
2866             my $type = $root->type();
2867              
2868             my $information;
2869             $information = $root->info if ($INDENT >= 0 && $root->can('info'));
2870             my $class = $CLASS_HANDLER->($root);
2871             $class = qq{$class$DELIMITER$information$pair} if defined($information);
2872              
2873             my $dot = qq{ $number [label = <$class>];\n};
2874              
2875             my $k = 0;
2876             my @dots = map { $k++; $_->_dot("$number$k") } $root->children;
2877              
2878             for($k = 1; $k <= $root->children; $k++) {;
2879             $dot .= qq{ $number -> $number$k;\n};
2880             }
2881              
2882             return $dot.join('',@dots);
2883             }
2884              
2885             sub dot {
2886             my $dot = $_[0]->_dot('0');
2887             return << "EOGRAPH";
2888             digraph G {
2889             ordering=out
2890              
2891             $dot
2892             }
2893             EOGRAPH
2894             }
2895              
2896             sub fdot {
2897             my ($self, $file) = @_;
2898              
2899             if ($file) {
2900             $file .= '.dot' unless $file =~ /\.dot$/;
2901             }
2902             else {
2903             $file = $self->type().".dot";
2904             }
2905             open my $f, "> $file";
2906             print $f $self->dot();
2907             close($f);
2908             }
2909              
2910             BEGIN {
2911             my @dotFormats = qw{bmp canon cgimage cmap cmapx cmapx_np eps exr fig gd gd2 gif gv imap imap_np ismap jp2 jpe jpeg jpg pct pdf pict plain plain-ext png ps ps2 psd sgi svg svgz tga tif tiff tk vml vmlz vrml wbmp x11 xdot xlib};
2912              
2913             for my $format (@dotFormats) {
2914            
2915             no strict 'refs';
2916             *{'Parse::Eyapp::Node::'.$format} = sub {
2917             my ($self, $file) = @_;
2918            
2919             $file = $self->type() unless defined($file);
2920            
2921             $self->fdot($file);
2922            
2923             $file =~ s/\.(dot|$format)$//;
2924             my $dotfile = "$file.dot";
2925             my $pngfile = "$file.$format";
2926             my $err = qx{dot -T$format $dotfile -o $pngfile 2>&1};
2927             return ($err, $?);
2928             }
2929             }
2930             }
2931              
2932             sub translation_scheme {
2933             my $self = CORE::shift; # root of the subtree
2934             my @children = $self->children();
2935             for (@children) {
2936             if (ref($_) eq 'CODE') {
2937             $_->($self, $self->Children);
2938             }
2939             elsif (defined($_)) {
2940             translation_scheme($_);
2941             }
2942             }
2943             }
2944              
2945             sub type {
2946             my $type = ref($_[0]);
2947              
2948             if ($type) {
2949             if (defined($_[1])) {
2950             $type = $_[1];
2951             Parse::Eyapp::Driver::BeANode($type);
2952             bless $_[0], $type;
2953             }
2954             return $type
2955             }
2956             return 'Parse::Eyapp::Node::STRING';
2957             }
2958              
2959             { # Tree "fuzzy" equality
2960              
2961             ####################################################################
2962             # Usage : $t1->equal($t2, n => sub { return $_[0] == $_[1] })
2963             # Purpose : Checks the equality between two AST
2964             # Returns : 1 if equal, 0 if not 'equal'
2965             # Parameters : Two Parse::Eyapp:Node nodes and a hash of comparison handlers.
2966             # The keys of the hash are the attributes of the nodes. The value is
2967             # a comparator function. The comparator for key $k receives the attribute
2968             # for the nodes being visited and rmust return true if they are considered similar
2969             # Throws : exceptions if the parameters aren't Parse::Eyapp::Nodes
2970              
2971             my %handler;
2972              
2973             # True if the two trees look similar
2974             sub equal {
2975             croak "Parse::Eyapp::Node::equal error. Expected two syntax trees \n" unless (@_ > 1);
2976              
2977             %handler = splice(@_, 2);
2978             my $key = '';
2979             defined($key=firstval {!UNIVERSAL::isa($handler{$_},'CODE') } keys %handler)
2980             and
2981             croak "Parse::Eyapp::Node::equal error. Expected a CODE ref for attribute $key\n";
2982             goto &_equal;
2983             }
2984              
2985             sub _equal {
2986             my $tree1 = CORE::shift;
2987             my $tree2 = CORE::shift;
2988              
2989             # Same type
2990             return 0 unless ref($tree1) eq ref($tree2);
2991              
2992             # Check attributes via handlers
2993             for (keys %handler) {
2994             # Check for existence
2995             return 0 if (exists($tree1->{$_}) && !exists($tree2->{$_}));
2996             return 0 if (exists($tree2->{$_}) && !exists($tree1->{$_}));
2997              
2998             # Check for definition
2999             return 0 if (defined($tree1->{$_}) && !defined($tree2->{$_}));
3000             return 0 if (defined($tree2->{$_}) && !defined($tree1->{$_}));
3001              
3002             # Check for equality
3003             return 0 unless $handler{$_}->($tree1->{$_}, $tree2->{$_});
3004             }
3005              
3006             # Same number of children
3007             my @children1 = @{$tree1->{children}};
3008             my @children2 = @{$tree2->{children}};
3009             return 0 unless @children1 == @children2;
3010              
3011             # Children must be similar
3012             for (@children1) {
3013             my $ch2 = CORE::shift @children2;
3014             return 0 unless _equal($_, $ch2);
3015             }
3016             return 1;
3017             }
3018             }
3019              
3020             1;
3021              
3022             package Parse::Eyapp::Node::Match;
3023             our @ISA = qw(Parse::Eyapp::Node);
3024              
3025             # A Parse::Eyapp::Node::Match object is a reference
3026             # to a tree of Parse::Eyapp::Nodes that has been used
3027             # in a tree matching regexp. You can think of them
3028             # as the equivalent of $1 $2, ... in treeregexeps
3029              
3030             # The depth of the Parse::Eyapp::Node being referenced
3031              
3032             sub new {
3033             my $class = shift;
3034              
3035             my $matchnode = { @_ };
3036             $matchnode->{children} = [];
3037             bless $matchnode, $class;
3038             }
3039              
3040             sub depth {
3041             my $self = shift;
3042              
3043             return $self->{depth};
3044             }
3045              
3046             # The coordinates of the Parse::Eyapp::Node being referenced
3047             sub coord {
3048             my $self = shift;
3049              
3050             return $self->{dewey};
3051             }
3052              
3053              
3054             # The Parse::Eyapp::Node being referenced
3055             sub node {
3056             my $self = shift;
3057              
3058             return $self->{node};
3059             }
3060              
3061             # The Parse::Eyapp::Node:Match that references
3062             # the nearest ancestor of $self->{node} that matched
3063             sub father {
3064             my $self = shift;
3065              
3066             return $self->{father};
3067             }
3068            
3069             # The patterns that matched with $self->{node}
3070             # Indexes
3071             sub patterns {
3072             my $self = shift;
3073              
3074             @{$self->{patterns}} = @_ if @_;
3075             return @{$self->{patterns}};
3076             }
3077            
3078             # The original list of patterns that produced this match
3079             sub family {
3080             my $self = shift;
3081              
3082             @{$self->{family}} = @_ if @_;
3083             return @{$self->{family}};
3084             }
3085            
3086             # The names of the patterns that matched
3087             sub names {
3088             my $self = shift;
3089              
3090             my @indexes = $self->patterns;
3091             my @family = $self->family;
3092              
3093             return map { $_->{NAME} or "Unknown" } @family[@indexes];
3094             }
3095            
3096             sub info {
3097             my $self = shift;
3098              
3099             my $node = $self->node;
3100             my @names = $self->names;
3101             my $nodeinfo;
3102             if (UNIVERSAL::can($node, 'info')) {
3103             $nodeinfo = ":".$node->info;
3104             }
3105             else {
3106             $nodeinfo = "";
3107             }
3108             return "[".ref($self->node).":".$self->depth.":@names$nodeinfo]"
3109             }
3110              
3111             1;
3112              
3113              
3114              
3115             MODULE_Parse_Eyapp_Node
3116 1 0 0 1   117 }; # Unless Parse::Eyapp::Node was loaded
  1 0 0 1   5  
  1 0 0 1   2  
  1 0 0 1   28  
  1 0 0 1   5  
  1 0 0 1   1  
  1 0 0 1   86  
  1 0 0 1   5  
  1 0 0 1   2  
  1 0 0 0   40  
  1 0 0 0   5  
  1 0 0 0   2  
  1 0 0 0   100  
  1 0 0 0   4255  
  1 0 0 0   12260  
  1 0 0 0   2198  
  1 0 0 0   10  
  1 0 0 0   2  
  1 0 0 0   820  
  1 0 0 0   6  
  1 0 0 0   3  
  1 0 0 0   3077  
  1 0 0 0   6  
  1 0 0 0   19  
  1 0 0 0   162  
  1 0 0 0   10  
  1 0 0 0   3  
  43 0   0   176  
  43 0   0   2709  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
3117             } ########### End of BEGIN { load /home/book/perl5/lib/perl5/Parse/Eyapp/Node.pm }
3118              
3119             # Loading Parse::Eyapp::YATW
3120             BEGIN {
3121 1 50   1   19 unless (Parse::Eyapp::YATW->can('m')) {
3122             eval << 'MODULE_Parse_Eyapp_YATW'
3123             # (c) Parse::Eyapp Copyright 2006-2008 Casiano Rodriguez-Leon, all rights reserved.
3124             package Parse::Eyapp::YATW;
3125             use strict;
3126             use warnings;
3127             use Carp;
3128             use Data::Dumper;
3129             use List::Util qw(first);
3130              
3131             sub firstval(&@) {
3132             my $handler = shift;
3133            
3134             return (grep { $handler->($_) } @_)[0]
3135             }
3136              
3137             sub lastval(&@) {
3138             my $handler = shift;
3139            
3140             return (grep { $handler->($_) } @_)[-1]
3141             }
3142              
3143             sub valid_keys {
3144             my %valid_args = @_;
3145              
3146             my @valid_args = keys(%valid_args);
3147             local $" = ", ";
3148             return "@valid_args"
3149             }
3150              
3151             sub invalid_keys {
3152             my $valid_args = shift;
3153             my $args = shift;
3154              
3155             return (first { !exists($valid_args->{$_}) } keys(%$args));
3156             }
3157              
3158              
3159             our $VERSION = $Parse::Eyapp::Driver::VERSION;
3160              
3161             our $FILENAME=__FILE__;
3162              
3163             # TODO: Check args. Typical args:
3164             # 'CHANGES' => 0,
3165             # 'PATTERN' => sub { "DUMMY" },
3166             # 'NAME' => 'fold',
3167             # 'PATTERN_ARGS' => [],
3168             # 'PENDING_TASKS' => {},
3169             # 'NODE' => []
3170              
3171             my %_new_yatw = (
3172             PATTERN => 'CODE',
3173             NAME => 'STRING',
3174             );
3175              
3176             my $validkeys = valid_keys(%_new_yatw);
3177              
3178             sub new {
3179             my $class = shift;
3180             my %args = @_;
3181              
3182             croak "Error. Expected a code reference when building a tree walker. " unless (ref($args{PATTERN}) eq 'CODE');
3183             if (defined($a = invalid_keys(\%_new_yatw, \%args))) {
3184             croak("Parse::Eyapp::YATW::new Error!: unknown argument $a. Valid arguments are: $validkeys")
3185             }
3186              
3187              
3188             # obsolete, I have to delete this
3189             #$args{PATTERN_ARGS} = [] unless (ref($args{PATTERN_ARGS}) eq 'ARRAY');
3190              
3191             # Internal fields
3192              
3193             # Tell us if the node has changed after the visit
3194             $args{CHANGES} = 0;
3195            
3196             # PENDING_TASKS is a queue storing the tasks waiting for a "safe time/node" to do them
3197             # Usually that time occurs when visiting the father of the node who generated the job
3198             # (when asap criteria is applied).
3199             # Keys are node references. Values are array references. Each entry defines:
3200             # [ the task kind, the node where to do the job, and info related to the particular job ]
3201             # Example: @{$self->{PENDING_TASKS}{$father}}, ['insert_before', $node, ${$self->{NODE}}[0] ];
3202             $args{PENDING_TASKS} = {};
3203              
3204             # NODE is a stack storing the ancestor of the node being visited
3205             # Example: my $ancestor = ${$self->{NODE}}[$k]; when k=1 is the father, k=2 the grandfather, etc.
3206             # Example: CORE::unshift @{$self->{NODE}}, $_[0]; Finished the visit so take it out
3207             $args{NODE} = [];
3208              
3209             bless \%args, $class;
3210             }
3211              
3212             sub buildpatterns {
3213             my $class = shift;
3214            
3215             my @family;
3216             while (my ($n, $p) = splice(@_, 0,2)) {
3217             push @family, Parse::Eyapp::YATW->new(NAME => $n, PATTERN => $p);
3218             }
3219             return wantarray? @family : $family[0];
3220             }
3221              
3222             ####################################################################
3223             # Usage : @r = $b{$_}->m($t)
3224             # See Simple4.eyp and m_yatw.pl in the examples directory
3225             # Returns : Returns an array of nodes matching the treeregexp
3226             # The set of nodes is a Parse::Eyapp::Node::Match tree
3227             # showing the relation between the matches
3228             # Parameters : The tree (and the object of course)
3229             # depth is no longer used: eliminate
3230             sub m {
3231             my $p = shift(); # pattern YATW object
3232             my $t = shift; # tree
3233             my $pattern = $p->{PATTERN}; # CODE ref
3234              
3235             # References to the found nodes are stored in @stack
3236             my @stack = ( Parse::Eyapp::Node::Match->new(node=>$t, depth=>0, dewey => "") );
3237             my @results;
3238             do {
3239             my $n = CORE::shift(@stack);
3240             my %n = %$n;
3241              
3242             my $dewey = $n->{dewey};
3243             my $d = $n->{depth};
3244             if ($pattern->($n{node})) {
3245             $n->{family} = [ $p ];
3246             $n->{patterns} = [ 0 ];
3247              
3248             # Is at this time that I have to compute the father
3249             my $f = lastval { $dewey =~ m{^$_->{dewey}}} @results;
3250             $n->{father} = $f;
3251             # ... and children
3252             push @{$f->{children}}, $n if defined($f);
3253             push @results, $n;
3254             }
3255             my $k = 0;
3256             CORE::unshift @stack,
3257             map {
3258             local $a;
3259             $a = Parse::Eyapp::Node::Match->new(node=>$_, depth=>$d+1, dewey=>"$dewey.$k" );
3260             $k++;
3261             $a;
3262             } $n{node}->children();
3263             } while (@stack);
3264              
3265             return wantarray? @results : $results[0];
3266             }
3267              
3268             ######################### getter-setter for YATW objects ###########################
3269              
3270             sub pattern {
3271             my $self = shift;
3272             $self->{PATTERN} = shift if (@_);
3273             return $self->{PATTERN};
3274             }
3275              
3276             sub name {
3277             my $self = shift;
3278             $self->{NAME} = shift if (@_);
3279             return $self->{NAME};
3280             }
3281              
3282             #sub pattern_args {
3283             # my $self = shift;
3284             #
3285             # $self->{PATTERN_ARGS} = @_ if @_;
3286             # return @{$self->{PATTERN_ARGS}};
3287             #}
3288              
3289             ########################## PENDING TASKS management ################################
3290              
3291             # Purpose : Deletes the node that matched from the list of children of its father.
3292             sub delete {
3293             my $self = shift;
3294              
3295             bless $self->{NODE}[0], 'Parse::Eyapp::Node::DELETE';
3296             }
3297            
3298             sub make_delete_effective {
3299             my $self = shift;
3300             my $node = shift;
3301              
3302             my $i = -1+$node->children;
3303             while ($i >= 0) {
3304             if (UNIVERSAL::isa($node->child($i), 'Parse::Eyapp::Node::DELETE')) {
3305             $self->{CHANGES}++ if defined(splice(@{$node->{children}}, $i, 1));
3306             }
3307             $i--;
3308             }
3309             }
3310              
3311             ####################################################################
3312             # Usage : my $b = Parse::Eyapp::Node->new( 'NUM(TERMINAL)', sub { $_[1]->{attr} = 4 });
3313             # $yatw_pattern->unshift($b);
3314             # Parameters : YATW object, node to insert,
3315             # ancestor offset: 0 = root of the tree that matched, 1 = father, 2 = granfather, etc.
3316              
3317             sub unshift {
3318             my ($self, $node, $k) = @_;
3319             $k = 1 unless defined($k); # father by default
3320              
3321             my $ancestor = ${$self->{NODE}}[$k];
3322             croak "unshift: does not exist ancestor $k of node ".Dumper(${$self->{NODE}}[0]) unless defined($ancestor);
3323              
3324             # Stringification of $ancestor. Hope it works
3325             # operation, node to insert,
3326             push @{$self->{PENDING_TASKS}{$ancestor}}, ['unshift', $node ];
3327             }
3328              
3329             sub insert_before {
3330             my ($self, $node) = @_;
3331              
3332             my $father = ${$self->{NODE}}[1];
3333             croak "insert_before: does not exist father of node ".Dumper(${$self->{NODE}}[0]) unless defined($father);
3334              
3335             # operation, node to insert, before this node
3336             push @{$self->{PENDING_TASKS}{$father}}, ['insert_before', $node, ${$self->{NODE}}[0] ];
3337             }
3338              
3339             sub _delayed_insert_before {
3340             my ($father, $node, $before) = @_;
3341              
3342             my $i = 0;
3343             for ($father->children()) {
3344             last if ($_ == $before);
3345             $i++;
3346             }
3347             splice @{$father->{children}}, $i, 0, $node;
3348             }
3349              
3350             sub do_pending_tasks {
3351             my $self = shift;
3352             my $node = shift;
3353              
3354             my $mytasks = $self->{PENDING_TASKS}{$node};
3355             while ($mytasks and (my $job = shift @{$mytasks})) {
3356             my @args = @$job;
3357             my $task = shift @args;
3358              
3359             # change this for a jump table
3360             if ($task eq 'unshift') {
3361             CORE::unshift(@{$node->{children}}, @args);
3362             $self->{CHANGES}++;
3363             }
3364             elsif ($task eq 'insert_before') {
3365             _delayed_insert_before($node, @args);
3366             $self->{CHANGES}++;
3367             }
3368             }
3369             }
3370              
3371             ####################################################################
3372             # Parameters : pattern, node, father of the node, index of the child in the children array
3373             # YATW object. Probably too many
3374             sub s {
3375             my $self = shift;
3376             my $node = $_[0] or croak("Error. Method __PACKAGE__::s requires a node");
3377             CORE::unshift @{$self->{NODE}}, $_[0];
3378             # father is $_[1]
3379             my $index = $_[2];
3380              
3381             # If is not a reference or can't children then simply check the matching and leave
3382             if (!ref($node) or !UNIVERSAL::can($node, "children")) {
3383            
3384             $self->{CHANGES}++ if $self->pattern->(
3385             $_[0], # Node being visited
3386             $_[1], # Father of this node
3387             $index, # Index of this node in @Father->children
3388             $self, # The YATW pattern object
3389             );
3390             return;
3391             };
3392            
3393             # Else, is not a leaf and is a regular Parse::Eyapp::Node
3394             # Recursively transform subtrees
3395             my $i = 0;
3396             for (@{$node->{children}}) {
3397             $self->s($_, $_[0], $i);
3398             $i++;
3399             }
3400            
3401             my $number_of_changes = $self->{CHANGES};
3402             # Now is safe to delete children nodes that are no longer needed
3403             $self->make_delete_effective($node);
3404              
3405             # Safely do pending jobs for this node
3406             $self->do_pending_tasks($node);
3407              
3408             #node , father, childindex, and ...
3409             #Change YATW object to be the first argument?
3410             if ($self->pattern->($_[0], $_[1], $index, $self)) {
3411             $self->{CHANGES}++;
3412             }
3413             shift @{$self->{NODE}};
3414             }
3415              
3416             1;
3417              
3418              
3419             MODULE_Parse_Eyapp_YATW
3420 1 0 0 1   102 }; # Unless Parse::Eyapp::YATW was loaded
  1 0 0 1   6  
  1 0   1   1  
  1 0   1   32  
  1 0   1   5  
  1 0   0   2  
  1 0   0   32  
  1 0   0   5  
  1 0   0   2  
  1 0   0   72  
  1 0   0   6  
  1 0   0   1  
  1 0   0   47  
  1 0   0   6  
  1 0   0   1  
  1 0   0   1631  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0 0   0   0  
  0     0   0  
  0     1   0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  1         2  
  1         4  
  1         2  
  1         5  
3421             } ########### End of BEGIN { load /home/book/perl5/lib/perl5/Parse/Eyapp/YATW.pm }
3422              
3423              
3424              
3425 0 0   0 0 0 sub unexpendedInput { defined($_) ? substr($_, (defined(pos $_) ? pos $_ : 0)) : '' }
    0          
3426              
3427              
3428              
3429             # Default lexical analyzer
3430             our $LEX = sub {
3431             my $self = shift;
3432             my $pos;
3433              
3434             for (${$self->input}) {
3435            
3436              
3437             /\G(\s*(?:#.*)?\s*)+/gc and $self->tokenline($1 =~ tr{\n}{});
3438              
3439             m{\G(\:|\}|\;|\{|\,|\%|\(|\))}gc and return ($1, $1);
3440              
3441             /\G([0-9]+(?:\.[0-9]*)?|\.[0-9]+)/gc and return ('NUM', $1);
3442             /\G([A-Za-z_][A-Za-z_0-9]*)/gc and return ('NAME', $1);
3443             /\G([-+*\/])/gc and return ('OP', $1);
3444             /\G([<>]=?|[!=]=)/gc and return ('BOP', $1);
3445              
3446              
3447             return ('', undef) if ($_ eq '') || (defined(pos($_)) && (pos($_) >= length($_)));
3448             /\G\s*(\S+)/;
3449             my $near = substr($1,0,10);
3450              
3451             return($near, $near);
3452              
3453             # die( "Error inside the lexical analyzer near '". $near
3454             # ."'. Line: ".$self->line()
3455             # .". File: '".$self->YYFilename()."'. No match found.\n");
3456             }
3457             }
3458             ;
3459              
3460              
3461             #line 3458 lib/Hash/Weighted/Categorize/Parser.pm
3462              
3463             my $warnmessage =<< "EOFWARN";
3464 1     1 0 4 Warning!: Did you changed the \@Hash::Weighted::Categorize::Parser::ISA variable inside the header section of the eyapp program?
3465 1 50       5 EOFWARN
3466              
3467 1 50       18 sub new {
3468             my($class)=shift;
3469             ref($class) and $class=ref($class);
3470              
3471             warn $warnmessage unless __PACKAGE__->isa('Parse::Eyapp::Driver');
3472             my($self)=$class->SUPER::new(
3473             yyversion => '1.182',
3474             yyGRAMMAR =>
3475             [#[productionNameAndLabel => lhs, [ rhs], bypass]]
3476             [ '_SUPERSTART' => '$start', [ 'input', '$end' ], 0 ],
3477             [ 'input_1' => 'input', [ 'line' ], 0 ],
3478             [ 'line_2' => 'line', [ 'stmt' ], 0 ],
3479             [ 'line_3' => 'line', [ 'line', ';', 'stmt' ], 0 ],
3480             [ 'stmt_4' => 'stmt', [ ], 0 ],
3481             [ 'stmt_5' => 'stmt', [ 'bool', ':', '{', 'line', '}' ], 0 ],
3482             [ 'stmt_6' => 'stmt', [ 'bool', ':', 'NAME' ], 0 ],
3483             [ 'stmt_7' => 'stmt', [ 'NAME' ], 0 ],
3484             [ 'bool_8' => 'bool', [ 'bool', ',', 'bool' ], 0 ],
3485             [ 'bool_9' => 'bool', [ 'exp', 'BOP', 'exp' ], 0 ],
3486             [ 'exp_10' => 'exp', [ 'NUM' ], 0 ],
3487             [ 'exp_11' => 'exp', [ 'NUM', '%' ], 0 ],
3488             [ 'exp_12' => 'exp', [ 'NAME' ], 0 ],
3489             [ 'exp_13' => 'exp', [ '%', 'NAME' ], 0 ],
3490             [ 'exp_14' => 'exp', [ 'exp', 'OP', 'exp' ], 0 ],
3491             [ 'exp_15' => 'exp', [ '(', 'exp', ')' ], 0 ],
3492             ],
3493             yyLABELS =>
3494             {
3495             '_SUPERSTART' => 0,
3496             'input_1' => 1,
3497             'line_2' => 2,
3498             'line_3' => 3,
3499             'stmt_4' => 4,
3500             'stmt_5' => 5,
3501             'stmt_6' => 6,
3502             'stmt_7' => 7,
3503             'bool_8' => 8,
3504             'bool_9' => 9,
3505             'exp_10' => 10,
3506             'exp_11' => 11,
3507             'exp_12' => 12,
3508             'exp_13' => 13,
3509             'exp_14' => 14,
3510             'exp_15' => 15,
3511             },
3512             yyTERMS =>
3513             { '' => { ISSEMANTIC => 0 },
3514             '%' => { ISSEMANTIC => 0 },
3515             '(' => { ISSEMANTIC => 0 },
3516             ')' => { ISSEMANTIC => 0 },
3517             ',' => { ISSEMANTIC => 0 },
3518             ':' => { ISSEMANTIC => 0 },
3519             ';' => { ISSEMANTIC => 0 },
3520             '{' => { ISSEMANTIC => 0 },
3521             '}' => { ISSEMANTIC => 0 },
3522             BOP => { ISSEMANTIC => 1 },
3523             NAME => { ISSEMANTIC => 1 },
3524             NUM => { ISSEMANTIC => 1 },
3525             OP => { ISSEMANTIC => 1 },
3526             error => { ISSEMANTIC => 0 },
3527             },
3528             yyFILENAME => 'lib/Hash/Weighted/Categorize/Parser.eyp',
3529             yystates =>
3530             [
3531             {#State 0
3532             ACTIONS => {
3533             'NUM' => 7,
3534             "(" => 8,
3535             'NAME' => 2,
3536             "%" => 5
3537             },
3538             DEFAULT => -4,
3539             GOTOS => {
3540             'stmt' => 6,
3541             'exp' => 1,
3542             'input' => 4,
3543             'bool' => 3,
3544             'line' => 9
3545             }
3546             },
3547             {#State 1
3548             ACTIONS => {
3549             'OP' => 11,
3550             'BOP' => 10
3551             }
3552             },
3553             {#State 2
3554             ACTIONS => {
3555             'OP' => -12,
3556             'BOP' => -12
3557             },
3558             DEFAULT => -7
3559             },
3560             {#State 3
3561             ACTIONS => {
3562             ":" => 12,
3563             "," => 13
3564             }
3565             },
3566             {#State 4
3567             ACTIONS => {
3568             '' => 14
3569             }
3570             },
3571             {#State 5
3572             ACTIONS => {
3573             'NAME' => 15
3574             }
3575             },
3576             {#State 6
3577             DEFAULT => -2
3578             },
3579             {#State 7
3580             ACTIONS => {
3581             "%" => 16
3582             },
3583             DEFAULT => -10
3584             },
3585             {#State 8
3586             ACTIONS => {
3587             'NUM' => 7,
3588             "(" => 8,
3589             'NAME' => 18,
3590             "%" => 5
3591             },
3592             GOTOS => {
3593             'exp' => 17
3594             }
3595             },
3596             {#State 9
3597             ACTIONS => {
3598             ";" => 19
3599             },
3600             DEFAULT => -1
3601             },
3602             {#State 10
3603             ACTIONS => {
3604             'NUM' => 7,
3605             "(" => 8,
3606             'NAME' => 18,
3607             "%" => 5
3608             },
3609             GOTOS => {
3610             'exp' => 20
3611             }
3612             },
3613             {#State 11
3614             ACTIONS => {
3615             'NUM' => 7,
3616             "(" => 8,
3617             'NAME' => 18,
3618             "%" => 5
3619             },
3620             GOTOS => {
3621             'exp' => 21
3622             }
3623             },
3624             {#State 12
3625             ACTIONS => {
3626             'NAME' => 22,
3627             "{" => 23
3628             }
3629             },
3630             {#State 13
3631             ACTIONS => {
3632             'NUM' => 7,
3633             "(" => 8,
3634             'NAME' => 18,
3635             "%" => 5
3636             },
3637             GOTOS => {
3638             'exp' => 1,
3639             'bool' => 24
3640             }
3641             },
3642             {#State 14
3643             DEFAULT => 0
3644             },
3645             {#State 15
3646             DEFAULT => -13
3647             },
3648             {#State 16
3649             DEFAULT => -11
3650             },
3651             {#State 17
3652             ACTIONS => {
3653             'OP' => 11,
3654             ")" => 25
3655             }
3656             },
3657             {#State 18
3658             DEFAULT => -12
3659             },
3660             {#State 19
3661             ACTIONS => {
3662             'NAME' => 2,
3663             "%" => 5,
3664             'NUM' => 7,
3665             "(" => 8
3666             },
3667             DEFAULT => -4,
3668             GOTOS => {
3669             'stmt' => 26,
3670             'exp' => 1,
3671             'bool' => 3
3672             }
3673             },
3674             {#State 20
3675             ACTIONS => {
3676             'OP' => 11
3677             },
3678             DEFAULT => -9
3679             },
3680             {#State 21
3681             ACTIONS => {
3682             'OP' => 11
3683             },
3684             DEFAULT => -14
3685             },
3686             {#State 22
3687             DEFAULT => -6
3688             },
3689             {#State 23
3690             ACTIONS => {
3691             'NUM' => 7,
3692             "(" => 8,
3693             'NAME' => 2,
3694             "%" => 5
3695             },
3696             DEFAULT => -4,
3697             GOTOS => {
3698             'stmt' => 6,
3699             'exp' => 1,
3700             'bool' => 3,
3701             'line' => 27
3702             }
3703             },
3704             {#State 24
3705             ACTIONS => {
3706             "," => 13
3707             },
3708             DEFAULT => -8
3709             },
3710             {#State 25
3711             DEFAULT => -15
3712             },
3713             {#State 26
3714             DEFAULT => -3
3715             },
3716             {#State 27
3717             ACTIONS => {
3718             "}" => 28,
3719             ";" => 19
3720             }
3721             },
3722             {#State 28
3723             DEFAULT => -5
3724             }
3725             ],
3726             yyrules =>
3727             [
3728             [#Rule _SUPERSTART
3729             '$start', 2, undef
3730             #line 3727 lib/Hash/Weighted/Categorize/Parser.pm
3731             ],
3732             [#Rule input_1
3733             'input', 1,
3734             sub {
3735             #line 11 "lib/Hash/Weighted/Categorize/Parser.eyp"
3736             my $content = $_[1];
3737              
3738             << 'CODE'
3739             sub {
3740             my %count = %{ shift() };
3741             my $total = 0;
3742             $total += $_ for values %count;
3743             my %percent
3744             = $total
3745             ? map +( $_ => $count{$_} / $total ), keys %count
3746             : map +( $_ => 0 ), keys %count;
3747             CODE
3748             . $content . "}\n";
3749              
3750             }
3751             #line 3748 lib/Hash/Weighted/Categorize/Parser.pm
3752             ],
3753             [#Rule line_2
3754             'line', 1,
3755             sub {
3756             #line 29 "lib/Hash/Weighted/Categorize/Parser.eyp"
3757             my $stmt = $_[1]; "$stmt" }
3758             #line 3755 lib/Hash/Weighted/Categorize/Parser.pm
3759             ],
3760             [#Rule line_3
3761             'line', 3,
3762             sub {
3763             #line 30 "lib/Hash/Weighted/Categorize/Parser.eyp"
3764             my $stmt = $_[3]; my $line = $_[1]; "$line$stmt" }
3765             #line 3762 lib/Hash/Weighted/Categorize/Parser.pm
3766             ],
3767             [#Rule stmt_4
3768             'stmt', 0,
3769             sub {
3770             #line 34 "lib/Hash/Weighted/Categorize/Parser.eyp"
3771             "" }
3772             #line 3769 lib/Hash/Weighted/Categorize/Parser.pm
3773             ],
3774             [#Rule stmt_5
3775             'stmt', 5,
3776             sub {
3777             #line 37 "lib/Hash/Weighted/Categorize/Parser.eyp"
3778             my $exp = $_[1]; my $line = $_[4]; $line =~ s/^/ /gm; # indent
3779             " if ( $exp ) {\n$line }\n" }
3780             #line 3777 lib/Hash/Weighted/Categorize/Parser.pm
3781             ],
3782             [#Rule stmt_6
3783             'stmt', 3,
3784             sub {
3785             #line 39 "lib/Hash/Weighted/Categorize/Parser.eyp"
3786             my $exp = $_[1]; my $NAME = $_[3]; " return '$NAME'\n if $exp;\n"; }
3787             #line 3784 lib/Hash/Weighted/Categorize/Parser.pm
3788             ],
3789             [#Rule stmt_7
3790             'stmt', 1,
3791             sub {
3792             #line 40 "lib/Hash/Weighted/Categorize/Parser.eyp"
3793             my $NAME = $_[1]; " return '$NAME';\n" }
3794             #line 3791 lib/Hash/Weighted/Categorize/Parser.pm
3795             ],
3796             [#Rule bool_8
3797             'bool', 3,
3798             sub {
3799             #line 44 "lib/Hash/Weighted/Categorize/Parser.eyp"
3800             my $left = $_[1]; my $right = $_[3]; "$left\n && $right" }
3801             #line 3798 lib/Hash/Weighted/Categorize/Parser.pm
3802             ],
3803             [#Rule bool_9
3804             'bool', 3,
3805             sub {
3806             #line 45 "lib/Hash/Weighted/Categorize/Parser.eyp"
3807             my $left = $_[1]; my $right = $_[3]; my $op = $_[2]; "$left $op $right" }
3808             #line 3805 lib/Hash/Weighted/Categorize/Parser.pm
3809             ],
3810             [#Rule exp_10
3811             'exp', 1,
3812             sub {
3813             #line 50 "lib/Hash/Weighted/Categorize/Parser.eyp"
3814             my $NUM = $_[1]; $NUM }
3815             #line 3812 lib/Hash/Weighted/Categorize/Parser.pm
3816             ],
3817             [#Rule exp_11
3818             'exp', 2,
3819             sub {
3820             #line 51 "lib/Hash/Weighted/Categorize/Parser.eyp"
3821             my $NUM = $_[1]; $NUM / 100 }
3822             #line 3819 lib/Hash/Weighted/Categorize/Parser.pm
3823             ],
3824             [#Rule exp_12
3825             'exp', 1,
3826             sub {
3827             #line 52 "lib/Hash/Weighted/Categorize/Parser.eyp"
3828             my $NAME = $_[1]; "( \$count{$NAME} ||= 0 )" }
3829             #line 3826 lib/Hash/Weighted/Categorize/Parser.pm
3830             ],
3831             [#Rule exp_13
3832             'exp', 2,
3833             sub {
3834             #line 53 "lib/Hash/Weighted/Categorize/Parser.eyp"
3835             my $NAME = $_[2]; "( \$percent{$NAME} ||= 0 )" }
3836             #line 3833 lib/Hash/Weighted/Categorize/Parser.pm
3837             ],
3838             [#Rule exp_14
3839             'exp', 3,
3840             sub {
3841             #line 54 "lib/Hash/Weighted/Categorize/Parser.eyp"
3842             my $left = $_[1]; my $right = $_[3]; my $op = $_[2]; "$left $op $right" }
3843             #line 3840 lib/Hash/Weighted/Categorize/Parser.pm
3844             ],
3845             [#Rule exp_15
3846             'exp', 3,
3847 1         449 sub {
3848             #line 55 "lib/Hash/Weighted/Categorize/Parser.eyp"
3849             my $exp = $_[2]; "( $exp )" }
3850             #line 3847 lib/Hash/Weighted/Categorize/Parser.pm
3851             ]
3852             ],
3853             #line 3850 lib/Hash/Weighted/Categorize/Parser.pm
3854             yybypass => 0,
3855             yybuildingtree => 0,
3856             yyprefix => '',
3857             yyaccessors => {
3858             },
3859             yyconflicthandlers => {}
3860 1         9 ,
3861             yystateconflict => { },
3862 1         48 @_,
3863             );
3864             bless($self,$class);
3865              
3866             $self->make_node_classes('TERMINAL', '_OPTIONAL', '_STAR_LIST', '_PLUS_LIST',
3867             '_SUPERSTART',
3868             'input_1',
3869             'line_2',
3870             'line_3',
3871             'stmt_4',
3872             'stmt_5',
3873             'stmt_6',
3874             'stmt_7',
3875             'bool_8',
3876             'bool_9',
3877             'exp_10',
3878             'exp_11',
3879 1         57 'exp_12',
3880             'exp_13',
3881             'exp_14',
3882             'exp_15', );
3883             $self;
3884             }
3885              
3886             #line 58 "lib/Hash/Weighted/Categorize/Parser.eyp"
3887              
3888              
3889              
3890              
3891              
3892             #line 3892 lib/Hash/Weighted/Categorize/Parser.pm
3893              
3894              
3895              
3896             1;
3897              
3898             __END__