File Coverage

blib/lib/Lingua/Zompist/Cadhinor.pm
Criterion Covered Total %
statement 190 202 94.0
branch 150 168 89.2
condition 201 270 74.4
subroutine 16 16 100.0
pod 13 13 100.0
total 570 669 85.2


line stmt bran cond sub pod time code
1             package Lingua::Zompist::Cadhinor;
2              
3 14     14   377514 use 5.005;
  14         56  
  14         883  
4 14     14   80 use strict;
  14         110  
  14         752  
5              
6             require Exporter;
7 14     14   75 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %verb);
  14         29  
  14         130756  
8             @ISA = qw(Exporter);
9              
10             # Items to export into callers namespace by default. Note: do not export
11             # names by default without a very good reason. Use EXPORT_OK instead.
12             # Do not simply export all your public functions/methods/constants.
13              
14             # This allows declaration use Lingua::Zompist::Cadhinor ':all';
15             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
16             # will save memory.
17             %EXPORT_TAGS = (
18             'all' => [ qw(
19             demeric
20             scrifel
21             izhcrifel
22             budemeric
23             buscrifel
24             bubefel
25             dynamic
26             part
27             noun
28             adj
29             comp
30             super
31             adv
32             ) ],
33             'verb' => [ qw(
34             demeric
35             scrifel
36             izhcrifel
37             budemeric
38             buscrifel
39             bubefel
40             dynamic
41             part
42             ) ],
43             'nonverb' => [ qw(
44             noun
45             adj
46             comp
47             super
48             adv
49             ) ],
50             );
51              
52             @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} }, '%verb' );
53              
54             @EXPORT = qw(
55            
56             );
57             $VERSION = '0.92';
58              
59             %verb = (
60             static => {
61             prilise => {
62             demeric => \&demeric,
63             scrifel => \&scrifel,
64             izhcrifel => \&izhcrifel,
65             befel => sub { return; }, # no definite imperative
66             },
67             buprilise => {
68             demeric => \&budemeric,
69             scrifel => \&buscrifel,
70             izhcrifel => sub { return; }, # no remote past anterior
71             befel => \&bubefel,
72             },
73             },
74             # dynamic => \&dynamic
75             dynamic => {
76             prilise => {
77             demeric => sub { dynamic( $_[0], 'prilise', 'demeric' ); },
78             scrifel => sub { dynamic( $_[0], 'prilise', 'scrifel' ); },
79             izhcrifel => sub { dynamic( $_[0], 'prilise', 'izhcrifel' ); },
80             befel => sub { return; }, # no definite imperative
81             },
82             buprilise => {
83             demeric => sub { dynamic( $_[0], 'buprilise', 'demeric' ); },
84             scrifel => sub { dynamic( $_[0], 'buprilise', 'scrifel' ); },
85             izhcrifel => sub { return; }, # no remote past anterior
86             befel => \&bubefel, # same for static and dynamic aspects
87             },
88             },
89             part => \&part,
90             );
91              
92             # Set up aliases
93             {
94             my($aspect, $mood, $tense);
95              
96             $verb{'nuncre'} = $verb{'static'};
97             $verb{'olocec'} = $verb{'dynamic'};
98              
99             for $aspect (qw(static dynamic)) {
100             $verb{$aspect}{definite} = $verb{$aspect}{prilise};
101             $verb{$aspect}{remote} = $verb{$aspect}{buprilise};
102              
103             for $mood (qw(prilise buprilise)) {
104             $verb{$aspect}{$mood}{'present'} = $verb{$aspect}{$mood}{demeric};
105             $verb{$aspect}{$mood}{'past'} = $verb{$aspect}{$mood}{scrifel};
106             $verb{$aspect}{$mood}{'pastanterior'} =
107             $verb{$aspect}{$mood}{'past anterior'} = $verb{$aspect}{$mood}{izhcrifel};
108             $verb{$aspect}{$mood}{'imperative'} = $verb{$aspect}{$mood}{befel};
109             }
110              
111             for $tense (qw(demeric scrifel izhcrifel
112             present past pastanterior), 'past anterior') {
113             $verb{$aspect}{$tense} = $verb{$aspect}{definite}{$tense};
114             }
115              
116             for $tense (qw(befel imperative)) {
117             $verb{$aspect}{$tense} = $verb{$aspect}{remote}{$tense};
118             }
119             }
120              
121             for $mood (qw(prilise buprilise definite remote)) {
122             $verb{$mood} = $verb{static}{$mood};
123             }
124              
125             for $tense (qw(demeric scrifel izhcrifel
126             present past pastanterior), 'past anterior') {
127             $verb{$tense} = $verb{static}{definite}{$tense};
128             }
129              
130             for $tense (qw(befel imperative)) {
131             $verb{$tense} = $verb{static}{remote}{$tense};
132             }
133             }
134              
135              
136             # Verbs borrowed form other languages, and thus not subject to
137             # stem-changing rules
138             my %borrowed = (
139             'DEBUTAN' => 1, # Mark says these two don't change;
140             'NACITAN' => 1, # however, I don't know why not.
141             'ONOTER' => 'Cuêzi o:inote',
142             );
143              
144             # Fricativised versions of consonants
145             my %fric = (
146             'T' => 'TH',
147             'D' => 'DH',
148             'P' => 'F',
149             );
150              
151             my $far = qr/^FAR$/;
152             my $kes = qr/^KES$/;
153             my $nen = qr/^NEN$/;
154              
155             my @persons = qw(SEO LET TU TAS MUKH CAI);
156              
157             my @cases = qw(nom gen acc dat abl);
158              
159             my @numbers = qw(sing pl);
160              
161             my %present = (
162             EC => [ qw( AO EOS ES OM OUS ONT ) ],
163             AN => [ qw( AI EIS ET AM US ONT ) ],
164             EN => [ qw( AI EIS ET EM ES ENT ) ],
165             ER => [ qw( U EUS ET UM US UNT ) ],
166             IR => [ qw( U EUS IT UM US INT ) ],
167             dyn => [ qw( UI UIS UT IM IS INT ) ],
168             );
169              
170             my %past = (
171             EC => [ qw( I IUS U UM US IUNT ) ],
172             AN => [ qw( IO IOS AE UOM UOS IONT ) ],
173             EN => [ qw( IO IOS AE UOM UES IONT ) ],
174             ER => [ qw( IE IES E EM ES IENT ) ],
175             IR => [ qw( IE IES AE EM ES IENT ) ],
176             );
177              
178              
179             my %demeric = (
180             ESAN => [ qw( SAI SEIS ES ESAM ESOS SONT ) ],
181             EPESAN => [ qw( EUSAI EUSEIS EPES EPESAM EPESOS EUSONT ) ],
182             CTANEN => [ qw( CTAI CTES CTET CTANAM CTANUS CTANONT ) ],
183             # FAR => [ qw( FAEO FAES FAET FASCOM FASCOUS FASCONT ) ],
184             FAR => [ qw( FAEU FAES FAET FASCOM FASCOUS FASCONT ) ],
185             IUSIR => [ qw( IUSU IUS IUT IUSUM IUSUS IUINT ) ],
186             LIUBEC => [ qw( LIUO LIUOS LIUS LIUBOM LIUBOUS LIUBONT ) ],
187             KETHEN => [ qw( KETHUI KETHUS KETHUT KETHEM KETHES KENT ) ],
188             CULLIR => [ qw( CULLU CULS CULT CULLUM CULLUS CULLINT ) ],
189             OHIR => [ qw( OHU UIS UIT OHUM OHUS OHINT ) ],
190             SCRIFEC => [ qw( SCRIFAO SCRIS SCRIT SCRIFOM SCRIFOUS SCRIFONT ) ],
191             NEN => [ qw( NEI NIS NIT NESEM NESES NENT ) ],
192             KES => [ qw( KEAI KIES KIET KEHAM KEHUS KEHONT ) ],
193             # VOLIR => [ qw( VULU VUIS VUIT VOLUM VOLUS VOLINT ) ],
194             VOLIR => [ qw( VULU VULS VULT VOLUM VOLUS VOLINT ) ],
195             FAUCIR => [ qw( FAU FEUS FEUT FAUCUM FAUCUS FAUCINT ) ],
196             FAILIR => [ qw( FAILU FELS FELT FAILUM FAILUS FAILINT ) ],
197             );
198              
199             sub demeric {
200 39     39 1 93 my $verb = shift;
201 39         60 my $stem = $verb;
202 39         48 my $table;
203              
204 39 100       259 return $demeric{$verb} if exists $demeric{$verb};
205              
206             ENDING:
207 16         52 for my $ending ( keys %present ) {
208 64 100       139 if(substr($stem, -2, 2) eq $ending) {
209 16         23 substr($stem, -2, 2) = '';
210 16         23 $table = [ map "$stem$_", @{$present{$ending}} ];
  16         121  
211 16         48 last ENDING;
212             }
213             }
214              
215             # Stem change
216 16 50 66     102 if($verb =~ /[AEIOU][TDP][IE]R$/ && !exists $borrowed{$verb} &&
      33        
      66        
217             ($verb !~ /ATIR$/ || $verb eq 'CLATIR')) {
218 6         11 for(@$table) {
219 36         163 s/([TDP])(U(?:[MS]|NT)?)$/$fric{$1}$2/;
220             }
221             }
222              
223 16         98 return $table;
224             }
225              
226             my %scrifel = (
227             ESAN => [ qw( FUIO FUIOS FUAE FUOM FUOS FUNT ) ],
228             EPESAN => [ qw( EUSIO EUSIOS EPAE EUSUOM EUSUOS EUSIONT ) ],
229             # KETHEN => [ qw( KIO/KETHIO KETHIOS KIAE KETHUOM KETHUES KIONT ) ],
230             KETHEN => [ qw( KIO/KETHIO KETHIOS KIAE KETHUOM KETHUES KETHIONT ) ],
231             NEN => [ qw( NIO NIOS NAE NESUOM NESUES NIONT ) ],
232              
233             # semi-regular: FAR is like FASCEC, KES like KAIVAN
234             FAR => [ qw( FASCI FASCIUS FASCU FASCUM FASCUS FASCIUNT ) ],
235             KES => [ qw( KAIVIO KAIVIOS KAIVAE KAIVUOM KAIVUOS KAIVIONT ) ],
236             );
237              
238             sub scrifel {
239 26     26 1 55 my $verb = shift;
240 26         37 my $stem = $verb;
241 26         28 my $table;
242              
243 26 100       104 return $scrifel{$verb} if exists $scrifel{$verb};
244              
245             ENDING:
246 22         69 for my $ending ( keys %past ) {
247 74 100       160 if(substr($stem, -2, 2) eq $ending) {
248 22         34 substr($stem, -2, 2) = '';
249 22         27 $table = [ map "$stem$_", @{$past{$ending}} ];
  22         175  
250 22         53 last ENDING;
251             }
252             }
253              
254             # Stem change
255 22 100 66     108 if($verb =~ /[AEIOU][TDP]EC$/ && !exists $borrowed{$verb}) {
256 4         10 for(@$table) {
257 24         105 s/([TDP])(U[MS]?)$/$fric{$1}$2/;
258             }
259             }
260              
261 22         125 return $table;
262             }
263              
264             my %izhcrifel = (
265             ESAN => [ qw( FURIO FURIOS FURAE FUROM FUROS FURIONT ) ],
266             EPESAN => [ qw( EUSERIO EUSERIOS EPERAE EUSEROM EUSEROS EUSERIONT ) ],
267             );
268              
269             sub izhcrifel {
270 119     119 1 255 my $verb = shift;
271 119         193 my $stem = $verb;
272 119         142 my $table;
273              
274 119 100       425 return $izhcrifel{$verb} if exists $izhcrifel{$verb};
275              
276 117 100 66     2814 if($stem =~ s/$far/FASCER/o ||
    100 100        
    100 66        
    100 100        
    50 66        
      100        
      100        
      66        
277             $stem =~ s/([BPDTGKCFVRSZMNL]|[TDK]?H)REC$/$1$1ER/ ||
278             $stem =~ s/EC$/ER/) {
279 36         44 $table = [ map "$stem$_", @{$past{EC}} ];
  36         272  
280             } elsif($stem =~ s/$kes/KAIVER/o ||
281             $stem =~ s/([BPDTGKCFVRSZMNL]|[TDK]?H)RAN$/$1$1ER/ ||
282             $stem =~ s/AN$/ER/) {
283 20         34 $table = [ map "$stem$_", @{$past{AN}} ];
  20         182  
284 20         71 for(@$table) {
285 120         207 s/UOM$/OM/;
286 120         233 s/UOS$/OS/;
287             }
288             } elsif($stem =~ s/$nen/NESER/o ||
289             $stem =~ s/([BPDTGKCFVRSZMNL]|[TDK]?H)REN$/$1$1ER/ ||
290             $stem =~ s/EN$/ER/) {
291 20         28 $table = [ map "$stem$_", @{$past{EN}} ];
  20         166  
292 20         48 for(@$table) {
293 120         204 s/UOM$/OM/;
294 120         222 s/UES$/ES/;
295             }
296             } elsif($stem =~ s/([BPDTGKCFVRSZMNL]|[TDK]?H)RER$/$1$1IR/ ||
297             $stem =~ s/ER$/IR/) {
298 20         28 $table = [ map "$stem$_", @{$past{ER}} ];
  20         160  
299 20         116 s/U(O[SM])$/$1/ for @$table;
300             } elsif($stem =~ s/([BPDTGKCFVRSZMNL]|[TDK]?H)RIR$/$1$1IR/ ||
301             $stem =~ m/IR$/) {
302 21         26 $table = [ map "$stem$_", @{$past{IR}} ];
  21         130  
303 21         107 s/U(ES|OM)$/$1/ for @$table;
304             } else {
305 0         0 return;
306             }
307              
308 117         792 return $table;
309             }
310              
311             sub budemeric {
312 42     42 1 96 my $verb = shift;
313 42         64 my $stem = $verb;
314              
315 42 100       129 return [ map "EST$_", qw( AO EIS ES OM OS ONT ) ] if $verb eq 'ESAN';
316              
317 41 100 100     1857 if($stem =~ s/$far/FASS/o ||
    100 100        
    100 100        
    100 100        
    100 100        
    100 100        
    100 100        
    100 100        
    100 100        
    50 100        
      100        
      100        
      100        
      100        
      100        
      100        
      100        
      66        
      66        
318             $stem =~ s/^CURREC$/CORS/) {
319 2         4 return [ map "$stem$_", @{$present{EC}} ];
  2         29  
320             } elsif($stem =~ s/^METTAN$/MESS/ ||
321             $stem =~ s/^DAN$/DON/ ||
322             $stem =~ s/^PU([GH])AN$/PO$1/ ||
323             $stem =~ s/^BRIGAN$/BROG/ ||
324             $stem =~ s/^SUBRAN$/SOBR/ ||
325             $stem =~ s/^LEGAN$/LOG/ ||
326             $stem =~ s/^LAUDAN$/LOD/ ||
327             $stem =~ s/^KUSAN$/KOSS/) {
328 9         14 return [ map "$stem$_", @{$present{AN}} ];
  9         112  
329             } elsif($stem =~ s/^([DKL]E|TO)SCEN$/$1SS/ ||
330             $stem =~ s/^(DES|FER)IEN$/$1S/ ||
331             $stem =~ s/^LEILEN$/LELS/ ||
332             $stem =~ s/^KETHEN$/KOTH/) {
333 7         12 return [ map "$stem$_", @{$present{EN}} ];
  7         158  
334             } elsif($stem =~ s/^([SV])ALTER$/$1ELS/ ||
335             $stem =~ s/^STERER$/STERS/ ||
336             $stem =~ s/^NOER$/NOS/) {
337 4         10 return [ map "$stem$_", @{$present{ER}} ];
  4         55  
338             } elsif($stem =~ s/^MERIR$/MERS/ ||
339             $stem =~ s/^NURIR$/NORS/ ||
340             $stem =~ s/^AMARIR$/AMERS/ ||
341             $stem =~ s/^DUCIR$/DOC/ ||
342             $stem =~ s/^IUSIR$/IOSS/) {
343 5         9 return [ map "$stem$_", @{$present{IR}} ];
  5         68  
344             } elsif($stem =~ s/EC$/ET/) {
345 6         77 return [ map "$stem$_", qw( AO EIS ES OM OS ONT ) ];
346             } elsif($stem =~ s/$kes/KAIVEM/o ||
347             $stem =~ s/AN$/EM/) {
348 2         32 return [ map "$stem$_", qw( AI ES ET AM US ONT ) ];
349             } elsif($stem =~ s/$nen/NESEM/o ||
350             $stem =~ s/EN$/EM/) {
351 2         35 return [ map "$stem$_", qw( AI ES ET EM ES ENT ) ];
352             } elsif($stem =~ s/ER$/ET/) {
353 2         30 return [ map "$stem$_", qw( U OS IS UM US UNT ) ];
354             } elsif($stem =~ s/IR$/ET/) {
355 2         31 return [ map "$stem$_", qw( U OS IS UM US INT ) ];
356             } else {
357 0         0 return;
358             }
359             }
360              
361             sub buscrifel {
362 79     79 1 208 my $verb = shift;
363 79         144 my $stem = $verb;
364              
365 79 100       317 return [ map "ESC$_", qw( AO EIS ES OM OS ONT ) ] if $verb eq 'ESAN';
366              
367 78 100 100     4834 if($stem =~ s/$far/FASS/o ||
    100 100        
    100 100        
    100 100        
    100 100        
    100 100        
    100 100        
    100 100        
    100 100        
    50 100        
      100        
      100        
      100        
      100        
      100        
      100        
      100        
      66        
      66        
      100        
      66        
368             $stem =~ s/^CURREC$/CORS/) {
369 2         6 return [ map "$stem$_", @{$past{EC}} ];
  2         34  
370             } elsif($stem =~ s/^METTAN$/MESS/ ||
371             $stem =~ s/^DAN$/DON/ ||
372             $stem =~ s/^PU([GH])AN$/PO$1/ ||
373             $stem =~ s/^BRIGAN$/BROG/ ||
374             $stem =~ s/^SUBRAN$/SOBR/ ||
375             $stem =~ s/^LEGAN$/LOG/ ||
376             $stem =~ s/^LAUDAN$/LOD/ ||
377             $stem =~ s/^KUSAN$/KOSS/) {
378 9         18 return [ map "$stem$_", @{$past{AN}} ];
  9         134  
379             } elsif($stem =~ s/^([DKL]E|TO)SCEN$/$1SS/ ||
380             $stem =~ s/^(DES|FER)IEN$/$1S/ ||
381             $stem =~ s/^LEILEN$/LELS/ ||
382             $stem =~ s/^KETHEN$/KOTH/) {
383 7         12 return [ map "$stem$_", @{$past{EN}} ];
  7         102  
384             } elsif($stem =~ s/^([SV])ALTER$/$1ELS/ ||
385             $stem =~ s/^STERER$/STERS/ ||
386             $stem =~ s/^NOER$/NOS/) {
387 4         11 return [ map "$stem$_", @{$past{ER}} ];
  4         62  
388             } elsif($stem =~ s/^MERIR$/MERS/ ||
389             $stem =~ s/^NURIR$/NORS/ ||
390             $stem =~ s/^AMARIR$/AMERS/ ||
391             $stem =~ s/^DUCIR$/DOC/ ||
392             $stem =~ s/^IUSIR$/IOSS/) {
393 5         8 return [ map "$stem$_", @{$past{IR}} ];
  5         72  
394             } elsif($stem =~ m/EC$/) {
395 6         86 return [ map "$stem$_", qw( AO EIS ES OM OS ONT ) ];
396             } elsif($stem =~ s/$kes/KAIVIN/o ||
397             $stem =~ s/AN$/IN/) {
398 2         31 return [ map "$stem$_", qw( AI ES ET AM US ONT ) ];
399             } elsif($stem =~ s/$nen/NESIN/o ||
400             $stem =~ s/EN$/IN/) {
401 2         32 return [ map "$stem$_", qw( AI ES ET EM ES ENT ) ];
402             } elsif($stem =~ s/([BPDTGKCFVRSZMNL]|[TDK]?H)RER$/$1$1IR/ ||
403             $stem =~ s/ER$/IR/) {
404 20         267 return [ map "$stem$_", qw( U OS IS UM US UNT ) ];
405             } elsif($stem =~ s/([BPDTGKCFVRSZMNL]|[TDK]?H)RIR$/$1$1IR/ ||
406             $stem =~ m/IR$/) {
407 21         310 return [ map "$stem$_", qw( U OS IS UM US INT ) ];
408             } else {
409 0         0 return;
410             }
411             }
412              
413             sub bubefel {
414 34     34 1 70 my $verb = shift;
415 34         56 my $stem = $verb;
416              
417 34 100 33     1206 if($stem =~ s/$far/FASS/o ||
    100 66        
    100 33        
    100 33        
    50 33        
      33        
      33        
      33        
      66        
      66        
      100        
      33        
      33        
      33        
      33        
      66        
      33        
      33        
      66        
      33        
      33        
      33        
      33        
      33        
418             $stem =~ s/^CURREC$/CORS/ ||
419             $stem =~ s/EC$//) {
420 16         180 return [ undef, map ( "$stem$_", qw( E UAS ) ),
421             undef, map ( "$stem$_", qw( EL UANT ) ) ];
422             } elsif($stem =~ s/$kes/KAIV/o ||
423             $stem =~ s/^METTAN$/MESS/ ||
424             $stem =~ s/^DAN$/DON/ ||
425             $stem =~ s/^PU([GH])AN$/PO$1/ ||
426             $stem =~ s/^BRIGAN$/BROG/ ||
427             $stem =~ s/^SUBRAN$/SOBR/ ||
428             $stem =~ s/^LEGAN$/LOG/ ||
429             $stem =~ s/^LAUDAN$/LOD/ ||
430             $stem =~ s/^KUSAN$/KOSS/ ||
431             $stem =~ s/AN$//) {
432 6         88 return [ undef, map ( "$stem$_", qw( I UAT ) ),
433             undef, map ( "$stem$_", qw( IL UANT ) ) ];
434             } elsif($stem =~ s/$nen/NES/o ||
435             $stem =~ s/^([DKL]E|TO)SCEN$/$1SS/ ||
436             $stem =~ s/^(DES|FER)IEN$/$1S/ ||
437             $stem =~ s/^LEILEN$/LELS/ ||
438             $stem =~ s/^KETHEN$/KOTH/ ||
439             $stem =~ s/EN$//) {
440 4         51 return [ undef, map ( "$stem$_", qw( I UAT ) ),
441             undef, map ( "$stem$_", qw( IL UANT ) ) ];
442             } elsif($stem =~ s/^([SV])ALTER$/$1ELS/ ||
443             $stem =~ s/^STERER$/STERS/ ||
444             $stem =~ s/^NOER$/NOS/ ||
445             $stem =~ s/ER$//) {
446 4         54 return [ undef, map ( "$stem$_", qw( U AS ) ),
447             undef, map ( "$stem$_", qw( UL ANT ) ) ];
448             } elsif($stem =~ s/^MERIR$/MERS/ ||
449             $stem =~ s/^NURIR$/NORS/ ||
450             $stem =~ s/^AMARIR$/AMERS/ ||
451             $stem =~ s/^DUCIR$/DOC/ ||
452             $stem =~ s/^IUSIR$/IOSS/ ||
453             $stem =~ s/IR$//) {
454 4         47 return [ undef, map ( "$stem$_", qw( U UAT ) ),
455             undef, map ( "$stem$_", qw( UL UANT ) ) ];
456             } else {
457 0         0 return;
458             }
459             }
460              
461              
462             my %dyntense = (
463             demeric => 'demeric',
464             present => 'demeric',
465              
466             scrifel => 'scrifel',
467             past => 'scrifel',
468              
469             izhcrifel => 'izhcrifel',
470             pastanterior => 'izhcrifel',
471             'past anterior' => 'izhcrifel',
472              
473             befel => 'befel',
474             imperative => 'befel',
475             );
476              
477             my %dynmood = (
478             prilise => 'prilise',
479             definite => 'prilise',
480              
481             buprilise => 'buprilise',
482             remote => 'buprilise',
483             );
484              
485             sub dynamic {
486 117     117 1 333 my($verb, $mood, $tense) = @_;
487 117         173 my $stem = $verb;
488 117         165 my $table;
489              
490 117 50 33     1728 if($stem =~ s/$far/FASC/o ||
      33        
      33        
491             $stem =~ s/$nen/NES/o ||
492             $stem =~ s/$kes/KAIV/o ||
493             $stem =~ s/(?:EC|[AE]N|[EI]R)$//) {
494 117 100       378 if($dynmood{$mood} eq 'prilise') {
    50          
495 64 50 100     313 return unless $dyntense{$tense} eq 'demeric' ||
      66        
496             $dyntense{$tense} eq 'scrifel' ||
497             $dyntense{$tense} eq 'izhcrifel';
498 64 100       145 $stem .= 'EV' if $dyntense{$tense} eq 'scrifel';
499 64 100       186 $stem .= 'ER' if $dyntense{$tense} eq 'izhcrifel';
500 64         80 $table = [ map "$stem$_", @{$present{dyn}} ];
  64         513  
501             } elsif($dynmood{$mood} eq 'buprilise') {
502 53 50 100     309 return unless $dyntense{$tense} eq 'demeric' ||
      66        
503             $dyntense{$tense} eq 'scrifel' ||
504             $dyntense{$tense} eq 'befel';
505 53 100       188 if($dyntense{$tense} eq 'demeric') {
    100          
    50          
506 30         259 $table = [ map "$stem$_", qw( I IS UAT UAM UAS UANT ) ];
507             } elsif($dyntense{$tense} eq 'scrifel') {
508 12         21 $stem .= 'IS';
509 12         102 $table = [ map "$stem$_", qw( I US AT AM AS ANT ) ];
510             } elsif($dyntense{$tense} eq 'befel') {
511             # imperative is the same for static and dynamic forms
512 11         37 $table = bubefel($verb);
513             } else {
514 0         0 return;
515             }
516             } else {
517 0         0 return;
518             }
519             } else {
520 0         0 return;
521             }
522              
523             # Stem change
524 117 50 100     1036 if($dyntense{$tense} ne 'befel' && # imperative endings don't trigger
      66        
      33        
      66        
525             # sound changes
526             $verb =~ /[AEIOU][TDP](?:[IE]R|[AE]N|EC)$/ && !exists $borrowed{$verb} &&
527             ($verb !~ /ATIR$/ || $verb eq 'CLATIR')) {
528 36         81 for(@$table) {
529             # UI UIS UT UAT UAM UAS UANT
530 216         1087 s/([TDP])(U(?:IS?|T|A(?:[SMT]|NT)))$/$fric{$1}$2/;
531             }
532             }
533              
534 117         774 return $table;
535             }
536              
537             sub part {
538 11     11 1 30 my $verb = shift;
539 11         25 for($verb) {
540 11         27 s/$far/FASCEC/o;
541 11         22 s/$nen/NESEN/o;
542 11         34 s/$kes/KAIVAN/o;
543             }
544              
545 11         30 my($present, $past, $gerund) = ($verb) x 3;
546              
547 11 50       54 return unless $verb =~ /(?:EC|[AE]N|[EI]R)$/;
548              
549 11         19 for($present) {
550 11 100 100     103 s/EC$/ILES/ || s/IR$/IC/ || s/(?:ER|[AE]N)$/EC/;
551             }
552              
553 11         24 for($past) {
554 11 100       66 s/E[CR]$/EL/ || s/(?:[AE]N|IR)$/UL/;
555             }
556              
557 11         21 for($gerund) {
558 11 100       60 s/E[CR]$/IM/ || s/(?:[AE]N|IR)$/AUM/;
559             }
560              
561 11 100       96 return wantarray ? ($present, $past, $gerund) : [ $present, $past, $gerund ];
562             }
563              
564              
565              
566             my %masc = (
567             );
568              
569             my %neut = (
570             ATITRIS => 'atüchy',
571             CRENIS => 'iscreniy',
572             DACTIS => 'dazhy',
573             DROGIS => 'drozhy',
574             FILIS => 'fiy',
575             FUELIS => 'föy',
576             ISCRENILIS => 'iscreniy',
577             IULIS => 'zhuy',
578             KATTIS => 'katy',
579             KILIS => 'ciy',
580             KRAIS => 'rhay',
581             LENTILIS => 'lëtiy',
582             LITIS => 'lichy',
583             LOIS => 'loy',
584             MEIS => 'mey',
585             MIHIS => 'miy',
586             MILGIS => 'mily',
587             MITIS => 'michy',
588             NACUIS => 'nacuy',
589             NMURTHANIS => 'múrtany',
590             NOTHONIS => 'nodhony',
591             OBELIS => 'obly',
592             ORAIS => 'oray',
593             PENGIS => 'peny',
594             PLASIS => 'plasy',
595             RAIS => 'ray',
596             SABLIS => 'sably',
597             SCRAIS => 'shray',
598             SEGLIS => 'segly',
599             SPAIS => 'sfay',
600             SUIS => 'suy',
601             VELAIS => 'vlay',
602             ZURRIS => 'zury',
603             );
604              
605             my %noun = (
606             # personal pronouns
607             SEO => [ qw( SEO EAE ETH SEON ED TAS TAIE TAIM TAUN TAD ) ],
608             LET => [ qw( LET LEAE EK LUN LETH MUKH MUIE MUIM MUIN MUOTH ) ],
609             TU => [ qw( TU TUAE TUA TUN TOTH CAI CAIE CAIM CAIN CAITH ) ],
610             ZE => [ undef, qw( ZEHIE ZETH ZEHUN ZEHOTH ),
611             undef, qw( ZAHIE ZAHAM ZAHAN ZAHATH ) ],
612             TAS => [ qw( TAS TAIE TAIM TAUN TAD ), (undef) x 5 ],
613             MUKH => [ qw( MUKH MUIE MUIM MUIN MUOTH ), (undef) x 5 ],
614             CAI => [ qw( CAI CAIE CAIM CAIN CAITH ), (undef) x 5 ],
615             ZA => [ undef, qw( ZAHIE ZAHAM ZAHAN ZAHATH ), (undef) x 5 ],
616              
617             # possessive adjectives:
618             # SEO -> ERIS
619             # LET -> LERIS
620             # TU -> TURIS
621             # TAS -> TANDES
622             # MUKH -> MUNDES
623             # CAI -> CAIRIS
624              
625             # pointers
626             AELU => [ qw( AELU AELUI AELETH AELUN AELOTH ), (undef) x 5 ],
627             AELO => [ qw( AELO AELOI AELOR AELON AELOTH ), (undef) x 5 ],
628             AELA => [ qw( AELA AELAE AELEA AELAN AELAD ), (undef) x 5 ],
629              
630             ILLU => [ qw( ILLU ILLUI ILLETH ILLUN ILLOTH ), (undef) x 5 ],
631             ILLO => [ qw( ILLO ILLOI ILLO ILLON ILLOTH ), (undef) x 5 ],
632             ILLA => [ qw( ILLA ILLAE ILLEA ILLAN ILLAD ), (undef) x 5 ],
633              
634             AETTOS => [ qw( AETTOS AETTEI AETTOT AETTAN AETTOTH ), (undef) x 5 ],
635             # TOTOS actually conjugates like a regular masculine noun, but I'm keeping
636             # it here with its relatives
637             TOTOS => [ qw( TOTOS TOTEI TOT TOTAN TOTOTH ), (undef) x 5 ],
638              
639             # AECTA and CESTA are like feminine nouns
640              
641             # question words
642             KAE => [ qw( KAE KAIE KAETH KAEN KAETH KAHE KAHIE KAHAM KAHAN KAHATH ) ],
643             KETTOS => [ qw( KETTOS KETTEI KETTOT KETTAN KETTOTH ), (undef) x 5 ],
644             # older forms:
645             # KESTU => [ qw( KESTU KEISE KEISAM KEISAN KEISE ), (undef) x 5 ],
646             KEDIE => [ qw( KEDIE KEDIEI KEDIA KEDIEN KEDID ), (undef) x 5 ],
647              
648             # quantity words
649             NIKTOS => [ qw( NIKTOS NIKTEI NIKTOT NIKTAN NIKTOTH ), (undef) x 5 ],
650             NISIOS => [ qw( NISIOS NISIEI NISIOT NISIAN NISIOTH ), (undef) x 5 ],
651             THISIOS => [ qw( THISIOS THISIEI THISIOT THISIAN THISIOTH ), (undef) x 5 ],
652              
653             PSIAT => [ qw( PSIAT PSIE PSIAT PSIAN PSIAD ), (undef) x 5 ],
654              
655             NIES => [ qw( NIES NIEI NIET NIEN NIETH ), (undef) x 5 ],
656             PSIES => [ qw( PSIES PSIEI PSIET PSIEN PSIETH ), (undef) x 5 ],
657              
658             THIKEDIE => [ qw( THIKEDIE THIKEDIEI THIKEDIA THIKEDIEN THIKEDID ), (undef) x 5 ],
659              
660             # NIKUDA and PSUDA are like feminine nouns
661             );
662              
663             sub noun {
664 78     78 1 217 my $noun = shift;
665 78         171 my $stem = $noun;
666 78         142 my $type = 'fem';
667 78         126 my $table;
668              
669 78 50       271 $type = 'masc' if exists $masc{$noun};
670 78 100       262 $type = 'neut' if exists $neut{$noun};
671              
672 78 100       571 return $noun{$noun} if exists $noun{$noun};
673              
674 56 100 66     939 if($stem =~ s/OS$//) {
    100 66        
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
675 2         23 $table = [ map "$stem$_", 'OS', 'EI', '', qw( AN OTH IT IE I IN ITH ) ];
676             } elsif($stem =~ s/AS$//) {
677 2         25 $table = [ map "$stem$_", qw( AS AI A AN ATH AIT AIE AI AIN AITH ) ];
678             } elsif($stem =~ s/O$//) {
679 2         22 $table = [ map "$stem$_", qw( O OI OM ON OTH OI OIE OIM OIN OITH ) ];
680             } elsif($stem =~ s/U$//) {
681 2         23 $table = [ map "$stem$_", qw( U UI UM UN UTH UI UIE UIM UIN UITH ) ];
682             } elsif($type eq 'neut' && $stem =~ s/IS$//) {
683 34         386 $table = [ map "$stem$_", qw( IS II IM IN ITH UI UIE UIM UIN UITH ) ];
684             } elsif($stem =~ s/US$//) {
685 2         23 $table = [ map "$stem$_", qw( US OI O UN UTH UIT UIE UI UIN UITH ) ];
686             } elsif($stem =~ s/A$//) {
687 6         67 $table = [ map "$stem$_", qw( A AE AA AN AD ET EIE EIM EIN EID ) ];
688             } elsif($stem =~ s/E$//) {
689 2         25 $table = [ map "$stem$_", qw( E EI EA EN ED ET EIE EIM EIN EID ) ];
690             } elsif($type eq 'fem' && $stem =~ s/IS$//) {
691 2         23 $table = [ map "$stem$_", qw( IS IE IA IN ID IAT IAE IAM IAN IAD ) ];
692             } elsif($stem =~ m/[PBTDHCGKFVSZMNLR]$/) {
693 2         26 $table = [ map "$stem$_", '', 'EI', '', qw( AN OTH IT IE I IN ITH ) ];
694             } else {
695 0         0 return;
696             }
697              
698 56         486 return $table;
699             }
700              
701             my %adj = (
702             AELU => [ [ qw( AELU AELUI AELETH AELUN AELOTH ), (undef) x 5 ],
703             [ qw( AELO AELOI AELOR AELON AELOTH ), (undef) x 5 ],
704             [ qw( AELA AELAE AELEA AELAN AELAD ), (undef) x 5 ], ],
705              
706             ILLU => [ [ qw( ILLU ILLUI ILLETH ILLUN ILLOTH ), (undef) x 5 ],
707             [ qw( ILLO ILLOI ILLO ILLON ILLOTH ), (undef) x 5 ],
708             [ qw( ILLA ILLAE ILLEA ILLAN ILLAD ), (undef) x 5 ], ],
709             );
710              
711             sub adj {
712 8     8 1 29 my $adj = shift;
713 8         16 my $stem = $adj;
714 8         13 my $table;
715              
716 8 100       62 return $adj{$adj} if exists $adj{$adj};
717              
718 6 100       88 if($stem =~ s/ES$//) {
    100          
    50          
719 2         57 $table = [ [ map "$stem$_", qw( ES EI E EN ETH EIT EIE EI EIN EITH ) ],
720             [ map "$stem$_", qw( E EI EM EN ETH EI EIE EIM EIN EITH ) ],
721             [ map "$stem$_", qw( IES IAE EA EN ED ET EIE EIM EIN EID ) ] ];
722             } elsif($stem =~ s/IS$//) {
723 2         51 $table = [ [ map "$stem$_", qw( IS II I IN ITH UIT UIE UI UIN UITH ) ],
724             [ map "$stem$_", qw( IS II IM IN ITH UI UIE UIM UIN UITH ) ],
725             [ map "$stem$_", qw( IS IE IA IN ID IAT IAE IAM IAN IAD ) ] ];
726             } elsif($stem =~ m/[PBTDHCGKFVSZMNLR]$/) {
727 2         50 $table = [ [ map "$stem$_", '', 'EI', '', qw( AN OTH IT IE I IN ITH ) ],
728             [ map "$stem$_", qw( O OI OM ON OTH OI OIE OIM OIN OITH ) ],
729             [ map "$stem$_", qw( A AE AA AN AD ET EIE EIM EIN EID ) ] ];
730             } else {
731 0         0 return;
732             }
733              
734 6         92 return $table;
735             }
736              
737              
738             my %comp = (
739             MELIS => 'MELIOR',
740             DURENGES => 'AVECOR',
741             );
742              
743             sub comp {
744 8     8 1 21 my $adj = shift;
745 8         15 my $stem = $adj;
746              
747 8 100       31 return $comp{$adj} if exists $comp{$adj};
748              
749 6 100       45 if($stem =~ s/ES$//) {
    100          
    50          
750 2         16 return $stem . 'EDHES';
751             } elsif($stem =~ s/IS$//) {
752 2         11 return $stem . 'IOR';
753             } elsif($stem =~ m/[PBTDHCGKFVSZMNLR]$/) {
754 2         15 return $stem . 'OR';
755             } else {
756 0         0 return;
757             }
758             }
759              
760              
761             my %super = (
762             MELIS => 'MELASTES',
763             DURENGES => 'AVESTES',
764             );
765              
766             sub super {
767 8     8 1 17 my $adj = shift;
768 8         12 my $stem = $adj;
769              
770 8 100       33 return $super{$adj} if exists $super{$adj};
771              
772 6 100       38 if($stem =~ s/ES$//) {
    100          
    50          
773 2         10 return $stem . 'ASCES';
774             } elsif($stem =~ s/IS$//) {
775 2         12 return $stem . 'ISCES';
776             } elsif($stem =~ m/[PBTDHCGKFVSZMNLR]$/) {
777 2         13 return $stem . 'ASTES';
778             } else {
779 0         0 return;
780             }
781             }
782              
783              
784             my %adv = (
785             MELIS => 'MELIO',
786             DURENGES => 'AVECUE',
787             );
788              
789             sub adv {
790 13     13 1 30 my $adj = shift;
791 13         19 my $stem = $adj;
792              
793 13 100       55 return $adv{$adj} if exists $adv{$adj};
794              
795 11 100       77 if($stem =~ s/ES$//) {
    100          
    50          
796 4         22 return $stem . 'ECUE';
797             } elsif($stem =~ s/IS$//) {
798 4         24 return $stem . 'ICUE';
799             } elsif($stem =~ m/[PBTDHCGKFVSZMNLR]$/) {
800 3         21 return $stem . 'A';
801             } else {
802 0           return;
803             }
804             }
805              
806              
807             1;
808             __END__