package Lingua::PT::Inflect;

use 5.006;
use strict;
use warnings;
use Lingua::PT::Hyphenate;

require Exporter;

our @ISA = qw(Exporter);

our %EXPORT_TAGS = ( 'all' => [ qw(
    sing2plural
) ] );

our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

our @EXPORT = qw(
    sing2plural
);

our $VERSION = '0.08';

=head1 NAME

=encoding latin1

Lingua::PT::Inflect - Converts Portuguese words from singular to plural

=head1 SYNOPSIS

  use Lingua::PT::Inflect;

  $plural = sing2plural('programador')   # now holds 'programadores'

=head1 DESCRIPTION

Converts Portuguese words from singular to plural. There may be some
special cases that will fail (words ending in -ão or -s might fail, as
many special cases are yet to be prevented; anyone volunteering to
look at a huge list of words?)

=cut

my (%exceptions,@rules,%rules);

BEGIN {
  %exceptions = (
    'lápis'     => 'lápis',
    'pires'     => 'pires',

    'mão'       => 'mãos',
    'afegão'    => 'afegãos',

    'pão'       => 'pães',
    'capitão'   => 'capitães',
    'cão'       => 'cães',
    'alemão'    => 'alemães',
  );

  @rules = map qr/$_/, qw(ás ês el ol al oi ul m ão (?<=[aeiou]) (?<=[rnsz]));

  %rules = (
    qr/ás/  => 'ases',
    qr/ês/  => 'eses',
    qr/el/  => 'éis',
    qr/ol/  => 'óis',
    qr/al/  => 'ais',
    qr/oi/  => 'ois',
    qr/ul/  => 'uis',
    qr/m/   => 'ns',
    qr/ão/  => 'ões',
    qr/(?<=[aeiou])/    => 's',
    qr/(?<=[rnsz])/     => 'es',
  );

}

#

=head1 METHODS

=head2 new

Creates a new C<Lingua::PT::Inflect> object.

If you're doing this lots of time, it would probably be better for you
to use the C<sing2plural> function directly (that is, creating a new
object for each word in a long text doesn't seem so bright if you're
not going to use it later on).

=cut

sub new {
  my ($self, $word) = @_;
  bless \$word, $self;
}

=head2 sing2plural

Converts a word in the singular gender to plural.

  $plural = sing2plural($singular);

=cut

sub sing2plural {
  defined $_[0] || return undef;

  my $word;
  if (ref($_[0]) eq 'Lingua::PT::Inflect') {
    my $self = shift;
    $word = $$self;
  }
  else {
    $word = shift;
  }

  $_ = $word;

  defined $exceptions{$_} && return $exceptions{$_};

  for my $rule (@rules) {
    if (s/$rule$/$rules{$rule}/) {return $_}
  }

  if (/il$/) {
    my @syl = hyphenate($_);

    s!il$!$syl[-2] =~ /[ãâáêéíóõôúÃÁÉÍÓÕÔÊÂÚ]/ ? 'eis' : 'is' !e;
  }

  return $_;
}

1;
__END__

=head1 TO DO

=over 6

=item * Several words are exceptions to the rules; there is a file of
those words that need to be checked.

=back

=head1 SEE ALSO

More tools for the Portuguese language processing can be found at the Natura
project: L<http://natura.di.uminho.pt>

=head1 AUTHOR

Jose Castro, C<< <cog@cpan.org> >>

=head1 COPYRIGHT & LICENSE

Copyright 2004 Jose Castro, All Rights Reserved.

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=cut
