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.
- data/.gitignore +0 -1
- data/Gemfile +1 -2
- data/README.markdown +54 -240
- data/etc/irreg_skel.json +104 -0
- data/{latinirb.gemspec → latinverb.gemspec} +4 -4
- data/lib/latinverb/chart.rb +94 -0
- data/lib/latinverb/version.rb +10 -0
- data/lib/latinverb.rb +710 -0
- data/lib/linguistics/latin/verb/classification_types.rb +59 -0
- data/lib/linguistics/latin/verb/constants.rb +201 -0
- data/lib/linguistics/latin/verb/deponent_tense_methods.rb +98 -0
- data/lib/linguistics/latin/verb/infinitives.rb +212 -0
- data/lib/linguistics/latin/verb/irregulars.rb +4393 -0
- data/lib/linguistics/latin/verb/latinverb/auxiliary_classes.rb +208 -0
- data/lib/linguistics/latin/verb/latinverb/classmethods.rb +215 -0
- data/lib/linguistics/latin/verb/latinverb/data.rb +90 -0
- data/lib/linguistics/latin/verb/latinverb/display.rb +23 -0
- data/lib/linguistics/latin/verb/latinverb/metaprogramming.rb +79 -0
- data/lib/linguistics/latin/verb/latinverb/validation.rb +66 -0
- data/lib/linguistics/latin/verb/participles.rb +202 -0
- data/lib/linguistics/latin/verb/phonographia.rb +109 -0
- data/lib/linguistics/latin/verb/supine.rb +42 -0
- data/lib/linguistics/latin/verb/tense_methods.rb +950 -0
- data/test/testAmbiguousLookups.rb +30 -0
- data/test/testClusterResolution.rb +20 -0
- data/test/testDataStructures.rb +29 -0
- data/test/testDefectSemiImp.rb +111 -0
- data/test/testDeponentFirstConjugation.rb +64 -0
- data/test/testDeponentFourthConjugation.rb +64 -0
- data/test/testDeponentSecondConjugation.rb +64 -0
- data/test/testDeponentThirdConjugation.rb +64 -0
- data/test/testDeponentThirdIOConjugation.rb +64 -0
- data/test/testDeserializeInfinitives.rb +38 -0
- data/test/testFirstConjugation.rb +388 -0
- data/test/testFourthConjugation.rb +190 -0
- data/test/testFreakishVerbs.rb +93 -0
- data/test/testImperativeBlock.rb +27 -0
- data/test/testIrregularSum.rb +22 -0
- data/test/testIrregulars.rb +652 -0
- data/test/testLatinVerb.rb +195 -0
- data/test/testMacronRules.rb +19 -0
- data/test/testSecondConjugation.rb +189 -0
- data/test/testThirdConjugation.rb +190 -0
- data/test/testThirdIOConjugation.rb +190 -0
- metadata +70 -18
- data/bin/latinirb.rb +0 -7
- data/latinverb.rb +0 -544
- data/lib/LatinIRB.rb +0 -172
- data/lib/latinirb/paradigmatic_verbs.rb +0 -17
- data/lib/latinirb/version.rb +0 -10
- data/lib/latirb.rb +0 -20
data/lib/latinverb.rb
ADDED
@@ -0,0 +1,710 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#------------------------------------------------------------------------------
|
3
|
+
# DEPENDENCIES
|
4
|
+
#------------------------------------------------------------------------------
|
5
|
+
# External dependencies
|
6
|
+
require 'verbvector'
|
7
|
+
require 'yaml'
|
8
|
+
require 'json'
|
9
|
+
require 'active_support'
|
10
|
+
|
11
|
+
##
|
12
|
+
#--
|
13
|
+
# Internal dependencies
|
14
|
+
# If the library is in the latin/verb, then it is a feature of the actual
|
15
|
+
# Latin language as abstracted into Ruby. If it is in the latin/verb/latinverb directory, it is part
|
16
|
+
# of the mechanics of the representation of that language as Ruby, i.e. this
|
17
|
+
# program. It's the difference between "This is part of Latin" and "This is
|
18
|
+
# Part of the machinery I use to represent Latin in Ruby."
|
19
|
+
#++
|
20
|
+
##
|
21
|
+
|
22
|
+
require 'linguistics/latin/verb/classification_types'
|
23
|
+
require 'linguistics/latin/verb/tense_methods'
|
24
|
+
require 'linguistics/latin/verb/deponent_tense_methods'
|
25
|
+
require 'linguistics/latin/verb/supine'
|
26
|
+
require 'linguistics/latin/verb/phonographia'
|
27
|
+
require 'linguistics/latin/verb/constants'
|
28
|
+
require 'linguistics/latin/verb/infinitives'
|
29
|
+
require 'linguistics/latin/verb/participles'
|
30
|
+
require 'linguistics/latin/verb/irregulars'
|
31
|
+
|
32
|
+
require 'linguistics/latin/verb/latinverb/classmethods'
|
33
|
+
require 'linguistics/latin/verb/latinverb/metaprogramming'
|
34
|
+
require 'linguistics/latin/verb/latinverb/validation'
|
35
|
+
require 'linguistics/latin/verb/latinverb/data'
|
36
|
+
require 'linguistics/latin/verb/latinverb/display'
|
37
|
+
|
38
|
+
require 'latinverb/version'
|
39
|
+
require 'latinverb/chart.rb'
|
40
|
+
|
41
|
+
=begin rdoc
|
42
|
+
|
43
|
+
==DESCRIPTION
|
44
|
+
|
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
|
+
|
47
|
+
=end
|
48
|
+
|
49
|
+
module Linguistics
|
50
|
+
# Generalized module for handling lingustics related to Latin
|
51
|
+
module Latin
|
52
|
+
# Generalized module for handling lingustics related to Latin's verbal aspects
|
53
|
+
module Verb
|
54
|
+
##
|
55
|
+
# == SYNOPSIS
|
56
|
+
#
|
57
|
+
# Abstraction of a Verb in the Latin language.
|
58
|
+
#
|
59
|
+
# == DESCRIPTION
|
60
|
+
#
|
61
|
+
# LatinVerb is:
|
62
|
+
# * a tool to help the student of Latin understand the rules of
|
63
|
+
# conjugation's heuristics by presenting said heuristics in Ruby
|
64
|
+
# * a way to get out of having to lug the 501 Latin Verbs book around
|
65
|
+
# (when wrapped in an application ;) )
|
66
|
+
# * a way to discover some of the interesting metacongnitive structures
|
67
|
+
# between natural language and programming language
|
68
|
+
# * <em>...and so much more...</em>
|
69
|
+
#
|
70
|
+
# === OPERATION
|
71
|
+
#
|
72
|
+
# LatinVerb operates by instantiating a LatinVerb based on a string
|
73
|
+
# containing the "four principal parts" that are used to describe a
|
74
|
+
# Latin verb. From this simple entry, one calls "vectors' upon the
|
75
|
+
# object. Vectors represent the unique, "fully-qualified" locus of a
|
76
|
+
# conjugated form. A feature that was of paramount importance in its
|
77
|
+
# implementation was that the conjugation <b>should occur by
|
78
|
+
# heruristic</b> in the exact same way that <b>humans have been
|
79
|
+
# taught</b> in Latin classes for _milennia_!
|
80
|
+
#
|
81
|
+
# An example should illustrate:
|
82
|
+
#
|
83
|
+
# === EXAMPLE
|
84
|
+
#
|
85
|
+
# <pre>
|
86
|
+
# to_love = LatinVerb.new("amō amāre amāvī amatum")
|
87
|
+
# to_love.active_voice_indicative_mood_present_tense_second_person_singular_number #=> amās
|
88
|
+
# to_love.active_voice_indicative_mood_present_tense_third_person_singular_number #=> amat
|
89
|
+
# </pre>
|
90
|
+
#
|
91
|
+
# === EXPLICATION
|
92
|
+
#
|
93
|
+
# Considering the above example, when the object was insantiated, it
|
94
|
+
# realized what its conjugation was, realized what its stem ("amā") was,
|
95
|
+
# and then added to itself support for
|
96
|
+
# <tt>active_voice_indicative_mood_present_tense</tt> which is defined
|
97
|
+
# as "take the stem and postpend "ō, s, t, mus, tis, nt" to the stem and
|
98
|
+
# return it as an array. It is through (mis-?)use of method_missing
|
99
|
+
# that this simple "vector" method for interfacing with a verb is
|
100
|
+
# possible. <em>Puto hoc bonum esse</em>.
|
101
|
+
#
|
102
|
+
# === MACRONS / QUANTITY
|
103
|
+
#
|
104
|
+
# In reference texts, quanitiy of vowel duration ("long" or "short") is
|
105
|
+
# marked with a macron. *LatinVerb assumes it will be provided strings
|
106
|
+
# with macrons*. This makes sense as per the previous section, the
|
107
|
+
# conjugation is done by heuristic. What isn't there cannot be altered.
|
108
|
+
# <em>Si hoc non aderit, non mutabitur</em>. To make this easier I
|
109
|
+
# wrote the MacronConversion library which supports conversion of
|
110
|
+
# LaTeX-styled ASCII macron transgraphia (e.g. \={a} => ā).
|
111
|
+
#
|
112
|
+
#
|
113
|
+
# === REFERENCE
|
114
|
+
#
|
115
|
+
# ==== Voices
|
116
|
+
# A&G Sec. 156:
|
117
|
+
#
|
118
|
+
# The Active and Passive Voices in Latin generally correspond to the
|
119
|
+
# active and passive in English; but --
|
120
|
+
#
|
121
|
+
# a. The passive voice often has a reflexive meaning: --
|
122
|
+
# b. Many verbs are passive in form, but active or reflexive in
|
123
|
+
# meaning. These are called Deponents (sec 190.)...
|
124
|
+
# c. Some verbs with active meaning have the passive form in the
|
125
|
+
# perfect tenses; these are called Semi-Deponents
|
126
|
+
#
|
127
|
+
# ==== Moods
|
128
|
+
#
|
129
|
+
# a. The Indicative Mood is used for most <em>direct assertions</em>
|
130
|
+
# and <em>interrogations</em>
|
131
|
+
# b. The Subjunctive Mood has many idiomatic uses, as in
|
132
|
+
# <em>commands</em>, <em>conditions</em>, and various <em>dependent
|
133
|
+
# clauses</em>.
|
134
|
+
# c. The Imperative is used for <em>exhortation</em>,
|
135
|
+
# <em>entreaty</em>, or <em>command</em>; but the Subjunctive is often
|
136
|
+
# used instead
|
137
|
+
#
|
138
|
+
# === WORKS CITED
|
139
|
+
#
|
140
|
+
# Allen, J.H. Allen and Greenough's New Latin Grammar. Dover,
|
141
|
+
# Mineola: 2006. Cited herein as "A&G."
|
142
|
+
#
|
143
|
+
# Wheelock, Frederic M. Wheelock's Latin. Collins, New York: 2005.
|
144
|
+
# Cited herein as "Wheelock."
|
145
|
+
#
|
146
|
+
##
|
147
|
+
class LatinVerb
|
148
|
+
# Modules used to validate the input in initialize
|
149
|
+
include Linguistics::Latin::Verb::Validation
|
150
|
+
include Linguistics::Latin::Verb::Participles
|
151
|
+
include Linguistics::Latin::Verb::Infinitives
|
152
|
+
|
153
|
+
# Attributes for storing submitted data. This will help remember the origin state
|
154
|
+
attr_reader :original_string
|
155
|
+
|
156
|
+
# 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
|
161
|
+
|
162
|
+
# 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
|
167
|
+
|
168
|
+
alias_method :conjugation, :classification
|
169
|
+
alias_method :irregular?, :irregular
|
170
|
+
|
171
|
+
##
|
172
|
+
#
|
173
|
+
# The constructor for a Latinverb
|
174
|
+
#
|
175
|
+
# ===ARGUMENTS
|
176
|
+
#
|
177
|
+
# *s:* :: +s+ is class-tested and supports String or Hash classes,
|
178
|
+
# with the standard path having been designed to accept a string
|
179
|
+
# containing 4 words ("four principal parts"). Latin's principal
|
180
|
+
# irregular verbs are also accepted (see CONSTANTS) as possible
|
181
|
+
# entries. +s+ also accepts a Hash as input. This is used for
|
182
|
+
# deserialization from JSON which initialized based on a Hash.
|
183
|
+
#
|
184
|
+
# == SEE ALSO
|
185
|
+
#
|
186
|
+
# #initialize does very little work. Therefore special attention
|
187
|
+
# should be paid to the #_init_by_string and _add_vector_methods.
|
188
|
+
# These are the workhorses of this class and do most of the decoration
|
189
|
+
# activity. In the case of extending to support irregular verbs,
|
190
|
+
# #_irregular_handler is a critical path to explore.
|
191
|
+
#
|
192
|
+
# == TODO
|
193
|
+
#
|
194
|
+
# * Array support for the argument
|
195
|
+
#
|
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.
|
464
|
+
#
|
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
|
471
|
+
|
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
|
+
##
|
596
|
+
# Generates all the methods to which a verb must be able to respond
|
597
|
+
# by implementing Linguistics::Verbs::Verbvector::VerbvectorGenerator.
|
598
|
+
#
|
599
|
+
# This conforms to the definition provided in Allen & Greenough Sec.
|
600
|
+
# 154:
|
601
|
+
#
|
602
|
+
# Through its conjugation the Verb expresses Voice, Mood, Tense
|
603
|
+
# Person, and Number.
|
604
|
+
#
|
605
|
+
# a. The Voices are two: Active and Passive
|
606
|
+
# b. The Moods are four: Indicative,Subjuncitve, Imperative, and
|
607
|
+
# Infinitive
|
608
|
+
#
|
609
|
+
# ...
|
610
|
+
#
|
611
|
+
# c. The Tenses are six, viz: --
|
612
|
+
# 1. For continued action: Present, Imperfect, Future
|
613
|
+
# 2. For completed action, Perfect, Pluperfect, Future Perfect
|
614
|
+
#
|
615
|
+
# The Indicative Mood has all six tenses, but the Subjunctive has
|
616
|
+
# no future or future perfect and the Imperative has only the
|
617
|
+
# present and the future. The Infinitive has the present, perfect,
|
618
|
+
# and future.
|
619
|
+
#
|
620
|
+
# d. The Persons are three: First, Secon, Third.
|
621
|
+
# 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
|
659
|
+
end
|
660
|
+
|
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
|
665
|
+
|
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
|
670
|
+
|
671
|
+
# POWER-UP with the vector methods
|
672
|
+
self.extend @verb_methods
|
673
|
+
end
|
674
|
+
|
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+/)
|
681
|
+
end
|
682
|
+
|
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
|
707
|
+
end
|
708
|
+
end
|
709
|
+
end
|
710
|
+
end
|