Blame lib/DateTime/Format/Builder/Parser/generic.pm

Packit 9002b2
package DateTime::Format::Builder::Parser::generic;
Packit 9002b2
{
Packit 9002b2
  $DateTime::Format::Builder::Parser::generic::VERSION = '0.81';
Packit 9002b2
}
Packit 9002b2
use strict;
Packit 9002b2
use warnings;
Packit 9002b2
use Carp;
Packit 9002b2
use Params::Validate qw(
Packit 9002b2
    validate SCALAR CODEREF UNDEF
Packit 9002b2
);
Packit 9002b2
Packit 9002b2
Packit 9002b2
Packit 9002b2
sub new {
Packit 9002b2
    my $class = shift;
Packit 9002b2
    bless {@_}, $class;
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
Packit 9002b2
sub generic_parser {
Packit 9002b2
    my $class = shift;
Packit 9002b2
    my %args  = validate(
Packit 9002b2
        @_,
Packit 9002b2
        {
Packit 9002b2
            (
Packit 9002b2
                map { $_ => { type => CODEREF, optional => 1 } }
Packit 9002b2
                    qw(
Packit 9002b2
                    on_match on_fail preprocess postprocess
Packit 9002b2
                    )
Packit 9002b2
            ),
Packit 9002b2
            label => { type => SCALAR | UNDEF, optional => 1 },
Packit 9002b2
        }
Packit 9002b2
    );
Packit 9002b2
    my $label = $args{label};
Packit 9002b2
Packit 9002b2
    my $callback
Packit 9002b2
        = ( exists $args{on_match} or exists $args{on_fail} ) ? 1 : undef;
Packit 9002b2
Packit 9002b2
    return sub {
Packit 9002b2
        my ( $self, $date, $p, @args ) = @_;
Packit 9002b2
        return unless defined $date;
Packit 9002b2
        my %p;
Packit 9002b2
        %p = %$p if $p;    # Look! A Copy!
Packit 9002b2
Packit 9002b2
        my %param = (
Packit 9002b2
            self => $self,
Packit 9002b2
            ( defined $label ? ( label => $label ) : () ),
Packit 9002b2
            ( @args          ? ( args  => \@args ) : () ),
Packit 9002b2
        );
Packit 9002b2
Packit 9002b2
        # Preprocess - can modify $date and fill %p
Packit 9002b2
        if ( $args{preprocess} ) {
Packit 9002b2
            $date = $args{preprocess}
Packit 9002b2
                ->( input => $date, parsed => \%p, %param );
Packit 9002b2
        }
Packit 9002b2
Packit 9002b2
        my $rv = $class->do_match( $date, @args ) if $class->can('do_match');
Packit 9002b2
Packit 9002b2
        # Funky callback thing
Packit 9002b2
        if ($callback) {
Packit 9002b2
            my $type = defined $rv ? "on_match" : "on_fail";
Packit 9002b2
            $args{$type}->( input => $date, %param ) if $args{$type};
Packit 9002b2
        }
Packit 9002b2
        return unless defined $rv;
Packit 9002b2
Packit 9002b2
        my $dt;
Packit 9002b2
        $dt = $class->post_match( $date, $rv, \%p )
Packit 9002b2
            if $class->can('post_match');
Packit 9002b2
Packit 9002b2
        # Allow post processing. Return undef if regarded as failure
Packit 9002b2
        if ( $args{postprocess} ) {
Packit 9002b2
            my $rv = $args{postprocess}->(
Packit 9002b2
                parsed => \%p,
Packit 9002b2
                input  => $date,
Packit 9002b2
                post   => $dt,
Packit 9002b2
                %param,
Packit 9002b2
            );
Packit 9002b2
            return unless $rv;
Packit 9002b2
        }
Packit 9002b2
Packit 9002b2
        # A successful match!
Packit 9002b2
        $dt = $class->make( $date, $dt, \%p ) if $class->can('make');
Packit 9002b2
        return $dt;
Packit 9002b2
    };
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
Packit 9002b2
{
Packit 9002b2
    no strict 'refs';
Packit 9002b2
    for (qw( valid_params params )) {
Packit 9002b2
        *$_ = *{"DateTime::Format::Builder::Parser::$_"};
Packit 9002b2
    }
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
1;
Packit 9002b2
Packit 9002b2
# ABSTRACT: Useful routines
Packit 9002b2
Packit 9002b2
__END__
Packit 9002b2
Packit 9002b2
=pod
Packit 9002b2
Packit 9002b2
=head1 NAME
Packit 9002b2
Packit 9002b2
DateTime::Format::Builder::Parser::generic - Useful routines
Packit 9002b2
Packit 9002b2
=head1 VERSION
Packit 9002b2
Packit 9002b2
version 0.81
Packit 9002b2
Packit 9002b2
=head1 METHODS
Packit 9002b2
Packit 9002b2
=head2 Useful
Packit 9002b2
Packit 9002b2
=head3 new
Packit 9002b2
Packit 9002b2
Standard constructor. Returns a blessed hash; any arguments are placed
Packit 9002b2
in the hash. This is useful for storing information between methods.
Packit 9002b2
Packit 9002b2
=head3 generic_parser
Packit 9002b2
Packit 9002b2
This is a method provided solely for the benefit of
Packit 9002b2
C<Parser> implementations. It semi-neatly abstracts
Packit 9002b2
a lot of the work involved.
Packit 9002b2
Packit 9002b2
Basically, it takes parameters matching the assorted
Packit 9002b2
callbacks from the parser declarations and makes a coderef
Packit 9002b2
out of it all.
Packit 9002b2
Packit 9002b2
Currently recognized callbacks are:
Packit 9002b2
Packit 9002b2
=over 4
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
on_match
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
on_fail
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
preprocess
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
postprocess
Packit 9002b2
Packit 9002b2
=back
Packit 9002b2
Packit 9002b2
=head2 Methods for subclassing
Packit 9002b2
Packit 9002b2
These are methods you should define when writing your own subclass.
Packit 9002b2
Packit 9002b2
B<Note>: these methods do not exist in this class. There is no point
Packit 9002b2
trying to call C<< $self->SUPER::do_match( ... ) >>.
Packit 9002b2
Packit 9002b2
=head3 do_match
Packit 9002b2
Packit 9002b2
C<do_match> is the first phase. Arguments are the date and @args.
Packit 9002b2
C<self>, C<label>, C<args>. Return value must be defined if you match
Packit 9002b2
successfully.
Packit 9002b2
Packit 9002b2
=head3 post_match
Packit 9002b2
Packit 9002b2
C<post_match> is called after the appropriate callback out of
Packit 9002b2
C<on_match>/C<on_fail> is done. It's passed the date, the return
Packit 9002b2
value from C<do_match> and the parsing hash.
Packit 9002b2
Packit 9002b2
Its return value is used as the C<post> argument to the C<postprocess>
Packit 9002b2
callback, and as the second argument to C<make>.
Packit 9002b2
Packit 9002b2
=head3 make
Packit 9002b2
Packit 9002b2
C<make> takes the original input, the return value from C<post_match>
Packit 9002b2
and the parsing hash and should return a C<DateTime> object or
Packit 9002b2
undefined.
Packit 9002b2
Packit 9002b2
=head2 Delegations
Packit 9002b2
Packit 9002b2
For use of C<Parser>, this module also delegates C<valid_params> and
Packit 9002b2
C<params>. This is just convenience to save typing the following:
Packit 9002b2
Packit 9002b2
    DateTime::Format::Builder::Parser->valid_params( blah )
Packit 9002b2
Packit 9002b2
Instead we get to type:
Packit 9002b2
Packit 9002b2
    $self->valid_params( blah );
Packit 9002b2
    __PACKAGE__->valid_params( blah );
Packit 9002b2
Packit 9002b2
=head1 WRITING A SUBCLASS
Packit 9002b2
Packit 9002b2
Rather than attempt to explain how it all works, I think it's best if
Packit 9002b2
you take a look at F<Regex.pm> and F<Strptime.pm> as examples and
Packit 9002b2
work from there.
Packit 9002b2
Packit 9002b2
=head1 SUPPORT
Packit 9002b2
Packit 9002b2
See L<DateTime::Format::Builder> for details.
Packit 9002b2
Packit 9002b2
=head1 SEE ALSO
Packit 9002b2
Packit 9002b2
C<datetime@perl.org> mailing list.
Packit 9002b2
Packit 9002b2
http://datetime.perl.org/
Packit 9002b2
Packit 9002b2
L<perl>, L<DateTime>, L<DateTime::Format::Builder>,
Packit 9002b2
L<DateTime::Format::Builder::Parser>.
Packit 9002b2
Packit 9002b2
=head1 AUTHORS
Packit 9002b2
Packit 9002b2
=over 4
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
Dave Rolsky <autarch@urth.org>
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
Iain Truskett
Packit 9002b2
Packit 9002b2
=back
Packit 9002b2
Packit 9002b2
=head1 COPYRIGHT AND LICENSE
Packit 9002b2
Packit 9002b2
This software is Copyright (c) 2013 by Dave Rolsky.
Packit 9002b2
Packit 9002b2
This is free software, licensed under:
Packit 9002b2
Packit 9002b2
  The Artistic License 2.0 (GPL Compatible)
Packit 9002b2
Packit 9002b2
=cut