package DateTime::Format::Builder::Parser::generic;

use strict;
use warnings;

our $VERSION = '0.82';

use Carp;
use Params::Validate qw(

sub new {
    my $class = shift;
    bless {@_}, $class;

sub generic_parser {
    my $class = shift;
    my %args  = validate(
                map { $_ => { type => CODEREF, optional => 1 } }
                    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,
            return unless $rv;

        # A successful match!
        $dt = $class->make( $date, $dt, \%p ) if $class->can('make');
        return $dt;

    no strict 'refs';
    for (qw( valid_params params )) {
        *$_ = *{"DateTime::Format::Builder::Parser::$_"};


# ABSTRACT: Useful routines



=encoding UTF-8

=head1 NAME

DateTime::Format::Builder::Parser::generic - Useful routines

=head1 VERSION

version 0.82

=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.

=head3 generic_parser

This is a method provided solely for the benefit of
C<Parser> 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 *


=item *


=item *


=item *



=head2 Methods for subclassing

These are methods you should define when writing your own subclass.

B<Note>: these methods do not exist in this class. There is no point
trying to call C<< $self->SUPER::do_match( ... ) >>.

=head3 do_match

C<do_match> is the first phase. Arguments are the date and @args.
C<self>, C<label>, C<args>. Return value must be defined if you match

=head3 post_match

C<post_match> is called after the appropriate callback out of
C<on_match>/C<on_fail> is done. It's passed the date, the return
value from C<do_match> and the parsing hash.

Its return value is used as the C<post> argument to the C<postprocess>
callback, and as the second argument to C<make>.

=head3 make

C<make> takes the original input, the return value from C<post_match>
and the parsing hash and should return a C<DateTime> object or

=head2 Delegations

For use of C<Parser>, this module also delegates C<valid_params> and
C<params>. This is just convenience to save typing the following:

    DateTime::Format::Builder::Parser->valid_params( blah )

Instead we get to type:

    $self->valid_params( blah );
    __PACKAGE__->valid_params( blah );


Rather than attempt to explain how it all works, I think it's best if
you take a look at F<> and F<> as examples and
work from there.

=head1 SEE ALSO

C<> mailing list.

L<perl>, L<DateTime>, L<DateTime::Format::Builder>,

=head1 SUPPORT

Bugs may be submitted at L<> or via email to L<|>.

I am also usually active on IRC as 'autarch' on C<irc://>.

=head1 SOURCE

The source code repository for DateTime-Format-Builder can be found at L<>.

=head1 AUTHORS

=over 4

=item *

Dave Rolsky <>

=item *

Iain Truskett



This software is Copyright (c) 2019 by Dave Rolsky.

This is free software, licensed under:

  The Artistic License 2.0 (GPL Compatible)

The full text of the license can be found in the
F<LICENSE> file included with this distribution.