latinverb 0.2.0 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. data/.gitignore +0 -1
  2. data/Gemfile +1 -2
  3. data/README.markdown +54 -240
  4. data/etc/irreg_skel.json +104 -0
  5. data/{latinirb.gemspec → latinverb.gemspec} +4 -4
  6. data/lib/latinverb/chart.rb +94 -0
  7. data/lib/latinverb/version.rb +10 -0
  8. data/lib/latinverb.rb +710 -0
  9. data/lib/linguistics/latin/verb/classification_types.rb +59 -0
  10. data/lib/linguistics/latin/verb/constants.rb +201 -0
  11. data/lib/linguistics/latin/verb/deponent_tense_methods.rb +98 -0
  12. data/lib/linguistics/latin/verb/infinitives.rb +212 -0
  13. data/lib/linguistics/latin/verb/irregulars.rb +4393 -0
  14. data/lib/linguistics/latin/verb/latinverb/auxiliary_classes.rb +208 -0
  15. data/lib/linguistics/latin/verb/latinverb/classmethods.rb +215 -0
  16. data/lib/linguistics/latin/verb/latinverb/data.rb +90 -0
  17. data/lib/linguistics/latin/verb/latinverb/display.rb +23 -0
  18. data/lib/linguistics/latin/verb/latinverb/metaprogramming.rb +79 -0
  19. data/lib/linguistics/latin/verb/latinverb/validation.rb +66 -0
  20. data/lib/linguistics/latin/verb/participles.rb +202 -0
  21. data/lib/linguistics/latin/verb/phonographia.rb +109 -0
  22. data/lib/linguistics/latin/verb/supine.rb +42 -0
  23. data/lib/linguistics/latin/verb/tense_methods.rb +950 -0
  24. data/test/testAmbiguousLookups.rb +30 -0
  25. data/test/testClusterResolution.rb +20 -0
  26. data/test/testDataStructures.rb +29 -0
  27. data/test/testDefectSemiImp.rb +111 -0
  28. data/test/testDeponentFirstConjugation.rb +64 -0
  29. data/test/testDeponentFourthConjugation.rb +64 -0
  30. data/test/testDeponentSecondConjugation.rb +64 -0
  31. data/test/testDeponentThirdConjugation.rb +64 -0
  32. data/test/testDeponentThirdIOConjugation.rb +64 -0
  33. data/test/testDeserializeInfinitives.rb +38 -0
  34. data/test/testFirstConjugation.rb +388 -0
  35. data/test/testFourthConjugation.rb +190 -0
  36. data/test/testFreakishVerbs.rb +93 -0
  37. data/test/testImperativeBlock.rb +27 -0
  38. data/test/testIrregularSum.rb +22 -0
  39. data/test/testIrregulars.rb +652 -0
  40. data/test/testLatinVerb.rb +195 -0
  41. data/test/testMacronRules.rb +19 -0
  42. data/test/testSecondConjugation.rb +189 -0
  43. data/test/testThirdConjugation.rb +190 -0
  44. data/test/testThirdIOConjugation.rb +190 -0
  45. metadata +70 -18
  46. data/bin/latinirb.rb +0 -7
  47. data/latinverb.rb +0 -544
  48. data/lib/LatinIRB.rb +0 -172
  49. data/lib/latinirb/paradigmatic_verbs.rb +0 -17
  50. data/lib/latinirb/version.rb +0 -10
  51. data/lib/latirb.rb +0 -20
@@ -0,0 +1,950 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'linguistics/latin/verb/phonographia'
4
+ require 'linguistics/latin/verb/latinverb/auxiliary_classes'
5
+ require 'yaml'
6
+
7
+ module Linguistics
8
+ module Latin
9
+ module Verb
10
+ ##
11
+ # == NAME
12
+ #
13
+ # TenseBlock
14
+ #
15
+ # == DESCRIPTION
16
+ #
17
+ # As per the LatinVerb documentation, LatinVerbs decorate themselves with
18
+ # the method which loads up a voice/tense/mood black box. That black box
19
+ # is a TenseBlock. The TenseBlock, in turn, responds to getting the final
20
+ # two components of the fully-qualified vector back (person and number).
21
+ # It also has Array-like behaviors (e.g. +[]+) based on the 2 * 3 matrix.
22
+ #
23
+ # == INTERNALS
24
+ #
25
+ # Internally, a Tenseblock is effectively an Array of the arguments passed
26
+ # in during TenseBlock.initialize. These are assumed to be
27
+ # first/singular, second/singular, third/singular and then
28
+ # first/plural, second/plural, third/plural.
29
+ #
30
+ # Syntactic sugar methods are added to access this array. Thus, in a
31
+ # LatinVerb a fully-qualified vectors first 3/5 data resolve to a
32
+ # TenseBlock. The last 2/5 of resolution occurs within the TenseBlock
33
+ # (effectively pulling the contents of the Array). Therefore, when a
34
+ # LatinVerb is accessed with the quinpartite fully-qualified vector it can
35
+ # return the unique value. The mechanics of this hook through (surprise!)
36
+ # method_missing.
37
+ #
38
+ #
39
+ ##
40
+
41
+ class TenseBlock
42
+ include Linguistics::Latin::Phonographia
43
+
44
+ # Idea from Mike Perham (6/1/2011): Add a way to leave a note that
45
+ # describes, in English, the signification of the given tense. Good
46
+ # idea.
47
+
48
+ attr_reader :meaning
49
+
50
+ # === ARGUMENTS
51
+ #
52
+ # *r:* :: An Array (or something that can respond to to_a) containing 0-6
53
+ # elements that will be mapped into the 2*3 matrix of Latin verb person /
54
+ # number specifications.
55
+ # === RETURNS
56
+ #
57
+ # Nothing
58
+ ##
59
+ def initialize(r, opts={})
60
+ begin
61
+ if r.class != Array
62
+ raise if r.nil?
63
+ r = r.to_a
64
+ end
65
+ @results = r.map{|v| Linguistics::Latin::Phonographia.fix_macrons v}
66
+ @meaning = opts[:meaning] if opts[:meaning]
67
+ rescue => e
68
+ raise e, "TenseBlock failed to initialize correctly. passed #{r.nil?}"
69
+ end
70
+ end
71
+
72
+ ##
73
+ #
74
+ # Required for serialization
75
+ #
76
+ ##
77
+ def to_json(*a)
78
+ {
79
+ 'json_class' => self.class.name,
80
+ 'data' => @results.map{|i| i.to_json}
81
+ }.to_json(*a)
82
+ end
83
+
84
+ ##
85
+ #
86
+ # Required for deserialization
87
+ #
88
+ ##
89
+ def TenseBlock.json_create(o)
90
+ new(o['data'])
91
+ end
92
+
93
+ ##
94
+ #
95
+ # Provides Array-like interface to the collection of results.
96
+ #
97
+ ##
98
+ def [](arg)
99
+ @results[arg]
100
+ end
101
+
102
+ ##
103
+ #
104
+ # To Array, useful in serialization
105
+ #
106
+ ##
107
+ def to_a
108
+ return @results
109
+ end
110
+
111
+ ##
112
+ #
113
+ # Add array compatibility support
114
+ #
115
+ ##
116
+ def length; return @results.length; end
117
+
118
+ ##
119
+ # Add array empty? compatibility
120
+ #
121
+ ##
122
+ def empty?; return @results.empty?; end
123
+
124
+ ##
125
+ #
126
+ # Add a sensible string display
127
+ #
128
+ ##
129
+ def to_s; return self.to_a.to_s; end
130
+
131
+ ##
132
+ # Return whether the result arrays is empty of words
133
+ ##
134
+ def wordless?
135
+ @results.map do |r|
136
+ return false if r =~ /\w/
137
+ end
138
+ true
139
+ end
140
+
141
+ ##
142
+ #
143
+ # Provide a method_missing so that ambiguous cases can be resolves
144
+ #
145
+ ##
146
+ def method_missing(symbol, *args)
147
+ begin
148
+ returnArray = []
149
+ methods.grep(/#{symbol.to_s}/) do |s|
150
+ returnArray.push(send s)
151
+ end
152
+ return returnArray unless returnArray.empty?
153
+ rescue Exception
154
+ end
155
+ super
156
+ end
157
+
158
+ ##
159
+ #--
160
+ # TODO: I dream of this being generated dynamically through the
161
+ # VerbvectorGenerator for more dynamicity. This would require a richer DSL in
162
+ # VerbvectorGenerator, but would be totally awesome if we could describe this
163
+ # language in a DSL.
164
+ #++
165
+ ##
166
+
167
+ # Syntactic sugar for accessing the final coordinates in the TenseBlock
168
+ def first_person_singular_number; return @results[0]; end
169
+
170
+ # Syntactic sugar for accessing the final coordinates in the TenseBlock
171
+ def second_person_singular_number; return @results[1]; end
172
+
173
+ # Syntactic sugar for accessing the final coordinates in the TenseBlock
174
+ def third_person_singular_number; return @results[2]; end
175
+
176
+ # Syntactic sugar for accessing the final coordinates in the TenseBlock
177
+ def first_person_plural_number; return @results[3]; end
178
+
179
+ # Syntactic sugar for accessing the final coordinates in the TenseBlock
180
+ def second_person_plural_number; return @results[4]; end
181
+
182
+ # Syntactic sugar for accessing the final coordinates in the TenseBlock
183
+ def third_person_plural_number; return @results[5]; end
184
+ end
185
+
186
+ class LatinVerb
187
+
188
+
189
+ ##
190
+ #
191
+ # === GRAMMATICAL FUNCTION
192
+ #
193
+ # Commands for immediate action. Always second person.
194
+ #
195
+ # === ARGUMENTS
196
+ #
197
+ # None
198
+ #
199
+ # === RETURNS
200
+ #
201
+ # TenseBlock
202
+ #
203
+ ###
204
+ def active_voice_imperative_mood_present_tense
205
+ imp = imperatives
206
+ TenseBlock.new( [ '', imp.present_tense_singular_number, '',
207
+ '', imp.present_tense_plural_number, ''
208
+ ],
209
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:active_voice_imperative_mood_present_tense] }
210
+ )
211
+ end
212
+
213
+ ##
214
+ #
215
+ # === GRAMMATICAL FUNCTION
216
+ #
217
+ # Commands for immediate action. Only supports second or third
218
+ # person.
219
+ #
220
+ # === ARGUMENTS
221
+ #
222
+ # None
223
+ #
224
+ # === RETURNS
225
+ #
226
+ # TenseBlock
227
+ #
228
+ ###
229
+ def active_voice_imperative_mood_future_tense
230
+ f = imperatives.future
231
+ return TenseBlock.new( [ '', f[0], f[2],
232
+ '', f[1], f[3]
233
+ ],
234
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:active_voice_imperative_mood_future_tense] }
235
+ )
236
+ end
237
+ ##
238
+ #
239
+ # === GRAMMATICAL FUNCTION
240
+ #
241
+ # Action to be completed in the future. A&G,160,a,3.
242
+ #
243
+ # === ARGUMENTS
244
+ #
245
+ # None
246
+ #
247
+ # === RETURNS
248
+ #
249
+ # TenseBlock
250
+ #
251
+ ###
252
+ def active_voice_indicative_mood_future_tense
253
+ return TenseBlock.new(
254
+ if conjugation == Linguistics::Latin::Verb::VerbTypes::First or
255
+ conjugation == Linguistics::Latin::Verb::VerbTypes::Second
256
+ [AF_ONE_TWO_ENDINGS.collect{|x| stem + x}].flatten
257
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::Third
258
+ [AF_OTHER_ENDINGS.collect{|x| stem + x}].flatten
259
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::ThirdIO or
260
+ conjugation == Linguistics::Latin::Verb::VerbTypes::Fourth
261
+ [AF_OTHER_ENDINGS.collect{|x| stem + "i" + x}].flatten
262
+ end,
263
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:active_voice_indicative_mood_future_tense] }
264
+ )
265
+ end
266
+
267
+ ##
268
+ #
269
+ # === GRAMMATICAL FUNCTION
270
+ #
271
+ # Action completed in the future.
272
+ # A&G,160,b,3.
273
+ #
274
+ # === ARGUMENTS
275
+ #
276
+ # None
277
+ #
278
+ # === RETURNS
279
+ #
280
+ # TenseBlock
281
+ #
282
+ ###
283
+ def active_voice_indicative_mood_futureperfect_tense
284
+ substem = @first_pers_perf[0..-2]
285
+ return TenseBlock.new [APERF_FUTURE_ENDINGS.collect{|x| substem+x}].flatten,
286
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:active_voice_indicative_mood_futureperfect_tense] }
287
+ end
288
+
289
+ ##
290
+ #
291
+ # === GRAMMATICAL FUNCTION
292
+ #
293
+ # Habitual action in the past. A&G,160,a,2.
294
+ #
295
+ # === ARGUMENTS
296
+ #
297
+ # None
298
+ #
299
+ # === RETURNS
300
+ #
301
+ # TenseBlock
302
+ #
303
+ ###
304
+ def active_voice_indicative_mood_imperfect_tense
305
+ return TenseBlock.new(
306
+ if conjugation == Linguistics::Latin::Verb::VerbTypes::First or
307
+ conjugation == Linguistics::Latin::Verb::VerbTypes::Second
308
+ [AI_FIRST_AND_SECOND_CONJUG_PERS_ENDINGS.collect{|x| stem + x}].flatten
309
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::Third
310
+ [AI_THIRD_CONJUG_PERS_ENDINGS.collect{|x| stem + x}].flatten
311
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::ThirdIO or
312
+ conjugation == Linguistics::Latin::Verb::VerbTypes::Fourth
313
+ [AI_THIRD_CONJUG_PERS_ENDINGS.collect do |x|
314
+ stem + "i" + x end ].flatten!
315
+ end,
316
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:active_voice_indicative_mood_imperfect_tense] }
317
+ )
318
+ end
319
+
320
+ ##
321
+ #
322
+ # === GRAMMATICAL FUNCTION
323
+ #
324
+ # Action completed in the past prior to an event in the past.
325
+ # A&G,160,b,3.
326
+ #
327
+ # === ARGUMENTS
328
+ #
329
+ # None
330
+ #
331
+ # === RETURNS
332
+ #
333
+ # TenseBlock
334
+ #
335
+ ###
336
+ def active_voice_indicative_mood_pastperfect_tense
337
+ substem = @first_pers_perf[0..-2]
338
+ return TenseBlock.new [APERF_PAST_ENDINGS.collect{|x| substem+x}].flatten,
339
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:active_voice_indicative_mood_pastperfect_tense] }
340
+ end
341
+
342
+
343
+
344
+ ##
345
+ #
346
+ # === GRAMMATICAL FUNCTION
347
+ #
348
+ # Action completed in the past. A&G,160,b,1.
349
+ #
350
+ # === ARGUMENTS
351
+ #
352
+ # None
353
+ #
354
+ # === RETURNS
355
+ #
356
+ # TenseBlock
357
+ #
358
+ ###
359
+ def active_voice_indicative_mood_perfect_tense
360
+ substem = @first_pers_perf[0..-2]
361
+ return TenseBlock.new [@first_pers_perf.to_s, APERF_ENDINGS.collect{|x| substem+x.to_s}].flatten,
362
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:active_voice_indicative_mood_perfect_tense] }
363
+ end
364
+
365
+ ##
366
+ #
367
+ # === GRAMMATICAL FUNCTION
368
+ #
369
+ # The canonical building block of learning to conjugate verbs in
370
+ # Latin. Take the present active infinitive, chop off the ending, and
371
+ # add the classic o,s,t,mus,tis,nt
372
+ #
373
+ # Wheelock Reference, p. 4.
374
+ # A&G, 160,a,1.
375
+ #
376
+ # === ARGUMENTS
377
+ #
378
+ # None
379
+ #
380
+ # === RETURNS
381
+ #
382
+ # TenseBlock
383
+ #
384
+ ###
385
+ def active_voice_indicative_mood_present_tense
386
+ return TenseBlock.new(
387
+ if conjugation == Linguistics::Latin::Verb::VerbTypes::First or
388
+ conjugation == Linguistics::Latin::Verb::VerbTypes::Second
389
+ [ @first_pers_singular,
390
+ AP_FIRST_AND_SECOND_CONJUG_PERS_ENDINGS.collect{ |ending| stem + ending}
391
+ ].flatten!
392
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::Third
393
+ [ AP_THIRD_CONJUG_PERS_ENDINGS.collect{ |ending| stem + ending } ].flatten!
394
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::ThirdIO or
395
+ conjugation == Linguistics::Latin::Verb::VerbTypes::Fourth
396
+ [ @first_pers_singular,
397
+ AP_THIRDIO_CONJG_PERS_ENDINGS.collect{ |ending| stem + ending }
398
+ ].flatten!
399
+ end,
400
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:active_voice_indicative_mood_present_tense] }
401
+ )
402
+ end
403
+
404
+ ##
405
+ #
406
+ # === GRAMMATICAL FUNCTION
407
+ #
408
+ # <em>Refer to "Moods," above. Tense is constrained by function of
409
+ # the verb in context.</em>
410
+ #
411
+ # === ARGUMENTS
412
+ #
413
+ # None
414
+ #
415
+ # === RETURNS
416
+ #
417
+ # TenseBlock
418
+ #
419
+ ###
420
+ def active_voice_subjunctive_mood_imperfect_tense
421
+ TenseBlock.new(
422
+ ['m', AP_FIRST_AND_SECOND_CONJUG_PERS_ENDINGS].flatten!.map do |ending|
423
+ @pres_act_inf.sub(/e$/,'ē') + ending
424
+ end,
425
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:active_voice_subjunctive_mood_imperfect_tense] }
426
+ )
427
+ end
428
+
429
+ ##
430
+ #
431
+ # === GRAMMATICAL FUNCTION
432
+ #
433
+ # <em>Refer to "Moods," above. Tense is constrained by function of
434
+ # the verb in context.</em>
435
+ #
436
+ # === ARGUMENTS
437
+ #
438
+ # None
439
+ #
440
+ # === RETURNS
441
+ #
442
+ # TenseBlock
443
+ #
444
+ ###
445
+ def active_voice_subjunctive_mood_pastperfect_tense
446
+ asp_base = @first_pers_perf[0..@first_pers_perf.length-2] + "issē"
447
+ TenseBlock.new( ['m', AP_FIRST_AND_SECOND_CONJUG_PERS_ENDINGS].flatten!.map do |ending|
448
+ asp_base + ending
449
+ end,
450
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:active_voice_subjunctive_mood_pastperfect_tense] }
451
+ )
452
+ end
453
+
454
+ ##
455
+ #
456
+ # === GRAMMATICAL FUNCTION
457
+ #
458
+ # <em>Refer to "Moods," above. Tense is constrained by function of
459
+ # the verb in context.</em>
460
+ #
461
+ # === ARGUMENTS
462
+ #
463
+ # None
464
+ #
465
+ # === RETURNS
466
+ #
467
+ # TenseBlock
468
+ #
469
+ ###
470
+ def active_voice_subjunctive_mood_perfect_tense
471
+ asp_base =
472
+ @first_pers_perf[0..@first_pers_perf.length-2] +
473
+ "erī"
474
+ TenseBlock.new(
475
+ ['m', AP_FIRST_AND_SECOND_CONJUG_PERS_ENDINGS].flatten!.map do |ending|
476
+ asp_base + ending
477
+ end,
478
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:active_voice_subjunctive_mood_perfect_tense] }
479
+ )
480
+ end
481
+
482
+ ##
483
+ #
484
+ # === GRAMMATICAL FUNCTION
485
+ #
486
+ # <em>Refer to "Moods," above. Tense is constrained by function of
487
+ # the verb in context.</em>
488
+ #
489
+ # === ARGUMENTS
490
+ #
491
+ # None
492
+ #
493
+ # === RETURNS
494
+ #
495
+ # TenseBlock
496
+ #
497
+ ###
498
+ def active_voice_subjunctive_mood_present_tense
499
+ key = lambda do
500
+ conjugation.to_s.split(/::/).last.to_sym
501
+ end
502
+
503
+ TenseBlock.new(
504
+ if conjugation == Linguistics::Latin::Verb::VerbTypes::First or
505
+ conjugation == Linguistics::Latin::Verb::VerbTypes::Second
506
+ asp_base = ACTIVE_PRESENT_SUBJUNCTIVE_ENDINGS[key.call].call(stem[0..-2])
507
+ ['m',
508
+ AP_FIRST_AND_SECOND_CONJUG_PERS_ENDINGS].flatten!.map do |ending|
509
+ asp_base + ending
510
+ end
511
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::Third or
512
+ conjugation == Linguistics::Latin::Verb::VerbTypes::Fourth
513
+ asp_base = ACTIVE_PRESENT_SUBJUNCTIVE_ENDINGS[key.call].call(stem[0..-1])
514
+ ['m',
515
+ AP_FIRST_AND_SECOND_CONJUG_PERS_ENDINGS].flatten!.map do |ending|
516
+ asp_base + ending
517
+ end
518
+ else
519
+ base =
520
+ ['m',
521
+ AP_FIRST_AND_SECOND_CONJUG_PERS_ENDINGS].flatten!.map do |ending|
522
+ ACTIVE_PRESENT_SUBJUNCTIVE_ENDINGS[key.call].call(@stem) + ending
523
+ end
524
+ end,
525
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:active_voice_subjunctive_mood_present_tense] }
526
+ )
527
+ end
528
+
529
+ ##
530
+ #
531
+ # === GRAMMATICAL FUNCTION
532
+ #
533
+ # <em>Refer to "Voice" section in reference, for function consult
534
+ # active-voice counterpart.</em>
535
+ #
536
+ # === ARGUMENTS
537
+ #
538
+ # None
539
+ #
540
+ # === RETURNS
541
+ #
542
+ # TenseBlock
543
+ #
544
+ ###
545
+ def passive_voice_indicative_mood_future_tense
546
+ TenseBlock.new(
547
+ if conjugation == Linguistics::Latin::Verb::VerbTypes::First or
548
+ conjugation == Linguistics::Latin::Verb::VerbTypes::Second
549
+ fp_stem=stem+"bi"
550
+ standards = PASSIVE_ENDINGS_FIRST_AND_SECOND_CONJG[2..-1].map{|x| fp_stem + x}
551
+ standards.pop
552
+ fp_stem.sub!(/.$/,'u')
553
+ [stem + "b\xc5\x8dr",
554
+ stem + "beris", standards, fp_stem+PASSIVE_ENDINGS_FIRST_AND_SECOND_CONJG.last].flatten!
555
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::Third
556
+ fp_stem=stem+"ē"
557
+ standards = PASSIVE_ENDINGS_FIRST_AND_SECOND_CONJG[1..-1].map{|x| fp_stem + x}
558
+ [stem + "ar", standards].flatten!
559
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::ThirdIO or
560
+ conjugation == Linguistics::Latin::Verb::VerbTypes::Fourth
561
+ ie_base=stem+"iē"
562
+ [stem+"ia"+PASSIVE_ENDINGS_FIRST_AND_SECOND_CONJG[0],
563
+ PASSIVE_ENDINGS_FIRST_AND_SECOND_CONJG[1..-1].map{|x| ie_base + x}].flatten!
564
+ end,
565
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:passive_voice_indicative_mood_future_tense] }
566
+ )
567
+ end
568
+
569
+ ##
570
+ #
571
+ # === GRAMMATICAL FUNCTION
572
+ #
573
+ # <em>Refer to "Voice" section in reference, for function consult
574
+ # active-voice counterpart.</em>
575
+ # Wheelock, 122
576
+ #
577
+ # === ARGUMENTS
578
+ #
579
+ # None
580
+ #
581
+ # === RETURNS
582
+ #
583
+ # TenseBlock
584
+ #
585
+ ###
586
+ def passive_voice_indicative_mood_futureperfect_tense
587
+ return TenseBlock.new(
588
+ PASS_PERF_FUTURE_ENDINGS.map{ |helping_verb| "#{@pass_perf_part} #{helping_verb}" },
589
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:passive_voice_indicative_mood_futureperfect_tense] }
590
+ )
591
+ end
592
+
593
+
594
+ ##
595
+ #
596
+ # === GRAMMATICAL FUNCTION
597
+ #
598
+ # <em>Refer to "Voice" section in reference, for function consult
599
+ # active-voice counterpart.</em>
600
+ # Wheelock, 117
601
+ #
602
+ # === ARGUMENTS
603
+ #
604
+ # None
605
+ #
606
+ # === RETURNS
607
+ #
608
+ # TenseBlock
609
+ #
610
+ ###
611
+ def passive_voice_indicative_mood_imperfect_tense
612
+ return TenseBlock.new(
613
+ if conjugation == Linguistics::Latin::Verb::VerbTypes::First or
614
+ conjugation == Linguistics::Latin::Verb::VerbTypes::Second
615
+ imperfect_stem = stem + "b\xc4\x81"
616
+ PASSIVE_ENDINGS_FIRST_AND_SECOND_CONJG.map{|x| imperfect_stem+x}
617
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::Third
618
+ ministem=stem + "ēbā"
619
+ PASSIVE_ENDINGS_FIRST_AND_SECOND_CONJG.map{|x| ministem + x}
620
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::ThirdIO or
621
+ conjugation == Linguistics::Latin::Verb::VerbTypes::Fourth
622
+ base=stem+"iēbā"
623
+ [PASSIVE_ENDINGS_FIRST_AND_SECOND_CONJG.map{|x| base + x}].flatten!
624
+ end,
625
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:passive_voice_indicative_mood_imperfect_tense] }
626
+ )
627
+ end
628
+
629
+
630
+ ##
631
+ #
632
+ # === GRAMMATICAL FUNCTION
633
+ #
634
+ # <em>Refer to "Voice" section in reference, for function consult
635
+ # active-voice counterpart.</em>
636
+ # Wheelock, 117
637
+ #
638
+ # === ARGUMENTS
639
+ #
640
+ # None
641
+ #
642
+ # === RETURNS
643
+ #
644
+ # TenseBlock
645
+ #
646
+ ###
647
+ def passive_voice_indicative_mood_pastperfect_tense
648
+ TenseBlock.new(
649
+ PASS_PERF_PAST_ENDINGS.map{ |helping_verb| "#{@pass_perf_part} #{helping_verb}" },
650
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:passive_voice_indicative_mood_pastperfect_tense]}
651
+ )
652
+ end
653
+
654
+
655
+ ##
656
+ #
657
+ # === GRAMMATICAL FUNCTION
658
+ #
659
+ # Wheelock, 122
660
+ #
661
+ # === ARGUMENTS
662
+ #
663
+ # None
664
+ #
665
+ # === RETURNS
666
+ #
667
+ # TenseBlock
668
+ #
669
+ ###
670
+ def passive_voice_indicative_mood_perfect_tense
671
+ TenseBlock.new(
672
+ PASS_PERF_PRESENT_ENDINGS.map{ |helping_verb| "#{@pass_perf_part} #{helping_verb}" },
673
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:passive_voice_indicative_mood_perfect_tense] }
674
+ )
675
+ end
676
+
677
+
678
+ ##
679
+ #
680
+ # === GRAMMATICAL FUNCTION
681
+ #
682
+ # <em>Refer to "Voice" section in reference, for function consult
683
+ # active-voice counterpart.</em>
684
+ # Wheelock, 117
685
+ #
686
+ # === ARGUMENTS
687
+ #
688
+ # None
689
+ #
690
+ # === RETURNS
691
+ #
692
+ # TenseBlock
693
+ #
694
+ ###
695
+ def passive_voice_indicative_mood_present_tense
696
+ return TenseBlock.new(
697
+ if conjugation == Linguistics::Latin::Verb::VerbTypes::First or
698
+ conjugation == Linguistics::Latin::Verb::VerbTypes::Second
699
+ local_pe=PASSIVE_ENDINGS_FIRST_AND_SECOND_CONJG.clone
700
+ [@first_pers_singular.to_s + "r",
701
+ local_pe[1..-1].map{|x| @stem + x}].flatten!
702
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::Third
703
+ [@first_pers_singular+"r",
704
+ PASSIVE_ENDINGS_OTHER[1..-1].map{|x| stem + x}].flatten!
705
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::ThirdIO
706
+ base=stem+"i"
707
+ [@first_pers_singular+"r",
708
+ PASSIVE_ENDINGS_OTHER[1..-2].map{|x| stem + x},
709
+ base+PASSIVE_ENDINGS_OTHER[-1]].flatten!
710
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::Fourth
711
+ base=@stem+"ī"
712
+ [@first_pers_singular+"r",
713
+ PASSIVE_ENDINGS_FIRST_AND_SECOND_CONJG[1..-2].map{|x| base + x},
714
+ base+PASSIVE_ENDINGS_OTHER[-1]].flatten!
715
+ end,
716
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:passive_voice_indicative_mood_present_tense] }
717
+ )
718
+ end
719
+
720
+ ##
721
+ #
722
+ # === GRAMMATICAL FUNCTION
723
+ #
724
+ # <em>Refer to "Moods," above. Tense is constrained by function of
725
+ # the verb in context.</em>
726
+ #
727
+ # === ARGUMENTS
728
+ #
729
+ # None
730
+ #
731
+ # === RETURNS
732
+ #
733
+ # TenseBlock
734
+ #
735
+ ###
736
+ def passive_voice_subjunctive_mood_imperfect_tense
737
+ base = @pres_act_inf.gsub(/(.*)(.)$/,"\\1" + 'ē')
738
+ TenseBlock.new(
739
+ PASSIVE_ENDINGS_FIRST_AND_SECOND_CONJG.map do |ending|
740
+ base + ending
741
+ end,
742
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:passive_voice_subjunctive_mood_imperfect_tense] }
743
+ )
744
+ end
745
+
746
+ ##
747
+ #
748
+ # === GRAMMATICAL FUNCTION
749
+ #
750
+ # <em>Refer to "Moods," above. Tense is constrained by function of
751
+ # the verb in context.</em>
752
+ #
753
+ # === ARGUMENTS
754
+ #
755
+ # None
756
+ #
757
+ # === RETURNS
758
+ #
759
+ # TenseBlock
760
+ #
761
+ ###
762
+ def passive_voice_subjunctive_mood_pastperfect_tense
763
+ count = -1
764
+ TenseBlock.new(PASS_PLUPERF_PAST_ENDINGS.map do |ending|
765
+ count += 1
766
+ (count <= 2 ?
767
+ "[ #{triplicate_and_genderize @pass_perf_part} ]" :
768
+ "[ #{pluralize_participial_listing(triplicate_and_genderize(@pass_perf_part))} ]" )+ " " + ending
769
+ end,
770
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:passive_voice_subjunctive_mood_pastperfect_tense] }
771
+ )
772
+ end
773
+
774
+ ##
775
+ #
776
+ # === GRAMMATICAL FUNCTION
777
+ #
778
+ # <em>Refer to "Moods," above. Tense is constrained by function of
779
+ # the verb in context.</em>
780
+ #
781
+ # === ARGUMENTS
782
+ #
783
+ # None
784
+ #
785
+ # === RETURNS
786
+ #
787
+ # TenseBlock
788
+ #
789
+ ###
790
+ def passive_voice_subjunctive_mood_perfect_tense
791
+ counter = -1
792
+ TenseBlock.new(PASS_PERF_SUBJ_ENDINGS.map do |ending|
793
+ counter += 1
794
+ (counter <=2 ?
795
+ "[ #{triplicate_and_genderize @pass_perf_part} ]" :
796
+ "[ #{pluralize_participial_listing(triplicate_and_genderize(@pass_perf_part))} ]" )+ " " + ending
797
+ end,
798
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:passive_voice_subjunctive_mood_perfect_tense] }
799
+ )
800
+ end
801
+
802
+ ##
803
+ #
804
+ # === GRAMMATICAL FUNCTION
805
+ #
806
+ # <em>Refer to "Moods," above. Tense is constrained by function of
807
+ # the verb in context.</em>
808
+ #
809
+ # === ARGUMENTS
810
+ #
811
+ # None
812
+ #
813
+ # === RETURNS
814
+ #
815
+ # TenseBlock
816
+ #
817
+ ###
818
+ def passive_voice_subjunctive_mood_present_tense
819
+ key = lambda do
820
+ conjugation.to_s.split(/::/).last.to_sym
821
+ end
822
+ TenseBlock.new(
823
+ if conjugation == Linguistics::Latin::Verb::VerbTypes::First or
824
+ conjugation == Linguistics::Latin::Verb::VerbTypes::Second
825
+ short_base =
826
+ ACTIVE_PRESENT_SUBJUNCTIVE_ENDINGS[key.call].call(stem[0..-2])
827
+ PASSIVE_ENDINGS_FIRST_AND_SECOND_CONJG.map do |ending|
828
+ short_base + ending
829
+ end
830
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::Third or
831
+ conjugation == Linguistics::Latin::Verb::VerbTypes::ThirdIO
832
+ subjunctive_stem = conjugation.to_s =~ /O$/i ? stem + "iā" : stem + "ā"
833
+ PASSIVE_ENDINGS_FIRST_AND_SECOND_CONJG.map do |ending|
834
+ subjunctive_stem + ending
835
+ end
836
+ elsif conjugation == Linguistics::Latin::Verb::VerbTypes::Fourth
837
+ subjunctive_stem = stem + "iā"
838
+ PASSIVE_ENDINGS_FIRST_AND_SECOND_CONJG.map do |ending|
839
+ subjunctive_stem + ending
840
+ end
841
+ end,
842
+ { :meaning => Linguistics::Latin::Verb::LatinVerb::MEANINGS[:passive_voice_subjunctive_mood_present_tense] }
843
+ )
844
+ end
845
+
846
+ ##
847
+ #
848
+ # === GRAMMATICAL FUNCTION
849
+ #
850
+ # Used to express command. As A&G notes, oftentimes the Subjunctive
851
+ # is the correct mood for exhortation.
852
+ #
853
+ # === ARGUMENTS
854
+ #
855
+ # None
856
+ #
857
+ # === RETURNS
858
+ #
859
+ # TenseBlock
860
+ #
861
+ ###
862
+ def imperatives
863
+ @imperatives ||= form_imperatives
864
+ end
865
+
866
+ private
867
+
868
+ def form_imperatives
869
+
870
+ imperative_exceptions = {
871
+ "ducere" => %w(duc ducite),
872
+ "dicere" => %w(dic dicite),
873
+ "facere" => %w(fac facite),
874
+ "ferre" => %w(fer ferte),
875
+ "nolere" => %w(nolo nolite)
876
+ }
877
+
878
+ # Exceptional imperatives. If we have one, return it straight away.
879
+ if imperative_exceptions.has_key?(@pres_act_inf)
880
+ return Linguistics::Latin::Verb::ImperativeBlock.new(
881
+ imperative_exceptions[@pres_act_inf])
882
+ end
883
+
884
+ # Therefore, let us assume that we are dealing with a standard verb
885
+ # with standard imperatives. Accordingly, we will create an
886
+ # ImperativeBlock.
887
+
888
+ return Linguistics::Latin::Verb::ImperativeBlock.new @stem, @pres_act_inf
889
+ end
890
+
891
+ ##
892
+ #
893
+ # === DESCRIPTION
894
+ #
895
+ # Used for handling verb states that are compounds like _amatus,
896
+ # amata, amatum sum_ and converting them to amati, amatae, amata,
897
+ # (sumus|estis|sunt).
898
+ #
899
+ # === ARGUMENTS
900
+ #
901
+ # +x:+ :: A string that looks like --us, --a, --um
902
+ # This method mutates those singular endings to plural forms
903
+ #
904
+ # === RETURNS
905
+ #
906
+ # Altered string
907
+ #
908
+ # === EXAMPLE
909
+ #
910
+ # pluralize_participial_listing(qq/amatus, amata, amatum/) #=>
911
+ # amatī, amatae, amata
912
+ #
913
+ ##
914
+ def pluralize_participial_listing(x)
915
+ x.sub!(/us,/, 'ī,' )
916
+ x.sub!(/a,/, 'ae,')
917
+ x.sub!(/um.*$/, 'a' )
918
+ end
919
+
920
+ ##
921
+ #
922
+ # === DESCRIPTION
923
+ #
924
+ # Used for turning a participial form --um into --us, --a, --um
925
+ #
926
+ # === ARGUMENTS
927
+ #
928
+ # +s:+ :: --um
929
+ #
930
+ # === RETURNS
931
+ #
932
+ # Altered string
933
+ #
934
+ # === EXAMPLE
935
+ #
936
+ # triplicate_and_genderize("amatum") #=> amatus, amata, amatum
937
+ #
938
+ ##
939
+ def triplicate_and_genderize(s)
940
+ stem = s.sub(/^(.*)um$/,"\\1")
941
+ [ stem + 'us',
942
+ stem + 'a',
943
+ s
944
+ ].join(', ')
945
+ end
946
+ end
947
+ end
948
+ end
949
+ end
950
+