File Coverage

blib/lib/Parse/Eyapp/Driver.pm
Criterion Covered Total %
statement 350 870 40.2
branch 126 446 28.2
condition 16 103 15.5
subroutine 46 101 45.5
pod 43 81 53.0
total 581 1601 36.2


line stmt bran cond sub pod time code
1             #
2             # Module Parse::Eyapp::Driver
3             #
4             # This module is part of the Parse::Eyapp package available on your
5             # nearest CPAN
6             #
7             # This module is based on Francois Desarmenien Parse::Yapp module
8             # (c) Parse::Yapp Copyright 1998-2001 Francois Desarmenien, all rights reserved.
9             # (c) Parse::Eyapp Copyright 2006-2010 Casiano Rodriguez-Leon, all rights reserved.
10              
11             our $SVNREVISION = '$Rev: 2399M $';
12             our $SVNDATE = '$Date: 2009-01-06 12:28:04 +0000 (mar, 06 ene 2009) $';
13              
14             package Parse::Eyapp::Driver;
15              
16             require 5.006;
17              
18 61     61   374 use strict;
  61         139  
  61         6481  
19              
20             our ( $VERSION, $COMPATIBLE, $FILENAME );
21              
22              
23             # $VERSION is also in Parse/Eyapp.pm
24             $VERSION = "1.182";
25             $COMPATIBLE = '0.07';
26             $FILENAME =__FILE__;
27              
28 61     61   624 use Carp;
  61         109  
  61         5841  
29 61     61   367 use Scalar::Util qw{blessed reftype looks_like_number};
  61         117  
  61         7426  
30              
31 61     61   94080 use Getopt::Long;
  61         869633  
  61         440  
32              
33             #Known parameters, all starting with YY (leading YY will be discarded)
34             my (%params)=(YYLEX => 'CODE', 'YYERROR' => 'CODE', YYVERSION => '',
35             YYRULES => 'ARRAY', YYSTATES => 'ARRAY', YYDEBUG => '',
36             # added by Casiano
37             #YYPREFIX => '', # Not allowed at YYParse time but in new
38             YYFILENAME => '',
39             YYBYPASS => '',
40             YYGRAMMAR => 'ARRAY',
41             YYTERMS => 'HASH',
42             YYBUILDINGTREE => '',
43             YYACCESSORS => 'HASH',
44             YYCONFLICTHANDLERS => 'HASH',
45             YYSTATECONFLICT => 'HASH',
46             YYLABELS => 'HASH',
47             );
48             my (%newparams) = (%params, YYPREFIX => '',);
49              
50             #Mandatory parameters
51             my (@params)=('LEX','RULES','STATES');
52              
53             sub new {
54 133     133 1 7859 my($class)=shift;
55              
56 133         294 my($errst,$nberr,$token,$value,$check,$dotpos);
57              
58 133         2373 my($self)={
59             ERRST => \$errst,
60             NBERR => \$nberr,
61             TOKEN => \$token,
62             VALUE => \$value,
63             DOTPOS => \$dotpos,
64             STACK => [],
65             DEBUG => 0,
66             PREFIX => "",
67             CHECK => \$check,
68             };
69              
70 133         1054 _CheckParams( [], \%newparams, \@_, $self );
71              
72 133 50 33     2841 exists($$self{VERSION})
73             and $$self{VERSION} < $COMPATIBLE
74             and croak "Eyapp driver version $VERSION ".
75             "incompatible with version $$self{VERSION}:\n".
76             "Please recompile parser module.";
77              
78 133 50       473 ref($class)
79             and $class=ref($class);
80              
81 133 100       602 unless($self->{ERROR}) {
82 132         1559 $self->{ERROR} = $class->error;
83 132 50       601 $self->{ERROR} = \&_Error unless ($self->{ERROR});
84             }
85              
86 133 100       508 unless ($self->{LEX}) {
87 132         1042 $self->{LEX} = $class->YYLexer;
88 132         661 @params = ('RULES','STATES');
89             }
90              
91 133         3580 my $parser = bless($self,$class);
92              
93 133         820 $parser;
94             }
95              
96             sub YYParse {
97 158     158 1 39763 my($self)=shift;
98 158         283 my($retval);
99              
100 158         848 _CheckParams( \@params, \%params, \@_, $self );
101              
102 158 50       730 unless($self->{ERROR}) {
103 0         0 $self->{ERROR} = $self->error;
104 0 0       0 $self->{ERROR} = \&_Error unless ($self->{ERROR});
105             }
106              
107 158 50       701 unless($self->{LEX}) {
108 0         0 $self->{LEX} = $self->YYLexer;
109 0 0 0     0 croak "Missing parameter 'yylex' " unless $self->{LEX} && reftype($self->{LEX}) eq 'CODE';
110             }
111              
112 158 50       627 if($$self{DEBUG}) {
113 0         0 _DBLoad();
114 0         0 $retval = eval '$self->_DBParse()';#Do not create stab entry on compile
115 0 0       0 $@ and die $@;
116             }
117             else {
118 158         1250 $retval = $self->_Parse();
119             }
120 158         852 return $retval;
121             }
122              
123             sub YYData {
124 2027     2027 0 31128 my($self)=shift;
125              
126 2027 100       6679 exists($$self{USER})
127             or $$self{USER}={};
128              
129 2027         6017 $$self{USER};
130            
131             }
132              
133             sub YYErrok {
134 2     2 1 20 my($self)=shift;
135              
136 2         4 ${$$self{ERRST}}=0;
  2         6  
137 2         4 undef;
138             }
139              
140             sub YYNberr {
141 1     1 1 2 my($self)=shift;
142              
143 1         2 ${$$self{NBERR}};
  1         124  
144             }
145              
146             sub YYRecovering {
147 0     0 1 0 my($self)=shift;
148              
149 0         0 ${$$self{ERRST}} != 0;
  0         0  
150             }
151              
152             sub YYAbort {
153 0     0 1 0 my($self)=shift;
154              
155 0         0 ${$$self{CHECK}}='ABORT';
  0         0  
156 0         0 undef;
157             }
158              
159             sub YYAccept {
160 158     158 1 447 my($self)=shift;
161              
162 158         255 ${$$self{CHECK}}='ACCEPT';
  158         651  
163 158         344 undef;
164             }
165              
166             # Used to set that we are in "error recovery" state
167             sub YYError {
168 0     0 1 0 my($self)=shift;
169              
170 0         0 ${$$self{CHECK}}='ERROR';
  0         0  
171 0         0 undef;
172             }
173              
174             sub YYSemval {
175 0     0 0 0 my($self)=shift;
176 0         0 my($index)= $_[0] - ${$$self{DOTPOS}} - 1;
  0         0  
177              
178 0         0 $index < 0
179 0 0 0     0 and -$index <= @{$$self{STACK}}
180             and return $$self{STACK}[$index][1];
181              
182 0         0 undef; #Invalid index
183             }
184              
185             ### Casiano methods
186              
187             sub YYRule {
188             # returns the list of rules
189             # counting the super rule as rule 0
190 0     0 1 0 my $self = shift;
191 0         0 my $index = shift;
192              
193 0 0       0 if ($index) {
194 0 0       0 $index = $self->YYIndex($index) unless (looks_like_number($index));
195 0 0       0 return wantarray? @{$self->{RULES}[$index]} : $self->{RULES}[$index]
  0         0  
196             }
197              
198 0 0       0 return wantarray? @{$self->{RULES}} : $self->{RULES}
  0         0  
199             }
200              
201             # YYState returns the list of states. Each state is an anonymous hash
202             # DB<4> x $parser->YYState(2)
203             # 0 HASH(0xfa7120)
204             # 'ACTIONS' => HASH(0xfa70f0) # token => state
205             # ':' => '-7'
206             # 'DEFAULT' => '-6'
207             # There are three keys: ACTIONS, GOTOS and DEFAULT
208             # DB<7> x $parser->YYState(13)
209             # 0 HASH(0xfa8b50)
210             # 'ACTIONS' => HASH(0xfa7530)
211             # 'VAR' => 17
212             # 'GOTOS' => HASH(0xfa8b20)
213             # 'type' => 19
214             sub YYState {
215 0     0 1 0 my $self = shift;
216 0         0 my $index = shift;
217              
218 0 0       0 if ($index) {
219             # Comes from the stack: a pair [state number, attribute]
220 0 0       0 $index = $index->[0] if 'ARRAY' eq reftype($index);
221 0 0       0 die "YYState error. Expecting a number, found <$index>" unless (looks_like_number($index));
222 0         0 return $self->{STATES}[$index]
223             }
224              
225 0         0 return $self->{STATES}
226             }
227              
228             sub YYGoto {
229 0     0 0 0 my ($self, $state, $symbol) = @_;
230            
231 0         0 my $stateLRactions = $self->YYState($state);
232              
233 0         0 $stateLRactions->{GOTOS}{$symbol};
234             }
235              
236             sub YYRHSLength {
237 0     0 1 0 my $self = shift;
238             # If no production index is given, is the production begin used in the current reduction
239 0   0     0 my $index = shift || $self->YYRuleindex;
240              
241             # If the production was given by its name, compute its index
242 0 0       0 $index = $self->YYIndex($index) unless looks_like_number($index);
243            
244 0 0       0 return unless looks_like_number($index);
245              
246 0         0 my $currentprod = $self->YYRule($index);
247              
248 0 0       0 $currentprod->[1] if reftype($currentprod);
249             }
250              
251             # To be used in a semantic action, when reducing ...
252             # It gives the next state after reduction
253             sub YYNextState {
254 0     0 1 0 my $self = shift;
255              
256 0         0 my $lhs = $self->YYLhs;
257              
258 0 0       0 if ($lhs) { # reduce
259 0         0 my $length = $self->YYRHSLength;
260              
261 0         0 my $state = $self->YYTopState($length);
262             #print "state = $$state[0]\n";
263 0         0 $self->YYGoto($state, $lhs);
264             }
265             else { # shift: a token must be provided as argument
266 0         0 my $token = shift;
267            
268 0         0 my $state = $self->YYTopState;
269 0         0 $self->YYGetLRAction($state, $token);
270             }
271             }
272              
273             # TODO: make it work with a list of indices ...
274             sub YYGrammar {
275 0     0 1 0 my $self = shift;
276 0         0 my $index = shift;
277              
278 0 0       0 if ($index) {
279 0 0       0 $index = $self->YYIndex($index) unless (looks_like_number($index));
280 0 0       0 return wantarray? @{$self->{GRAMMAR}[$index]} : $self->{GRAMMAR}[$index]
  0         0  
281             }
282 0 0       0 return wantarray? @{$self->{GRAMMAR}} : $self->{GRAMMAR}
  0         0  
283             }
284              
285             # Return the list of production names
286             sub YYNames {
287 0     0 1 0 my $self = shift;
288              
289 0         0 my @names = map { $_->[0] } @{$self->{GRAMMAR}};
  0         0  
  0         0  
290              
291 0 0       0 return wantarray? @names : \@names;
292             }
293              
294             # Return the hash of indices for each production name
295             # Initializes the INDICES attribute of the parser
296             # Returns the index of the production rule with name $name
297             sub YYIndex {
298 0     0 1 0 my $self = shift;
299              
300 0 0       0 if (@_) {
301 0         0 my @indices = map { $self->{LABELS}{$_} } @_;
  0         0  
302 0 0       0 return wantarray? @indices : $indices[0];
303             }
304 0 0       0 return wantarray? %{$self->{LABELS}} : $self->{LABELS};
  0         0  
305              
306             }
307              
308             sub YYTopState {
309 0     0 1 0 my $self = shift;
310 0   0     0 my $length = shift || 0;
311              
312 0 0       0 $length = -$length unless $length <= 0;
313 0         0 $length--;
314              
315 0 0       0 $_[1] and $self->{STACK}[$length] = $_[1];
316 0         0 $self->{STACK}[$length];
317             }
318              
319             sub YYStack {
320 0     0 0 0 my $self = shift;
321              
322 0         0 return $self->{STACK};
323             }
324              
325             # To dynamically set syntactic actions
326             # Change it to state, token, action
327             # it is more natural
328             sub YYSetLRAction {
329 0     0 1 0 my ($self, $state, $token, $action) = @_;
330              
331 0 0       0 die "YYLRAction: Provide a state " unless defined($state);
332              
333             # Action can be given using the name of the production
334 0 0       0 $action = -$self->YYIndex($action) unless looks_like_number($action);
335 0 0       0 $token = [ $token ] unless ref($token);
336 0         0 for (@$token) {
337 0         0 $self->{STATES}[$state]{ACTIONS}{$_} = $action;
338             }
339             }
340              
341             sub YYRestoreLRAction {
342 0     0 1 0 my $self = shift;
343 0         0 my $conflictname = shift;
344 0         0 my @tokens = @_;
345              
346 0         0 for (@tokens) {
347 0         0 my ($conflictstate, $action) = @{$self->{CONFLICT}{$conflictname}{$_}};
  0         0  
348 0         0 $self->{STATES}[$conflictstate]{ACTIONS}{$_} = $action;
349             }
350             }
351              
352             # Fools the lexer to get a new token
353             # without modifying the parsing position (pos)
354             # Warning, warning! this and YYLookaheads assume
355             # that the input comes from the string
356             # referenced by $self->input.
357             # It will not work for a stream
358             sub YYLookahead {
359 0     0 0 0 my $self = shift;
360              
361 0         0 my $pos = pos(${$self->input});
  0         0  
362 0         0 my ($nextToken, $val) = $self->YYLexer->($self);
363             # restore pos
364 0         0 pos(${$self->input}) = $pos;
  0         0  
365 0         0 return $nextToken;
366             }
367              
368             # Fools the lexer to get $spec new tokens
369             sub YYLookaheads {
370 0     0 0 0 my $self = shift;
371 0   0     0 my $spec = shift || 1; # a number
372              
373 0         0 my $pos = pos(${$self->input});
  0         0  
374 0         0 my @r; # list of lookahead tokens
375              
376 0         0 my ($t, $v);
377 0 0       0 if (looks_like_number($spec)) {
378 0         0 for my $i (1..$spec) {
379 0         0 ($t, $v) = $self->YYLexer->($self);
380 0         0 push @r, $t;
381 0 0       0 last if $t eq '';
382             }
383             }
384             else { # if string
385 0   0     0 do {
386 0         0 ($t, $v) = $self->YYLexer->($self);
387 0         0 push @r, $t;
388             } while ($t ne $spec && $t ne '');
389             }
390              
391             # restore pos
392 0         0 pos(${$self->input}) = $pos;
  0         0  
393              
394 0         0 return @r;
395             }
396              
397              
398             # more parameters: debug, etc, ...
399             #sub YYNestedParse {
400             sub YYPreParse {
401 0     0 0 0 my $self = shift;
402 0         0 my $parser = shift;
403 0   0     0 my $file = shift() || $parser;
404              
405             # Check for errors!
406 0         0 eval "require $file";
407            
408             # optimize to state variable for 5.10
409 0     0   0 my $rp = $parser->new( yyerror => sub {});
  0         0  
410              
411 0         0 my $pos = pos(${$self->input});
  0         0  
412 0         0 my $rpos = $self->{POS};
413              
414             #print "pos = $pos\n";
415 0         0 $rp->input($self->input);
416 0         0 pos(${$rp->input}) = $rpos;
  0         0  
417              
418 0         0 my $t = $rp->Run(@_);
419 0         0 my $ne = $rp->YYNberr;
420              
421             #print "After nested parsing\n";
422              
423 0         0 pos(${$self->input}) = $pos;
  0         0  
424              
425 0 0       0 return (wantarray ? ($t, !$ne) : !$ne);
426             }
427              
428             sub YYNestedParse {
429 0     0 0 0 my $self = shift;
430 0         0 my $parser = shift;
431 0         0 my $conflictName = shift;
432              
433 0 0       0 $conflictName = $self->YYLhs unless $conflictName;
434              
435 0         0 my ($t, $ok) = $self->YYPreParse($parser, @_);
436              
437 0         0 $self->{CONFLICTHANDLERS}{$conflictName}{".".$parser} = [$ok, $t];
438              
439 0         0 return $ok;
440             }
441              
442             sub YYNestedRegexp {
443 0     0 0 0 my $self = shift;
444 0         0 my $regexp = shift;
445 0         0 my $conflictName = $self->YYLhs;
446              
447 0         0 my $ok = $_ =~ /$regexp/gc;
448              
449 0         0 $self->{CONFLICTHANDLERS}{$conflictName}{'..regexp'} = [$ok, undef];
450              
451 0         0 return $ok;
452             }
453              
454             sub YYIs {
455 0     0 0 0 my $self = shift;
456             # this is ungly and dangeorus. Don't use the dot. Change it!
457 0         0 my $syntaxVariable = '.'.(shift());
458 0         0 my $conflictName = $self->YYLhs;
459 0         0 my $v = $self->{CONFLICTHANDLERS}{$conflictName};
460              
461 0 0       0 $v->{$syntaxVariable}[0] = shift if @_;
462 0         0 return $v->{$syntaxVariable}[0];
463             }
464              
465              
466             sub YYVal {
467 0     0 0 0 my $self = shift;
468             # this is ungly and dangeorus. Don't use the dot. Change it!
469 0         0 my $syntaxVariable = '.'.(shift());
470 0         0 my $conflictName = $self->YYLhs;
471 0         0 my $v = $self->{CONFLICTHANDLERS}{$conflictName};
472              
473 0 0       0 $v->{$syntaxVariable}[1] = shift if @_;
474 0         0 return $v->{$syntaxVariable}[1];
475             }
476              
477             #x $self->{CONFLICTHANDLERS}
478             #0 HASH(0x100b306c0)
479             # 'rangeORenum' => HASH(0x100b30660)
480             # 'explorerline' => 12
481             # 'line' => 5
482             # 'production' => HASH(0x100b30580)
483             # '-13' => ARRAY(0x100b30520)
484             # 0 1 <------- mark: conflictive position in the rhs
485             # '-5' => ARRAY(0x100b30550)
486             # 0 1 <------- mark: conflictive position in the rhs
487             # 'states' => ARRAY(0x100b30630)
488             # 0 HASH(0x100b30600)
489             # 25 => ARRAY(0x100b305c0)
490             # 0 '\',\''
491             # 1 '\')\''
492             sub YYSetReduceXXXXX {
493 0     0 0 0 my $self = shift;
494 0         0 my $action = pop;
495 0         0 my $token = shift;
496            
497              
498 0 0       0 croak "YYSetReduce error: specify a production" unless defined($action);
499              
500             # Conflict state
501 0         0 my $conflictstate = $self->YYNextState();
502              
503 0         0 my $conflictName = $self->YYLhs;
504              
505             #$self->{CONFLICTHANDLERS}{conflictName}{states}
506             # is a hash
507             # statenumber => [ tokens, '\'-\'' ]
508 0         0 my $cS = $self->{CONFLICTHANDLERS}{$conflictName}{states};
509 0 0       0 my @conflictStates = $cS ? @$cS : ();
510              
511             # Perform the action to change the LALR tables only if the next state
512             # is listed as a conflictstate
513 0         0 my ($cs) = (grep { exists $_->{$conflictstate}} @conflictStates);
  0         0  
514 0 0       0 return unless $cs;
515              
516             # Action can be given using the name of the production
517 0 0       0 unless (looks_like_number($action)) {
518 0         0 my $actionnum = $self->{LABELS}{$action};
519 0 0       0 unless (looks_like_number($actionnum)) {
520 0         0 croak "YYSetReduce error: can't find production '$action'. Did you forget to name it?";
521             }
522 0         0 $action = -$actionnum;
523             }
524              
525 0 0       0 $token = $cs->{$conflictstate} unless defined($token);
526 0 0       0 $token = [ $token ] unless ref($token);
527 0         0 for (@$token) {
528             # save if shift
529 0 0 0     0 if (exists($self->{STATES}[$conflictstate]{ACTIONS}) and $self->{STATES}[$conflictstate]{ACTIONS}{$_} >= 0) {
530 0         0 $self->{CONFLICT}{$conflictName}{$_} = [ $conflictstate, $self->{STATES}[$conflictstate]{ACTIONS}{$_} ];
531             }
532 0         0 $self->{STATES}[$conflictstate]{ACTIONS}{$_} = $action;
533             }
534             }
535              
536             sub YYSetReduce {
537 0     0 1 0 my $self = shift;
538 0         0 my $action = pop;
539 0         0 my $token = shift;
540            
541              
542 0 0       0 croak "YYSetReduce error: specify a production" unless defined($action);
543              
544 0         0 my $conflictName = $self->YYLhs;
545              
546             #$self->{CONFLICTHANDLERS}{conflictName}{states}
547             # is a hash
548             # statenumber => [ tokens, '\'-\'' ]
549 0         0 my $cS = $self->{CONFLICTHANDLERS}{$conflictName}{states};
550 0 0       0 my @conflictStates = $cS ? @$cS : ();
551            
552 0 0       0 return unless @conflictStates;
553              
554             # Conflict state
555 0         0 my $cs = $conflictStates[0];
556              
557              
558 0         0 my ($conflictstate) = keys %{$cs};
  0         0  
559              
560             # Action can be given using the name of the production
561 0 0       0 unless (looks_like_number($action)) {
562 0         0 my $actionnum = $self->{LABELS}{$action};
563 0 0       0 unless (looks_like_number($actionnum)) {
564 0         0 croak "YYSetReduce error: can't find production '$action'. Did you forget to name it?";
565             }
566 0         0 $action = -$actionnum;
567             }
568              
569 0 0       0 $token = $cs->{$conflictstate} unless defined($token);
570 0 0       0 $token = [ $token ] unless ref($token);
571 0         0 for (@$token) {
572             # save if shift
573 0 0 0     0 if (exists($self->{STATES}[$conflictstate]{ACTIONS}) and $self->{STATES}[$conflictstate]{ACTIONS}{$_} >= 0) {
574 0         0 $self->{CONFLICT}{$conflictName}{$_} = [ $conflictstate, $self->{STATES}[$conflictstate]{ACTIONS}{$_} ];
575             }
576 0         0 $self->{STATES}[$conflictstate]{ACTIONS}{$_} = $action;
577             }
578             }
579              
580             sub YYSetShift {
581 0     0 1 0 my ($self, $token) = @_;
582              
583             # my ($self, $token, $action) = @_;
584             # $action is syntactic sugar ...
585              
586              
587 0         0 my $conflictName = $self->YYLhs;
588              
589 0         0 my $cS = $self->{CONFLICTHANDLERS}{$conflictName}{states};
590 0 0       0 my @conflictStates = $cS ? @$cS : ();
591            
592 0 0       0 return unless @conflictStates;
593              
594 0         0 my $cs = $conflictStates[0];
595              
596 0         0 my ($conflictstate) = keys %{$cs};
  0         0  
597              
598 0 0       0 $token = $cs->{$conflictstate} unless defined($token);
599 0 0       0 $token = [ $token ] unless ref($token);
600              
601 0         0 for (@$token) {
602 0 0       0 if (defined($self->{CONFLICT}{$conflictName}{$_})) {
603 0         0 my ($conflictstate2, $action) = @{$self->{CONFLICT}{$conflictName}{$_}};
  0         0  
604             # assert($conflictstate == $conflictstate2)
605              
606 0         0 $self->{STATES}[$conflictstate]{ACTIONS}{$_} = $self->{CONFLICT}{$conflictName}{$_}[1];
607             }
608             else {
609             #croak "YYSetShift error. No shift action found";
610             # shift is the default ... hope to be lucky!
611             }
612             }
613             }
614              
615              
616             # if is reduce ...
617             # x $self->{CONFLICTHANDLERS}{$conflictName}{production}{$action} $action is a number
618             #0 ARRAY(0x100b3f930)
619             # 0 2
620             # has the position in the item, starting at 0
621             # DB<19> x $self->YYRHSLength(4)
622             # 0 3
623             # if pos is length -1 then is reduce otherwise is shift
624              
625              
626             # It does YYSetReduce or YYSetshift according to the
627             # decision variable
628             # I need to know the kind of conflict that there is
629             # shift-reduce or reduce-reduce
630             sub YYIf {
631 0     0 0 0 my $self = shift;
632 0         0 my $syntaxVariable = shift;
633              
634 0 0       0 if ($self->YYIs($syntaxVariable)) {
635 0 0       0 if ($_[0] eq 'shift') {
636 0         0 $self->YYSetShift(@_);
637             }
638             else {
639 0         0 $self->YYSetReduce($_[0]);
640             }
641             }
642             else {
643 0 0       0 if ($_[1] eq 'shift') {
644 0         0 $self->YYSetShift(@_);
645             }
646             else {
647 0         0 $self->YYSetReduce($_[1]);
648             }
649             }
650 0         0 $self->YYIs($syntaxVariable, 0);
651             }
652              
653             sub YYGetLRAction {
654 0     0 1 0 my ($self, $state, $token) = @_;
655              
656 0 0 0     0 $state = $state->[0] if reftype($state) && (reftype($state) eq 'ARRAY');
657 0         0 my $stateentry = $self->{STATES}[$state];
658              
659 0 0       0 if (defined($token)) {
660 0 0       0 return $stateentry->{ACTIONS}{$token} if exists $stateentry->{ACTIONS}{$token};
661             }
662              
663 0 0       0 return $stateentry->{DEFAULT} if exists $stateentry->{DEFAULT};
664              
665 0         0 return;
666             }
667              
668             # to dynamically set semantic actions
669             sub YYAction {
670 0     0 1 0 my $self = shift;
671 0         0 my $index = shift;
672 0         0 my $newaction = shift;
673              
674 0 0       0 croak "YYAction error: Expecting an index" unless $index;
675              
676             # If $index is the production 'name' find the actual index
677 0 0       0 $index = $self->YYIndex($index) unless looks_like_number($index);
678 0         0 my $rule = $self->{RULES}->[$index];
679 0 0 0     0 $rule->[2] = $newaction if $newaction && (reftype($newaction) eq 'CODE');
680              
681 0         0 return $rule->[2];
682             }
683              
684             sub YYSetaction {
685 0     0 1 0 my $self = shift;
686 0         0 my %newaction = @_;
687              
688 0         0 for my $n (keys(%newaction)) {
689 0 0       0 my $m = looks_like_number($n) ? $n : $self->YYIndex($n);
690 0         0 my $rule = $self->{RULES}->[$m];
691 0 0 0     0 $rule->[2] = $newaction{$n} if ($newaction{$n} && (reftype($newaction{$n}) eq 'CODE'));
692             }
693             }
694              
695             #sub YYDebugtree {
696             # my ($self, $i, $e) = @_;
697             #
698             # my ($name, $lhs, $rhs) = @$e;
699             # my @rhs = @$rhs;
700             #
701             # return if $name =~ /_SUPERSTART/;
702             # $name = $lhs."::"."@rhs";
703             # $name =~ s/\W/_/g;
704             # return $name;
705             #}
706             #
707             #sub YYSetnames {
708             # my $self = shift;
709             # my $newname = shift || \&YYDebugtree;
710             #
711             # die "YYSetnames error. Exected a CODE reference found <$newname>"
712             # unless $newname && (reftype($newname) eq 'CODE');
713             #
714             # my $i = 0;
715             # for my $e (@{$self->{GRAMMAR}}) {
716             # my $nn= $newname->($self, $i, $e);
717             # $e->[0] = $nn if defined($nn);
718             # $i++;
719             # }
720             #}
721              
722             sub YYLhs {
723             # returns the syntax variable on
724             # the left hand side of the current production
725 696     696 1 1036 my $self = shift;
726              
727 696         1465 return $self->{CURRENT_LHS}
728             }
729              
730             sub YYRuleindex {
731             # returns the index of the rule
732             # counting the super rule as rule 0
733 10     10 1 37 my $self = shift;
734              
735 10         30 return $self->{CURRENT_RULE}
736             }
737              
738             sub YYRightside {
739             # returns the rule
740             # counting the super rule as rule 0
741 1257     1257 1 1965 my $self = shift;
742 1257   33     5428 my $index = shift || $self->{CURRENT_RULE};
743 1257 50       4126 $index = $self->YYIndex($index) unless looks_like_number($index);
744              
745 1257         1563 return @{$self->{GRAMMAR}->[$index]->[2]};
  1257         5557  
746             }
747              
748             sub YYTerms {
749 0     0 0 0 my $self = shift;
750              
751 0         0 return $self->{TERMS};
752             }
753              
754              
755             sub YYIsterm {
756 1352     1352 1 1760 my $self = shift;
757 1352         1503 my $symbol = shift;
758              
759 1352         9767 return exists ($self->{TERMS}->{$symbol});
760             }
761              
762             sub YYIssemantic {
763 1426     1426 1 1681 my $self = shift;
764 1426         2161 my $symbol = shift;
765              
766 1426 100       5120 return 0 unless exists($self->{TERMS}{$symbol});
767 871 50       1794 $self->{TERMS}{$symbol}{ISSEMANTIC} = shift if @_;
768 871         3331 return ($self->{TERMS}{$symbol}{ISSEMANTIC});
769             }
770              
771             sub YYName {
772 1262     1262 1 1460 my $self = shift;
773              
774 1262         2575 my $current_rule = $self->{GRAMMAR}->[$self->{CURRENT_RULE}];
775 1262 50       3274 $current_rule->[0] = shift if @_;
776 1262         2555 return $current_rule->[0];
777             }
778              
779             sub YYPrefix {
780 1717     1717 1 2447 my $self = shift;
781              
782 1717 50       3819 $self->{PREFIX} = $_[0] if @_;
783 1717         5655 $self->{PREFIX};
784             }
785              
786             sub YYAccessors {
787 133     133 0 291 my $self = shift;
788              
789 133         463 $self->{ACCESSORS}
790             }
791              
792             # name of the file containing
793             # the source grammar
794             sub YYFilename {
795 0     0 0 0 my $self = shift;
796              
797 0 0       0 $self->{FILENAME} = $_[0] if @_;
798 0         0 $self->{FILENAME};
799             }
800              
801             sub YYBypass {
802 0     0 1 0 my $self = shift;
803              
804 0 0       0 $self->{BYPASS} = $_[0] if @_;
805 0         0 $self->{BYPASS};
806             }
807              
808             sub YYBypassrule {
809 499     499 1 674 my $self = shift;
810              
811 499 50       1115 $self->{GRAMMAR}->[$self->{CURRENT_RULE}][3] = $_[0] if @_;
812 499         1363 return $self->{GRAMMAR}->[$self->{CURRENT_RULE}][3];
813             }
814              
815             sub YYFirstline {
816 0     0 1 0 my $self = shift;
817              
818 0 0       0 $self->{FIRSTLINE} = $_[0] if @_;
819 0         0 $self->{FIRSTLINE};
820             }
821              
822             # Used as default action when writing a reusable grammar.
823             # See files examples/recycle/NoacInh.eyp
824             # and examples/recycle/icalcu_and_ipost.pl
825             # in the Parse::Eyapp distribution
826             sub YYDelegateaction {
827 0     0 1 0 my $self = shift;
828              
829 0         0 my $action = $self->YYName;
830            
831 0         0 $self->$action(@_);
832             }
833              
834             # Influences the behavior of YYActionforT_X1X2
835             # YYActionforT_single and YYActionforT_empty
836             # If true these methods will build simple lists of attributes
837             # for the lists operators X*, X+ and X? and parenthesis (X Y)
838             # Otherwise the classic node construction for the
839             # syntax tree is used
840             sub YYBuildingTree {
841 1075     1075 1 1402 my $self = shift;
842              
843 1075 50       2331 $self->{BUILDINGTREE} = $_[0] if @_;
844 1075         5030 $self->{BUILDINGTREE};
845             }
846              
847             sub BeANode {
848 8621     8621 1 13177 my $class = shift;
849              
850 61     61   305458 no strict 'refs';
  61         165  
  61         8600  
851 8621 100       56661 push @{$class."::ISA"}, "Parse::Eyapp::Node" unless $class->isa("Parse::Eyapp::Node");
  7032         99733  
852             }
853              
854             #sub BeATranslationScheme {
855             # my $class = shift;
856             #
857             # no strict 'refs';
858             # push @{$class."::ISA"}, "Parse::Eyapp::TranslationScheme" unless $class->isa("Parse::Eyapp::TranslationScheme");
859             #}
860              
861             {
862             my $attr = sub {
863 2 50   2   11 $_[0]{attr} = $_[1] if @_ > 1;
864 2         28 $_[0]{attr}
865             };
866              
867             sub make_node_classes {
868 133     133 0 1365 my $self = shift;
869 133   100     1420 my $prefix = $self->YYPrefix() || '';
870              
871 61     61   337 { no strict 'refs';
  61         132  
  61         8025  
  133         273  
872 133         265 *{$prefix."TERMINAL::attr"} = $attr;
  133         883  
873             }
874              
875 133         396 for (@_) {
876 8533         17997 my ($class) = split /:/, $_;
877 8533         20503 BeANode("$prefix$class");
878             }
879              
880 133         1555 my $accessors = $self->YYAccessors();
881 133         995 for (keys %$accessors) {
882 52         77 my $position = $accessors->{$_};
883 61     61   530 no strict 'refs';
  61         139  
  61         39980  
884 52         270 *{$prefix.$_} = sub {
885 12     12   7945 my $self = shift;
886              
887 12         105 return $self->child($position, @_)
888             }
889 52         144 } # for
890             }
891             }
892              
893             ####################################################################
894             # Usage : ????
895             # Purpose : Responsible for the %tree directive
896             # On each production the default action becomes:
897             # sub { goto &Parse::Eyapp::Driver::YYBuildAST }
898             #
899             # Returns : ????
900             # Parameters : ????
901             # Throws : no exceptions
902             # Comments : none
903             # See Also : n/a
904             # To Do : many things: Optimize this!!!!
905             sub YYBuildAST {
906 499     499 1 2373 my $self = shift;
907 499         1090 my $PREFIX = $self->YYPrefix();
908 499         1360 my @right = $self->YYRightside(); # Symbols on the right hand side of the production
909 499         1859 my $lhs = $self->YYLhs;
910 499         1240 my $fullname = $self->YYName();
911 499         1420 my ($name) = split /:/, $fullname;
912 499         1682 my $bypass = $self->YYBypassrule; # Boolean: shall we do bypassing of lonely nodes?
913 499         971 my $class = "$PREFIX$name";
914 499         559 my @children;
915              
916 499         1239 my $node = bless {}, $class;
917              
918 499         1558 for(my $i = 0; $i < @right; $i++) {
919 992         1511 local $_ = $right[$i]; # The symbol
920 992         1442 my $ch = $_[$i]; # The attribute/reference
921              
922             # is $ch already a Parse::Eyapp::Node. May be a terminal and a syntax variable share the same name?
923 992 100       3905 unless (UNIVERSAL::isa($ch, 'Parse::Eyapp::Node')) {
924 723 100       1664 if ($self->YYIssemantic($_)) {
925 417         814 my $class = $PREFIX.'TERMINAL';
926 417         2191 my $node = bless { token => $_, attr => $ch, children => [] }, $class;
927 417         811 push @children, $node;
928 417         1478 next;
929             }
930              
931 306 100       1007 if ($self->YYIsterm($_)) {
932 304 50       1851 TERMINAL::save_attributes($ch, $node) if UNIVERSAL::can($PREFIX."TERMINAL", "save_attributes");
933 304         1045 next;
934             }
935             }
936              
937 271 50       1518 if (UNIVERSAL::isa($ch, $PREFIX."_PAREN")) { # Warning: weak code!!!
938 0         0 push @children, @{$ch->{children}};
  0         0  
939 0         0 next;
940             }
941              
942             # If it is an intermediate semantic action skip it
943 271 50       1831 next if $_ =~ qr{@}; # intermediate rule
944 271 100       1007 next unless ref($ch);
945 269         979 push @children, $ch;
946             }
947              
948            
949 499 100 100     1393 if ($bypass and @children == 1) {
950 8         12 $node = $children[0];
951              
952 8         67 my $childisterminal = ref($node) =~ /TERMINAL$/;
953             # Re-bless unless is "an automatically named node", but the characterization of this is
954 8 50       69 bless $node, $class unless $name =~ /${lhs}_\d+$/; # lazy, weak (and wicked).
955              
956            
957 8         15 my $finalclass = ref($node);
958             $childisterminal and !$finalclass->isa($PREFIX.'TERMINAL')
959 8 100 66     114 and do {
960 61     61   561 no strict 'refs';
  61         141  
  61         127387  
961 2         5 push @{$finalclass."::ISA"}, $PREFIX.'TERMINAL'
  2         29  
962             };
963              
964 8         34 return $node;
965             }
966 491         2223 $node->{children} = \@children;
967 491         1520 return $node;
968             }
969              
970             sub YYBuildTS {
971 187     187 1 2386 my $self = shift;
972 187         596 my $PREFIX = $self->YYPrefix();
973 187         541 my @right = $self->YYRightside(); # Symbols on the right hand side of the production
974 187         667 my $lhs = $self->YYLhs;
975 187         465 my $fullname = $self->YYName();
976 187         488 my ($name) = split /:/, $fullname;
977 187         268 my $class;
978             my @children;
979              
980 187         520 for(my $i = 0; $i < @right; $i++) {
981 331         571 local $_ = $right[$i]; # The symbol
982 331         569 my $ch = $_[$i]; # The attribute/reference
983              
984 331 100       831 if ($self->YYIsterm($_)) {
985 175         333 $class = $PREFIX.'TERMINAL';
986 175         964 push @children, bless { token => $_, attr => $ch, children => [] }, $class;
987 175         747 next;
988             }
989              
990 156 50       1022 if (UNIVERSAL::isa($ch, $PREFIX."_PAREN")) { # Warning: weak code!!!
991 0         0 push @children, @{$ch->{children}};
  0         0  
992 0         0 next;
993             }
994              
995             # Substitute intermediate code node _CODE(CODE()) by CODE()
996 156 100       810 if (UNIVERSAL::isa($ch, $PREFIX."_CODE")) { # Warning: weak code!!!
997 10         58 push @children, $ch->child(0);
998 10         34 next;
999             }
1000              
1001 146 50       426 next unless ref($ch);
1002 146         542 push @children, $ch;
1003             }
1004              
1005 187 100       598 if (unpack('A1',$lhs) eq '@') { # class has to be _CODE check
1006 10 50       55 $lhs =~ /^\@[0-9]+\-([0-9]+)$/
1007             or croak "In line rule name '$lhs' ill formed: report it as a BUG.\n";
1008 10         22 my $dotpos = $1;
1009            
1010 10 50 33     72 croak "Fatal error building metatree when processing $lhs -> @right"
1011             unless exists($_[$dotpos]) and UNIVERSAL::isa($_[$dotpos], 'CODE') ;
1012 10         21 push @children, $_[$dotpos];
1013             }
1014             else {
1015 177         269 my $code = $_[@right];
1016 177 100       498 if (UNIVERSAL::isa($code, 'CODE')) {
1017 169         299 push @children, $code;
1018             }
1019             else {
1020 8 50       21 croak "Fatal error building translation scheme. Code or undef expected" if (defined($code));
1021             }
1022             }
1023              
1024 187         330 $class = "$PREFIX$name";
1025 187         653 my $node = bless { children => \@children }, $class;
1026 187         679 $node;
1027             }
1028              
1029             sub YYActionforT_TX1X2_tree {
1030 322     322 0 602 my $self = shift;
1031 322         458 my $head = shift;
1032 322         701 my $PREFIX = $self->YYPrefix();
1033 322         779 my @right = $self->YYRightside();
1034 322         494 my $class;
1035              
1036 322         1078 for(my $i = 1; $i < @right; $i++) {
1037 464         754 local $_ = $right[$i];
1038 464         974 my $ch = $_[$i-1];
1039 464 100       1110 if ($self->YYIssemantic($_)) {
1040 5         9 $class = $PREFIX.'TERMINAL';
1041 5         9 push @{$head->{children}}, bless { token => $_, attr => $ch, children => [] }, $class;
  5         838  
1042            
1043 5         25 next;
1044             }
1045 459 100       1186 next if $self->YYIsterm($_);
1046 317 100       1320 if (ref($ch) eq $PREFIX."_PAREN") { # Warning: weak code!!!
1047 77         96 push @{$head->{children}}, @{$ch->{children}};
  77         154  
  77         148  
1048 77         284 next;
1049             }
1050 240 100       639 next unless ref($ch);
1051 237         306 push @{$head->{children}}, $ch;
  237         1301  
1052             }
1053              
1054 322         809 return $head;
1055             }
1056              
1057             # For * and + lists
1058             # S2 -> S2 X { push @$_[1] the node associated with X; $_[1] }
1059             # S2 -> /* empty */ { a node with empty children }
1060             sub YYActionforT_TX1X2 {
1061 322 50   322 0 1474 goto &YYActionforT_TX1X2_tree if $_[0]->YYBuildingTree;
1062              
1063 0         0 my $self = shift;
1064 0         0 my $head = shift;
1065              
1066 0         0 push @$head, @_;
1067 0         0 return $head;
1068             }
1069              
1070             sub YYActionforParenthesis {
1071 177 50   177 0 821 goto &YYBuildAST if $_[0]->YYBuildingTree;
1072              
1073 0         0 my $self = shift;
1074              
1075 0         0 return [ @_ ];
1076             }
1077              
1078              
1079             sub YYActionforT_empty_tree {
1080 337     337 0 438 my $self = shift;
1081 337         1119 my $PREFIX = $self->YYPrefix();
1082 337         799 my $name = $self->YYName();
1083              
1084             # Allow use of %name
1085 337         640 my $class = $PREFIX.$name;
1086 337         1389 my $node = bless { children => [] }, $class;
1087             #BeANode($class);
1088 337         720 $node;
1089             }
1090              
1091             sub YYActionforT_empty {
1092 337 50   337 0 1456 goto &YYActionforT_empty_tree if $_[0]->YYBuildingTree;
1093              
1094 0         0 [];
1095             }
1096              
1097             sub YYActionforT_single_tree {
1098 239     239 0 383 my $self = shift;
1099 239         573 my $PREFIX = $self->YYPrefix();
1100 239         600 my $name = $self->YYName();
1101 239         669 my @right = $self->YYRightside();
1102 239         382 my $class;
1103              
1104             # Allow use of %name
1105             my @t;
1106 239         769 for(my $i = 0; $i < @right; $i++) {
1107 239         439 local $_ = $right[$i];
1108 239         397 my $ch = $_[$i];
1109 239 100       722 if ($self->YYIssemantic($_)) {
1110 3         7 $class = $PREFIX.'TERMINAL';
1111 3         20 push @t, bless { token => $_, attr => $ch, children => [] }, $class;
1112             #BeANode($class);
1113 3         25 next;
1114             }
1115 236 50       770 next if $self->YYIsterm($_);
1116 236 100       825 if (ref($ch) eq $PREFIX."_PAREN") { # Warning: weak code!!!
1117 100         152 push @t, @{$ch->{children}};
  100         292  
1118 100         720 next;
1119             }
1120 136 100       383 next unless ref($ch);
1121 128         480 push @t, $ch;
1122             }
1123 239         394 $class = $PREFIX.$name;
1124 239         888 my $node = bless { children => \@t }, $class;
1125             #BeANode($class);
1126 239         685 $node;
1127             }
1128              
1129             sub YYActionforT_single {
1130 239 50   239 0 1171 goto &YYActionforT_single_tree if $_[0]->YYBuildingTree;
1131              
1132 0         0 my $self = shift;
1133 0         0 [ @_ ];
1134             }
1135              
1136             ### end Casiano methods
1137              
1138             sub YYCurtok {
1139 0     0 1 0 my($self)=shift;
1140              
1141             @_
1142 0 0       0 and ${$$self{TOKEN}}=$_[0];
  0         0  
1143 0         0 ${$$self{TOKEN}};
  0         0  
1144             }
1145              
1146             sub YYCurval {
1147 0     0 1 0 my($self)=shift;
1148              
1149             @_
1150 0 0       0 and ${$$self{VALUE}}=$_[0];
  0         0  
1151 0         0 ${$$self{VALUE}};
  0         0  
1152             }
1153              
1154             {
1155             sub YYSimStack {
1156 0     0 0 0 my $self = shift;
1157 0         0 my $stack = shift;
1158 0         0 my @reduce = @_;
1159 0         0 my @expected;
1160              
1161 0         0 for my $index (@reduce) {
1162 0         0 my ($lhs, $length) = @{$self->{RULES}[-$index]};
  0         0  
1163 0 0       0 if (@$stack > $length) {
1164 0         0 my @auxstack = @$stack;
1165 0 0       0 splice @auxstack, -$length if $length;
1166              
1167 0         0 my $state = $auxstack[-1]->[0];
1168 0         0 my $nextstate = $self->{STATES}[$state]{GOTOS}{$lhs};
1169 0 0       0 if (defined($nextstate)) {
1170 0         0 push @auxstack, [$nextstate, undef];
1171 0         0 push @expected, $self->YYExpected(\@auxstack);
1172             }
1173             }
1174             # else something went wrong!!! See Frank Leray report
1175             }
1176              
1177 0         0 return map { $_ => 1 } @expected;
  0         0  
1178             }
1179              
1180             sub YYExpected {
1181 0     0 0 0 my($self)=shift;
1182 0         0 my $stack = shift;
1183              
1184             # The state in the top of the stack
1185 0         0 my $state = $self->{STATES}[$stack->[-1][0]];
1186              
1187 0         0 my %actions;
1188 0 0       0 %actions = %{$state->{ACTIONS}} if exists $state->{ACTIONS};
  0         0  
1189              
1190             # The keys of %reduction are the -production numbers
1191             # Use hashes and not lists to guarantee that no tokens are repeated
1192 0         0 my (%expected, %reduce);
1193 0         0 for (keys(%actions)) {
1194 0 0       0 if ($actions{$_} > 0) { # shift
1195 0         0 $expected{$_} = 1;
1196 0         0 next;
1197             }
1198 0         0 $reduce{$actions{$_}} = 1;
1199             }
1200 0 0       0 $reduce{$state->{DEFAULT}} = 1 if exists($state->{DEFAULT});
1201              
1202 0 0       0 if (keys %reduce) {
1203 0         0 %expected = (%expected, $self->YYSimStack($stack, keys %reduce));
1204             }
1205            
1206 0         0 return keys %expected;
1207             }
1208              
1209             sub YYExpect {
1210 0     0 1 0 my $self = shift;
1211 0         0 $self->YYExpected($self->{STACK}, @_);
1212             }
1213             }
1214              
1215             # $self->expects($token) : returns true if the token is among the expected ones
1216             sub expects {
1217 0     0 0 0 my $self = shift;
1218 0         0 my $token = shift;
1219              
1220 0         0 my @expected = $self->YYExpect;
1221 0         0 return grep { $_ eq $token } @expected;
  0         0  
1222             }
1223              
1224             BEGIN {
1225 61     61   3224 *YYExpects = \&expects;
1226             }
1227              
1228             # Set/Get a static/class attribute for $class
1229             # Searches the $class ancestor tree for an ancestor
1230             # having defined such attribute. If found, that value is returned
1231             sub static_attribute {
1232 21293     21293 0 26558 my $class = shift;
1233 21293 100       52499 $class = ref($class) if ref($class);
1234 21293         26009 my $attributename = shift;
1235              
1236             # class/static method
1237 61     61   666 no strict 'refs';
  61         129  
  61         121803  
1238 21293         22817 my $classlexer;
1239 21293         42288 my $classname = $classlexer = $class.'::'.$attributename;
1240 21293 50       43181 if (@_) {
1241 0         0 ${$classlexer} = shift;
  0         0  
1242             }
1243              
1244 21293 100       78074 return ${$classlexer} if defined($$classlexer);
  20947         95466  
1245            
1246             # Traverse the inheritance tree for a defined
1247             # version of the attribute
1248 346         519 my @classes = @{$class.'::ISA'};
  346         1931  
1249 346         14338 my %classes = map { $_ => undef } @classes;
  346         1490  
1250 346         2092 while (@classes) {
1251 346   50     1642 my $c = shift @classes || return;
1252 346         872 $classlexer = $c.'::'.$attributename;
1253 346 100       1805 if (defined($$classlexer)) {
1254 265         1468 $$classname = $$classlexer;
1255 265         3329 return $$classlexer;
1256             }
1257             # push those that aren't already there
1258 81         180 push @classes, grep { !exists $classes{$_} } @{$c.'::ISA'};
  0         0  
  81         614  
1259             }
1260 81         365 return undef;
1261             }
1262              
1263             sub YYEndOfInput {
1264 0     0 1 0 my $self = shift;
1265              
1266 0         0 for (${$self->input}) {
  0         0  
1267 0   0     0 return !defined($_) || ($_ eq '') || (defined(pos($_)) && (pos($_) >= length($_)));
1268             }
1269             }
1270              
1271             #################
1272             # Private stuff #
1273             #################
1274              
1275              
1276             sub _CheckParams {
1277 291     291   615 my ($mandatory,$checklist,$inarray,$outhash)=@_;
1278 291         499 my ($prm,$value);
1279 291         607 my ($prmlst)={};
1280              
1281 291         1596 while(($prm,$value)=splice(@$inarray,0,2)) {
1282 2075         3404 $prm=uc($prm);
1283 2075 50       12001 exists($$checklist{$prm})
1284             or croak("Unknown parameter '$prm'");
1285 2075 50       8870 ref($value) eq $$checklist{$prm}
1286             or croak("Invalid value for parameter '$prm'");
1287 2075         12195 $prm=unpack('@2A*',$prm);
1288 2075         9700 $$outhash{$prm}=$value;
1289             }
1290 291         1192 for (@$mandatory) {
1291 316 50       1863 exists($$outhash{$_})
1292             or croak("Missing mandatory parameter '".lc($_)."'");
1293             }
1294             }
1295              
1296             #################### TailSupport ######################
1297             sub line {
1298 0     0 0 0 my $self = shift;
1299              
1300 0 0       0 if (ref($self)) {
1301 0 0       0 $self->{TOKENLINE} = shift if @_;
1302              
1303 0 0       0 return $self->static_attribute('TOKENLINE', @_,) unless defined($self->{TOKENLINE}); # class/static method
1304 0         0 return $self->{TOKENLINE};
1305             }
1306             else { # class/static method
1307 0         0 return $self->static_attribute('TOKENLINE', @_,); # class/static method
1308             }
1309             }
1310              
1311             # attribute to count the lines
1312             sub tokenline {
1313 0     0 0 0 my $self = shift;
1314              
1315 0 0       0 if (ref($self)) {
1316 0 0       0 $self->{TOKENLINE} += shift if @_;
1317              
1318 0 0       0 return $self->static_attribute('TOKENLINE', @_,) unless defined($self->{TOKENLINE}); # class/static method
1319 0         0 return $self->{TOKENLINE};
1320             }
1321             else { # class/static method
1322 0         0 return $self->static_attribute('TOKENLINE', @_,); # class/static method
1323             }
1324             }
1325              
1326             our $ERROR = \&_Error;
1327             sub error {
1328 132     132 0 313 my $self = shift;
1329              
1330 132 50       697 if (ref $self) { # instance method
1331 0 0       0 $self->{ERROR} = shift if @_;
1332              
1333 0 0       0 return $self->static_attribute('ERROR', @_,) unless defined($self->{ERROR}); # class/static method
1334 0         0 return $self->{ERROR};
1335             }
1336             else { # class/static method
1337 132         1292 return $self->static_attribute('ERROR', @_,); # class/static method
1338             }
1339             }
1340              
1341             # attribute with the input
1342             # is a reference to the actual input
1343             # slurp_file.
1344             # Parameters: object or class, filename, prompt messagge, mode (interactive or not: undef or "\n")
1345             *YYSlurpFile = \&slurp_file;
1346             sub slurp_file {
1347 0     0 0 0 my $self = shift;
1348 0         0 my $fn = shift;
1349 0         0 my $f;
1350              
1351 0         0 my $mode = undef;
1352 0 0 0     0 if ($fn && -r $fn) {
1353 0 0       0 open $f, $fn or die "Can't find file '$fn'!\n";
1354             }
1355             else {
1356 0         0 $f = \*STDIN;
1357 0         0 my $msg = $self->YYPrompt();
1358 0         0 $mode = shift;
1359 0 0       0 print($msg) if $msg;
1360             }
1361 0         0 $self->YYInputFile($f);
1362              
1363 0         0 local $/ = $mode;
1364 0         0 my $input = <$f>;
1365              
1366 0 0       0 if (ref($self)) { # called as object method
1367 0         0 $self->input(\$input);
1368             }
1369             else { # class/static method
1370 0         0 my $classinput = $self.'::input';
1371 0         0 ${$classinput}->input(\$input);
  0         0  
1372             }
1373             }
1374              
1375             our $INPUT = \undef;
1376             *Parse::Eyapp::Driver::YYInput = \&input;
1377             sub input {
1378 21029     21029 0 25470 my $self = shift;
1379              
1380 21029 50       48389 $self->line(1) if @_; # used as setter
1381 21029 50       40123 if (ref $self) { # instance method
1382 21029 50       41827 if (@_) {
1383 0 0       0 if (ref $_[0]) {
1384 0         0 $self->{INPUT} = shift;
1385             }
1386             else {
1387 0         0 my $input = shift;
1388 0         0 $self->{INPUT} = \$input;
1389             }
1390             }
1391              
1392 21029 50       75350 return $self->static_attribute('INPUT', @_,) unless defined($self->{INPUT}); # class/static method
1393 0         0 return $self->{INPUT};
1394             }
1395             else { # class/static method
1396 0         0 return $self->static_attribute('INPUT', @_,); # class/static method
1397             }
1398             }
1399             *YYInput = \&input; # alias
1400              
1401             # Opened file used to get the input
1402             # static and instance method
1403             our $INPUTFILE = \*STDIN;
1404             sub YYInputFile {
1405 0     0 0 0 my $self = shift;
1406              
1407 0 0       0 if (ref($self)) { # object method
1408 0         0 my $file = shift;
1409 0 0       0 if ($file) { # setter
1410 0         0 $self->{INPUTFILE} = $file;
1411             }
1412            
1413 0 0       0 return $self->static_attribute('INPUTFILE', @_,) unless defined($self->{INPUTFILE}); # class/static method
1414 0         0 return $self->{INPUTFILE};
1415             }
1416             else { # static
1417 0         0 return $self->static_attribute('INPUTFILE', @_,); # class/static method
1418             }
1419             }
1420              
1421              
1422             our $PROMPT;
1423             sub YYPrompt {
1424 0     0 0 0 my $self = shift;
1425              
1426 0 0       0 if (ref($self)) { # object method
1427 0         0 my $prompt = shift;
1428 0 0       0 if ($prompt) { # setter
1429 0         0 $self->{PROMPT} = $prompt;
1430             }
1431            
1432 0 0       0 return $self->static_attribute('PROMPT', @_,) unless defined($self->{PROMPT}); # class/static method
1433 0         0 return $self->{PROMPT};
1434             }
1435             else { # static
1436 0         0 return $self->static_attribute('PROMPT', @_,); # class/static method
1437             }
1438             }
1439              
1440             # args: parser, debug and optionally the input or a reference to the input
1441             sub Run {
1442 0     0 0 0 my ($self) = shift;
1443 0         0 my $yydebug = shift;
1444            
1445 0 0       0 if (defined($_[0])) {
1446 0 0       0 if (ref($_[0])) { # if arg is a reference
1447 0         0 $self->input(shift());
1448             }
1449             else { # arg isn't a ref: make a copy
1450 0         0 my $x = shift();
1451 0         0 $self->input(\$x);
1452             }
1453             }
1454 0 0 0     0 croak "Provide some input for parsing" unless ($self->input && defined(${$self->input()}));
  0         0  
1455 0         0 return $self->YYParse(
1456             #yylex => $self->lexer(),
1457             #yyerror => $self->error(),
1458             yydebug => $yydebug, # 0xF
1459             );
1460             }
1461             *Parse::Eyapp::Driver::YYRun = \&run;
1462              
1463             # args: class, prompt, file, optionally input (ref or not)
1464             # return the abstract syntax tree (or whatever was returned by the parser)
1465             *Parse::Eyapp::Driver::YYMain = \&main;
1466             sub main {
1467 0     0 0 0 my $package = shift;
1468 0         0 my $prompt = shift;
1469              
1470 0         0 my $debug = 0;
1471 0         0 my $file = '';
1472 0         0 my $showtree = 0;
1473 0         0 my $TERMINALinfo;
1474             my $help;
1475 0         0 my $slurp;
1476 0         0 my $inputfromfile = 1;
1477 0         0 my $commandinput = '';
1478 0         0 my $quotedcommandinput = '';
1479 0         0 my $yaml = 0;
1480 0         0 my $dot = 0;
1481              
1482 0         0 my $result = GetOptions (
1483             "debug!" => \$debug, # sets yydebug on
1484             "file=s" => \$file, # read input from that file
1485             "commandinput=s" => \$commandinput, # read input from command line arg
1486             "tree!" => \$showtree, # prints $tree->str
1487             "info" => \$TERMINALinfo, # prints $tree->str and provides default TERMINAL::info
1488             "help" => \$help, # shows SYNOPSIS section from the script pod
1489             "slurp!" => \$slurp, # read until EOF or CR is reached
1490             "argfile!" => \$inputfromfile, # take input string from @_
1491             "yaml" => \$yaml, # dumps YAML for $tree: YAML must be installed
1492             "dot=s" => \$dot, # dumps YAML for $tree: YAML must be installed
1493             "margin=i" => \$Parse::Eyapp::Node::INDENT,
1494             );
1495              
1496 0 0       0 $package->_help() if $help;
1497              
1498 0 0       0 $debug = 0x1F if $debug;
1499 0 0 0     0 $file = shift if !$file && @ARGV; # file is taken from the @ARGV unless already defined
1500 0 0       0 $slurp = "\n" if defined($slurp);
1501              
1502 0         0 my $parser = $package->new();
1503 0 0       0 $parser->YYPrompt($prompt) if defined($prompt);
1504              
1505 0 0       0 if ($commandinput) {
    0          
1506 0         0 $parser->input(\$commandinput);
1507             }
1508             elsif ($inputfromfile) {
1509 0         0 $parser->slurp_file( $file, $slurp);
1510             }
1511             else { # input must be a string argument
1512 0 0       0 croak "No input provided for parsing! " unless defined($_[0]);
1513 0 0       0 if (ref($_[0])) {
1514 0         0 $parser->input(shift());
1515             }
1516             else {
1517 0         0 my $x = shift();
1518 0         0 $parser->input(\$x);
1519             }
1520             }
1521              
1522 0 0       0 if (defined($TERMINALinfo)) {
1523 0   0     0 my $prefix = ($parser->YYPrefix || '');
1524 61     61   476 no strict 'refs';
  61         148  
  61         207107  
1525 0         0 *{$prefix.'TERMINAL::info'} = sub {
1526 0 0   0   0 (ref($_[0]->attr) eq 'ARRAY')? $_[0]->attr->[0] : $_[0]->attr
1527 0         0 };
1528             }
1529              
1530 0         0 my $tree = $parser->Run( $debug, @_ );
1531              
1532 0 0       0 if (my $ne = $parser->YYNberr > 0) {
1533 0         0 print "There were $ne errors during parsing\n";
1534 0         0 return undef;
1535             }
1536             else {
1537 0 0       0 if ($showtree) {
1538 0 0 0     0 if ($tree && blessed $tree && $tree->isa('Parse::Eyapp::Node')) {
    0 0        
    0 0        
1539              
1540 0         0 print $tree->str()."\n";
1541             }
1542             elsif ($tree && ref $tree) {
1543 0         0 require Data::Dumper;
1544 0         0 print Data::Dumper::Dumper($tree)."\n";
1545             }
1546             elsif (defined($tree)) {
1547 0         0 print "$tree\n";
1548             }
1549             }
1550 0 0 0     0 if ($yaml && ref($tree)) {
1551 0         0 eval {
1552 0         0 require YAML;
1553             };
1554 0 0       0 if ($@) {
1555 0         0 print "You must install 'YAML' to use this option\n";
1556             }
1557             else {
1558 0         0 YAML->import;
1559 0         0 print Dump($tree);
1560             }
1561             }
1562 0 0 0     0 if ($dot && blessed($tree)) {
1563 0         0 my ($sfile, $extension) = $dot =~ /^(.*)\.([^.]*)$/;
1564 0 0 0     0 $extension = 'png' unless (defined($extension) and $tree->can($extension));
1565 0 0 0     0 ($sfile) = $file =~ m{(.*[^.])} if !defined($sfile) and defined($file);
1566 0         0 $tree->$extension($sfile);
1567             }
1568              
1569 0         0 return $tree
1570             }
1571             }
1572              
1573             sub _help {
1574 0     0   0 my $package = shift;
1575              
1576 0         0 print << 'AYUDA';
1577             Available options:
1578             --debug sets yydebug on
1579             --nodebug sets yydebug off
1580             --file filepath read input from filepath
1581             --commandinput string read input from string
1582             --tree prints $tree->str
1583             --notree does not print $tree->str
1584             --info When printing $tree->str shows the value of TERMINALs
1585             --help shows this help
1586             --slurp read until EOF reached
1587             --noslurp read until CR is reached
1588             --argfile main() will take the input string from its @_
1589             --noargfile main() will not take the input string from its @_
1590             --yaml dumps YAML for $tree: YAML module must be installed
1591             --margin=i controls the indentation of $tree->str (i.e. $Parse::Eyapp::Node::INDENT)
1592             --dot format produces a .dot and .format file (png,jpg,bmp, etc.)
1593             AYUDA
1594              
1595 0 0       0 $package->help() if ($package & $package->can("help"));
1596              
1597 0         0 exit(0);
1598             }
1599              
1600             # Generic error handler
1601             # Convention adopted: if the attribute of a token is an object
1602             # assume it has 'line' and 'str' methods. Otherwise, if it
1603             # is an array, follows the convention [ str, line, ...]
1604             # otherwise is just an string representing the value of the token
1605             sub _Error {
1606 0     0   0 my $parser = shift;
1607              
1608 0         0 my $yydata = $parser->YYData;
1609              
1610             exists $yydata->{ERRMSG}
1611 0 0       0 and do {
1612 0         0 warn $yydata->{ERRMSG};
1613 0         0 delete $yydata->{ERRMSG};
1614 0         0 return;
1615             };
1616              
1617 0         0 my ($attr)=$parser->YYCurval;
1618              
1619 0         0 my $stoken = '';
1620              
1621 0 0 0     0 if (blessed($attr) && $attr->can('str')) {
    0          
1622 0         0 $stoken = " near '".$attr->str."'"
1623             }
1624             elsif (ref($attr) eq 'ARRAY') {
1625 0         0 $stoken = " near '".$attr->[0]."'";
1626             }
1627             else {
1628 0 0       0 if ($attr) {
1629 0         0 $stoken = " near '$attr'";
1630             }
1631             else {
1632 0         0 $stoken = " near end of input";
1633             }
1634             }
1635              
1636 0 0       0 my @expected = map { ($_ ne '')? "'$_'" : q{'end of input'}} $parser->YYExpect();
  0         0  
1637 0         0 my $expected = '';
1638 0 0       0 if (@expected) {
1639 0 0       0 $expected = (@expected >1) ? "Expected one of these terminals: @expected"
1640             : "Expected terminal: @expected"
1641             }
1642              
1643 0         0 my $tline = '';
1644 0 0 0     0 if (blessed($attr) && $attr->can('line')) {
    0          
1645 0         0 $tline = " (line number ".$attr->line.")"
1646             }
1647             elsif (ref($attr) eq 'ARRAY') {
1648 0         0 $tline = " (line number ".$attr->[1].")";
1649             }
1650             else {
1651             # May be the parser object knows the line number ?
1652 0         0 my $lineno = $parser->line;
1653 0 0       0 $tline = " (line number $lineno)" if $lineno > 1;
1654             }
1655              
1656 0         0 local $" = ', ';
1657 0         0 warn << "ERRMSG";
1658              
1659             Syntax error$stoken$tline.
1660             $expected
1661             ERRMSG
1662             };
1663              
1664             ################ end TailSupport #####################
1665              
1666             sub _DBLoad {
1667              
1668             #Already loaded ?
1669 0 0   0   0 __PACKAGE__->can('_DBParse') and return;
1670            
1671 0         0 my($fname)=__FILE__;
1672 0         0 my(@drv);
1673 0         0 local $/ = "\n";
1674 0 0       0 if (open(DRV,"<$fname")) {
1675 0         0 local $_;
1676 0         0 while() {
1677             #/^\s*sub\s+_Parse\s*{\s*$/ .. /^\s*}\s*#\s*_Parse\s*$/ and do {
1678 0 0       0 /^my\s+\$lex;##!!##$/ .. /^\s*}\s*#\s*_Parse\s*$/ and do {
1679 0         0 s/^#DBG>//;
1680 0         0 push(@drv,$_);
1681             }
1682             }
1683 0         0 close(DRV);
1684              
1685 0         0 $drv[1]=~s/_P/_DBP/;
1686 0         0 eval join('',@drv);
1687             }
1688             else {
1689             # TODO: debugging for standalone modules isn't supported yet
1690 0         0 *Parse::Eyapp::Driver::_DBParse = \&_Parse;
1691             }
1692             }
1693              
1694             ### Receives an index for the parsing stack: -1 is the top
1695             ### Returns the symbol associated with the state $index
1696             sub YYSymbol {
1697 0     0 0 0 my $self = shift;
1698 0         0 my $index = shift;
1699            
1700 0         0 return $self->{STACK}[$index][2];
1701             }
1702              
1703             # # YYSymbolStack(0,-k) string with symbols from 0 to last-k
1704             # # YYSymbolStack(-k-2,-k) string with symbols from last-k-2 to last-k
1705             # # YYSymbolStack(-k-2,-k, filter) string with symbols from last-k-2 to last-k that match with filter
1706             # # YYSymbolStack('SYMBOL',-k, filter) string with symbols from the last occurrence of SYMBOL to last-k
1707             # # where filter can be code, regexp or string
1708             # sub YYSymbolStack {
1709             # my $self = shift;
1710             # my ($a, $b, $filter) = @_;
1711             #
1712             # # $b must be negative
1713             # croak "Error: Second index in YYSymbolStack must be negative\n" unless $b < 0;
1714             #
1715             # my $stack = $self->{STACK};
1716             # my $bottom = -@{$stack};
1717             # unless (looks_like_number($a)) {
1718             # # $a is a string: search from the top to the bottom for $a. Return empty list if not found
1719             # # $b must be a negative number
1720             # # $b must be a negative number
1721             # my $p = $b;
1722             # while ($p >= $bottom) {
1723             # last if (defined($stack->[$p][2]) && ($stack->[$p][2] eq $a));
1724             # $p--;
1725             # }
1726             # return () if $p < $bottom;
1727             # $a = $p;
1728             # }
1729             # # If positive, $a is an offset from the bottom of the stack
1730             # $a = $bottom+$a if $a >= 0;
1731             #
1732             # my @a = map { $self->YYSymbol($_) or '' } $a..$b;
1733             #
1734             # return @a unless defined $filter; # no filter
1735             # return (grep { $filter->{$_} } @a) if reftype($filter) && (reftype($filter) eq 'CODE'); # sub
1736             # return (grep /$filter/, @a) if reftype($filter) && (reftype($filter) eq 'SCALAR'); # regexp
1737             # return (grep { $_ eq $filter } @a); # string
1738             # }
1739              
1740             #Note that for loading debugging version of the driver,
1741             #this file will be parsed from 'sub _Parse' up to '}#_Parse' inclusive.
1742             #So, DO NOT remove comment at end of sub !!!
1743             my $lex;##!!##
1744             sub _Parse {
1745 158     158   385 my($self)=shift;
1746              
1747             #my $lex = $self->{LEX};
1748              
1749 158         616 my($rules,$states,$error)
1750             = @$self{ 'RULES', 'STATES', 'ERROR' };
1751 158         795 my($errstatus,$nberror,$token,$value,$stack,$check,$dotpos)
1752             = @$self{ 'ERRST', 'NBERR', 'TOKEN', 'VALUE', 'STACK', 'CHECK', 'DOTPOS' };
1753              
1754 158         281 my %conflictiveStates = %{$self->{STATECONFLICT}};
  158         612  
1755             #DBG> my($debug)=$$self{DEBUG};
1756             #DBG> my($dbgerror)=0;
1757              
1758             #DBG> my($ShowCurToken) = sub {
1759             #DBG> my($tok)='>';
1760             #DBG> for (split('',$$token)) {
1761             #DBG> $tok.= (ord($_) < 32 or ord($_) > 126)
1762             #DBG> ? sprintf('<%02X>',ord($_))
1763             #DBG> : $_;
1764             #DBG> }
1765             #DBG> $tok.='<';
1766             #DBG> };
1767              
1768 158         327 $$errstatus=0;
1769 158         275 $$nberror=0;
1770 158         442 ($$token,$$value)=(undef,undef);
1771 158         586 @$stack=( [ 0, undef, ] );
1772             #DBG> push(@{$stack->[-1]}, undef);
1773             #@$stack=( [ 0, undef, undef ] );
1774 158         506 $$check='';
1775              
1776 158         281 while(1) {
1777 21029         23941 my($actions,$act,$stateno);
1778              
1779 21029         25023 $self->{POS} = pos(${$self->input()});
  21029         49358  
1780 21029         40858 $stateno=$$stack[-1][0];
1781 21029 50       68701 if (exists($conflictiveStates{$stateno})) {
1782             #warn "Conflictive state $stateno managed by conflict handler '$conflictiveStates{$stateno}{name}'\n"
1783 0         0 for my $h (@{$conflictiveStates{$stateno}}) {
  0         0  
1784 0         0 $self->{CURRENT_LHS} = $h->{name};
1785 0         0 $h->{codeh}($self);
1786             }
1787             }
1788              
1789             # check if the state is a conflictive one,
1790             # if so, execute its conflict handlers
1791 21029         41536 $actions=$$states[$stateno];
1792              
1793             #DBG> print STDERR ('-' x 40),"\n";
1794             #DBG> $debug & 0x2
1795             #DBG> and print STDERR "In state $stateno:\n";
1796             #DBG> $debug & 0x08
1797             #DBG> and print STDERR "Stack: ".
1798             #DBG> join('->',map { defined($$_[2])? "'$$_[2]'->".$$_[0] : $$_[0] } @$stack).
1799             #DBG> "\n";
1800              
1801              
1802 21029 100       51696 if (exists($$actions{ACTIONS})) {
1803              
1804             defined($$token)
1805 10796 100       22386 or do {
1806 6807         22073 ($$token,$$value)=$self->{LEX}->($self); # original line
1807             #($$token,$$value)=$self->$lex; # to make it a method call
1808             #($$token,$$value) = $self->{LEX}->($self); # sensitive to the lexer changes
1809             #DBG> $debug & 0x01
1810             #DBG> and do {
1811             #DBG> print STDERR "Need token. Got ".&$ShowCurToken."\n";
1812             #DBG> };
1813             };
1814              
1815 10796 100       65458 $act= exists($$actions{ACTIONS}{$$token})
    100          
1816             ? $$actions{ACTIONS}{$$token}
1817             : exists($$actions{DEFAULT})
1818             ? $$actions{DEFAULT}
1819             : undef;
1820             }
1821             else {
1822 10233         20200 $act=$$actions{DEFAULT};
1823             #DBG> $debug & 0x01
1824             #DBG> and print STDERR "Don't need token.\n";
1825             }
1826              
1827             defined($act)
1828 21029 100       43286 and do {
1829              
1830             $act > 0
1831 21017 100       46081 and do { #shift
1832              
1833             #DBG> $debug & 0x04
1834             #DBG> and print STDERR "Shift and go to state $act.\n";
1835              
1836             $$errstatus
1837 6797 100       14137 and do {
1838 2         4 --$$errstatus;
1839              
1840             #DBG> $debug & 0x10
1841             #DBG> and $dbgerror
1842             #DBG> and $$errstatus == 0
1843             #DBG> and do {
1844             #DBG> print STDERR "**End of Error recovery.\n";
1845             #DBG> $dbgerror=0;
1846             #DBG> };
1847             };
1848              
1849              
1850 6797         17222 push(@$stack,[ $act, $$value ]);
1851             #DBG> push(@{$stack->[-1]},$$token);
1852              
1853 6797 100 66     34625 defined($$token) and ($$token ne '') #Don't eat the eof
1854             and $$token=$$value=undef;
1855 6797         10677 next;
1856             };
1857              
1858             #reduce
1859 14220         16469 my($lhs,$len,$code,@sempar,$semval);
1860 14220         17044 ($lhs,$len,$code)=@{$$rules[-$act]};
  14220         38741  
1861              
1862             #DBG> $debug & 0x04
1863             #DBG> and $act
1864             #DBG> #and print STDERR "Reduce using rule ".-$act." ($lhs,$len): "; # old Parse::Yapp line
1865             #DBG> and do { my @rhs = @{$self->{GRAMMAR}->[-$act]->[2]};
1866             #DBG> @rhs = ( '/* empty */' ) unless @rhs;
1867             #DBG> my $rhs = "@rhs";
1868             #DBG> $rhs = substr($rhs, 0, 30).'...' if length($rhs) > 30; # chomp if too large
1869             #DBG> print STDERR "Reduce using rule ".-$act." ($lhs --> $rhs): ";
1870             #DBG> };
1871              
1872 14220 100       36960 $act
1873             or $self->YYAccept();
1874              
1875 14220         25534 $$dotpos=$len;
1876              
1877             unpack('A1',$lhs) eq '@' #In line rule
1878 14220 100       51191 and do {
1879 104 50       900 $lhs =~ /^\@[0-9]+\-([0-9]+)$/
1880             or die "In line rule name '$lhs' ill formed: ".
1881             "report it as a BUG.\n";
1882 104         323 $$dotpos = $1;
1883             };
1884              
1885 21009         72964 @sempar = $$dotpos
1886 14220 100       43319 ? map { $$_[1] } @$stack[ -$$dotpos .. -1 ]
1887             : ();
1888              
1889 14220         26420 $self->{CURRENT_LHS} = $lhs;
1890 14220         22118 $self->{CURRENT_RULE} = -$act; # count the super-rule?
1891 14220 100       50106 $semval = $code ? $self->$code( @sempar )
    100          
1892             : @sempar ? $sempar[0] : undef;
1893              
1894 14220         50317 splice(@$stack,-$len,$len);
1895              
1896             $$check eq 'ACCEPT'
1897 14220 100       40155 and do {
1898              
1899             #DBG> $debug & 0x04
1900             #DBG> and print STDERR "Accept.\n";
1901              
1902 158         881 return($semval);
1903             };
1904              
1905             $$check eq 'ABORT'
1906 14062 50       45887 and do {
1907              
1908             #DBG> $debug & 0x04
1909             #DBG> and print STDERR "Abort.\n";
1910              
1911 0         0 return(undef);
1912              
1913             };
1914              
1915             #DBG> $debug & 0x04
1916             #DBG> and print STDERR "Back to state $$stack[-1][0], then ";
1917              
1918             $$check eq 'ERROR'
1919 14062 50       25833 or do {
1920             #DBG> $debug & 0x04
1921             #DBG> and print STDERR
1922             #DBG> "go to state $$states[$$stack[-1][0]]{GOTOS}{$lhs}.\n";
1923              
1924             #DBG> $debug & 0x10
1925             #DBG> and $dbgerror
1926             #DBG> and $$errstatus == 0
1927             #DBG> and do {
1928             #DBG> print STDERR "**End of Error recovery.\n";
1929             #DBG> $dbgerror=0;
1930             #DBG> };
1931              
1932 14062         51622 push(@$stack,
1933             [ $$states[$$stack[-1][0]]{GOTOS}{$lhs}, $semval, ]);
1934             #[ $$states[$$stack[-1][0]]{GOTOS}{$lhs}, $semval, $lhs ]);
1935             #DBG> push(@{$stack->[-1]},$lhs);
1936 14062         27776 $$check='';
1937 14062         23238 $self->{CURRENT_LHS} = undef;
1938 14062         34564 next;
1939             };
1940              
1941             #DBG> $debug & 0x04
1942             #DBG> and print STDERR "Forced Error recovery.\n";
1943              
1944 0         0 $$check='';
1945              
1946             };
1947              
1948             #Error
1949             $$errstatus
1950 12 100       29 or do {
1951              
1952 2         5 $$errstatus = 1;
1953 2         6 &$error($self);
1954 2 50       7 $$errstatus # if 0, then YYErrok has been called
1955             or next; # so continue parsing
1956              
1957             #DBG> $debug & 0x10
1958             #DBG> and do {
1959             #DBG> print STDERR "**Entering Error recovery.\n";
1960             #DBG> {
1961             #DBG> local $" = ", ";
1962             #DBG> my @expect = map { ">$_<" } $self->YYExpect();
1963             #DBG> print STDERR "Expecting one of: @expect\n";
1964             #DBG> };
1965             #DBG> ++$dbgerror;
1966             #DBG> };
1967              
1968 2         3 ++$$nberror;
1969              
1970             };
1971              
1972             $$errstatus == 3 #The next token is not valid: discard it
1973 12 100       30 and do {
1974             $$token eq '' # End of input: no hope
1975 10 50       66 and do {
1976             #DBG> $debug & 0x10
1977             #DBG> and print STDERR "**At eof: aborting.\n";
1978 0         0 return(undef);
1979             };
1980              
1981             #DBG> $debug & 0x10
1982             #DBG> and print STDERR "**Discard invalid token ".&$ShowCurToken.".\n";
1983              
1984 10         19 $$token=$$value=undef;
1985             };
1986              
1987 12         15 $$errstatus=3;
1988              
1989 12   66     112 while( @$stack
      33        
1990             and ( not exists($$states[$$stack[-1][0]]{ACTIONS})
1991             or not exists($$states[$$stack[-1][0]]{ACTIONS}{error})
1992             or $$states[$$stack[-1][0]]{ACTIONS}{error} <= 0)) {
1993              
1994             #DBG> $debug & 0x10
1995             #DBG> and print STDERR "**Pop state $$stack[-1][0].\n";
1996              
1997 13         133 pop(@$stack);
1998             }
1999              
2000             @$stack
2001 12 50       29 or do {
2002              
2003             #DBG> $debug & 0x10
2004             #DBG> and print STDERR "**No state left on stack: aborting.\n";
2005              
2006 0         0 return(undef);
2007             };
2008              
2009             #shift the error token
2010              
2011             #DBG> $debug & 0x10
2012             #DBG> and print STDERR "**Shift \$error token and go to state ".
2013             #DBG> $$states[$$stack[-1][0]]{ACTIONS}{error}.
2014             #DBG> ".\n";
2015              
2016 12         48 push(@$stack, [ $$states[$$stack[-1][0]]{ACTIONS}{error}, undef, 'error' ]);
2017              
2018             }
2019              
2020             #never reached
2021 0         0 croak("Error in driver logic. Please, report it as a BUG");
2022              
2023             }#_Parse
2024             #DO NOT remove comment
2025              
2026             *Parse::Eyapp::Driver::lexer = \&Parse::Eyapp::Driver::YYLexer;
2027             sub YYLexer {
2028 132     132 1 401 my $self = shift;
2029              
2030 132 50       557 if (ref $self) { # instance method
2031             # The class attribute isn't changed, only the instance
2032 0 0       0 $self->{LEX} = shift if @_;
2033              
2034 0 0       0 return $self->static_attribute('LEX', @_,) unless defined($self->{LEX}); # class/static method
2035 0         0 return $self->{LEX};
2036             }
2037             else {
2038 132         507 return $self->static_attribute('LEX', @_,);
2039             }
2040             }
2041              
2042              
2043             1;
2044