File Coverage

blib/lib/Math/Symbolic/Parser/Yapp.pm
Criterion Covered Total %
statement 70 326 21.4
branch 6 154 3.9
condition 1 21 4.7
subroutine 18 53 33.9
pod 0 3 0.0
total 95 557 17.0


line stmt bran cond sub pod time code
1             package Math::Symbolic::Parser::Yapp::Driver;
2 1     1   6 use strict;
  1         3  
  1         77  
3             our $VERSION = '1.05';
4              
5             ####################################################################
6             #
7             # This file was generated using Parse::Yapp version 1.05.
8             #
9             # Don't edit this file, use source file instead.
10             #
11             # ANY CHANGE MADE HERE WILL BE LOST !
12             #
13             ####################################################################
14             package Math::Symbolic::Parser::Yapp;
15 1     1   6 use vars qw ( @ISA );
  1         2  
  1         46  
16 1     1   4 use strict;
  1         3  
  1         54  
17              
18             @ISA= qw ( Math::Symbolic::Parser::Yapp::Driver );
19             #Included Parse/Yapp/Driver.pm file----------------------------------------
20             {
21             #
22             # Module Parse::Yapp::Driver
23             #
24             # This module is part of the Parse::Yapp package available on your
25             # nearest CPAN
26             #
27             # Any use of this module in a standalone parser make the included
28             # text under the same copyright as the Parse::Yapp module itself.
29             #
30             # This notice should remain unchanged.
31             #
32             # (c) Copyright 1998-2001 Francois Desarmenien, all rights reserved.
33             # (see the pod text in Parse::Yapp module for use and distribution rights)
34             #
35              
36             package Math::Symbolic::Parser::Yapp::Driver;
37              
38             require 5.004;
39              
40 1     1   6 use strict;
  1         3  
  1         29  
41              
42 1     1   5 use vars qw ( $VERSION $COMPATIBLE $FILENAME );
  1         2  
  1         71  
43              
44             $VERSION = '1.05';
45             $COMPATIBLE = '0.07';
46             $FILENAME=__FILE__;
47              
48 1     1   7 use Carp;
  1         1  
  1         1052  
49              
50             #Known parameters, all starting with YY (leading YY will be discarded)
51             my(%params)=(YYLEX => 'CODE', 'YYERROR' => 'CODE', YYVERSION => '',
52             YYRULES => 'ARRAY', YYSTATES => 'ARRAY', YYDEBUG => '');
53             #Mandatory parameters
54             my(@params)=('LEX','RULES','STATES');
55              
56             sub new {
57 1     1   3 my($class)=shift;
58 1         2 my($errst,$nberr,$token,$value,$check,$dotpos);
59 1         11 my($self)={ ERROR => \&_Error,
60             ERRST => \$errst,
61             NBERR => \$nberr,
62             TOKEN => \$token,
63             VALUE => \$value,
64             DOTPOS => \$dotpos,
65             STACK => [],
66             DEBUG => 0,
67             CHECK => \$check };
68              
69 1         7 _CheckParams( [], \%params, \@_, $self );
70              
71 1 50 33     12 exists($$self{VERSION})
72             and $$self{VERSION} < $COMPATIBLE
73             and croak "Yapp driver version $VERSION ".
74             "incompatible with version $$self{VERSION}:\n".
75             "Please recompile parser module.";
76              
77 1 50       4 ref($class)
78             and $class=ref($class);
79              
80 1         5 bless($self,$class);
81             }
82              
83             sub YYParse {
84 0     0   0 my($self)=shift;
85 0         0 my($retval);
86              
87 0         0 _CheckParams( \@params, \%params, \@_, $self );
88              
89 0 0       0 if($$self{DEBUG}) {
90 0         0 _DBLoad();
91 0         0 $retval = eval '$self->_DBParse()';#Do not create stab entry on compile
92 0 0       0 $@ and die $@;
93             }
94             else {
95 0         0 $retval = $self->_Parse();
96             }
97 0         0 $retval
98             }
99              
100             sub YYData {
101 0     0   0 my($self)=shift;
102              
103 0 0       0 exists($$self{USER})
104             or $$self{USER}={};
105              
106 0         0 $$self{USER};
107            
108             }
109              
110             sub YYErrok {
111 0     0   0 my($self)=shift;
112              
113 0         0 ${$$self{ERRST}}=0;
  0         0  
114 0         0 undef;
115             }
116              
117             sub YYNberr {
118 0     0   0 my($self)=shift;
119              
120 0         0 ${$$self{NBERR}};
  0         0  
121             }
122              
123             sub YYRecovering {
124 0     0   0 my($self)=shift;
125              
126 0         0 ${$$self{ERRST}} != 0;
  0         0  
127             }
128              
129             sub YYAbort {
130 0     0   0 my($self)=shift;
131              
132 0         0 ${$$self{CHECK}}='ABORT';
  0         0  
133 0         0 undef;
134             }
135              
136             sub YYAccept {
137 0     0   0 my($self)=shift;
138              
139 0         0 ${$$self{CHECK}}='ACCEPT';
  0         0  
140 0         0 undef;
141             }
142              
143             sub YYError {
144 0     0   0 my($self)=shift;
145              
146 0         0 ${$$self{CHECK}}='ERROR';
  0         0  
147 0         0 undef;
148             }
149              
150             sub YYSemval {
151 0     0   0 my($self)=shift;
152 0         0 my($index)= $_[0] - ${$$self{DOTPOS}} - 1;
  0         0  
153              
154 0         0 $index < 0
155 0 0 0     0 and -$index <= @{$$self{STACK}}
156             and return $$self{STACK}[$index][1];
157              
158 0         0 undef; #Invalid index
159             }
160              
161             sub YYCurtok {
162 0     0   0 my($self)=shift;
163              
164             @_
165 0 0       0 and ${$$self{TOKEN}}=$_[0];
  0         0  
166 0         0 ${$$self{TOKEN}};
  0         0  
167             }
168              
169             sub YYCurval {
170 0     0   0 my($self)=shift;
171              
172             @_
173 0 0       0 and ${$$self{VALUE}}=$_[0];
  0         0  
174 0         0 ${$$self{VALUE}};
  0         0  
175             }
176              
177             sub YYExpect {
178 0     0   0 my($self)=shift;
179              
180 0         0 keys %{$self->{STATES}[$self->{STACK}[-1][0]]{ACTIONS}}
  0         0  
181             }
182              
183             sub YYLexer {
184 0     0   0 my($self)=shift;
185              
186 0         0 $$self{LEX};
187             }
188              
189              
190             #################
191             # Private stuff #
192             #################
193              
194              
195             sub _CheckParams {
196 1     1   2 my($mandatory,$checklist,$inarray,$outhash)=@_;
197 1         2 my($prm,$value);
198 1         2 my($prmlst)={};
199              
200 1         6 while(($prm,$value)=splice(@$inarray,0,2)) {
201 3         5 $prm=uc($prm);
202 3 50       8 exists($$checklist{$prm})
203             or croak("Unknow parameter '$prm'");
204 3 50       8 ref($value) eq $$checklist{$prm}
205             or croak("Invalid value for parameter '$prm'");
206 3         11 $prm=unpack('@2A*',$prm);
207 3         12 $$outhash{$prm}=$value;
208             }
209 1         6 for (@$mandatory) {
210 0 0       0 exists($$outhash{$_})
211             or croak("Missing mandatory parameter '".lc($_)."'");
212             }
213             }
214              
215             sub _Error {
216 0     0   0 print "Parse error.\n";
217             }
218              
219             sub _DBLoad {
220             {
221 1     1   6 no strict 'refs';
  1     0   2  
  1         2092  
  0         0  
222              
223 0 0       0 exists(${__PACKAGE__.'::'}{_DBParse})#Already loaded ?
  0         0  
224             and return;
225             }
226 0         0 my($fname)=__FILE__;
227 0         0 my(@drv);
228 0 0       0 open(DRV,"<$fname") or die "Report this as a BUG: Cannot open $fname";
229 0         0 while() {
230             /^\s*sub\s+_Parse\s*{\s*$/ .. /^\s*}\s*#\s*_Parse\s*$/
231 0 0       0 and do {
232 0         0 s/^#DBG>//;
233 0         0 push(@drv,$_);
234             }
235             }
236 0         0 close(DRV);
237              
238 0         0 $drv[0]=~s/_P/_DBP/;
239 0         0 eval join('',@drv);
240             }
241              
242             #Note that for loading debugging version of the driver,
243             #this file will be parsed from 'sub _Parse' up to '}#_Parse' inclusive.
244             #So, DO NOT remove comment at end of sub !!!
245             sub _Parse {
246 0     0   0 my($self)=shift;
247              
248 0         0 my($rules,$states,$lex,$error)
249             = @$self{ 'RULES', 'STATES', 'LEX', 'ERROR' };
250 0         0 my($errstatus,$nberror,$token,$value,$stack,$check,$dotpos)
251             = @$self{ 'ERRST', 'NBERR', 'TOKEN', 'VALUE', 'STACK', 'CHECK', 'DOTPOS' };
252              
253             #DBG> my($debug)=$$self{DEBUG};
254             #DBG> my($dbgerror)=0;
255              
256             #DBG> my($ShowCurToken) = sub {
257             #DBG> my($tok)='>';
258             #DBG> for (split('',$$token)) {
259             #DBG> $tok.= (ord($_) < 32 or ord($_) > 126)
260             #DBG> ? sprintf('<%02X>',ord($_))
261             #DBG> : $_;
262             #DBG> }
263             #DBG> $tok.='<';
264             #DBG> };
265              
266 0         0 $$errstatus=0;
267 0         0 $$nberror=0;
268 0         0 ($$token,$$value)=(undef,undef);
269 0         0 @$stack=( [ 0, undef ] );
270 0         0 $$check='';
271              
272 0         0 while(1) {
273 0         0 my($actions,$act,$stateno);
274              
275 0         0 $stateno=$$stack[-1][0];
276 0         0 $actions=$$states[$stateno];
277              
278             #DBG> print STDERR ('-' x 40),"\n";
279             #DBG> $debug & 0x2
280             #DBG> and print STDERR "In state $stateno:\n";
281             #DBG> $debug & 0x08
282             #DBG> and print STDERR "Stack:[".
283             #DBG> join(',',map { $$_[0] } @$stack).
284             #DBG> "]\n";
285              
286              
287 0 0       0 if (exists($$actions{ACTIONS})) {
288              
289             defined($$token)
290 0 0       0 or do {
291 0         0 ($$token,$$value)=&$lex($self);
292             #DBG> $debug & 0x01
293             #DBG> and print STDERR "Need token. Got ".&$ShowCurToken."\n";
294             };
295              
296 0 0       0 $act= exists($$actions{ACTIONS}{$$token})
    0          
297             ? $$actions{ACTIONS}{$$token}
298             : exists($$actions{DEFAULT})
299             ? $$actions{DEFAULT}
300             : undef;
301             }
302             else {
303 0         0 $act=$$actions{DEFAULT};
304             #DBG> $debug & 0x01
305             #DBG> and print STDERR "Don't need token.\n";
306             }
307              
308             defined($act)
309 0 0       0 and do {
310              
311             $act > 0
312 0 0       0 and do { #shift
313              
314             #DBG> $debug & 0x04
315             #DBG> and print STDERR "Shift and go to state $act.\n";
316              
317             $$errstatus
318 0 0       0 and do {
319 0         0 --$$errstatus;
320              
321             #DBG> $debug & 0x10
322             #DBG> and $dbgerror
323             #DBG> and $$errstatus == 0
324             #DBG> and do {
325             #DBG> print STDERR "**End of Error recovery.\n";
326             #DBG> $dbgerror=0;
327             #DBG> };
328             };
329              
330              
331 0         0 push(@$stack,[ $act, $$value ]);
332              
333 0 0       0 $$token ne '' #Don't eat the eof
334             and $$token=$$value=undef;
335 0         0 next;
336             };
337              
338             #reduce
339 0         0 my($lhs,$len,$code,@sempar,$semval);
340 0         0 ($lhs,$len,$code)=@{$$rules[-$act]};
  0         0  
341              
342             #DBG> $debug & 0x04
343             #DBG> and $act
344             #DBG> and print STDERR "Reduce using rule ".-$act." ($lhs,$len): ";
345              
346 0 0       0 $act
347             or $self->YYAccept();
348              
349 0         0 $$dotpos=$len;
350              
351             unpack('A1',$lhs) eq '@' #In line rule
352 0 0       0 and do {
353 0 0       0 $lhs =~ /^\@[0-9]+\-([0-9]+)$/
354             or die "In line rule name '$lhs' ill formed: ".
355             "report it as a BUG.\n";
356 0         0 $$dotpos = $1;
357             };
358              
359 0         0 @sempar = $$dotpos
360 0 0       0 ? map { $$_[1] } @$stack[ -$$dotpos .. -1 ]
361             : ();
362              
363 0 0       0 $semval = $code ? &$code( $self, @sempar )
    0          
364             : @sempar ? $sempar[0] : undef;
365              
366 0         0 splice(@$stack,-$len,$len);
367              
368             $$check eq 'ACCEPT'
369 0 0       0 and do {
370              
371             #DBG> $debug & 0x04
372             #DBG> and print STDERR "Accept.\n";
373              
374 0         0 return($semval);
375             };
376              
377             $$check eq 'ABORT'
378 0 0       0 and do {
379              
380             #DBG> $debug & 0x04
381             #DBG> and print STDERR "Abort.\n";
382              
383 0         0 return(undef);
384              
385             };
386              
387             #DBG> $debug & 0x04
388             #DBG> and print STDERR "Back to state $$stack[-1][0], then ";
389              
390             $$check eq 'ERROR'
391 0 0       0 or do {
392             #DBG> $debug & 0x04
393             #DBG> and print STDERR
394             #DBG> "go to state $$states[$$stack[-1][0]]{GOTOS}{$lhs}.\n";
395              
396             #DBG> $debug & 0x10
397             #DBG> and $dbgerror
398             #DBG> and $$errstatus == 0
399             #DBG> and do {
400             #DBG> print STDERR "**End of Error recovery.\n";
401             #DBG> $dbgerror=0;
402             #DBG> };
403              
404 0         0 push(@$stack,
405             [ $$states[$$stack[-1][0]]{GOTOS}{$lhs}, $semval ]);
406 0         0 $$check='';
407 0         0 next;
408             };
409              
410             #DBG> $debug & 0x04
411             #DBG> and print STDERR "Forced Error recovery.\n";
412              
413 0         0 $$check='';
414              
415             };
416              
417             #Error
418             $$errstatus
419 0 0       0 or do {
420              
421 0         0 $$errstatus = 1;
422 0         0 &$error($self);
423 0 0       0 $$errstatus # if 0, then YYErrok has been called
424             or next; # so continue parsing
425              
426             #DBG> $debug & 0x10
427             #DBG> and do {
428             #DBG> print STDERR "**Entering Error recovery.\n";
429             #DBG> ++$dbgerror;
430             #DBG> };
431              
432 0         0 ++$$nberror;
433              
434             };
435              
436             $$errstatus == 3 #The next token is not valid: discard it
437 0 0       0 and do {
438             $$token eq '' # End of input: no hope
439 0 0       0 and do {
440             #DBG> $debug & 0x10
441             #DBG> and print STDERR "**At eof: aborting.\n";
442 0         0 return(undef);
443             };
444              
445             #DBG> $debug & 0x10
446             #DBG> and print STDERR "**Dicard invalid token ".&$ShowCurToken.".\n";
447              
448 0         0 $$token=$$value=undef;
449             };
450              
451 0         0 $$errstatus=3;
452              
453 0   0     0 while( @$stack
      0        
454             and ( not exists($$states[$$stack[-1][0]]{ACTIONS})
455             or not exists($$states[$$stack[-1][0]]{ACTIONS}{error})
456             or $$states[$$stack[-1][0]]{ACTIONS}{error} <= 0)) {
457              
458             #DBG> $debug & 0x10
459             #DBG> and print STDERR "**Pop state $$stack[-1][0].\n";
460              
461 0         0 pop(@$stack);
462             }
463              
464             @$stack
465 0 0       0 or do {
466              
467             #DBG> $debug & 0x10
468             #DBG> and print STDERR "**No state left on stack: aborting.\n";
469              
470 0         0 return(undef);
471             };
472              
473             #shift the error token
474              
475             #DBG> $debug & 0x10
476             #DBG> and print STDERR "**Shift \$error token and go to state ".
477             #DBG> $$states[$$stack[-1][0]]{ACTIONS}{error}.
478             #DBG> ".\n";
479              
480 0         0 push(@$stack, [ $$states[$$stack[-1][0]]{ACTIONS}{error}, undef ]);
481              
482             }
483              
484             #never reached
485 0         0 croak("Error in driver logic. Please, report it as a BUG");
486              
487             }#_Parse
488             #DO NOT remove comment
489              
490             1;
491              
492             }
493             #End of include--------------------------------------------------
494              
495              
496              
497              
498             sub new {
499 1     1 0 2 my($class)=shift;
500 1 50       3 ref($class)
501             and $class=ref($class);
502              
503             my($self)=$class->SUPER::new( yyversion => '1.05',
504             yystates =>
505             [
506             {#State 0
507             ACTIONS => {
508             "-" => 1,
509             'PRED' => 3,
510             'PRIVEFUNC' => 4,
511             'FUNC' => 5,
512             'NUM' => 6,
513             "(" => 7,
514             'EFUNC' => 8,
515             'VAR' => 9
516             },
517             GOTOS => {
518             'exp' => 2
519             }
520             },
521             {#State 1
522             ACTIONS => {
523             "-" => 1,
524             'PRED' => 3,
525             'PRIVEFUNC' => 4,
526             'FUNC' => 5,
527             'NUM' => 6,
528             "(" => 7,
529             'VAR' => 9,
530             'EFUNC' => 8
531             },
532             GOTOS => {
533             'exp' => 10
534             }
535             },
536             {#State 2
537             ACTIONS => {
538             '' => 12,
539             "-" => 11,
540             "^" => 15,
541             "*" => 16,
542             "+" => 13,
543             "/" => 14
544             }
545             },
546             {#State 3
547             ACTIONS => {
548             "{" => 17
549             }
550             },
551             {#State 4
552             DEFAULT => -4
553             },
554             {#State 5
555             ACTIONS => {
556             "(" => 18
557             }
558             },
559             {#State 6
560             DEFAULT => -1
561             },
562             {#State 7
563             ACTIONS => {
564             "-" => 1,
565             'PRED' => 3,
566             'PRIVEFUNC' => 4,
567             'FUNC' => 5,
568             'NUM' => 6,
569             "(" => 7,
570             'VAR' => 9,
571             'EFUNC' => 8
572             },
573             GOTOS => {
574             'exp' => 19
575             }
576             },
577             {#State 8
578             DEFAULT => -5
579             },
580             {#State 9
581             DEFAULT => -6
582             },
583             {#State 10
584             ACTIONS => {
585             "^" => 15
586             },
587             DEFAULT => -11
588             },
589             {#State 11
590             ACTIONS => {
591             "-" => 1,
592             'PRED' => 3,
593             'PRIVEFUNC' => 4,
594             'FUNC' => 5,
595             'NUM' => 6,
596             "(" => 7,
597             'VAR' => 9,
598             'EFUNC' => 8
599             },
600             GOTOS => {
601             'exp' => 20
602             }
603             },
604             {#State 12
605             DEFAULT => 0
606             },
607             {#State 13
608             ACTIONS => {
609             "-" => 1,
610             'PRED' => 3,
611             'PRIVEFUNC' => 4,
612             'FUNC' => 5,
613             'NUM' => 6,
614             "(" => 7,
615             'VAR' => 9,
616             'EFUNC' => 8
617             },
618             GOTOS => {
619             'exp' => 21
620             }
621             },
622             {#State 14
623             ACTIONS => {
624             "-" => 1,
625             'PRED' => 3,
626             'PRIVEFUNC' => 4,
627             'FUNC' => 5,
628             'NUM' => 6,
629             "(" => 7,
630             'VAR' => 9,
631             'EFUNC' => 8
632             },
633             GOTOS => {
634             'exp' => 22
635             }
636             },
637             {#State 15
638             ACTIONS => {
639             "-" => 1,
640             'PRED' => 3,
641             'PRIVEFUNC' => 4,
642             'FUNC' => 5,
643             'NUM' => 6,
644             "(" => 7,
645             'VAR' => 9,
646             'EFUNC' => 8
647             },
648             GOTOS => {
649             'exp' => 23
650             }
651             },
652             {#State 16
653             ACTIONS => {
654             "-" => 1,
655             'PRED' => 3,
656             'PRIVEFUNC' => 4,
657             'FUNC' => 5,
658             'NUM' => 6,
659             "(" => 7,
660             'VAR' => 9,
661             'EFUNC' => 8
662             },
663             GOTOS => {
664             'exp' => 24
665             }
666             },
667             {#State 17
668             ACTIONS => {
669             "-" => 1,
670             'PRED' => 3,
671             'PRIVEFUNC' => 4,
672             'FUNC' => 5,
673             'NUM' => 6,
674             "(" => 7,
675             'VAR' => 9,
676             'EFUNC' => 8
677             },
678             GOTOS => {
679             'exp' => 25
680             }
681             },
682             {#State 18
683             ACTIONS => {
684             "-" => 1,
685             'PRED' => 3,
686             'PRIVEFUNC' => 4,
687             'FUNC' => 5,
688             'NUM' => 6,
689             "(" => 7,
690             'VAR' => 9,
691             'EFUNC' => 8
692             },
693             GOTOS => {
694             'exp' => 26,
695             'list' => 27
696             }
697             },
698             {#State 19
699             ACTIONS => {
700             "-" => 11,
701             "^" => 15,
702             "*" => 16,
703             "+" => 13,
704             "/" => 14,
705             ")" => 28
706             }
707             },
708             {#State 20
709             ACTIONS => {
710             "/" => 14,
711             "^" => 15,
712             "*" => 16
713             },
714             DEFAULT => -8
715             },
716             {#State 21
717             ACTIONS => {
718             "/" => 14,
719             "^" => 15,
720             "*" => 16
721             },
722             DEFAULT => -7
723             },
724             {#State 22
725             ACTIONS => {
726             "^" => 15
727             },
728             DEFAULT => -10
729             },
730             {#State 23
731             ACTIONS => {
732             "^" => 15
733             },
734             DEFAULT => -12
735             },
736             {#State 24
737             ACTIONS => {
738             "^" => 15
739             },
740             DEFAULT => -9
741             },
742             {#State 25
743             ACTIONS => {
744             "}" => 29,
745             "-" => 11,
746             "^" => 15,
747             "*" => 16,
748             "+" => 13,
749             "/" => 14
750             }
751             },
752             {#State 26
753             ACTIONS => {
754             "-" => 11,
755             "+" => 13,
756             "/" => 14,
757             "," => 30,
758             "^" => 15,
759             "*" => 16
760             },
761             DEFAULT => -15
762             },
763             {#State 27
764             ACTIONS => {
765             ")" => 31
766             }
767             },
768             {#State 28
769             DEFAULT => -13
770             },
771             {#State 29
772             DEFAULT => -3
773             },
774             {#State 30
775             ACTIONS => {
776             "-" => 1,
777             'PRED' => 3,
778             'PRIVEFUNC' => 4,
779             'FUNC' => 5,
780             'NUM' => 6,
781             "(" => 7,
782             'VAR' => 9,
783             'EFUNC' => 8
784             },
785             GOTOS => {
786             'exp' => 26,
787             'list' => 32
788             }
789             },
790             {#State 31
791             DEFAULT => -2
792             },
793             {#State 32
794             DEFAULT => -14
795             }
796             ],
797             yyrules =>
798             [
799             [#Rule 0
800             '$start', 2, undef
801             ],
802             [#Rule 1
803             'exp', 1,
804 0     0   0 sub { $_[1] }
805             ],
806             [#Rule 2
807             'exp', 4,
808             sub {
809 0 0   0   0 if (exists($Math::Symbolic::Parser::Parser_Functions{$_[1]})) {
810 0         0 $Math::Symbolic::Parser::Parser_Functions{$_[1]}->($_[1], @{$_[3]})
  0         0  
811             }
812             else {
813 0         0 Math::Symbolic::Operator->new($_[1], @{$_[3]})
  0         0  
814             }
815             }
816             ],
817             [#Rule 3
818             'exp', 4,
819             sub {
820 0     0   0 Math::Symbolic::Variable->new(
821             'TRANSFORMATION_HOOK',
822             [$_[1], $_[3]]
823             );
824             }
825             ],
826             [#Rule 4
827             'exp', 1,
828             sub {
829 0 0   0   0 $_[1] =~ /^([^(]+)\((.*)\)$/ or die "invalid per-object parser extension function: '$_[1]'";
830 0         0 $_[0]->{__PRIV_EXT_FUNCTIONS}->{$1}->($2);
831             }
832             ],
833             [#Rule 5
834             'exp', 1,
835             sub {
836 0 0   0   0 $_[1] =~ /^([^(]+)\((.*)\)$/ or die "invalid global parser extension function: '$_[1]'";
837 0         0 $Math::SymbolicX::ParserExtensionFactory::Functions->{$1}->($2)
838             }
839             ],
840             [#Rule 6
841             'exp', 1,
842 0     0   0 sub { $_[1] }
843             ],
844             [#Rule 7
845             'exp', 3,
846 0     0   0 sub { Math::Symbolic::Operator->new('+', $_[1], $_[3]) }
847             ],
848             [#Rule 8
849             'exp', 3,
850 0     0   0 sub { Math::Symbolic::Operator->new('-', $_[1], $_[3]) }
851             ],
852             [#Rule 9
853             'exp', 3,
854 0     0   0 sub { Math::Symbolic::Operator->new('*', $_[1], $_[3]) }
855             ],
856             [#Rule 10
857             'exp', 3,
858 0     0   0 sub { Math::Symbolic::Operator->new('/', $_[1], $_[3]) }
859             ],
860             [#Rule 11
861             'exp', 2,
862 0     0   0 sub { Math::Symbolic::Operator->new('neg', $_[2]) }
863             ],
864             [#Rule 12
865             'exp', 3,
866 0     0   0 sub { Math::Symbolic::Operator->new('^', $_[1], $_[3]) }
867             ],
868             [#Rule 13
869             'exp', 3,
870 0     0   0 sub { $_[2] }
871             ],
872             [#Rule 14
873             'list', 3,
874 0     0   0 sub { unshift @{$_[3]}, $_[1]; $_[3] }
  0         0  
  0         0  
875             ],
876             [#Rule 15
877             'list', 1,
878 0     0   0 sub { [$_[1]] }
879 1         126 ]
880             ],
881             @_);
882 1         6 bless($self,$class);
883             }
884              
885              
886              
887 1     1   9 use strict;
  1         3  
  1         35  
888 1     1   7 use warnings;
  1         2  
  1         40  
889 1     1   5 use Math::Symbolic qw//;
  1         2  
  1         16  
890 1     1   4 use constant DAT => 0;
  1         2  
  1         73  
891 1     1   6 use constant OP => 1;
  1         1  
  1         453  
892              
893             sub _Error {
894             exists $_[0]->YYData->{ERRMSG}
895 0 0   0   0 and do {
896 0         0 my $x = $_[0]->YYData->{ERRMSG};
897 0         0 delete $_[0]->YYData->{ERRMSG};
898 0         0 die $x;
899             };
900 0         0 die "Syntax error in input string while parsing the following string: '".$_[0]->{USER}{INPUT}."'\n";
901             }
902              
903             my $Num = qr/[+-]?(?=\d|\.\d)\d*(?:\.\d*)?(?:[Ee]([+-]?\d+))?/o;
904             my $Ident = qr/[a-zA-Z][a-zA-Z0-9_]*/o;
905             my $Op = qr/\+|\-|\*|\/|\^/o;
906             my $Func = qr/log|partial_derivative|total_derivative|a?(?:sin|sinh|cos|cosh|tan|cot)|exp|sqrt/;
907             my $Unary = qr/\+|\-/o;
908              
909             # taken from perlre
910             my $balanced_parens_re;
911             $balanced_parens_re = qr{\((?:(?>[^()]+)|(??{$balanced_parens_re}))*\)};
912              
913             # This is a hack so we can hook into the new() method.
914             {
915 1     1   5 no warnings; no strict;
  1     1   2  
  1         42  
  1         5  
  1         1  
  1         1885  
916             *real_new = \&new;
917             *new = sub {
918 1     1   3 my $class = shift;
919 1         2 my %args = @_;
920 1         2 my $predicates = $args{predicates};
921 1         2 delete $args{predicates};
922 1         4 my $parser = real_new($class, %args);
923 1 50       4 if ($predicates) {
924 0         0 $parser->{__PREDICATES} = $predicates;
925             }
926 1         9 return $parser;
927             };
928             }
929              
930             sub _Lexer {
931 0     0     my($parser)=shift;
932              
933 0   0       my $ExtFunc = $Math::SymbolicX::ParserExtensionFactory::RegularExpression || qr/(?!)/;
934 0           my $PrivExtFunc = $parser->{__PRIV_EXT_FUNC_REGEX};
935              
936 0           my $data = $parser->{USER};
937 0           my $predicates = $parser->{__PREDICATES};
938              
939 0 0         pos($data->{INPUT}) < length($data->{INPUT})
940             or return('',undef);
941              
942             # This is a huge hack
943 0 0         if (defined $predicates) {
944 0           for ($data->{INPUT}) {
945 0 0         if ($data->{STATE} == DAT) {
946 0 0         if ($data->{INPUT} =~ /\G($Func)(?=\()/cg) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
947 0           return('FUNC', $1);
948             }
949             elsif ($PrivExtFunc ? $data->{INPUT} =~ /\G($PrivExtFunc$balanced_parens_re)/cg : 0) {
950 0           $data->{STATE} = OP;
951 0           return('PRIVEFUNC', $1);
952             }
953             elsif ($data->{INPUT} =~ /\G($ExtFunc$balanced_parens_re)/cg) {
954 0           $data->{STATE} = OP;
955 0           return('EFUNC', $1);
956             }
957             elsif ($data->{INPUT} =~ /\G($predicates)(?=\{)/cg) {
958 0           return('PRED', $1);
959             }
960             elsif ($data->{INPUT} =~ /\G($Ident)((?>\'*))(?:\(($Ident(?:,$Ident)*)\))?/cgo) {
961 0           $data->{STATE} = OP;
962 0           my $name = $1;
963 0           my $ticks = $2;
964 0           my $sig = $3;
965 0           my $n;
966 0 0 0       if (defined $ticks and ($n = length($ticks))) {
    0          
967 0 0         my @sig = defined($sig) ? (split /,/, $sig) : ('x');
968 0           my $return = Math::Symbolic::Variable->new(
969             {name=>$name, signature=>\@sig}
970             );
971 0           my $var = $sig[0];
972 0           foreach (1..$n) {
973 0           $return = Math::Symbolic::Operator->new(
974             'partial_derivative',
975             $return, $var,
976             );
977             }
978 0           return('VAR', $return);
979             }
980             elsif (defined $sig) {
981             return(
982 0           'VAR', Math::Symbolic::Variable->new({name=>$name, signature=>[split /,/, $sig]})
983             );
984             }
985             else {
986 0           return('VAR', Math::Symbolic::Variable->new($name));
987             }
988             }
989             elsif ($data->{INPUT} =~ /\G\(/cgo) {
990 0           return('(', '(');
991             }
992             elsif ($data->{INPUT} =~ /\G\{/cgo) {
993 0           return('{', '{');
994             }
995             elsif ($data->{INPUT} =~ /\G($Num)/cgo) {
996 0           $data->{STATE} = OP;
997 0           return('NUM', Math::Symbolic::Constant->new($1));
998             }
999             elsif ($data->{INPUT} =~ /\G($Unary)/cgo) {
1000 0           return($1, $1);
1001             }
1002             else {
1003 0           my $pos = pos($data->{INPUT});
1004 0           die "Parse error at position $pos of string '$data->{INPUT}'.\nCould not find a suitable token while expecting data (identifier, function, number, etc.).";
1005             }
1006             }
1007             else { # $data->{STATE} == OP
1008 0 0         if ($data->{INPUT} =~ /\G\)/cgo) {
    0          
    0          
    0          
1009 0           return(')', ')');
1010             }
1011             elsif ($data->{INPUT} =~ /\G\}/cgo) {
1012 0           return('}', '}');
1013             }
1014             elsif ($data->{INPUT} =~ /\G($Op)/cgo) {
1015 0           $data->{STATE} = DAT;
1016 0           return($1, $1);
1017             }
1018             elsif ($data->{INPUT} =~ /\G,/cgo) {
1019 0           $data->{STATE} = DAT;
1020 0           return(',', ',');
1021             }
1022             else {
1023 0           my $pos = pos($data->{INPUT});
1024 0           die "Parse error at position $pos of string '$data->{INPUT}'.\nCould not find a suitable token while expecting an operator (+, -, etc).";
1025             }
1026             }
1027             }
1028             } # }}} end if defined $predicates
1029             else { # {{{ not defined $predicates
1030 0           for ($data->{INPUT}) {
1031 0 0         if ($data->{STATE} == DAT) {
1032 0 0         if ($data->{INPUT} =~ /\G($Func)(?=\()/cg) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1033 0           return('FUNC', $1);
1034             }
1035             elsif ($PrivExtFunc ? $data->{INPUT} =~ /\G($PrivExtFunc\s*$balanced_parens_re)/cg : 0) {
1036 0           $data->{STATE} = OP;
1037 0           return('PRIVEFUNC', $1);
1038             }
1039             elsif ($data->{INPUT} =~ /\G($ExtFunc\s*$balanced_parens_re)/cg) {
1040 0           $data->{STATE} = OP;
1041 0           return('EFUNC', $1);
1042             }
1043             elsif ($data->{INPUT} =~ /\G($Ident)((?>\'*))(?:\(($Ident(?:,$Ident)*)\))?/cgo) {
1044 0           $data->{STATE} = OP;
1045 0           my $name = $1;
1046 0           my $ticks = $2;
1047 0           my $sig = $3;
1048 0           my $n;
1049 0 0 0       if (defined $ticks and ($n = length($ticks))) {
    0          
1050 0 0         my @sig = defined($sig) ? (split /,/, $sig) : ('x');
1051 0           my $return = Math::Symbolic::Variable->new(
1052             {name=>$name, signature=>\@sig}
1053             );
1054 0           my $var = $sig[0];
1055 0           foreach (1..$n) {
1056 0           $return = Math::Symbolic::Operator->new(
1057             'partial_derivative',
1058             $return, $var,
1059             );
1060             }
1061 0           return('VAR', $return);
1062             }
1063             elsif (defined $sig) {
1064             return(
1065 0           'VAR', Math::Symbolic::Variable->new({name=>$name, signature=>[split /,/, $sig]})
1066             );
1067             }
1068             else {
1069 0           return('VAR', Math::Symbolic::Variable->new($name));
1070             }
1071             }
1072             elsif ($data->{INPUT} =~ /\G\(/cgo) {
1073 0           return('(', '(');
1074             }
1075             elsif ($data->{INPUT} =~ /\G($Num)/cgo) {
1076 0           $data->{STATE} = OP;
1077 0           return('NUM', Math::Symbolic::Constant->new($1));
1078             }
1079             elsif ($data->{INPUT} =~ /\G($Unary)/cgo) {
1080 0           return($1, $1);
1081             }
1082             else {
1083 0           my $pos = pos($data->{INPUT});
1084 0           die "Parse error at position $pos of string '$data->{INPUT}'.\nCould not find a suitable token while expecting data (identifier, function, number, etc.).";
1085             }
1086             }
1087             else { # $data->{STATE} == OP
1088 0 0         if ($data->{INPUT} =~ /\G\)/cgo) {
    0          
    0          
1089 0           return(')', ')');
1090             }
1091             elsif ($data->{INPUT} =~ /\G($Op)/cgo) {
1092 0           $data->{STATE} = DAT;
1093 0           return($1, $1);
1094             }
1095             elsif ($data->{INPUT} =~ /\G,/cgo) {
1096 0           $data->{STATE} = DAT;
1097 0           return(',', ',');
1098             }
1099             else {
1100 0           my $pos = pos($data->{INPUT});
1101 0           die "Parse error at position $pos of string '$data->{INPUT}'.\nCould not find a suitable token while expecting an operator (+, -, etc).";
1102             }
1103             }
1104             }
1105             } # }}} end else => not defined $predicates
1106              
1107             }
1108              
1109             sub parse {
1110 0     0 0   my($self)=shift;
1111 0           my $in = shift;
1112 0           $in =~ s/\s+//g;
1113 0           $self->{USER}{STATE} = DAT;
1114 0           $self->{USER}{INPUT} = $in;
1115 0           pos($self->{USER}{INPUT}) = 0;
1116 0           return $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
1117             }
1118              
1119             sub parsedebug {
1120 0     0 0   my($self)=shift;
1121 0           my $in = shift;
1122 0           $in =~ s/\s+//g;
1123 0           $self->{USER}{STATE} = DAT;
1124 0           $self->{USER}{INPUT} = $in;
1125 0           pos($self->{USER}{INPUT}) = 0;
1126 0           return $self->YYParse( yydebug => 0x1F, yylex => \&_Lexer, yyerror => \&_Error );
1127             }
1128              
1129             1;
1130              
1131             1;