package DateTime::Format::Builder::Parser::generic; use strict; use vars qw( $VERSION ); use Carp; use Params::Validate qw( validate SCALAR CODEREF UNDEF ); $VERSION = '0.77'; =head1 NAME DateTime::Format::Builder::Parser::generic - Useful routines =head1 METHODS =head2 Useful =head3 new Standard constructor. Returns a blessed hash; any arguments are placed in the hash. This is useful for storing information between methods. =cut sub new { my $class = shift; bless { @_ }, $class; } =head3 generic_parser This is a method provided solely for the benefit of C implementations. It semi-neatly abstracts a lot of the work involved. Basically, it takes parameters matching the assorted callbacks from the parser declarations and makes a coderef out of it all. Currently recognized callbacks are: =over 4 =item * on_match =item * on_fail =item * preprocess =item * postprocess =back =cut sub generic_parser { my $class = shift; my %args = validate( @_, { ( map { $_ => { type => CODEREF, optional => 1 } } qw( on_match on_fail preprocess postprocess ) ), label => { type => SCALAR|UNDEF, optional => 1 }, }); my $label = $args{label}; my $callback = (exists $args{on_match} or exists $args{on_fail}) ? 1 : undef; return sub { my ($self, $date, $p, @args) = @_; return unless defined $date; my %p; %p = %$p if $p; # Look! A Copy! my %param = ( self => $self, ( defined $label ? ( label => $label ) : ()), (@args ? (args => \@args) : ()), ); # Preprocess - can modify $date and fill %p if ($args{preprocess}) { $date = $args{preprocess}->( input => $date, parsed => \%p, %param ); } my $rv = $class->do_match( $date, @args ) if $class->can('do_match'); # Funky callback thing if ($callback) { my $type = defined $rv ? "on_match" : "on_fail"; $args{$type}->( input => $date, %param ) if $args{$type}; } return unless defined $rv; my $dt; $dt = $class->post_match( $date, $rv, \%p ) if $class->can('post_match'); # Allow post processing. Return undef if regarded as failure if ($args{postprocess}) { my $rv = $args{postprocess}->( parsed => \%p, input => $date, post => $dt, %param, ); return unless $rv; } # A successful match! $dt = $class->make( $date, $dt, \%p ) if $class->can('make'); return $dt; }; } =head2 Methods for subclassing These are methods you should define when writing your own subclass. B: these methods do not exist in this class. There is no point trying to call C<< $self->SUPER::do_match( ... ) >>. =head3 do_match C is the first phase. Arguments are the date and @args. C, C