latinverb 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/Gemfile +4 -1
  2. data/Gemfile.lock +24 -0
  3. data/Guardfile +10 -0
  4. data/README.markdown +1 -1
  5. data/Rakefile +12 -9
  6. data/latinverb.gemspec +4 -0
  7. data/lib/latinverb/chart.rb +5 -5
  8. data/lib/latinverb/version.rb +1 -1
  9. data/lib/latinverb.rb +266 -534
  10. data/lib/linguistics/latin/verb/classification_types.rb +19 -17
  11. data/lib/linguistics/latin/verb/constants.rb +14 -14
  12. data/lib/linguistics/latin/verb/deponent_tense_methods.rb +8 -21
  13. data/lib/linguistics/latin/verb/imperative_block.rb +118 -0
  14. data/lib/linguistics/latin/verb/infinitive_block.rb +39 -0
  15. data/lib/linguistics/latin/verb/infinitives.rb +181 -181
  16. data/lib/linguistics/latin/verb/irregulars.rb +74 -74
  17. data/lib/linguistics/latin/verb/latinverb/classmethods.rb +36 -117
  18. data/lib/linguistics/latin/verb/latinverb/data.rb +12 -15
  19. data/lib/linguistics/latin/verb/latinverb/defective_checker.rb +17 -0
  20. data/lib/linguistics/latin/verb/latinverb/deponent.rb +159 -0
  21. data/lib/linguistics/latin/verb/latinverb/display.rb +1 -2
  22. data/lib/linguistics/latin/verb/latinverb/impersonal.rb +34 -0
  23. data/lib/linguistics/latin/verb/latinverb/irregular.rb +83 -0
  24. data/lib/linguistics/latin/verb/latinverb/latin_verb_type_evaluator.rb +32 -0
  25. data/lib/linguistics/latin/verb/latinverb/latinverb_classifier.rb +100 -0
  26. data/lib/linguistics/latin/verb/latinverb/latinverb_input_sanitizer.rb +32 -0
  27. data/lib/linguistics/latin/verb/latinverb/latinverb_pp_extractor.rb +106 -0
  28. data/lib/linguistics/latin/verb/latinverb/metaprogramming.rb +30 -29
  29. data/lib/linguistics/latin/verb/latinverb/semideponent.rb +28 -0
  30. data/lib/linguistics/latin/verb/latinverb/validation.rb +5 -29
  31. data/lib/linguistics/latin/verb/latinverb/verbvector_description.rb +50 -0
  32. data/lib/linguistics/latin/verb/participle_block.rb +36 -0
  33. data/lib/linguistics/latin/verb/participles.rb +25 -25
  34. data/lib/linguistics/latin/verb/phonographia.rb +51 -51
  35. data/lib/linguistics/latin/verb/supine.rb +6 -6
  36. data/lib/linguistics/latin/verb/tense_block.rb +227 -0
  37. data/lib/linguistics/latin/verb/tense_definitions/first.rb +92 -0
  38. data/lib/linguistics/latin/verb/tense_definitions/fourth.rb +92 -0
  39. data/lib/linguistics/latin/verb/tense_definitions/impersonal.rb +25 -0
  40. data/lib/linguistics/latin/verb/tense_definitions/invariant.rb +613 -0
  41. data/lib/linguistics/latin/verb/tense_definitions/irregular.rb +82 -0
  42. data/lib/linguistics/latin/verb/tense_definitions/second.rb +97 -0
  43. data/lib/linguistics/latin/verb/tense_definitions/third.rb +86 -0
  44. data/lib/linguistics/latin/verb/tense_definitions/third_io.rb +91 -0
  45. data/test/testClusterResolution.rb +0 -1
  46. data/test/testDataStructures.rb +8 -5
  47. data/test/testDefectSemiImp.rb +9 -10
  48. data/test/testDeponentFirstConjugation.rb +2 -2
  49. data/test/testDeponentFourthConjugation.rb +2 -2
  50. data/test/testDeponentSecondConjugation.rb +2 -2
  51. data/test/testDeponentThirdConjugation.rb +2 -2
  52. data/test/testDeponentThirdIOConjugation.rb +2 -2
  53. data/test/testDeserializeInfinitives.rb +2 -4
  54. data/test/testFirstConjugation.rb +53 -53
  55. data/test/testFourthConjugation.rb +11 -11
  56. data/test/testFreakishVerbs.rb +12 -11
  57. data/test/testIrregulars.rb +24 -23
  58. data/test/testLatinVerb.rb +46 -55
  59. data/test/testSecondConjugation.rb +27 -27
  60. data/test/testThirdConjugation.rb +14 -14
  61. data/test/testThirdIOConjugation.rb +13 -13
  62. metadata +95 -53
  63. data/lib/linguistics/latin/verb/latinverb/auxiliary_classes.rb +0 -208
  64. data/lib/linguistics/latin/verb/tense_methods.rb +0 -950
data/lib/latinverb.rb CHANGED
@@ -1,14 +1,16 @@
1
1
  # encoding: UTF-8
2
- #------------------------------------------------------------------------------
2
+ # vim: set fdm=marker tw=80 sw=2:
3
+ #
4
+ #------------------------------------------------------------------------------
3
5
  # DEPENDENCIES
4
- #------------------------------------------------------------------------------
6
+ #------------------------------------------------------------------------------
5
7
  # External dependencies
6
8
  require 'verbvector'
7
9
  require 'yaml'
8
10
  require 'json'
9
11
  require 'active_support'
10
12
 
11
- ##
13
+ ### {{{
12
14
  #--
13
15
  # Internal dependencies
14
16
  # If the library is in the latin/verb, then it is a feature of the actual
@@ -17,57 +19,80 @@ require 'active_support'
17
19
  # program. It's the difference between "This is part of Latin" and "This is
18
20
  # Part of the machinery I use to represent Latin in Ruby."
19
21
  #++
20
- ##
21
-
22
- require 'linguistics/latin/verb/classification_types'
23
- require 'linguistics/latin/verb/tense_methods'
22
+ ### }}}
23
+
24
+ # Latin Language Rules
25
+ require 'linguistics/latin/verb/classification_types'# {{{
26
+ require 'linguistics/latin/verb/tense_block'
27
+ require 'linguistics/latin/verb/participle_block'
28
+ require 'linguistics/latin/verb/infinitive_block'
29
+ require 'linguistics/latin/verb/imperative_block'
30
+ require 'linguistics/latin/verb/tense_definitions/impersonal'
31
+ require 'linguistics/latin/verb/tense_definitions/invariant'
32
+ require 'linguistics/latin/verb/tense_definitions/first'
33
+ require 'linguistics/latin/verb/tense_definitions/second'
34
+ require 'linguistics/latin/verb/tense_definitions/third'
35
+ require 'linguistics/latin/verb/tense_definitions/third_io'
36
+ require 'linguistics/latin/verb/tense_definitions/fourth'
37
+ require 'linguistics/latin/verb/tense_definitions/irregular'
24
38
  require 'linguistics/latin/verb/deponent_tense_methods'
25
39
  require 'linguistics/latin/verb/supine'
26
40
  require 'linguistics/latin/verb/phonographia'
27
41
  require 'linguistics/latin/verb/constants'
28
42
  require 'linguistics/latin/verb/infinitives'
29
43
  require 'linguistics/latin/verb/participles'
30
- require 'linguistics/latin/verb/irregulars'
31
-
44
+ require 'linguistics/latin/verb/irregulars'# }}}
45
+
46
+ # LatinVerb design
47
+ require 'linguistics/latin/verb/latinverb/impersonal'# {{{
48
+ require 'linguistics/latin/verb/latinverb/irregular'
49
+ require 'linguistics/latin/verb/latinverb/semideponent'
50
+ require 'linguistics/latin/verb/latinverb/deponent'
51
+ require 'linguistics/latin/verb/latinverb/latinverb_classifier'
52
+ require 'linguistics/latin/verb/latinverb/latinverb_pp_extractor'
53
+ require 'linguistics/latin/verb/latinverb/latinverb_input_sanitizer'
54
+ require 'linguistics/latin/verb/latinverb/defective_checker'
55
+ require 'linguistics/latin/verb/latinverb/latin_verb_type_evaluator'
32
56
  require 'linguistics/latin/verb/latinverb/classmethods'
57
+ require 'linguistics/latin/verb/latinverb/verbvector_description'
33
58
  require 'linguistics/latin/verb/latinverb/metaprogramming'
34
59
  require 'linguistics/latin/verb/latinverb/validation'
35
60
  require 'linguistics/latin/verb/latinverb/data'
36
- require 'linguistics/latin/verb/latinverb/display'
61
+ require 'linguistics/latin/verb/latinverb/display'# }}}
37
62
 
38
- require 'latinverb/version'
39
- require 'latinverb/chart.rb'
63
+ require 'latinverb/version'# {{{
64
+ require 'latinverb/chart.rb'# }}}
40
65
 
41
66
  =begin rdoc
42
-
67
+ # {{{
43
68
  ==DESCRIPTION
44
69
 
45
- Linguistics is a module that forms a primordial node for storing Modules and classes dealing with lingustics. The namespace is immediately sub-divided by language (e.g. Latin, Spanish) then part of speech (e.g. Noun, Verb) or function (e.g. Phonographia).
46
-
70
+ Linguistics is a module that forms a primordial node for storing Modules and classes dealing with linguistics. The namespace is immediately sub-divided by language (e.g. Latin, Spanish) then part of speech (e.g. Noun, Verb) or function (e.g. Phonographia).
71
+ # }}}
47
72
  =end
48
73
 
49
74
  module Linguistics
50
- # Generalized module for handling lingustics related to Latin
75
+ # Generalized module for handling linguistics related to Latin
51
76
  module Latin
52
- # Generalized module for handling lingustics related to Latin's verbal aspects
77
+ # Generalized module for handling linguistics related to Latin's verbal aspects
53
78
  module Verb
54
- ##
55
- # == SYNOPSIS
79
+ ### {{{
80
+ # == SYNOPSIS# {{{# {{{
56
81
  #
57
82
  # Abstraction of a Verb in the Latin language.
58
- #
59
- # == DESCRIPTION
83
+ ## }}}
84
+ # == DESCRIPTION# {{{
60
85
  #
61
86
  # LatinVerb is:
62
87
  # * a tool to help the student of Latin understand the rules of
63
- # conjugation's heuristics by presenting said heuristics in Ruby
88
+ # conjugation's heuristics by presenting said heuristics in Ruby
64
89
  # * a way to get out of having to lug the 501 Latin Verbs book around
65
90
  # (when wrapped in an application ;) )
66
91
  # * a way to discover some of the interesting metacongnitive structures
67
92
  # between natural language and programming language
68
93
  # * <em>...and so much more...</em>
69
- #
70
- # === OPERATION
94
+ ## }}}
95
+ # === OPERATION# {{{
71
96
  #
72
97
  # LatinVerb operates by instantiating a LatinVerb based on a string
73
98
  # containing the "four principal parts" that are used to describe a
@@ -79,16 +104,16 @@ module Linguistics
79
104
  # taught</b> in Latin classes for _milennia_!
80
105
  #
81
106
  # An example should illustrate:
82
- #
83
- # === EXAMPLE
107
+ ## }}}
108
+ # === EXAMPLE# {{{
84
109
  #
85
110
  # <pre>
86
111
  # to_love = LatinVerb.new("amō amāre amāvī amatum")
87
112
  # to_love.active_voice_indicative_mood_present_tense_second_person_singular_number #=> amās
88
113
  # to_love.active_voice_indicative_mood_present_tense_third_person_singular_number #=> amat
89
114
  # </pre>
90
- #
91
- # === EXPLICATION
115
+ ## }}}
116
+ # === EXPLICATION# {{{
92
117
  #
93
118
  # Considering the above example, when the object was insantiated, it
94
119
  # realized what its conjugation was, realized what its stem ("amā") was,
@@ -98,8 +123,8 @@ module Linguistics
98
123
  # return it as an array. It is through (mis-?)use of method_missing
99
124
  # that this simple "vector" method for interfacing with a verb is
100
125
  # possible. <em>Puto hoc bonum esse</em>.
101
- #
102
- # === MACRONS / QUANTITY
126
+ ## }}}
127
+ # === MACRONS / QUANTITY# {{{
103
128
  #
104
129
  # In reference texts, quanitiy of vowel duration ("long" or "short") is
105
130
  # marked with a macron. *LatinVerb assumes it will be provided strings
@@ -108,12 +133,11 @@ module Linguistics
108
133
  # <em>Si hoc non aderit, non mutabitur</em>. To make this easier I
109
134
  # wrote the MacronConversion library which supports conversion of
110
135
  # LaTeX-styled ASCII macron transgraphia (e.g. \={a} => ā).
111
- #
112
- #
113
- # === REFERENCE
114
- #
115
- # ==== Voices
116
- # A&G Sec. 156:
136
+ ## }}}
137
+ # === REFERENCE# {{{
138
+ ## }}}
139
+ # ==== Voices# {{{
140
+ # A&G Sec. 156:
117
141
  #
118
142
  # The Active and Passive Voices in Latin generally correspond to the
119
143
  # active and passive in English; but --
@@ -123,8 +147,8 @@ module Linguistics
123
147
  # meaning. These are called Deponents (sec 190.)...
124
148
  # c. Some verbs with active meaning have the passive form in the
125
149
  # perfect tenses; these are called Semi-Deponents
126
- #
127
- # ==== Moods
150
+ ## }}}
151
+ # ==== Moods# {{{
128
152
  #
129
153
  # a. The Indicative Mood is used for most <em>direct assertions</em>
130
154
  # and <em>interrogations</em>
@@ -134,41 +158,33 @@ module Linguistics
134
158
  # c. The Imperative is used for <em>exhortation</em>,
135
159
  # <em>entreaty</em>, or <em>command</em>; but the Subjunctive is often
136
160
  # used instead
137
- #
138
- # === WORKS CITED
161
+ ## }}}
162
+ # === WORKS CITED# {{{
139
163
  #
140
164
  # Allen, J.H. Allen and Greenough's New Latin Grammar. Dover,
141
165
  # Mineola: 2006. Cited herein as "A&G."
142
166
  #
143
- # Wheelock, Frederic M. Wheelock's Latin. Collins, New York: 2005.
144
- # Cited herein as "Wheelock."
167
+ # Wheelock, Frederic M. Wheelock's Latin. Collins, New York: 2005.
168
+ # Cited herein as "Wheelock."# }}}# }}}
145
169
  #
146
- ##
170
+ ### }}}
147
171
  class LatinVerb
148
- # Modules used to validate the input in initialize
172
+ # Modules used to validate the input in initialize# {{{
149
173
  include Linguistics::Latin::Verb::Validation
150
174
  include Linguistics::Latin::Verb::Participles
151
175
  include Linguistics::Latin::Verb::Infinitives
152
-
153
- # Attributes for storing submitted data. This will help remember the origin state
176
+ # }}}
177
+
178
+ # Attributes for storing submitted data. This will help remember the origin state# {{{
154
179
  attr_reader :original_string
155
-
180
+
156
181
  # Attributes for storing calculated status.
157
- attr_reader :classification, :classification_error, :principal_parts,
158
- :four_pp, :irregular, :stem, :first_pers_singular, :pres_act_inf,
159
- :first_pers_perf, :pass_perf_part, :participial_stem, :verb_methods,
160
- :data_structure
182
+ attr_reader :verb_methods
161
183
 
162
184
  # Access the Module that provides all the methods
163
- attr_reader :latin_verbvector_generator, :latin_verb_methods
164
-
165
- # Accessors for "odd forms"
166
- attr_reader :present_only
185
+ attr_reader :latin_verbvector_generator, :latin_verb_methods# }}}
167
186
 
168
- alias_method :conjugation, :classification
169
- alias_method :irregular?, :irregular
170
-
171
- ##
187
+ ### {{{
172
188
  #
173
189
  # The constructor for a Latinverb
174
190
  #
@@ -193,406 +209,12 @@ module Linguistics
193
209
  #
194
210
  # * Array support for the argument
195
211
  #
196
- ##
197
- def initialize(s)
198
- raise SyntaxError if s.nil?
199
-
200
- if s.class == String
201
- _init_by_string(s)
202
- _impersonal_handler if @impersonal
203
- _irregular_handler if @irregular
204
- _deponent_handler if ( @deponent || @semideponent )
205
- end
206
-
207
- if (s.class == Hash )
208
- if (s['irregular'] == false and
209
- s.has_key?('original_string'))
210
- # We're restoring a standard verb
211
- _init_by_string(s['original_string'])
212
- end
213
- end
214
-
215
- if s.class == Array
216
- # TODO: Fill this out.
217
- end
218
-
219
- # Load up the specialized vector complement of methods
220
- #
221
- unless @impersonal
222
- _add_vector_methods
223
-
224
- # Given the use of method_missing to handle resolution, it's wise to
225
- # make sure that every cluster method /is/ actually defined.
226
- @tense_list.each do |m|
227
- raise "FAILURE: Critical method #{m} was not defined." unless
228
- (self.respond_to? m.to_sym)
229
- end
230
- end
231
-
232
- # Placeholder the data structure that holds all the answers (a hash
233
- # of TenseBlocks). This may be the typical case, but the
234
- # calculation is an expensive operation compared to the simple
235
- # vector query, so this won't actually get defined unless #to_hash
236
- # is called (cf. latinverb/display).
237
- # TODO: This probably needs some work, make it useful in the
238
- # to_json methods
239
-
240
- @data_structure = {}
241
-
242
- # In a bit of cleverness, if the verb is deponent, we have built out
243
- # this verb as if it were regular, but we have also created a
244
- # @proxyVerb which is the active 'pseudo verb' corresponding to this
245
- # verb. We should be able to take this verb's active formulations
246
- # and set their results to the @proxyVerb's passive formulations
247
- #
248
- # Ergo: miror/mirari/miratus =~ miro/mirare/JUNK/miratus
249
- # Therefore make a LatinVerb.new(miro/mirare/JUNK/miratus). Take
250
- # its passives and set them to this verb's actives. This is
251
- # actually what students do heuristically in Latin classes.
252
- apply_deponent_masking if @deponent
253
-
254
- # Previously @deponent and @semideponent followed the same paths,
255
- # but in semideponents, the "present system" is handled as normal
256
- # (completed by _add_vector_methods, supra). We need only mask, as
257
- # A&G #192 says: "the completed methods" i.e. the perfect system.
258
- apply_semideponent_masking if @semideponent
259
-
260
- # Per A&G206, some verbs are to have their perfect system
261
- # conjugations removed.
262
- remove_perfect_tenses if present_only?
263
- end
264
-
265
- ######################################################################
266
- # Instance methods
267
- ######################################################################
268
-
269
- ##
270
- #
271
- # Some verbs only take a active/indic/pres/3rd/sg ("it rains"). For
272
- # these we will not add the full vectors of methods, but will only
273
- # respond to THAT vector. It's a bit of an identity relationship and
274
- # seems a bit silly to return, but I think it keeps the proper
275
- # completeness
276
- #
277
- ##
278
-
279
- def _impersonal_handler
280
- singleton_class.class_eval do
281
- def active_voice_indicative_mood_present_tense
282
- TenseBlock.new ["", "", @original_string,
283
- "", "", ""]
284
- end
285
- def active_voice_indicative_mood_present_tense_third_person_singular_number
286
- return active_voice_indicative_mood_present_tense[2]
287
- end
288
- end
289
- end
290
-
291
- ##
292
- #
293
- # Removes perfect-system tenses by blanking them out.
294
- #
295
- ##
296
- def remove_perfect_tenses
297
- # Get perfect system methods
298
- tense_blocks_to_eclipse =
299
- self.methods.grep /^(active|passive).*(_|past|future)perfect_/
300
-
301
- # Re-assgin their methods to point to a blank TenseBlock, thus
302
- # eclipsing any values thatm ight come in.
303
- tense_blocks_to_eclipse.each do |s|
304
- singleton_class.class_eval do
305
- define_method s do
306
- return TenseBlock.new [ '', '', '', '', '', '']
307
- end
308
- end
309
- end
310
- end
311
-
312
- ##
313
- #
314
- # Determines whether a verb should have its perfect tenses removed.
315
- # This is an exceptional behavior described in A&G206
316
- #
317
- ##
318
-
319
- def present_only?
320
- @present_only =
321
- (
322
- Linguistics::Latin::Verb::LatinVerb::PRESENT_ONLY.member?(@pres_act_inf) ||
323
- Linguistics::Latin::Verb::LatinVerb::PRESENT_ONLY.member?(@first_pers_singular)
324
- ) ? true : false
325
- end
326
- ##
327
- #
328
- # Imports replacements to the standard tense_methods and thus
329
- # overwrites the old method definitions defined by verbvector
330
- #
331
- ##
332
- def apply_semideponent_masking
333
- self.singleton_class.class_eval do
334
- include Linguistics::Latin::Verb::DeponentTenseMethods
335
- end
336
- end
337
-
338
- ##
339
- #
340
- # Top-level method used to call the sub-methods which create a facade so that
341
- # active_ vectors can be called on a deponent which actually forwards that
342
- # call to a "fake" non-deponent (+@proxyVerb+) whose passives fit the correct
343
- # morphology
344
- #
345
- # It calls the following methods, each of which applies the masking to a
346
- # certain collection of vectors:
347
- #
348
- # * +deponent_swap+ :: active_voice* remaps "standard" calls like
349
- # +active_voice_indicative_mood_present_tense...+
350
- # * +deponent_imperative_mutations+ :: masks the imperatives
351
- # * +deponent_participle_mutations+ :: masks the participles
352
- # * +deponent_infinitive_mutations+ :: masks the infinitives
353
- #
354
- ##
355
- def apply_deponent_masking
356
- deponent_swap
357
- deponent_imperative_mutations
358
- deponent_participle_mutations
359
- deponent_infinitive_mutations
360
- end
361
-
362
- ##
363
- #
364
- # The deponent's imperatives require a bit of consideration. They don't
365
- # follow the stem/stem+'ite' format.
366
- #
367
- ##
368
-
369
- def deponent_imperative_mutations # :nodoc:
370
- self.singleton_class.class_eval do
371
- def active_voice_imperative_mood_present_tense_second_person_singular_number
372
- return @proxyVerb.instance_variable_get '@pres_act_inf'
373
- end
374
- def active_voice_imperative_mood_present_tense_second_person_plural_number
375
- return @proxyVerb.send :passive_voice_indicative_mood_present_tense_second_person_plural_number
376
- end
377
- def active_voice_imperative_mood_future_tense_second_person_singular_number
378
- k=@proxyVerb.send :passive_voice_indicative_mood_present_tense_second_person_plural_number
379
- k.sub! /minī$/, ''
380
- k += 'tor'
381
- Linguistics::Latin::Phonographia.fix_macrons k
382
- end
383
- end
384
- end
385
-
386
- def deponent_participle_mutations # :nodoc:
387
- self.singleton_class.class_eval do
388
- def present_active_participle
389
- return @proxyVerb.present_active_participle
390
- end
391
-
392
- def future_active_participle
393
- return @proxyVerb.future_active_participle
394
- end
395
-
396
- def perfect_active_participle
397
- return @proxyVerb.perfect_passive_participle
398
- end
399
-
400
- def future_passive_participle
401
- return @proxyVerb.future_passive_participle
402
- end
403
-
404
- # Mask the supine
405
- def supine
406
- return @proxyVerb.supine
407
- end
408
- end
409
- end
410
-
411
- def deponent_infinitive_mutations # :nodoc:
412
- self.singleton_class.class_eval do
413
- def present_active_infinitive
414
- return @proxyVerb.send :present_passive_infinitive
415
- end
416
- def perfect_active_infinitive
417
- return @proxyVerb.send :perfect_passive_infinitive
418
- end
419
- def future_active_infinitive
420
- return @proxyVerb.send :future_active_infinitive
421
- end
422
- end
423
- end
424
-
425
- ##
426
- #
427
- # Swaps this verb's active_ vectors and replaces them with
428
- # @proxyVerb's passive_ vectors. This is pretty darned sneaky. See
429
- # Also deponent_swap
430
- #
431
- ##
432
- def deponent_swap
433
- # First, get the methods that were defined in the proxy as passive
434
-
435
- storage = {}
436
-
437
- @proxyVerb.methods.grep(/^passive/).each do |pass|
438
- # Find the active correlate
439
- active_corr = pass.to_s.sub /^passive(.*)/, "active\\1"
440
-
441
- # Keep @proxyVerb in the binding scope
442
- pV = @proxyVerb
443
-
444
- # In self, find the passive and save it's resultant object into a
445
- # hash for future use.
446
- self.singleton_class.class_eval do
447
- storage[active_corr.to_sym] = pV.send(pass)
448
- end
449
- end
450
-
451
- # Take the stored hashes and define instance methods on self such
452
- # that we intercept the mixed-in methods ( C-c-c-combo breaker! ).
453
- storage.each_pair do |k,v|
454
- self.singleton_class.class_eval do
455
- define_method k, lambda { return v }
456
- end
457
- end
458
- end
459
-
460
- # Returns the "short" version, sans the module specifier. in previous
461
- # versions, the classification was expressed as a String. While this
462
- # had a certain amount of simplicity, building function is based on
463
- # these classifications seems a linkely future direction.
212
+ ### }}}
464
213
  #
465
- # Furthermore, it is not the case that these are actuallly Strings,
466
- # they are entities of an ontological sttus of their own and it seems
467
- # "off" to consider them as mere strings.
468
- def short_class
469
- return @classification.to_s.gsub(/.*::(\w+)$/,"\\1")
470
- end
214
+ def initialize(data)# {{{
215
+ raise LatinVerbInitializationError if data.nil?
471
216
 
472
- ##
473
- #
474
- # Returns the four principal parts and regularity designation
475
- ##
476
- def to_s
477
- return "#{self.class}: [EMPTY PP]" if @four_pp.nil?
478
- return self.class if @four_pp.empty?
479
- @four_pp.join(', ') + " [Irregular?: #{@irregular.to_s}]"
480
- end
481
-
482
- ##
483
- #
484
- # When working in irb or LatinIRB it's good to find out what the
485
- # instance methods are on this
486
- def instance_methods
487
- self.latin_verbvector_generator.vector_list
488
- end
489
-
490
- private
491
-
492
- def _deponent_handler
493
- @proxyVerb = Linguistics::Latin::Verb::LatinVerb.new @deponent_proxy
494
- end
495
-
496
- def _irregular_handler
497
- begin
498
- # Translation added to account for Ruby not liking constants /^/
499
- # with a multibyte. Probably a bug.
500
- #
501
- # This buy can be discovered by running #constants on
502
- # Linguistics::Latin::Verb and seeing that Ōxxx is not found. To
503
- # fix this i had to store it as ODI_. To make /that/ hack work, I
504
- # had to add this bit beginning two lines below :-/
505
- o = ActiveSupport::Multibyte::Chars.new( @original_string.gsub(/\s+/,'_') ).upcase
506
-
507
- if o.match /^([ĀĒĪŌŪ])(.*)/
508
- x=o[0,1].tr 'ĀĒĪŌŪ', 'AEIOU'
509
- y=o[1,o.length]
510
- o= x+y
511
- end
512
-
513
- o_upcase_and_symbolic = o.to_sym
514
- json_string = Linguistics::Latin::Verb.const_get o_upcase_and_symbolic
515
-
516
-
517
- raise "Found a JSON string with null length!" if json_string.length <= 10
518
- revivified_data_structure = JSON.parse json_string
519
- rescue JSON::ParserError => e
520
- puts "We were unable to parse JSON for #{@original_string} [o:#{o}] [o_sym:#{o_upcase_and_symbolic}]. Please verify your syntax."
521
- raise e
522
- rescue NameError => e
523
- puts "We were unable to find a definition for #{@original_string} [o:#{o}] [o_sym:#{o_upcase_and_symbolic}]. Please provide one."
524
- raise e
525
- rescue => error
526
- warn "#{@original_string} was identified as irregular but did not have a definition provided."
527
- raise error
528
- end
529
-
530
- revivified_data_structure['tense_blocks'].each_pair do |k,v|
531
- singleton_class.class_eval do
532
- define_method k.to_sym do
533
- TenseBlock.new v, { :meaning => MEANINGS[k.to_sym] }
534
- end
535
- end
536
- end
537
-
538
- @irregular_infinitives = revivified_data_structure['infinitives']
539
- @irregular_participles = revivified_data_structure['participles']
540
-
541
- return if @irregular_infinitives.nil?
542
- return if @irregular_participles.nil?
543
-
544
- singleton_class.class_eval do
545
- def present_active_infinitive; return @irregular_infinitives.present_active_infinitive; end
546
- def present_passive_infinitive; return @irregular_infinitives.present_passive_infinitive; end
547
- def perfect_active_infinitive; return @irregular_infinitives.perfect_active_infinitive; end
548
- def perfect_passive_infinitive; return @irregular_infinitives.perfect_passive_infinitive; end
549
- def future_passive_infinitive; return @irregular_infinitives.future_passive_infinitive; end
550
- def future_active_infinitive; return @irregular_infinitives.future_active_infinitive; end
551
- end
552
- singleton_class.class_eval do
553
- def present_active_participle; return @irregular_participles.present_active_participle; end
554
- def future_active_participle; return @irregular_participles.future_active_participle; end
555
- def perfect_passive_participle; return @irregular_participles.perfect_passive_participle; end
556
- def future_passive_participle; return @irregular_participles.future_passive_participle; end
557
- def gerundive; return @irregular_participles.gerundive; end
558
- def gerund; return @irregular_participles.d; end
559
- end
560
-
561
- end
562
-
563
- def respondable_methods
564
- end
565
-
566
- def _init_by_string(s)
567
- # Store the original input
568
- @original_string = s
569
- @classification_error = nil
570
-
571
- # pre-validate the string
572
- self.valid?
573
-
574
- # If the error callback has been created, then call it
575
- @classification_error.call unless @classification_error.nil?
576
-
577
- # Derive from the original, valid string useful specifiers in handy data structures
578
-
579
- unless ( @deponent or @semideponent or @impersonal)
580
- _derive_parts_from_given_string s
581
-
582
- # Derive iVar from derived variables
583
- (@participial_stem ||= calculate_participial_stem) unless @irregular
584
- else
585
- unless @impersonal
586
- fake_string = Linguistics::Latin::Verb::LatinVerb.create_pseudo_active_mask_for_deponent(s)
587
- #_derive_parts_from_given_string fake_string
588
- @deponent_proxy = fake_string
589
- end
590
- end
591
-
592
- end
593
-
594
- def _add_vector_methods
595
- ##
217
+ ### {{{
596
218
  # Generates all the methods to which a verb must be able to respond
597
219
  # by implementing Linguistics::Verbs::Verbvector::VerbvectorGenerator.
598
220
  #
@@ -619,91 +241,201 @@ module Linguistics
619
241
  #
620
242
  # d. The Persons are three: First, Secon, Third.
621
243
  # e. The Numbers are two: Singular and Plural
622
- ##
623
- @latin_verbvector_generator =
624
- Linguistics::Verbs::Verbvector::VerbvectorGenerator.new do
625
- language :Latin do
626
- all_vectors :start_with do
627
- {
628
- :voice => %w(active passive),
629
- :mood => %w(indicative subjunctive imperative)
630
- }
631
- end
632
- vectors_that /.*_indicative_mood/ do
633
- {
634
- :tense => %w(present imperfect future
635
- perfect pastperfect futureperfect)
636
- }
637
- end
638
- vectors_that /.*_subjunctive_mood/ do
639
- {
640
- :tense => %w(present imperfect
641
- perfect pastperfect)
642
- }
643
- end
644
- vectors_that /.*_imperative_mood/ do
645
- {
646
- :tense => %w(present future)
647
- }
648
- end
649
- all_vectors :end_with do
650
- {
651
- :person => %w(first second third),
652
- :number => %w(singular plural)
653
- }
654
- end
655
- exception :remove, :passive_voice_imperative_mood_present_tense
656
- exception :remove, :passive_voice_imperative_mood_future_tense
657
- cluster_on :tense, "as method", :tense_list
658
- end
244
+ ### }}}
245
+ @latin_verbvector_generator =
246
+ Linguistics::Verbs::Verbvector::VerbvectorGenerator.new(
247
+ &Linguistics::Latin::Verb::LatinVerb::LATIN_VERBVECTOR_DESCRIPTION )
248
+
249
+ # We're restoring a standard verb from JSON
250
+ data = data['original_string'] if init_data_is_a_hash_of_a_regular_restorable_verb(data)
251
+
252
+ if data.is_a? String
253
+ @sanitizer = LatinVerbInputSanitizer.new data
254
+ @original_string = @sanitizer.to_s
255
+ @classifier = LatinVerbClassifier.new @original_string
256
+ @prin_parts_extractor = LatinVerbPPExtractor.new @sanitizer.to_s, @classifier
257
+ @verb_type = LatinVerbTypeEvaluator.new first_person_singular, present_active_infinitive, @classifier
258
+
259
+ load_tense_methods
260
+ generate_methods_for_accessing_tense_blocks_from_tense_methods_components
261
+ include_classification_specific_mixins
262
+ check_and_mutate_defectives
659
263
  end
264
+ end# }}}
660
265
 
661
- # This provides methods of the form #{language_name}_#{fake_name}.
662
- # They are actually called sans #{language_name} so that
663
- # method_missing is called.
664
- @verb_methods = @latin_verbvector_generator.method_extension_module
266
+ ######################################################################
267
+ # Instance methods
268
+ ######################################################################
269
+ ##
665
270
 
666
- # Make sure all the cluster methods are defined. Ensure we don't
667
- # get infinite stack method_missing lookups
668
- @tense_list =
669
- @latin_verbvector_generator.cluster_methods[:tense_list].call
271
+ def present_only?# {{{
272
+ @present_only ||= @classifier.present_only?
273
+ end# }}}
274
+ def short_class# {{{
275
+ return classification.to_s.gsub(/.*::(\w+)$/,"\\1")
276
+ end# }}}
670
277
 
671
- # POWER-UP with the vector methods
672
- self.extend @verb_methods
278
+ ### {{{
279
+ #
280
+ # Returns the four principal parts and regularity designation
281
+ ### }}}
282
+ def to_s# {{{
283
+ return sprintf("%s [%s]", short_class, original_string)
284
+ end# }}}
285
+
286
+ ### {{{
287
+ #
288
+ # When working in irb or LatinIRB it's good to find out what the
289
+ # instance methods are on this# }}}
290
+ def instance_methods# {{{
291
+ @latin_verbvector_generator.vector_list
292
+ end# }}}
293
+
294
+ def regular?# {{{
295
+ @classifier.regular?
296
+ end# }}}
297
+
298
+ def irregular?# {{{
299
+ @classifier.irregular?
300
+ end# }}}
301
+
302
+ def classification# {{{
303
+ @classifier.classification
304
+ end# }}}
305
+
306
+ def verb_type# {{{
307
+ @verb_type.inspect
308
+ end# }}}
309
+
310
+ def stem# {{{
311
+ unless classified_as.irregular?
312
+ @stem ||= @prin_parts_extractor.stem
673
313
  end
314
+ end# }}}
315
+
316
+ def conjugation# {{{
317
+ classification.to_s
318
+ end# }}}
319
+
320
+ def principal_parts# {{{
321
+ @principal_parts ||= @prin_parts_extractor.principal_parts
322
+ end# }}}
323
+
324
+ def classified_as# {{{
325
+ return @classifier
326
+ end# }}}
327
+
328
+ def first_person_singular# {{{
329
+ @first_person_singular ||= @prin_parts_extractor.first_person_singular
330
+ end# }}}
331
+
332
+ def present_active_infinitive# {{{
333
+ @present_active_infinitive ||= @prin_parts_extractor.present_active_infinitive
334
+ end# }}}
335
+
336
+ def first_person_perfect# {{{
337
+ @first_person_perfect ||= @prin_parts_extractor.first_person_perfect
338
+ end# }}}
339
+
340
+ def passive_perfect_participle# {{{
341
+ @passive_perfect_participle ||= @prin_parts_extractor.passive_perfect_participle
342
+ end# }}}
343
+
344
+ def participial_stem# {{{
345
+ @participial_stem ||= @prin_parts_extractor.participial_stem
346
+ end# }}}
347
+
348
+ # ===============================================================================
349
+
350
+ private
351
+
352
+ def load_tense_methods# {{{
353
+ load_tense_methods_that_do_not_vary_by_verb_type
354
+ load_tense_methods_based_on_verb_type
355
+ end# }}}
356
+
357
+ def load_tense_methods_that_do_not_vary_by_verb_type# {{{
358
+ self.extend Linguistics::Latin::Verb::TenseDefinitions::Invariant
359
+ end# }}}
360
+
361
+ def load_tense_methods_based_on_verb_type #{{{
362
+ # Turn Linguistics::Latin::Verb::VerbTypes::First into
363
+ # Linguistics::Latin::Verb::TenseDefinitions::First and extend with it
364
+ mod_path = @verb_type.inspect.to_s
365
+ return if mod_path.empty?
366
+ mod_path.sub!('VerbTypes', 'TenseDefinitions' )
367
+ the_mod = mod_path.split('::').inject(Object) do |mod, class_name|
368
+ mod.const_get(class_name)
369
+ end
370
+ self.extend the_mod
371
+ end# }}}
372
+
373
+ def verify_generated_tense_list# {{{
374
+ # Given the use of method_missing to handle resolution, it's wise to
375
+ # make sure that every cluster method /is/ actually defined.
376
+ @tense_list.each do |m|
377
+ raise "FAILURE: Critical method #{m} was not defined." unless
378
+ (self.respond_to? m.to_sym)
379
+ end
380
+ end# }}}
381
+
382
+ def init_data_is_a_hash_of_a_regular_restorable_verb(data)# {{{
383
+ (data.is_a?(Hash) && !data['irregular'] && data.has_key?('original_string'))
384
+ end# }}}
385
+
386
+ def generate_methods_for_accessing_tense_blocks_from_tense_methods_components# {{{
387
+ self.extend @latin_verbvector_generator.method_extension_module
388
+ @tense_list =
389
+ @latin_verbvector_generator.cluster_methods[:tense_list].call
390
+ verify_generated_tense_list
391
+ end# }}}
392
+
393
+ def include_classification_specific_mixins# {{{
394
+ the_mod = if classified_as.impersonal?
395
+ Linguistics::Latin::Verb::LatinVerb::Impersonal
396
+ elsif classified_as.irregular?
397
+ Linguistics::Latin::Verb::LatinVerb::Irregular
398
+ elsif classified_as.deponent?
399
+ Linguistics::Latin::Verb::LatinVerb::Deponent
400
+ elsif classified_as.semideponent?
401
+ Linguistics::Latin::Verb::LatinVerb::Semideponent
402
+ elsif classified_as.present_only?
403
+ Linguistics::Latin::Verb::LatinVerb::PresentOnly
404
+ end
405
+
406
+ return unless the_mod
407
+
408
+ # Tell the instance to pull in the instance methods in the module by
409
+ # extending itself.
410
+ self.instance_eval do
411
+ self.extend the_mod
412
+ end
413
+
414
+ end# }}}
674
415
 
675
- def _derive_parts_from_given_string(s)
676
- @principal_parts
677
- @first_pers_singular,
678
- @pres_act_inf,
679
- @first_pers_perf,
680
- @pass_perf_part = @four_pp = @principal_parts = s.split(/\s+/)
416
+ def check_and_mutate_defectives# {{{
417
+ is_defective = Linguistics::Latin::Verb::LatinVerb::DefectiveChecker::is_it_defective?(self)
418
+ if is_defective
419
+ @classifier.set_as_defective
420
+ remove_perfect_tenses
681
421
  end
422
+ end# }}}
682
423
 
683
- def calculate_participial_stem
684
- raise("@pres_act_inf was nil!") if
685
- @pres_act_inf.nil? or @first_pers_singular.nil?
686
-
687
- if @pres_act_inf.to_s =~ /(.*ā)re$/
688
- return $1
689
- end
690
-
691
- if @pres_act_inf.to_s =~ /(.*ē)re$/
692
- return $1
693
- end
694
-
695
- if @pres_act_inf.to_s =~ /(.*)ere$/
696
- match=$1
697
- if @first_pers_singular =~ /iō/
698
- return match + "iē"
699
- else
700
- return match + "e"
701
- end end
702
-
703
- if @pres_act_inf.to_s =~ /(.*)īre$/
704
- return $1 + "iē"
705
- end
706
- end
424
+ def remove_perfect_tenses# {{{
425
+ # Get perfect system methods
426
+ tense_blocks_to_eclipse =
427
+ self.methods.grep( /^(active|passive).*(_|past|future)perfect_/ )
428
+
429
+ # Re-assign their methods to point to a blank TenseBlock, thus
430
+ # eclipsing any values thatm ight come in.
431
+ tense_blocks_to_eclipse.each do |s|
432
+ singleton_class.class_eval do
433
+ define_method s do
434
+ return TenseBlock.null_tense_block
435
+ end
436
+ end
437
+ end
438
+ end# }}}
707
439
  end
708
440
  end
709
441
  end