| XML-Filter-Dispatcher documentation | Contained in the XML-Filter-Dispatcher distribution. |
XML::Filter::Dispatcher::Parser - Parses the XPath subset used by ...::Dispatcher
use XML::Filter::Dispatcher::Parser; my $result = XML::Filter::Dispatcher::Parser->parse( $xpath );
Some notes on the parsing and evaluation:
| XML-Filter-Dispatcher documentation | Contained in the XML-Filter-Dispatcher distribution. |
#################################################################### # # This file was generated using Parse::Yapp version 1.05. # # Don't edit this file, use source file instead. # # ANY CHANGE MADE HERE WILL BE LOST ! # #################################################################### package XML::Filter::Dispatcher::Parser; use vars qw ( @ISA ); use strict; @ISA= qw ( Parse::Yapp::Driver ); #Included Parse/Yapp/Driver.pm file---------------------------------------- { # # Module Parse::Yapp::Driver # # This module is part of the Parse::Yapp package available on your # nearest CPAN # # Any use of this module in a standalone parser make the included # text under the same copyright as the Parse::Yapp module itself. # # This notice should remain unchanged. # # (c) Copyright 1998-2001 Francois Desarmenien, all rights reserved. # (see the pod text in Parse::Yapp module for use and distribution rights) # package Parse::Yapp::Driver; require 5.004; use strict; use vars qw ( $VERSION $COMPATIBLE $FILENAME ); $VERSION = '1.05'; $COMPATIBLE = '0.07'; $FILENAME=__FILE__; use Carp; #Known parameters, all starting with YY (leading YY will be discarded) my(%params)=(YYLEX => 'CODE', 'YYERROR' => 'CODE', YYVERSION => '', YYRULES => 'ARRAY', YYSTATES => 'ARRAY', YYDEBUG => ''); #Mandatory parameters my(@params)=('LEX','RULES','STATES'); sub new { my($class)=shift; my($errst,$nberr,$token,$value,$check,$dotpos); my($self)={ ERROR => \&_Error, ERRST => \$errst, NBERR => \$nberr, TOKEN => \$token, VALUE => \$value, DOTPOS => \$dotpos, STACK => [], DEBUG => 0, CHECK => \$check }; _CheckParams( [], \%params, \@_, $self ); exists($$self{VERSION}) and $$self{VERSION} < $COMPATIBLE and croak "Yapp driver version $VERSION ". "incompatible with version $$self{VERSION}:\n". "Please recompile parser module."; ref($class) and $class=ref($class); bless($self,$class); } sub YYParse { my($self)=shift; my($retval); _CheckParams( \@params, \%params, \@_, $self ); if($$self{DEBUG}) { _DBLoad(); $retval = eval '$self->_DBParse()';#Do not create stab entry on compile $@ and die $@; } else { $retval = $self->_Parse(); } $retval } sub YYData { my($self)=shift; exists($$self{USER}) or $$self{USER}={}; $$self{USER}; } sub YYErrok { my($self)=shift; ${$$self{ERRST}}=0; undef; } sub YYNberr { my($self)=shift; ${$$self{NBERR}}; } sub YYRecovering { my($self)=shift; ${$$self{ERRST}} != 0; } sub YYAbort { my($self)=shift; ${$$self{CHECK}}='ABORT'; undef; } sub YYAccept { my($self)=shift; ${$$self{CHECK}}='ACCEPT'; undef; } sub YYError { my($self)=shift; ${$$self{CHECK}}='ERROR'; undef; } sub YYSemval { my($self)=shift; my($index)= $_[0] - ${$$self{DOTPOS}} - 1; $index < 0 and -$index <= @{$$self{STACK}} and return $$self{STACK}[$index][1]; undef; #Invalid index } sub YYCurtok { my($self)=shift; @_ and ${$$self{TOKEN}}=$_[0]; ${$$self{TOKEN}}; } sub YYCurval { my($self)=shift; @_ and ${$$self{VALUE}}=$_[0]; ${$$self{VALUE}}; } sub YYExpect { my($self)=shift; keys %{$self->{STATES}[$self->{STACK}[-1][0]]{ACTIONS}} } sub YYLexer { my($self)=shift; $$self{LEX}; } ################# # Private stuff # ################# sub _CheckParams { my($mandatory,$checklist,$inarray,$outhash)=@_; my($prm,$value); my($prmlst)={}; while(($prm,$value)=splice(@$inarray,0,2)) { $prm=uc($prm); exists($$checklist{$prm}) or croak("Unknow parameter '$prm'"); ref($value) eq $$checklist{$prm} or croak("Invalid value for parameter '$prm'"); $prm=unpack('@2A*',$prm); $$outhash{$prm}=$value; } for (@$mandatory) { exists($$outhash{$_}) or croak("Missing mandatory parameter '".lc($_)."'"); } } sub _Error { print "Parse error.\n"; } sub _DBLoad { { no strict 'refs'; exists(${__PACKAGE__.'::'}{_DBParse})#Already loaded ? and return; } my($fname)=__FILE__; my(@drv); open(DRV,"<$fname") or die "Report this as a BUG: Cannot open $fname"; while(<DRV>) { /^\s*sub\s+_Parse\s*{\s*$/ .. /^\s*}\s*#\s*_Parse\s*$/ and do { s/^#DBG>//; push(@drv,$_); } } close(DRV); $drv[0]=~s/_P/_DBP/; eval join('',@drv); } #Note that for loading debugging version of the driver, #this file will be parsed from 'sub _Parse' up to '}#_Parse' inclusive. #So, DO NOT remove comment at end of sub !!! sub _Parse { my($self)=shift; my($rules,$states,$lex,$error) = @$self{ 'RULES', 'STATES', 'LEX', 'ERROR' }; my($errstatus,$nberror,$token,$value,$stack,$check,$dotpos) = @$self{ 'ERRST', 'NBERR', 'TOKEN', 'VALUE', 'STACK', 'CHECK', 'DOTPOS' }; #DBG> my($debug)=$$self{DEBUG}; #DBG> my($dbgerror)=0; #DBG> my($ShowCurToken) = sub { #DBG> my($tok)='>'; #DBG> for (split('',$$token)) { #DBG> $tok.= (ord($_) < 32 or ord($_) > 126) #DBG> ? sprintf('<%02X>',ord($_)) #DBG> : $_; #DBG> } #DBG> $tok.='<'; #DBG> }; $$errstatus=0; $$nberror=0; ($$token,$$value)=(undef,undef); @$stack=( [ 0, undef ] ); $$check=''; while(1) { my($actions,$act,$stateno); $stateno=$$stack[-1][0]; $actions=$$states[$stateno]; #DBG> print STDERR ('-' x 40),"\n"; #DBG> $debug & 0x2 #DBG> and print STDERR "In state $stateno:\n"; #DBG> $debug & 0x08 #DBG> and print STDERR "Stack:[". #DBG> join(',',map { $$_[0] } @$stack). #DBG> "]\n"; if (exists($$actions{ACTIONS})) { defined($$token) or do { ($$token,$$value)=&$lex($self); #DBG> $debug & 0x01 #DBG> and print STDERR "Need token. Got ".&$ShowCurToken."\n"; }; $act= exists($$actions{ACTIONS}{$$token}) ? $$actions{ACTIONS}{$$token} : exists($$actions{DEFAULT}) ? $$actions{DEFAULT} : undef; } else { $act=$$actions{DEFAULT}; #DBG> $debug & 0x01 #DBG> and print STDERR "Don't need token.\n"; } defined($act) and do { $act > 0 and do { #shift #DBG> $debug & 0x04 #DBG> and print STDERR "Shift and go to state $act.\n"; $$errstatus and do { --$$errstatus; #DBG> $debug & 0x10 #DBG> and $dbgerror #DBG> and $$errstatus == 0 #DBG> and do { #DBG> print STDERR "**End of Error recovery.\n"; #DBG> $dbgerror=0; #DBG> }; }; push(@$stack,[ $act, $$value ]); $$token ne '' #Don't eat the eof and $$token=$$value=undef; next; }; #reduce my($lhs,$len,$code,@sempar,$semval); ($lhs,$len,$code)=@{$$rules[-$act]}; #DBG> $debug & 0x04 #DBG> and $act #DBG> and print STDERR "Reduce using rule ".-$act." ($lhs,$len): "; $act or $self->YYAccept(); $$dotpos=$len; unpack('A1',$lhs) eq '@' #In line rule and do { $lhs =~ /^\@[0-9]+\-([0-9]+)$/ or die "In line rule name '$lhs' ill formed: ". "report it as a BUG.\n"; $$dotpos = $1; }; @sempar = $$dotpos ? map { $$_[1] } @$stack[ -$$dotpos .. -1 ] : (); $semval = $code ? &$code( $self, @sempar ) : @sempar ? $sempar[0] : undef; splice(@$stack,-$len,$len); $$check eq 'ACCEPT' and do { #DBG> $debug & 0x04 #DBG> and print STDERR "Accept.\n"; return($semval); }; $$check eq 'ABORT' and do { #DBG> $debug & 0x04 #DBG> and print STDERR "Abort.\n"; return(undef); }; #DBG> $debug & 0x04 #DBG> and print STDERR "Back to state $$stack[-1][0], then "; $$check eq 'ERROR' or do { #DBG> $debug & 0x04 #DBG> and print STDERR #DBG> "go to state $$states[$$stack[-1][0]]{GOTOS}{$lhs}.\n"; #DBG> $debug & 0x10 #DBG> and $dbgerror #DBG> and $$errstatus == 0 #DBG> and do { #DBG> print STDERR "**End of Error recovery.\n"; #DBG> $dbgerror=0; #DBG> }; push(@$stack, [ $$states[$$stack[-1][0]]{GOTOS}{$lhs}, $semval ]); $$check=''; next; }; #DBG> $debug & 0x04 #DBG> and print STDERR "Forced Error recovery.\n"; $$check=''; }; #Error $$errstatus or do { $$errstatus = 1; &$error($self); $$errstatus # if 0, then YYErrok has been called or next; # so continue parsing #DBG> $debug & 0x10 #DBG> and do { #DBG> print STDERR "**Entering Error recovery.\n"; #DBG> ++$dbgerror; #DBG> }; ++$$nberror; }; $$errstatus == 3 #The next token is not valid: discard it and do { $$token eq '' # End of input: no hope and do { #DBG> $debug & 0x10 #DBG> and print STDERR "**At eof: aborting.\n"; return(undef); }; #DBG> $debug & 0x10 #DBG> and print STDERR "**Dicard invalid token ".&$ShowCurToken.".\n"; $$token=$$value=undef; }; $$errstatus=3; while( @$stack and ( not exists($$states[$$stack[-1][0]]{ACTIONS}) or not exists($$states[$$stack[-1][0]]{ACTIONS}{error}) or $$states[$$stack[-1][0]]{ACTIONS}{error} <= 0)) { #DBG> $debug & 0x10 #DBG> and print STDERR "**Pop state $$stack[-1][0].\n"; pop(@$stack); } @$stack or do { #DBG> $debug & 0x10 #DBG> and print STDERR "**No state left on stack: aborting.\n"; return(undef); }; #shift the error token #DBG> $debug & 0x10 #DBG> and print STDERR "**Shift \$error token and go to state ". #DBG> $$states[$$stack[-1][0]]{ACTIONS}{error}. #DBG> ".\n"; push(@$stack, [ $$states[$$stack[-1][0]]{ACTIONS}{error}, undef ]); } #never reached croak("Error in driver logic. Please, report it as a BUG"); }#_Parse #DO NOT remove comment 1; } #End of include-------------------------------------------------- #line 9 "xfdxpath.yp" use Carp; use UNIVERSAL; use XML::Filter::Dispatcher::Ops; sub _no { my $p = shift; # push @{$p->{USER}->{NONONO}}, join( die join( "", "XPath construct not supported: ", join( " ", map defined $_ ? ref $_ ? do { my $f = ref $_; $f =~ s/^XFD:://; $f; } : $_ : "<undef>" , @_ ), " (grammar rule at ", (caller)[1], ", line ", (caller)[2], ")" ); return (); } sub _step { my @ops = grep $_, @_; for ( 0..$#ops-1 ) { $ops[$_]->set_next( $ops[$_+1] ); } return $ops[0]; } sub new { my($class)=shift; ref($class) and $class=ref($class); my($self)=$class->SUPER::new( yyversion => '1.05', yystates => [ {#State 0 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'and_expr' => 18, 'absolute_location_path' => 3, 'or_expr' => 20, 'equality_expr' => 6, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'expr' => 13, 'additive_expr' => 22, 'location_path' => 14, 'unary_expr' => 23, 'primary_expr' => 24, 'union_expr' => 25, 'relational_expr' => 28, 'multiplicative_expr' => 27 } }, {#State 1 DEFAULT => -44 }, {#State 2 ACTIONS => { 'DOT_DOT' => 1, 'DOT' => 17, 'AT' => 7, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'step' => 12, 'relative_location_path' => 29, 'axis' => 10 } }, {#State 3 DEFAULT => -35 }, {#State 4 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 30, 'union_expr' => 25 } }, {#State 5 ACTIONS => { 'SLASH_SLASH' => 31, 'SLASH' => 32 }, DEFAULT => -34 }, {#State 6 ACTIONS => { 'BANG_EQUALS' => 35, 'EQUALS_EQUALS' => 34, 'EQUALS' => 33 }, DEFAULT => -5 }, {#State 7 DEFAULT => -47 }, {#State 8 DEFAULT => -52 }, {#State 9 DEFAULT => -27 }, {#State 10 ACTIONS => { 'TEXT' => 38, 'NAME_COLON_STAR' => 36, 'QNAME' => 40, 'STAR' => 42, 'PI' => 41, 'COMMENT' => 37, 'NODE' => 39 }, GOTOS => { 'node_test' => 43 } }, {#State 11 ACTIONS => { 'NAME_COLON_STAR' => -45, 'AT' => 7, 'COMMENT' => -45, 'DOT' => 17, 'STAR' => -45, 'AXIS_NAME' => 26, 'DOT_DOT' => 1, 'TEXT' => -45, 'NODE' => -45, 'QNAME' => -45, 'PI' => -45 }, DEFAULT => -36, GOTOS => { 'step' => 12, 'relative_location_path' => 44, 'axis' => 10 } }, {#State 12 DEFAULT => -39 }, {#State 13 ACTIONS => { '' => 45 } }, {#State 14 DEFAULT => -29 }, {#State 15 DEFAULT => -53 }, {#State 16 ACTIONS => { 'LPAR' => 46 } }, {#State 17 DEFAULT => -43 }, {#State 18 ACTIONS => { 'AMP_AMP' => 47, 'AMP' => 48, 'AND' => 49 }, DEFAULT => -2 }, {#State 19 DEFAULT => -50 }, {#State 20 ACTIONS => { 'VBAR_VBAR' => 50, 'OR' => 51 }, DEFAULT => -1 }, {#State 21 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'and_expr' => 18, 'absolute_location_path' => 3, 'or_expr' => 20, 'equality_expr' => 6, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'expr' => 52, 'additive_expr' => 22, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'relational_expr' => 28, 'multiplicative_expr' => 27 } }, {#State 22 ACTIONS => { 'MINUS' => 53, 'PLUS' => 54 }, DEFAULT => -13 }, {#State 23 DEFAULT => -21 }, {#State 24 DEFAULT => -48, GOTOS => { 'predicates' => 55 } }, {#State 25 ACTIONS => { 'VBAR' => 56 }, DEFAULT => -25 }, {#State 26 ACTIONS => { 'COLON_COLON' => 57 } }, {#State 27 ACTIONS => { 'MULTIPLY' => 58, 'MOD' => 59, 'DIV' => 60 }, DEFAULT => -18 }, {#State 28 ACTIONS => { 'LTE' => 63, 'LT' => 64, 'GTE' => 61, 'GT' => 62 }, DEFAULT => -9 }, {#State 29 ACTIONS => { 'SLASH_SLASH' => 31, 'SLASH' => 32 }, DEFAULT => -38 }, {#State 30 DEFAULT => -26 }, {#State 31 ACTIONS => { 'DOT_DOT' => 1, 'DOT' => 17, 'AT' => 7, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'step' => 65, 'axis' => 10 } }, {#State 32 ACTIONS => { 'DOT_DOT' => 1, 'DOT' => 17, 'AT' => 7, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'step' => 66, 'axis' => 10 } }, {#State 33 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'additive_expr' => 22, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'relational_expr' => 67, 'multiplicative_expr' => 27 } }, {#State 34 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'additive_expr' => 22, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'relational_expr' => 68, 'multiplicative_expr' => 27 } }, {#State 35 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'additive_expr' => 22, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'relational_expr' => 69, 'multiplicative_expr' => 27 } }, {#State 36 DEFAULT => -61 }, {#State 37 ACTIONS => { 'LPAR' => 70 } }, {#State 38 ACTIONS => { 'LPAR' => 71 } }, {#State 39 ACTIONS => { 'LPAR' => 72 } }, {#State 40 DEFAULT => -59 }, {#State 41 ACTIONS => { 'LPAR' => 73 } }, {#State 42 DEFAULT => -60 }, {#State 43 DEFAULT => -48, GOTOS => { 'predicates' => 74 } }, {#State 44 ACTIONS => { 'SLASH_SLASH' => 31, 'SLASH' => 32 }, DEFAULT => -37 }, {#State 45 DEFAULT => 0 }, {#State 46 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26, 'RPAR' => -55 }, DEFAULT => -45, GOTOS => { 'and_expr' => 18, 'absolute_location_path' => 3, 'or_expr' => 20, 'equality_expr' => 6, 'relative_location_path' => 5, 'args' => 75, 'opt_args' => 77, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'expr' => 76, 'additive_expr' => 22, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'relational_expr' => 28, 'multiplicative_expr' => 27 } }, {#State 47 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'equality_expr' => 78, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'additive_expr' => 22, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'relational_expr' => 28, 'multiplicative_expr' => 27 } }, {#State 48 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'equality_expr' => 79, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'additive_expr' => 22, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'relational_expr' => 28, 'multiplicative_expr' => 27 } }, {#State 49 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'equality_expr' => 80, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'additive_expr' => 22, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'relational_expr' => 28, 'multiplicative_expr' => 27 } }, {#State 50 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'and_expr' => 81, 'absolute_location_path' => 3, 'equality_expr' => 6, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'additive_expr' => 22, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'relational_expr' => 28, 'multiplicative_expr' => 27 } }, {#State 51 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'and_expr' => 82, 'absolute_location_path' => 3, 'equality_expr' => 6, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'additive_expr' => 22, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'relational_expr' => 28, 'multiplicative_expr' => 27 } }, {#State 52 ACTIONS => { 'RPAR' => 83 } }, {#State 53 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'multiplicative_expr' => 84 } }, {#State 54 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'multiplicative_expr' => 85 } }, {#State 55 ACTIONS => { 'SLASH_SLASH' => 86, 'SLASH' => 88, 'LSQB' => 89 }, DEFAULT => -31, GOTOS => { 'segment' => 87 } }, {#State 56 ACTIONS => { 'DOT_DOT' => 1, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'step' => 12, 'absolute_location_path' => 3, 'primary_expr' => 24, 'location_path' => 14, 'relative_location_path' => 5, 'path_expr' => 90, 'axis' => 10 } }, {#State 57 DEFAULT => -46 }, {#State 58 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 91, 'union_expr' => 25 } }, {#State 59 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 92, 'union_expr' => 25 } }, {#State 60 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 93, 'union_expr' => 25 } }, {#State 61 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'additive_expr' => 94, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'multiplicative_expr' => 27 } }, {#State 62 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'additive_expr' => 95, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'multiplicative_expr' => 27 } }, {#State 63 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'additive_expr' => 96, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'multiplicative_expr' => 27 } }, {#State 64 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'absolute_location_path' => 3, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'additive_expr' => 97, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'multiplicative_expr' => 27 } }, {#State 65 DEFAULT => -41 }, {#State 66 DEFAULT => -40 }, {#State 67 ACTIONS => { 'LTE' => 63, 'LT' => 64, 'GTE' => 61, 'GT' => 62 }, DEFAULT => -10 }, {#State 68 ACTIONS => { 'LTE' => 63, 'LT' => 64, 'GTE' => 61, 'GT' => 62 }, DEFAULT => -12 }, {#State 69 ACTIONS => { 'LTE' => 63, 'LT' => 64, 'GTE' => 61, 'GT' => 62 }, DEFAULT => -11 }, {#State 70 ACTIONS => { 'RPAR' => 98 } }, {#State 71 ACTIONS => { 'RPAR' => 99 } }, {#State 72 ACTIONS => { 'RPAR' => 100 } }, {#State 73 ACTIONS => { 'LITERAL' => 101 }, DEFAULT => -66, GOTOS => { 'opt_literal' => 102 } }, {#State 74 ACTIONS => { 'LSQB' => 89 }, DEFAULT => -42 }, {#State 75 ACTIONS => { 'COMMA' => 103 }, DEFAULT => -56 }, {#State 76 DEFAULT => -57 }, {#State 77 ACTIONS => { 'RPAR' => 104 } }, {#State 78 ACTIONS => { 'BANG_EQUALS' => 35, 'EQUALS_EQUALS' => 34, 'EQUALS' => 33 }, DEFAULT => -7 }, {#State 79 ACTIONS => { 'BANG_EQUALS' => 35, 'EQUALS_EQUALS' => 34, 'EQUALS' => 33 }, DEFAULT => -8 }, {#State 80 ACTIONS => { 'BANG_EQUALS' => 35, 'EQUALS_EQUALS' => 34, 'EQUALS' => 33 }, DEFAULT => -6 }, {#State 81 ACTIONS => { 'AMP_AMP' => 47, 'AMP' => 48, 'AND' => 49 }, DEFAULT => -4 }, {#State 82 ACTIONS => { 'AMP_AMP' => 47, 'AMP' => 48, 'AND' => 49 }, DEFAULT => -3 }, {#State 83 DEFAULT => -51 }, {#State 84 ACTIONS => { 'MULTIPLY' => 58, 'MOD' => 59, 'DIV' => 60 }, DEFAULT => -20 }, {#State 85 ACTIONS => { 'MULTIPLY' => 58, 'MOD' => 59, 'DIV' => 60 }, DEFAULT => -19 }, {#State 86 ACTIONS => { 'DOT_DOT' => 1, 'DOT' => 17, 'AT' => 7, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'step' => 12, 'relative_location_path' => 105, 'axis' => 10 } }, {#State 87 DEFAULT => -30 }, {#State 88 ACTIONS => { 'DOT_DOT' => 1, 'DOT' => 17, 'AT' => 7, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'step' => 12, 'relative_location_path' => 106, 'axis' => 10 } }, {#State 89 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'and_expr' => 18, 'absolute_location_path' => 3, 'or_expr' => 20, 'equality_expr' => 6, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'expr' => 107, 'additive_expr' => 22, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'relational_expr' => 28, 'multiplicative_expr' => 27 } }, {#State 90 DEFAULT => -28 }, {#State 91 DEFAULT => -22 }, {#State 92 DEFAULT => -24 }, {#State 93 DEFAULT => -23 }, {#State 94 ACTIONS => { 'MINUS' => 53, 'PLUS' => 54 }, DEFAULT => -17 }, {#State 95 ACTIONS => { 'MINUS' => 53, 'PLUS' => 54 }, DEFAULT => -15 }, {#State 96 ACTIONS => { 'MINUS' => 53, 'PLUS' => 54 }, DEFAULT => -16 }, {#State 97 ACTIONS => { 'MINUS' => 53, 'PLUS' => 54 }, DEFAULT => -14 }, {#State 98 DEFAULT => -63 }, {#State 99 DEFAULT => -64 }, {#State 100 DEFAULT => -65 }, {#State 101 DEFAULT => -67 }, {#State 102 ACTIONS => { 'RPAR' => 108 } }, {#State 103 ACTIONS => { 'DOT_DOT' => 1, 'MINUS' => 4, 'SLASH_SLASH' => 2, 'AT' => 7, 'LITERAL' => 8, 'SLASH' => 11, 'NUMBER' => 15, 'FUNCTION_NAME' => 16, 'DOT' => 17, 'DOLLAR_QNAME' => 19, 'LPAR' => 21, 'AXIS_NAME' => 26 }, DEFAULT => -45, GOTOS => { 'and_expr' => 18, 'absolute_location_path' => 3, 'or_expr' => 20, 'equality_expr' => 6, 'relative_location_path' => 5, 'path_expr' => 9, 'axis' => 10, 'step' => 12, 'expr' => 109, 'additive_expr' => 22, 'location_path' => 14, 'primary_expr' => 24, 'unary_expr' => 23, 'union_expr' => 25, 'relational_expr' => 28, 'multiplicative_expr' => 27 } }, {#State 104 DEFAULT => -54 }, {#State 105 ACTIONS => { 'SLASH_SLASH' => 31, 'SLASH' => 32 }, DEFAULT => -33 }, {#State 106 ACTIONS => { 'SLASH_SLASH' => 31, 'SLASH' => 32 }, DEFAULT => -32 }, {#State 107 ACTIONS => { 'RSQB' => 110 } }, {#State 108 DEFAULT => -62 }, {#State 109 DEFAULT => -58 }, {#State 110 DEFAULT => -49 } ], yyrules => [ [#Rule 0 '$start', 2, undef ], [#Rule 1 'expr', 1, undef ], [#Rule 2 'or_expr', 1, undef ], [#Rule 3 'or_expr', 3, sub #line 107 "xfdxpath.yp" { XFD::Operator::or->new( @_[1,3] ) } ], [#Rule 4 'or_expr', 3, sub #line 108 "xfdxpath.yp" { die "XPath uses 'or' instead of Perl's '||'\n"; } ], [#Rule 5 'and_expr', 1, undef ], [#Rule 6 'and_expr', 3, sub #line 115 "xfdxpath.yp" { XFD::Operator::and->new( @_[1,3] ) } ], [#Rule 7 'and_expr', 3, sub #line 116 "xfdxpath.yp" { die "XPath uses 'and' instead of Perl's '&&'\n"; } ], [#Rule 8 'and_expr', 3, sub #line 119 "xfdxpath.yp" { die "XPath uses 'and' instead of Perl's '&'\n"; } ], [#Rule 9 'equality_expr', 1, undef ], [#Rule 10 'equality_expr', 3, sub #line 126 "xfdxpath.yp" { XFD::relational_op equals => @_[1,3] } ], [#Rule 11 'equality_expr', 3, sub #line 127 "xfdxpath.yp" { XFD::relational_op not_equals => @_[1,3] } ], [#Rule 12 'equality_expr', 3, sub #line 128 "xfdxpath.yp" { die "XPath uses '=' instead of Perl's '=='\n"; } ], [#Rule 13 'relational_expr', 1, undef ], [#Rule 14 'relational_expr', 3, sub #line 135 "xfdxpath.yp" { XFD::relational_op lt => @_[1,3] } ], [#Rule 15 'relational_expr', 3, sub #line 136 "xfdxpath.yp" { XFD::relational_op gt => @_[1,3] } ], [#Rule 16 'relational_expr', 3, sub #line 137 "xfdxpath.yp" { XFD::relational_op lte => @_[1,3] } ], [#Rule 17 'relational_expr', 3, sub #line 138 "xfdxpath.yp" { XFD::relational_op gte => @_[1,3] } ], [#Rule 18 'additive_expr', 1, undef ], [#Rule 19 'additive_expr', 3, sub #line 143 "xfdxpath.yp" { XFD::math_op addition => @_[1,3] } ], [#Rule 20 'additive_expr', 3, sub #line 144 "xfdxpath.yp" { XFD::math_op subtraction => @_[1,3] } ], [#Rule 21 'multiplicative_expr', 1, undef ], [#Rule 22 'multiplicative_expr', 3, sub #line 149 "xfdxpath.yp" { XFD::math_op multiplication => @_[1,3] } ], [#Rule 23 'multiplicative_expr', 3, sub #line 150 "xfdxpath.yp" { XFD::math_op division => @_[1,3] } ], [#Rule 24 'multiplicative_expr', 3, sub #line 151 "xfdxpath.yp" { XFD::math_op modulus => @_[1,3] } ], [#Rule 25 'unary_expr', 1, undef ], [#Rule 26 'unary_expr', 2, sub #line 156 "xfdxpath.yp" { XFD::Negation->new( $_[2] ) } ], [#Rule 27 'union_expr', 1, undef ], [#Rule 28 'union_expr', 3, sub #line 161 "xfdxpath.yp" { for ( $_[1], $_[3] ) { next if $_->can( "set_next" ); $_ = ref $_; s/^XFD:://; die "Can't use a $_ in a union, perhaps you want || instead of |\n"; } my $union; if ( $_[1]->isa( "XFD::union" ) ) { $_[1]->add( $_[3] ); $union = $_[1]; } else { $union = XFD::union->new( @_[1,3] ) } $union; } ], [#Rule 29 'path_expr', 1, undef ], [#Rule 30 'path_expr', 3, sub #line 183 "xfdxpath.yp" { return $_[1] unless defined $_[2] || defined $_[3]; my $expr = $_[1]; $expr = $expr->[0] if $expr->isa( "XFD::Parens" ); ## TODO: Cope with nodesets passed in vars or ## returned from functions. die "node-set is required before a predicate or '/' (variables and functions returning nodesets are not (yet) supported)" unless $expr->isa( "XFD::PathTest" ); $expr->set_next( $_[2] ) if defined $_[2]; $expr->set_next( $_[3] ) if defined $_[3]; $expr; } ], [#Rule 31 'segment', 0, undef ], [#Rule 32 'segment', 2, sub #line 202 "xfdxpath.yp" { $_[2] } ], [#Rule 33 'segment', 2, sub #line 203 "xfdxpath.yp" { my $op = XFD::Axis::descendant_or_self->new; $op->set_next( $_[2] ); $op; } ], [#Rule 34 'location_path', 1, undef ], [#Rule 35 'location_path', 1, undef ], [#Rule 36 'absolute_location_path', 1, sub #line 215 "xfdxpath.yp" { XFD::doc_node->new } ], [#Rule 37 'absolute_location_path', 2, sub #line 216 "xfdxpath.yp" { my $op = XFD::doc_node->new; $op->set_next( $_[2] ); $op; } ], [#Rule 38 'absolute_location_path', 2, sub #line 221 "xfdxpath.yp" { ## /descendant-or-self::node()/relative_location_path my $op = XFD::doc_node->new; my $step = _step( XFD::Axis::descendant_or_self->new, XFD::EventType::node->new, ); $op->set_next( $step ); $step->set_next( $_[2] ); $op; } ], [#Rule 39 'relative_location_path', 1, undef ], [#Rule 40 'relative_location_path', 3, sub #line 235 "xfdxpath.yp" { $_[1]->set_next( $_[3] ) ; $_[1] } ], [#Rule 41 'relative_location_path', 3, sub #line 238 "xfdxpath.yp" { my $step = _step( XFD::Axis::descendant_or_self->new, XFD::EventType::node->new, ); $_[1]->set_next( $step ); $step->set_next( $_[3] ); $_[1]; } ], [#Rule 42 'step', 3, sub #line 250 "xfdxpath.yp" { _step( @_[1..$#_] ) } ], [#Rule 43 'step', 1, sub #line 251 "xfdxpath.yp" { XFD::self_node->new } ], [#Rule 44 'step', 1, sub #line 252 "xfdxpath.yp" { _no @_; } ], [#Rule 45 'axis', 0, sub #line 256 "xfdxpath.yp" { XFD::Axis::child->new } ], [#Rule 46 'axis', 2, sub #line 257 "xfdxpath.yp" { XFD::axis( $_[1] ) } ], [#Rule 47 'axis', 1, sub #line 258 "xfdxpath.yp" { XFD::Axis::attribute->new } ], [#Rule 48 'predicates', 0, undef ], [#Rule 49 'predicates', 4, sub #line 263 "xfdxpath.yp" { my $p = XFD::predicate->new( $_[3] ); if ( defined $_[1] ) { $_[1]->set_next( $p ); return $_[1]; } return $p; } ], [#Rule 50 'primary_expr', 1, sub #line 274 "xfdxpath.yp" { XFD::VariableReference->new( $_[1] ) } ], [#Rule 51 'primary_expr', 3, sub #line 275 "xfdxpath.yp" { XFD::Parens->new( $_[2] ) } ], [#Rule 52 'primary_expr', 1, undef ], [#Rule 53 'primary_expr', 1, undef ], [#Rule 54 'primary_expr', 4, sub #line 278 "xfdxpath.yp" { XFD::function( @_[1,3] ) } ], [#Rule 55 'opt_args', 0, sub #line 282 "xfdxpath.yp" { [] } ], [#Rule 56 'opt_args', 1, undef ], [#Rule 57 'args', 1, sub #line 287 "xfdxpath.yp" { [ $_[1] ] } ], [#Rule 58 'args', 3, sub #line 288 "xfdxpath.yp" { push @{$_[1]}, $_[3]; $_[1]; } ], [#Rule 59 'node_test', 1, sub #line 295 "xfdxpath.yp" { $XFD::dispatcher->{Namespaces} ? do { my ( $ns_uri, $local_name ) = XFD::PathTest->_parse_ns_uri_and_localname( $_[1] ); my $op = XFD::namespace_test->new( $ns_uri ); $op->set_next( XFD::node_local_name->new( $local_name ) ); $op; } : XFD::node_name->new( $_[1] ); } ], [#Rule 60 'node_test', 1, sub #line 309 "xfdxpath.yp" { XFD::EventType::principal_event_type->new; } ], [#Rule 61 'node_test', 1, sub #line 310 "xfdxpath.yp" { my ( $ns_uri ) = XFD::PathTest->_parse_ns_uri_and_localname( $_[1] ); XFD::namespace_test->new( $ns_uri ) } ], [#Rule 62 'node_test', 4, sub #line 315 "xfdxpath.yp" { XFD::EventType::processing_instruction ->new( $_[2] ) } ], [#Rule 63 'node_test', 3, sub #line 317 "xfdxpath.yp" { XFD::EventType::comment ->new } ], [#Rule 64 'node_test', 3, sub #line 318 "xfdxpath.yp" { XFD::EventType::text ->new } ], [#Rule 65 'node_test', 3, sub #line 319 "xfdxpath.yp" { XFD::EventType::node ->new } ], [#Rule 66 'opt_literal', 0, undef ], [#Rule 67 'opt_literal', 1, sub #line 324 "xfdxpath.yp" { _no @_; } ] ], @_); bless($self,$class); } #line 327 "xfdxpath.yp"
use Carp; my %tokens = (qw( . DOT .. DOT_DOT @ AT * STAR ( LPAR ) RPAR [ LSQB ] RSQB :: COLON_COLON / SLASH // SLASH_SLASH | VBAR + PLUS - MINUS = EQUALS != BANG_EQUALS > GT < LT >= GTE <= LTE == EQUALS_EQUALS || VBAR_VBAR && AMP_AMP & AMP ), "," => "COMMA" ); my $simple_tokens = join "|", map quotemeta, reverse sort { length $a <=> length $b } keys %tokens; my $NCName = "(?:[a-zA-Z_][a-zA-Z0-9_.-]*)"; ## TODO: comb. chars & Extenders my %EventType = qw( node NODE text TEXT comment COMMENT processing-instruction PI ); my $EventType = "(?:" . join( "|", map quotemeta, sort {length $a <=> length $b} keys %EventType ) . ")"; my $AxisName = "(?:" . join( "|", split /\n+/, <<AXIS_LIST_END ) . ")" ; ancestor ancestor-or-self attribute child descendant descendant-or-self following following-sibling namespace parent preceding preceding-sibling self end AXIS_LIST_END my %preceding_tokens = map { ( $_ => undef ) } ( qw( @ :: [ and or mod div * / // | + - = != < <= > >= == & && || ), "(", "," ) ; sub debugging () { 0 } sub lex { my ( $p ) = @_; ## Optimization notes: we aren't parsing War and Peace here, so ## readability over performance. my $d = $p->{USER}; my $input = \$d->{Input}; ## This needs to be more contextual, only recognizing axis/function-name if ( ( pos( $$input ) || 0 ) == length $$input ) { $d->{LastToken} = undef; return ( '', undef ); } my ( $token, $val ) ; ## First do the disambiguation rules: ## If there is a preceding token and the preceding token is not ## one of "@", "::", "(", "[", "," or an Operator, if ( defined $d->{LastToken} && ! exists $preceding_tokens{$d->{LastToken}} ) { ## a * must be recognized as a MultiplyOperator if ( $$input =~ /\G\s*\*/gc ) { ( $token, $val ) = ( MULTIPLY => "*" ); } ## an NCName must be recognized as an OperatorName. elsif ( $$input =~ /\G\s*($NCName)/gc ) { die "Expected and, or, mod or div, got '$1'\n" unless 0 <= index "and|or|mod|div", $1; ( $token, $val ) = ( uc $1, $1 ); } } ## NOTE: \s is only an approximation for ExprWhitespace unless ( defined $token ) { $$input =~ m{\G\s*(?: ## If the character following an NCName (possibly after ## intervening ExprWhitespace) is (, then the token must be ## recognized as a EventType or a FunctionName. ($NCName)\s*(?=\() ## If the two characters following an NCName (possibly after ## intervening ExprWhitespace) are ::, then the token must be ## recognized as an AxisName |($NCName)\s*(?=::) ## Otherwise, it's just a normal lexer. |($NCName:\*) #NAME_COLON_STAR |((?:$NCName:)?$NCName) #QNAME |('[^']*'|"[^"]*") #LITERAL |(-?\d+(?:\.\d+)?|\.\d+) #NUMBER |\$((?:$NCName:)?$NCName) #DOLLAR_QNAME |($simple_tokens) )\s*}gcx; ( $token, $val ) = defined $1 ? ( exists $EventType{$1} ? ( $EventType{$1}, $1 ) : ( FUNCTION_NAME => $1 ) ) : defined $2 ? ( AXIS_NAME => $2 ) : defined $3 ? ( NAME_COLON_STAR => $3 ) : defined $4 ? ( QNAME => $4 ) : defined $5 ? ( LITERAL => do { my $s = substr( $5, 1, -1 ); $s =~ s/([\\'])/\\$1/g; XFD::StringConstant->new( $s ); } ) : defined $6 ? ( NUMBER => XFD::NumericConstant->new( "$6") ) : defined $7 ? ( DOLLAR_QNAME => $7 ) : defined $8 ? ( $tokens{$8} => $8 ) : die "Failed to parse '$$input' at ", pos $$input, "\n"; } $d->{LastToken} = $val; if ( debugging ) { warn "'", $$input, "' (", pos $$input, "):", join( " => ", map defined $_ ? $_ : "<undef>", $token, $val ), "\n"; } return ( $token, $val ); } sub error { my ( $p ) = @_; print "Couldn't parse '$p->{USER}->{Input}' at position ", pos $p->{USER}->{Input}, "\n"; } ## _parse is an internal, reentrant entry point; it's used to parse rules ## and subrules. sub _parse { my $self = shift; my ( $expr, $action_code ) = @_; my $options = $XFD::dispatcher; warn "Parsing '$expr'\n" if $options->{Debug}; my $p = XML::Filter::Dispatcher::Parser->new( yylex => \&lex, yyerror => \&error, ( $options->{Debug} || 0 ) > 5 ? ( yydebug => 0x1D ) : (), ); %{$p->{USER}} = %$options if $options; $p->{USER}->{Input} = $expr; local $XFD::dispatcher->{ParseNestingDepth} = $XFD::dispatcher->{ParseNestingDepth} + 1; my $op_tree = eval { $p->YYParse; ## <== the actual parse }; die $@ if $@; die map "$_\n", @{$p->{USER}->{NONONO}} if $p->{USER}->{NONONO} ; return undef unless defined $op_tree; die "grammar returned '$op_tree', needed a ref\n" unless ref $op_tree; ## TODO: figure a way to allow a limited subset ## of EventPath patterns, kinda like allowing ## a pattern match against the generated Op tree, ## or alternate grammar files. The former could ## give more helpful error messages, the latter ## could be more flexible because it would allow ## non-standard grammars. $op_tree = XFD::ExprEval->new( $op_tree ) unless $op_tree->isa( "XFD::PathTest" ); $op_tree->set_next( XFD::action( $action_code ) ); return $op_tree; } sub parse { my $self = shift; local $XFD::dispatcher = shift; my ( $expr, $context ) = @_; $XFD::dispatcher->{ParseNestingDepth} = 0; $XFD::dispatcher->{OpTree} ||= XFD::union->new; my $op_tree = $self->_parse( @_ ); my $rule = XFD::Rule->new( $expr ); $rule->set_next( $op_tree ); $XFD::dispatcher->{OpTree}->add( $rule ); } 1 ; 1;