####################################################################
#
#    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 PlistParse;
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 1 "PlistParse.yp"


# Globals
my $indent = 0;
my $XML;
my @regexp;
my $showtags;

my @lastkey;
my @lasttag;
my $lasttag_len = 0;
my $lastkey_len = 0;



sub new {
        my($class)=shift;
        ref($class)
    and $class=ref($class);

    my($self)=$class->SUPER::new( yyversion => '1.05',
                                  yystates =>
[
	{#State 0
		ACTIONS => {
			'TAG__' => 1,
			'PLIST_' => 4,
			'TAG_' => 3
		},
		GOTOS => {
			'tag' => 2,
			'plist' => 6,
			'tags' => 5
		}
	},
	{#State 1
		DEFAULT => -5
	},
	{#State 2
		DEFAULT => -3
	},
	{#State 3
		ACTIONS => {
			'PCDATA' => 7,
			'TAG' => 8
		},
		DEFAULT => -6
	},
	{#State 4
		ACTIONS => {
			'TRUE' => 9,
			'DATE_' => 10,
			'DATA_' => 15,
			'ARRAY_' => 17,
			'FALSE' => 20,
			'INTEGER_' => 27,
			'STRING_' => 28,
			'REAL_' => 29,
			'DICT_' => 21
		},
		GOTOS => {
			'dict_s' => 23,
			'false' => 11,
			'date' => 12,
			'data' => 24,
			'string' => 14,
			'true' => 13,
			'array_s' => 26,
			'dict' => 25,
			'array' => 16,
			'plist_object' => 18,
			'integer' => 19,
			'real' => 22
		}
	},
	{#State 5
		ACTIONS => {
			'TAG__' => 1,
			'PLIST_' => 30,
			'TAG_' => 3
		},
		GOTOS => {
			'tag' => 31
		}
	},
	{#State 6
		ACTIONS => {
			'' => 32
		}
	},
	{#State 7
		ACTIONS => {
			'TAG' => 33
		}
	},
	{#State 8
		DEFAULT => -7
	},
	{#State 9
		DEFAULT => -41
	},
	{#State 10
		ACTIONS => {
			'PCDATA' => 35,
			'DATE' => 34
		}
	},
	{#State 11
		DEFAULT => -17
	},
	{#State 12
		DEFAULT => -11
	},
	{#State 13
		DEFAULT => -16
	},
	{#State 14
		DEFAULT => -15
	},
	{#State 15
		ACTIONS => {
			'PCDATA' => 36,
			'DATA' => 37
		}
	},
	{#State 16
		DEFAULT => -9
	},
	{#State 17
		DEFAULT => -19
	},
	{#State 18
		ACTIONS => {
			'PLIST' => 38
		}
	},
	{#State 19
		DEFAULT => -14
	},
	{#State 20
		DEFAULT => -42
	},
	{#State 21
		DEFAULT => -25
	},
	{#State 22
		DEFAULT => -13
	},
	{#State 23
		ACTIONS => {
			'DICT' => 39,
			'KEY_' => 43
		},
		GOTOS => {
			'dict_object' => 42,
			'dict_e' => 40,
			'dict_objects' => 44,
			'key' => 41
		}
	},
	{#State 24
		DEFAULT => -10
	},
	{#State 25
		DEFAULT => -12
	},
	{#State 26
		ACTIONS => {
			'TRUE' => 9,
			'DATE_' => 10,
			'DATA_' => 15,
			'ARRAY_' => 17,
			'FALSE' => 20,
			'INTEGER_' => 27,
			'STRING_' => 28,
			'REAL_' => 29,
			'DICT_' => 21
		},
		GOTOS => {
			'dict_s' => 23,
			'false' => 11,
			'date' => 12,
			'array_body' => 46,
			'data' => 24,
			'string' => 14,
			'true' => 13,
			'dict' => 25,
			'array_s' => 26,
			'array' => 16,
			'plist_object' => 45,
			'integer' => 19,
			'real' => 22
		}
	},
	{#State 27
		ACTIONS => {
			'INTEGER' => 48,
			'PCDATA' => 47
		}
	},
	{#State 28
		ACTIONS => {
			'PCDATA' => 50,
			'STRING' => 49
		}
	},
	{#State 29
		ACTIONS => {
			'PCDATA' => 51,
			'REAL' => 52
		}
	},
	{#State 30
		ACTIONS => {
			'TRUE' => 9,
			'DATE_' => 10,
			'DATA_' => 15,
			'ARRAY_' => 17,
			'FALSE' => 20,
			'INTEGER_' => 27,
			'STRING_' => 28,
			'REAL_' => 29,
			'DICT_' => 21
		},
		GOTOS => {
			'dict_s' => 23,
			'false' => 11,
			'date' => 12,
			'data' => 24,
			'string' => 14,
			'true' => 13,
			'dict' => 25,
			'array_s' => 26,
			'array' => 16,
			'integer' => 19,
			'plist_object' => 53,
			'real' => 22
		}
	},
	{#State 31
		DEFAULT => -4
	},
	{#State 32
		DEFAULT => 0
	},
	{#State 33
		DEFAULT => -8
	},
	{#State 34
		DEFAULT => -35
	},
	{#State 35
		ACTIONS => {
			'DATE' => 54
		}
	},
	{#State 36
		ACTIONS => {
			'DATA' => 55
		}
	},
	{#State 37
		DEFAULT => -33
	},
	{#State 38
		DEFAULT => -1
	},
	{#State 39
		DEFAULT => -29
	},
	{#State 40
		DEFAULT => -23
	},
	{#State 41
		ACTIONS => {
			'TRUE' => 9,
			'DATE_' => 10,
			'DATA_' => 15,
			'ARRAY_' => 17,
			'FALSE' => 20,
			'INTEGER_' => 27,
			'STRING_' => 28,
			'REAL_' => 29,
			'DICT_' => 21
		},
		GOTOS => {
			'dict_s' => 23,
			'false' => 11,
			'date' => 12,
			'data' => 24,
			'string' => 14,
			'true' => 13,
			'dict' => 25,
			'array_s' => 26,
			'array' => 16,
			'integer' => 19,
			'plist_object' => 56,
			'real' => 22
		}
	},
	{#State 42
		DEFAULT => -27
	},
	{#State 43
		ACTIONS => {
			'PCDATA' => 57
		}
	},
	{#State 44
		ACTIONS => {
			'DICT' => 39,
			'KEY_' => 43
		},
		GOTOS => {
			'dict_object' => 59,
			'dict_e' => 58,
			'key' => 41
		}
	},
	{#State 45
		DEFAULT => -20
	},
	{#State 46
		ACTIONS => {
			'TRUE' => 9,
			'DATE_' => 10,
			'ARRAY' => 62,
			'DATA_' => 15,
			'ARRAY_' => 17,
			'FALSE' => 20,
			'INTEGER_' => 27,
			'STRING_' => 28,
			'REAL_' => 29,
			'DICT_' => 21
		},
		GOTOS => {
			'dict_s' => 23,
			'false' => 11,
			'array_e' => 61,
			'date' => 12,
			'data' => 24,
			'string' => 14,
			'true' => 13,
			'dict' => 25,
			'array_s' => 26,
			'array' => 16,
			'integer' => 19,
			'plist_object' => 60,
			'real' => 22
		}
	},
	{#State 47
		ACTIONS => {
			'INTEGER' => 63
		}
	},
	{#State 48
		DEFAULT => -37
	},
	{#State 49
		DEFAULT => -31
	},
	{#State 50
		ACTIONS => {
			'STRING' => 64
		}
	},
	{#State 51
		ACTIONS => {
			'REAL' => 65
		}
	},
	{#State 52
		DEFAULT => -39
	},
	{#State 53
		ACTIONS => {
			'PLIST' => 66
		}
	},
	{#State 54
		DEFAULT => -36
	},
	{#State 55
		DEFAULT => -34
	},
	{#State 56
		DEFAULT => -28
	},
	{#State 57
		ACTIONS => {
			'KEY' => 67
		}
	},
	{#State 58
		DEFAULT => -24
	},
	{#State 59
		DEFAULT => -26
	},
	{#State 60
		DEFAULT => -21
	},
	{#State 61
		DEFAULT => -18
	},
	{#State 62
		DEFAULT => -22
	},
	{#State 63
		DEFAULT => -38
	},
	{#State 64
		DEFAULT => -32
	},
	{#State 65
		DEFAULT => -40
	},
	{#State 66
		DEFAULT => -2
	},
	{#State 67
		DEFAULT => -30
	}
],
                                  yyrules  =>
[
	[#Rule 0
		 '$start', 2, undef
	],
	[#Rule 1
		 'plist', 3, undef
	],
	[#Rule 2
		 'plist', 4, undef
	],
	[#Rule 3
		 'tags', 1, undef
	],
	[#Rule 4
		 'tags', 2, undef
	],
	[#Rule 5
		 'tag', 1, undef
	],
	[#Rule 6
		 'tag', 1, undef
	],
	[#Rule 7
		 'tag', 2, undef
	],
	[#Rule 8
		 'tag', 3, undef
	],
	[#Rule 9
		 'plist_object', 1, undef
	],
	[#Rule 10
		 'plist_object', 1, undef
	],
	[#Rule 11
		 'plist_object', 1, undef
	],
	[#Rule 12
		 'plist_object', 1, undef
	],
	[#Rule 13
		 'plist_object', 1, undef
	],
	[#Rule 14
		 'plist_object', 1, undef
	],
	[#Rule 15
		 'plist_object', 1, undef
	],
	[#Rule 16
		 'plist_object', 1, undef
	],
	[#Rule 17
		 'plist_object', 1, undef
	],
	[#Rule 18
		 'array', 3, undef
	],
	[#Rule 19
		 'array_s', 1,
sub
#line 43 "PlistParse.yp"
{
                         $indent++; 
                         print "  "x$indent, "Array:\n" if ($showtags);
			 if (!$showtags and (key_match() or block_match())) {
			     print "  Array_\n";
			     lasttag_push("Block");
			 }
                        }
	],
	[#Rule 20
		 'array_body', 1, undef
	],
	[#Rule 21
		 'array_body', 2, undef
	],
	[#Rule 22
		 'array_e', 1,
sub
#line 55 "PlistParse.yp"
{
                         print "  "x$indent, "EndArray:\n" if ($showtags); 
                         $indent--;
			 if (!$showtags and block_match()) {
			     print "  _Array\n";
			     lasttag_pop();
			 }
                        }
	],
	[#Rule 23
		 'dict', 2, undef
	],
	[#Rule 24
		 'dict', 3, undef
	],
	[#Rule 25
		 'dict_s', 1,
sub
#line 68 "PlistParse.yp"
{
			 if ($showtags) {
                             $indent++; 
                             print "  "x$indent, "Dict:\n";
			 }
			 elsif (key_match() or block_match()) {
			     lasttag_push("Block");
			     print "  Dict_\n";
			 }
                        }
	],
	[#Rule 26
		 'dict_objects', 2, undef
	],
	[#Rule 27
		 'dict_objects', 1, undef
	],
	[#Rule 28
		 'dict_object', 2,
sub
#line 82 "PlistParse.yp"
{
					 lastkey_pop(); # key value
					 if (key_match()) {
					     lasttag_pop(); # key tag
					 }
					}
	],
	[#Rule 29
		 'dict_e', 1,
sub
#line 89 "PlistParse.yp"
{
			 if ($showtags) {
                             print "  "x$indent, "EndDict:\n";
                             $indent--;
			 }
			 elsif (block_match()) {
			     print "  _Dict\n";
			     lasttag_pop(); # key tag
                         }
                        }
	],
	[#Rule 30
		 'key', 3,
sub
#line 101 "PlistParse.yp"
{
                                 lastkey_push ($_[2]);
                                 if (re_match ($_[2]) or key_match() or 
				                            block_match()) {
                                     lasttag_push ("Key"); 
                                     print "  "x$indent if ($showtags);
				     print "  Key: $_[2]\n";
				 }
                                }
	],
	[#Rule 31
		 'string', 2,
sub
#line 112 "PlistParse.yp"
{
				  process_pcdata ("String", "<empty>");
				}
	],
	[#Rule 32
		 'string', 3,
sub
#line 115 "PlistParse.yp"
{
				  process_pcdata ("String", $_[2]);
				}
	],
	[#Rule 33
		 'data', 2,
sub
#line 120 "PlistParse.yp"
{
				  process_pcdata ("Data", "<empty>");
				}
	],
	[#Rule 34
		 'data', 3,
sub
#line 123 "PlistParse.yp"
{
				  process_pcdata ("Data", $_[2]);
				}
	],
	[#Rule 35
		 'date', 2,
sub
#line 128 "PlistParse.yp"
{ 
				  process_pcdata ("Date", "<empty>");
				}
	],
	[#Rule 36
		 'date', 3,
sub
#line 131 "PlistParse.yp"
{
					  process_pcdata ("Date", $_[2]);
					}
	],
	[#Rule 37
		 'integer', 2,
sub
#line 136 "PlistParse.yp"
{
					  process_pcdata ("Integer", "<empty>");
					}
	],
	[#Rule 38
		 'integer', 3,
sub
#line 139 "PlistParse.yp"
{
					  process_pcdata ("Integer", $_[2]);
					}
	],
	[#Rule 39
		 'real', 2,
sub
#line 144 "PlistParse.yp"
{
			  process_pcdata ("Integer", "<empty>");
			}
	],
	[#Rule 40
		 'real', 3,
sub
#line 147 "PlistParse.yp"
{
				  process_pcdata ("Integer", $_[2]);
				}
	],
	[#Rule 41
		 'true', 1,
sub
#line 152 "PlistParse.yp"
{
			  process_pcdata ("Boolean", "TRUE");
			}
	],
	[#Rule 42
		 'false', 1,
sub
#line 157 "PlistParse.yp"
{
			  process_pcdata ("Boolean", "FALSE");
			}
	]
],
                                  @_);
    bless($self,$class);
}

#line 161 "PlistParse.yp"


sub _yyerror {
        exists $_[0]->YYData->{ERRMSG}
    and do {
        print $_[0]->YYData->{ERRMSG};
        delete $_[0]->YYData->{ERRMSG};
        return;
    };
    print "Syntax error.\n";
}

sub _yylex {
    my($parser)=shift;

    while (! $parser->YYData->{INPUT}) {
        $parser->YYData->{INPUT} = <$XML> or return('',undef);

        chomp $parser->YYData->{INPUT};
        $parser->YYData->{INPUT} =~ s/^\s*//; # strip leading spaces
    }

    # <plist>
    $parser->YYData->{INPUT} =~ s/^(<plist(\s+version="[0-9\.]+")?>)// and 
        return("PLIST_", $1);
    $parser->YYData->{INPUT} =~ s/^(<\/plist>)// and 
        return("PLIST", $1);

    # <dict>
    $parser->YYData->{INPUT} =~ s/^(<dict>)// and 
        return("DICT_", $1);
    $parser->YYData->{INPUT} =~ s/^(<\/dict>)// and 
        return("DICT", $1);
    
    # <array>
    $parser->YYData->{INPUT} =~ s/^(<array>)// and
        return("ARRAY_", $1);
    $parser->YYData->{INPUT} =~ s/^(<\/array>)// and
        return("ARRAY", $1);

    # <data>
    $parser->YYData->{INPUT} =~ s/^(<data>)// and 
        return("DATA_", $1);
    $parser->YYData->{INPUT} =~ s/^(<\/data>)// and 
        return("DATA", $1);

    # <key>
    $parser->YYData->{INPUT} =~ s/^(<key>)// and 
        return("KEY_", $1);
    $parser->YYData->{INPUT} =~ s/^(<\/key>)// and
        return("KEY", $1);

    # <date>
    $parser->YYData->{INPUT} =~ s/^(<date>)// and 
        return("DATE_", $1);
    $parser->YYData->{INPUT} =~ s/^(<\/date>)// and 
        return("DATE", $1);

    # <real>
    $parser->YYData->{INPUT} =~ s/^(<real>)// and 
        return("REAL_", $1);
    $parser->YYData->{INPUT} =~ s/^(<\/real>)// and 
        return("REAL", $1);

    # <integer>
    $parser->YYData->{INPUT} =~ s/^(<integer>)// and 
        return("INTEGER_", $1);
    $parser->YYData->{INPUT} =~ s/^(<\/integer>)// and 
        return("INTEGER", $1);

    # <string>
    $parser->YYData->{INPUT} =~ s/^(<string>)// and 
        return("STRING_", $1);
    $parser->YYData->{INPUT} =~ s/^(<\/string>)// and 
        return("STRING", $1);

    # <true>
    $parser->YYData->{INPUT} =~ s/^(<true\s*\/>)// and 
        return("TRUE", $1);
    # <false>
    $parser->YYData->{INPUT} =~ s/^(<false\s*\/>)// and 
        return("FALSE", $1);

    # Any other XML tag 
    $parser->YYData->{INPUT} =~ s/^(<[^>]*>)// and 
        return("TAG_", $1);
    $parser->YYData->{INPUT} =~ s/^(<\/[^>]*>)// and 
        return("TAG", $1);
    $parser->YYData->{INPUT} =~ s/^(<[^\/]*\/>)// and
        return("TAG__", $1);

    # PCDATA
    $parser->YYData->{INPUT} =~ s/^([^<]*)// and 
        return("PCDATA", $1);

    # Catch-all
    # Just passing the char back to the parser to keep the process moving
    # Error should be caught (and possibly ignored) by the parser.
    $parser->YYData->{INPUT} =~ s/(.)// and 
        return("UNEXPECTED_CHAR", $1);
}

sub re_match {
    my ($str) = @_;
    my $ismatch = 0;
    my $rex;

    foreach $rex (@regexp) {
        # use eval to catch issues with passed in regular expression
        eval {
            if ($str =~ /$rex/) { 
               $ismatch = 1;
               return;  # from eval
            }
        };
        warn $@ if $@;
    }
    return ($ismatch);
}

sub key_match {
    return ( (lasttag_val() eq "Key") ? 1 : 0 );
}

sub block_match {
    return ( (lasttag_val() eq "Block") ? 1 : 0 );
}

sub lastkey_push {
    my ($key) = @_;

    $lastkey_len = unshift (@lastkey, $key);
    return ($lastkey_len);
}

sub lastkey_pop {
    my $key = shift (@lastkey);

    $lastkey_len--;
    return($key);
}

sub lastkey_val {
    return ($lastkey[0] or "<undef>");
}

sub lasttag_push {
    my ($tag) = @_;

    $lasttag_len = unshift (@lasttag, $tag);
    return ($lasttag_len);
}

sub lasttag_pop {
    my $tag = shift (@lasttag);

    $lasttag_len--;
    return($tag);
}

sub lasttag_val {
    return ($lasttag[0] or "<undef>");
}

sub process_pcdata {
    my ($label, $value) = @_;

    if (key_match() or block_match()) {
        print "  "x$indent if ($showtags);
        print "  $label: $value\n";
    }
     elsif (re_match ($value)) {
        print "  "x$indent if ($showtags);
        print "  Key: ", lastkey_val(), "\n";
        print "  $label: $value\n";
    }
}

sub Run {
    my($self)=shift;

    # Move static input parameters to more efficient storage
    $XML = $self->YYData->{XML};
    @regexp = @{ $self->YYData->{REX} };
    $showtags = $self->YYData->{TAGS};

    $self->YYParse( yylex => \&_yylex, yyerror => \&_yyerror );
}

1;
