package Lingua::EN::Conjugate;

use Data::Dumper;

@ISA = qw( Exporter );

@EXPORT_OK = qw(
	conjugate
	@tenses
	@pron
);


use warnings;
use strict;
use diagnostics;


use vars qw(
	$VERSION
	%irreg
	@pron
	@tenses
	%conj

);

$VERSION = '0.1';
@pron = qw(I you we he she it they);

@tenses = qw(	present	
		present_prog 	
		past		
		past_prog 	
		perfect			
		past_perfect	
		perfect_prog	
		past_perfect_prog
		modal 		
		modal_prog 	
		modal_perf 	
		modal_perf_prog 
		conjunctive_present 
		imperative 	
	);

while (<DATA>) {
	chomp;
	my ($verb, $simp, $part) = split /\t/, $_;
	$verb =~ s/\(.*//;
	$simp =~ s/\/.*//;
	$part =~ s/\/.*//;
	($verb, $simp, $part) = map {s/ +$//; $_} ($verb, $simp, $part);
	$irreg{$verb} = {past=>$simp, part=>$part};
	#print "$verb, $simp, $part\n";
}




sub conjugate {


	my %params = @_;
	#print Dumper \%params;
	
	my $inf = defined $params{verb}? $params{verb} : warn "must define a verb!!\n", return;
	my $modal = defined $params{modal}? $params{modal} : 'will';
	
	my @conjs = ();


	my ($part, $past, $gerund);

	my $stem = $inf;

	if ($stem=~/[bcdfghjklmnpqrstvwxyz][aeiou][bcdfghjklmnpqrstv]$/) {
		#if the word ends in CVC pattern (but final consonant is not w,x,y, or z)
		# and if the stress is not on the penultimate syllable, then double
		# the final consonant.
		#
		# works for stop, sit, spit, refer, begin, admit, etc.
		# but breaks for visit, happen, enter, etc.
		
		$stem =~ s/(\w)$/$1$1/;

	}
	
	$part = $past = $stem . 'ed' ;
	$part =~ s/([bcdfghjklmnpqrstvwxyz])eed$/$1ed/;
	$part =~ s/([bcdfghjklmnpqrstvwxyz])yed$/$1ied/;

	$gerund = $stem . 'ing';
	$gerund =~ s/([bcdfghjklmnpqrstvwxyz])eing$/$1ing/;

	if ($inf eq 'be') {
		$gerund = 'being';
	}

	if (defined $irreg{$inf} ) {
		$part = $irreg{$inf}{part};
		$past = $irreg{$inf}{past};
	}


	#print "$inf, $past, $part\n";

	my %conj = (

		present		=> {(map {$_ => $_ . " $inf"} 		qw(I you we they)) , 
				    (map {$_ => $_ . " ${inf}s"} 	qw(he she it)) },

		present_prog 	=> {(map {$_ => $_ . " am $gerund"}     qw(I)), 
				    (map {$_ => $_ . " are $gerund"} 	qw(you we they)) , 
				    (map {$_ => $_ . " is $gerund"} 	qw(he she it)) }, 

		past		=> {map {$_ => $_ . " $past"} 		@pron},

		past_prog 	=> {(map {$_ => $_ . " were $gerund"} 	qw(you we they)) ,
				    (map {$_ => $_ . " was $gerund"} 	qw(I he she it)) }, 

		perfect		=> {(map {$_ => $_ . " have $part"} 	qw(I you we they)), 
				    (map {$_ => $_ . " has $part"} 	qw(he she it))},

		past_perfect	=> {map {$_ => $_ . " had $part"} 	@pron},

		perfect_prog	=> {(map {$_ => $_ . " have been $gerund"} 	qw(I you we they)), 
				    (map {$_ => $_ . " has been $gerund"}  	qw(he she it))},

		past_perfect_prog=>{map {$_ => $_ . " had been $gerund"} 	@pron},

		modal 		=> {map {$_ => $_ . " $modal $inf"} 		@pron},
		modal_prog 	=> {map {$_ => $_ . " $modal be $gerund"} 	@pron},
		modal_perf 	=> {map {$_ => $_ . " $modal have $part"} 	@pron},
		modal_perf_prog => {map {$_ => $_ . " $modal have been $gerund"} 	@pron},
		conjunctive_present => {map {$_ => $_ ." $inf"} 		@pron},
		imperative 	=> { "you"=> "$inf", "we"=>"let's $inf" },
		);

	if ($inf eq 'be') {

		$conj{present} = {  (map {$_ => $_ . " am"}     	qw(I)), 
				    (map {$_ => $_ . " are"} 	qw(you we they)) , 
				    (map {$_ => $_ . " is"} 	qw(he she it)) };
		$conj{past} = 	{   (map {$_ => $_ . " were"} 	qw(you we they)) ,
				    (map {$_ => $_ . " was"} 	qw(I he she it)) }; 


	}

	if (ref $params{pronoun} or ref $params{tense} or !defined $params{pronoun} or !defined $params{tense}) {
		my $ret = {};
		my @t = ref $params{tense}? @{$params{tense}} : 
					defined $params{tense}? $params{tense} : 
						@tenses;

		for my $t (@t) {
			#print "$t: \n";
			#print Dumper $conj{$t};
			#print "\n";



				
			my @p = ref $params{pronoun} ? grep {defined $conj{$t}{$_}} @{$params{pronoun}} : 
				defined $params{pronoun}? $params{pronoun} : 
				grep {defined $conj{$t}{$_}} @pron ;
			

			for my $p (@p) {
				next unless defined $conj{$t}{$p};
				$ret->{$t}{$p} =  $conj{$t}{$p};
			}
		}
		
		if (wantarray) {
			my @return = ();
			for my $t (keys %{ $ret }) {
				for my $p (keys %{ $ret->{$t} }) {
	
					push @return, $ret->{$t}{$p};
				}
			}
			return @return;
		}
		else {return $ret}

	}
	
	return $conj{$params{tense}}{$params{pronoun}};
	

}


"true";


=head1 NAME

Lingua::EN::Conjugate - Conjugation of English verbs

=head1 SYNOPSIS

use Lingua::EN::Conjugate qw( conjugate );
use Data::Dumper;
	

	# scalar context with tense and pronoun defined as scalars, 
	#returns a scalar
	my $walk = conjugate( 'verb'=>'walk', 
				'tense'=>'perfect_prog', 
				'pronoun'=>'he' );  
	print $walk . "\n";

	# scalar context with tense and pronoun undefined or defined 
	#as array refs, returns a hashref
	my $go = conjugate( 'verb'=>'go', 
				'tense'=>[qw(past modal_perf)], 
				'modal'=>'might not' ) ;       	
	print Dumper($go);

	# array context, returns an array of conjugated forms
	my @be = conjugate( 'verb'=>'be', 
				'pronoun'=>[qw(I we)], 
				'tense'=>'past_prog' );

	print join("\n", @be);



=head1 DESCRIPTION

This module conjugates English verbs.

Thanks to Susan Jones for the list of irregular verbs and an explanation of English verb tenses: http://www2.gsu.edu/~wwwesl/egw/grlists.htm.

present         -> we drive
present_prog    -> we are driving
past            -> we drove
past_prog       -> we were driving
perfect         -> we have driven
past_perfect    -> we had driven
perfect_prog    -> we have been driving
past_perfect_prog -> we had been driving
modal           -> we will drive
modal_prog      -> we will be driving
modal_perf      -> we will have driven
modal_perf_prog -> we will have been driving
conjunctive_present -> we drive
imperative      -> let's drive

note that the "future tense" is called "modal" here, with "will" as the default.  You could 
substitute any of (shall / can / can't / could / must) as the modal verb, and it would still 
make sense.  See http://www.englishclub.com/grammar/verbs-modals_can.htm.  I'm not quite 
sure what to do with "Be able to" asa modal verb.


=head2 EXPORT

None by default. You can export the following functions and variables:

	conjugate
	@tenses
	@pronouns

=head1 BUGS
I've tried to implement double-consonants for -ed and -ing ("admitted", 
"stopping" etc.)  The rules for doing so are here: 
http://www.english-zone.com/spelling/doubles.html.  However, the 
xception to the rule is when thestress is on the penultimate syllable, 
such as "visit", "open", etc.  So I need a list of words ending in CVC, 
with the stress on the next to the last syllable, to get the spelling right.


=head1 HISTORY

=over 4

=item 0.1

Original version -- no guarantees.

=back


=head1 AUTHOR

Russ Graham, russgraham@gmail.com

=head1 SEE ALSO

perl(1).

=cut
__DATA__
awake 	awoke 	awoken
be 	was, were 	been
bear 	bore 	born
beat 	beat 	beat
become 	became 	become
begin 	began 	begun
bend 	bent 	bent
beset 	beset 	beset
bet 	bet 	bet
bid 	bid/bade 	bid/bidden
bind 	bound 	bound
bite 	bit 	bitten
bleed 	bled 	bled
blow 	blew 	blown
break 	broke 	broken
breed 	bred 	bred
bring 	brought 	brought
broadcast 	broadcast 	broadcast
build 	built 	built
burn 	burned/burnt 	burned/burnt
burst 	burst 	burst
buy 	bought 	bought
cast 	cast 	cast
catch 	caught 	caught
choose 	chose 	chosen
cling 	clung 	clung
come 	came 	come
cost 	cost 	cost
creep 	crept 	crept
cut 	cut 	cut
deal 	dealt 	dealt
dig 	dug 	dug
dive 	dived/dove 	dived
do 	did 	done
draw 	drew 	drawn
dream 	dreamed/dreamt 	dreamed/dreamt
drive 	drove 	driven
drink 	drank 	drunk
eat 	ate 	eaten
fall 	fell 	fallen
feed 	fed 	fed
feel 	felt 	felt
fight 	fought 	fought
find 	found 	found
fit 	fit 	fit
flee 	fled 	fled
fling 	flung 	flung
fly 	flew 	flown
forbid 	forbade 	forbidden
forget 	forgot 	forgotten
forego (forgo) 	forewent 	foregone
forgive 	forgave 	forgiven
forsake 	forsook 	forsaken
freeze 	froze 	frozen
get 	got 	gotten
give 	gave 	given
go 	went 	gone
grind 	ground 	ground
grow 	grew 	grown
hang 	hung 	hung
hear 	heard 	heard
hide 	hid 	hidden
hit 	hit 	hit
hold 	held 	held
hurt 	hurt 	hurt
keep 	kept 	kept
kneel 	knelt 	knelt
knit 	knit 	knit
know 	knew 	know
lay 	laid 	laid
lead 	led 	led
leap 	leaped/lept 	leaped/lept
learn 	learned/learnt 	learned/learnt
leave 	left 	left
lend 	lent 	lent
let 	let 	let
lie 	lay 	lain
light 	lighted/lit 	lighted
lose 	lost 	lost
make 	made 	made
mean 	meant 	meant
meet 	met 	met
misspell 	misspelled/misspelt 	misspelled/misspelt
mistake 	mistook 	mistaken
mow 	mowed 	mowed/mown
overcome 	overcame 	overcome
overdo 	overdid 	overdone
overtake 	overtook 	overtaken
overthrow 	overthrew 	overthrown
pay 	paid 	paid
plead 	pled 	pled
prove 	proved 	proved/proven
put 	put 	put
quit 	quit 	quit
read 	read 	read
rid 	rid 	rid
ride 	rode 	ridden
ring 	rang 	rung
rise 	rose 	risen
run 	ran 	run
saw 	sawed 	sawed/sawn
say 	said 	said
see 	saw 	seen
seek 	sought 	sought
sell 	sold 	sold
send 	sent 	sent
set 	set 	set
sew 	sewed 	sewed/sewn
shake 	shook 	shaken
shave 	shaved 	shaved/shaven
shear 	shore 	shorn
shed 	shed 	shed
shine 	shone 	shone
shoe 	shoed 	shoed/shod
shoot 	shot 	shot
show 	showed 	showed/shown
shrink 	shrank 	shrunk
shut 	shut 	shut
sing 	sang 	sung
sink 	sank 	sunk
sit 	sat 	sat
sleep 	slept 	slept
slay 	slew 	slain
slide 	slid 	slid
sling 	slung 	slung
slit 	slit 	slit
smite 	smote 	smitten
sow 	sowed 	sowed/sown
speak 	spoke 	spoken
speed 	sped 	sped
spend 	spent 	spent
spill 	spilled/spilt 	spilled/spilt
spin 	spun 	spun
spit 	spit/spat 	spit
split 	split 	split
spread 	spread 	spread
spring 	sprang/sprung 	sprung
stand 	stood 	stood
steal 	stole 	stolen
stick 	stuck 	stuck
sting 	stung 	stung
stink 	stank 	stunk
stride 	strod 	stridden
strike 	struck 	struck
string 	strung 	strung
strive 	strove 	striven
swear 	swore 	sworn
sweep 	swept 	swept
swell 	swelled 	swelled/swollen 
swim 	swam 	swum
swing 	swung 	swung
take 	took 	taken
teach 	taught 	taught
tear 	tore 	torn
tell 	told 	told
think 	thought 	thought
thrive 	thrived/throve 	thrived
throw 	threw 	thrown
thrust 	thrust 	thrust
tread 	trod 	trodden
understand 	understood 	understood
uphold 	upheld 	upheld
upset 	upset 	upset
wake 	woke 	woken
wear 	wore 	worn
weave 	weaved/wove 	weaved/woven
wed 	wed 	wed
weep 	wept 	wept
wind 	wound 	wound
win 	won 	won
withhold 	withheld 	withheld
withstand 	withstood 	withstood
wring 	wrung 	wrung
write 	wrote 	written
