1package DateTime::Format::Builder::Parser::generic; 2{ 3 $DateTime::Format::Builder::Parser::generic::VERSION = '0.81'; 4} 5use strict; 6use warnings; 7use Carp; 8use Params::Validate qw( 9 validate SCALAR CODEREF UNDEF 10); 11 12 13 14sub new { 15 my $class = shift; 16 bless {@_}, $class; 17} 18 19 20sub generic_parser { 21 my $class = shift; 22 my %args = validate( 23 @_, 24 { 25 ( 26 map { $_ => { type => CODEREF, optional => 1 } } 27 qw( 28 on_match on_fail preprocess postprocess 29 ) 30 ), 31 label => { type => SCALAR | UNDEF, optional => 1 }, 32 } 33 ); 34 my $label = $args{label}; 35 36 my $callback 37 = ( exists $args{on_match} or exists $args{on_fail} ) ? 1 : undef; 38 39 return sub { 40 my ( $self, $date, $p, @args ) = @_; 41 return unless defined $date; 42 my %p; 43 %p = %$p if $p; # Look! A Copy! 44 45 my %param = ( 46 self => $self, 47 ( defined $label ? ( label => $label ) : () ), 48 ( @args ? ( args => \@args ) : () ), 49 ); 50 51 # Preprocess - can modify $date and fill %p 52 if ( $args{preprocess} ) { 53 $date = $args{preprocess} 54 ->( input => $date, parsed => \%p, %param ); 55 } 56 57 my $rv = $class->do_match( $date, @args ) if $class->can('do_match'); 58 59 # Funky callback thing 60 if ($callback) { 61 my $type = defined $rv ? "on_match" : "on_fail"; 62 $args{$type}->( input => $date, %param ) if $args{$type}; 63 } 64 return unless defined $rv; 65 66 my $dt; 67 $dt = $class->post_match( $date, $rv, \%p ) 68 if $class->can('post_match'); 69 70 # Allow post processing. Return undef if regarded as failure 71 if ( $args{postprocess} ) { 72 my $rv = $args{postprocess}->( 73 parsed => \%p, 74 input => $date, 75 post => $dt, 76 %param, 77 ); 78 return unless $rv; 79 } 80 81 # A successful match! 82 $dt = $class->make( $date, $dt, \%p ) if $class->can('make'); 83 return $dt; 84 }; 85} 86 87 88{ 89 no strict 'refs'; 90 for (qw( valid_params params )) { 91 *$_ = *{"DateTime::Format::Builder::Parser::$_"}; 92 } 93} 94 951; 96 97# ABSTRACT: Useful routines 98 99__END__ 100 101=pod 102 103=head1 NAME 104 105DateTime::Format::Builder::Parser::generic - Useful routines 106 107=head1 VERSION 108 109version 0.81 110 111=head1 METHODS 112 113=head2 Useful 114 115=head3 new 116 117Standard constructor. Returns a blessed hash; any arguments are placed 118in the hash. This is useful for storing information between methods. 119 120=head3 generic_parser 121 122This is a method provided solely for the benefit of 123C<Parser> implementations. It semi-neatly abstracts 124a lot of the work involved. 125 126Basically, it takes parameters matching the assorted 127callbacks from the parser declarations and makes a coderef 128out of it all. 129 130Currently recognized callbacks are: 131 132=over 4 133 134=item * 135 136on_match 137 138=item * 139 140on_fail 141 142=item * 143 144preprocess 145 146=item * 147 148postprocess 149 150=back 151 152=head2 Methods for subclassing 153 154These are methods you should define when writing your own subclass. 155 156B<Note>: these methods do not exist in this class. There is no point 157trying to call C<< $self->SUPER::do_match( ... ) >>. 158 159=head3 do_match 160 161C<do_match> is the first phase. Arguments are the date and @args. 162C<self>, C<label>, C<args>. Return value must be defined if you match 163successfully. 164 165=head3 post_match 166 167C<post_match> is called after the appropriate callback out of 168C<on_match>/C<on_fail> is done. It's passed the date, the return 169value from C<do_match> and the parsing hash. 170 171Its return value is used as the C<post> argument to the C<postprocess> 172callback, and as the second argument to C<make>. 173 174=head3 make 175 176C<make> takes the original input, the return value from C<post_match> 177and the parsing hash and should return a C<DateTime> object or 178undefined. 179 180=head2 Delegations 181 182For use of C<Parser>, this module also delegates C<valid_params> and 183C<params>. This is just convenience to save typing the following: 184 185 DateTime::Format::Builder::Parser->valid_params( blah ) 186 187Instead we get to type: 188 189 $self->valid_params( blah ); 190 __PACKAGE__->valid_params( blah ); 191 192=head1 WRITING A SUBCLASS 193 194Rather than attempt to explain how it all works, I think it's best if 195you take a look at F<Regex.pm> and F<Strptime.pm> as examples and 196work from there. 197 198=head1 SUPPORT 199 200See L<DateTime::Format::Builder> for details. 201 202=head1 SEE ALSO 203 204C<datetime@perl.org> mailing list. 205 206http://datetime.perl.org/ 207 208L<perl>, L<DateTime>, L<DateTime::Format::Builder>, 209L<DateTime::Format::Builder::Parser>. 210 211=head1 AUTHORS 212 213=over 4 214 215=item * 216 217Dave Rolsky <autarch@urth.org> 218 219=item * 220 221Iain Truskett 222 223=back 224 225=head1 COPYRIGHT AND LICENSE 226 227This software is Copyright (c) 2013 by Dave Rolsky. 228 229This is free software, licensed under: 230 231 The Artistic License 2.0 (GPL Compatible) 232 233=cut 234