llt-form_builder 0.0.1

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 (118) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +8 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +29 -0
  8. data/Rakefile +8 -0
  9. data/lib/llt/form/adjective.rb +19 -0
  10. data/lib/llt/form/adverb.rb +13 -0
  11. data/lib/llt/form/cardinal.rb +31 -0
  12. data/lib/llt/form/conjunction.rb +7 -0
  13. data/lib/llt/form/declinable.rb +23 -0
  14. data/lib/llt/form/demonstrative_pronoun.rb +7 -0
  15. data/lib/llt/form/ethnic.rb +6 -0
  16. data/lib/llt/form/fp.rb +6 -0
  17. data/lib/llt/form/gerund.rb +9 -0
  18. data/lib/llt/form/gerundive.rb +12 -0
  19. data/lib/llt/form/indefinite_pronoun.rb +7 -0
  20. data/lib/llt/form/infinitive.rb +13 -0
  21. data/lib/llt/form/interrogative_pronoun.rb +7 -0
  22. data/lib/llt/form/noun.rb +17 -0
  23. data/lib/llt/form/participle.rb +9 -0
  24. data/lib/llt/form/personal_pronoun.rb +13 -0
  25. data/lib/llt/form/ppa.rb +6 -0
  26. data/lib/llt/form/ppp.rb +6 -0
  27. data/lib/llt/form/preposition.rb +32 -0
  28. data/lib/llt/form/pronoun.rb +17 -0
  29. data/lib/llt/form/relative_pronoun.rb +7 -0
  30. data/lib/llt/form/subjunction.rb +7 -0
  31. data/lib/llt/form/supinum.rb +6 -0
  32. data/lib/llt/form/uninflectable.rb +22 -0
  33. data/lib/llt/form/verb.rb +28 -0
  34. data/lib/llt/form/verbal_noun.rb +18 -0
  35. data/lib/llt/form.rb +80 -0
  36. data/lib/llt/form_builder/adjective_builder.rb +86 -0
  37. data/lib/llt/form_builder/adverb_builder.rb +25 -0
  38. data/lib/llt/form_builder/declinable_builder.rb +164 -0
  39. data/lib/llt/form_builder/ethnic_builder.rb +17 -0
  40. data/lib/llt/form_builder/fp_builder.rb +13 -0
  41. data/lib/llt/form_builder/gerund_builder.rb +37 -0
  42. data/lib/llt/form_builder/gerundive_builder.rb +24 -0
  43. data/lib/llt/form_builder/helpers/adjective_like_building.rb +29 -0
  44. data/lib/llt/form_builder/helpers/pronoun_segments.rb +226 -0
  45. data/lib/llt/form_builder/helpers/stem_hash_parser.rb +263 -0
  46. data/lib/llt/form_builder/helpers/verb_segments.rb +562 -0
  47. data/lib/llt/form_builder/infinitivum_builder.rb +19 -0
  48. data/lib/llt/form_builder/irregular_gerund_builder.rb +7 -0
  49. data/lib/llt/form_builder/irregular_gerundive_builder.rb +7 -0
  50. data/lib/llt/form_builder/irregular_ppa_builder.rb +7 -0
  51. data/lib/llt/form_builder/irregular_praesens_builder.rb +5 -0
  52. data/lib/llt/form_builder/irregular_praesens_infinitivum_builder.rb +5 -0
  53. data/lib/llt/form_builder/noun_builder.rb +24 -0
  54. data/lib/llt/form_builder/perfectum_builder.rb +14 -0
  55. data/lib/llt/form_builder/perfectum_infinitivum_builder.rb +7 -0
  56. data/lib/llt/form_builder/personal_pronoun_builder.rb +107 -0
  57. data/lib/llt/form_builder/ppa_builder.rb +20 -0
  58. data/lib/llt/form_builder/ppp_builder.rb +10 -0
  59. data/lib/llt/form_builder/praesens_builder.rb +41 -0
  60. data/lib/llt/form_builder/praesens_infinitivum_builder.rb +9 -0
  61. data/lib/llt/form_builder/pronoun_builder.rb +106 -0
  62. data/lib/llt/form_builder/supinum_builder.rb +23 -0
  63. data/lib/llt/form_builder/verb_builder.rb +37 -0
  64. data/lib/llt/form_builder/version.rb +5 -0
  65. data/lib/llt/form_builder.rb +370 -0
  66. data/lib/llt/stem/adjective_pack.rb +122 -0
  67. data/lib/llt/stem/adjective_stem.rb +23 -0
  68. data/lib/llt/stem/ethnic_stem.rb +9 -0
  69. data/lib/llt/stem/noun_pack.rb +14 -0
  70. data/lib/llt/stem/noun_stem.rb +26 -0
  71. data/lib/llt/stem/pack.rb +46 -0
  72. data/lib/llt/stem/verb_pack.rb +53 -0
  73. data/lib/llt/stem/verb_stem.rb +18 -0
  74. data/lib/llt/stem.rb +145 -0
  75. data/lib/llt/stem_builder.rb +53 -0
  76. data/llt-form_builder.gemspec +30 -0
  77. data/spec/lib/llt/form/adjective_spec.rb +10 -0
  78. data/spec/lib/llt/form/adverb_spec.rb +17 -0
  79. data/spec/lib/llt/form/conjunction_spec.rb +23 -0
  80. data/spec/lib/llt/form/demonstrative_pronoun_spec.rb +14 -0
  81. data/spec/lib/llt/form/fp_spec.rb +12 -0
  82. data/spec/lib/llt/form/functions_spec.rb +13 -0
  83. data/spec/lib/llt/form/gerund_spec.rb +10 -0
  84. data/spec/lib/llt/form/gerundive_spec.rb +13 -0
  85. data/spec/lib/llt/form/noun_spec.rb +18 -0
  86. data/spec/lib/llt/form/ppa_spec.rb +12 -0
  87. data/spec/lib/llt/form/ppp_spec.rb +12 -0
  88. data/spec/lib/llt/form/preposition_spec.rb +43 -0
  89. data/spec/lib/llt/form/supinum_spec.rb +9 -0
  90. data/spec/lib/llt/form/verb_spec.rb +14 -0
  91. data/spec/lib/llt/form_builder/adjective_builder_spec.rb +182 -0
  92. data/spec/lib/llt/form_builder/adverb_builder_spec.rb +27 -0
  93. data/spec/lib/llt/form_builder/ethnic_builder_spec.rb +17 -0
  94. data/spec/lib/llt/form_builder/form_builder_spec.rb +16 -0
  95. data/spec/lib/llt/form_builder/fp_builder_spec.rb +42 -0
  96. data/spec/lib/llt/form_builder/gerund_builder_spec.rb +80 -0
  97. data/spec/lib/llt/form_builder/gerundive_builder_spec.rb +102 -0
  98. data/spec/lib/llt/form_builder/helpers/stem_hash_parser_spec.rb +197 -0
  99. data/spec/lib/llt/form_builder/irregular_gerund_builder_spec.rb +22 -0
  100. data/spec/lib/llt/form_builder/irregular_gerundive_builder_spec.rb +21 -0
  101. data/spec/lib/llt/form_builder/irregular_praesens_builder_spec.rb +14 -0
  102. data/spec/lib/llt/form_builder/irregular_praesens_infinitivum_builder_spec.rb +32 -0
  103. data/spec/lib/llt/form_builder/noun_builder_spec.rb +245 -0
  104. data/spec/lib/llt/form_builder/personal_pronoun_builder_spec.rb +49 -0
  105. data/spec/lib/llt/form_builder/ppa_builder_spec.rb +137 -0
  106. data/spec/lib/llt/form_builder/ppp_builder_spec.rb +45 -0
  107. data/spec/lib/llt/form_builder/pronoun_builder_spec.rb +203 -0
  108. data/spec/lib/llt/form_builder/supinum_builder_spec.rb +24 -0
  109. data/spec/lib/llt/form_builder/verb_builder_spec.rb +557 -0
  110. data/spec/lib/llt/form_spec.rb +27 -0
  111. data/spec/lib/llt/stem/adjective_pack_spec.rb +78 -0
  112. data/spec/lib/llt/stem/adjective_stem_spec.rb +15 -0
  113. data/spec/lib/llt/stem/noun_pack_spec.rb +20 -0
  114. data/spec/lib/llt/stem/noun_stem_spec.rb +14 -0
  115. data/spec/lib/llt/stem/verb_pack_spec.rb +56 -0
  116. data/spec/lib/llt/stem_builder_spec.rb +20 -0
  117. data/spec/spec_helper.rb +21 -0
  118. metadata +330 -0
@@ -0,0 +1,370 @@
1
+ require 'set'
2
+
3
+ require 'llt/helpers'
4
+ require 'llt/constants'
5
+ require 'llt/core_extensions/array'
6
+
7
+ require 'llt/form'
8
+ require 'llt/form_builder/version'
9
+ require 'llt/form_builder/helpers/adjective_like_building'
10
+ require 'llt/form_builder/helpers/pronoun_segments'
11
+ require 'llt/form_builder/helpers/stem_hash_parser'
12
+ require 'llt/form_builder/helpers/verb_segments'
13
+
14
+ require 'llt/stem'
15
+
16
+ module LLT
17
+ class FormBuilder
18
+
19
+ include Helpers::Constantize
20
+ include Helpers::Initialize
21
+ include Helpers::Metrical
22
+ include Helpers::Normalizer
23
+
24
+ extend Helpers::Normalizer
25
+ extend Helpers::Constantize
26
+
27
+ class << self
28
+ def build(*stem_hashes)
29
+ stem_hashes = StemHashParser.new(stem_hashes).parse
30
+ stem_hashes.flat_map do |stem|
31
+ builder_kl = constant_by_type(stem[:type], suffix: "builder")
32
+ builder_kl.new(stem).compute
33
+ end.compact # adverb might return nil forms
34
+ end
35
+
36
+ # Defines the class to use for obtaining additional build information
37
+ # like thematic vowels or stem extension (e.g. an Imperfectum -ba-).
38
+ # Defaults to VerbSegments, most commonly used.
39
+ #
40
+ # The argument should be a Class name.
41
+ def lookup_class(arg = nil)
42
+ arg ? @lookup_class = arg : @lookup_class ||= VerbSegments
43
+ end
44
+
45
+ # Holds a list of attributes, that will be validated.
46
+ def validations
47
+ @validations ||= []
48
+ end
49
+
50
+ private
51
+
52
+ # Defines the class of the outputted forms. Defaults to the
53
+ # stem type, # e.g. a :noun stem will build Noun objects.
54
+ #
55
+ # Takes a symbol as argument.
56
+ def form_class(arg)
57
+ define_method(:form_class) do
58
+ constant_by_type(arg, namespace: LLT::Form)
59
+ end
60
+ end
61
+
62
+ # Defines which information is needed to obtain the proper set of
63
+ # endings for a stem. E.g. a noun uses its inflection_class and sexus.
64
+ def endings_defined_through(*args)
65
+ define_method(:endings_attributes) do
66
+ args.map { |arg| instance_variable_get("@#{arg}") }
67
+ end
68
+ end
69
+
70
+ # Defines which endings shall be used, defaults to the stem's type,
71
+ # a noun stem uses noun endings.
72
+ # Used by irregular_ppa stems - they use the regular ppa endings.
73
+ def uses_endings_of(val)
74
+ define_method(:endings_container) { val }
75
+ end
76
+
77
+ # Defines additional attributes that shall be passed
78
+ # to the newly built Form object. Cf. #default_args
79
+ def builds_with(*args)
80
+ anonymous = Module.new do
81
+ define_method(:default_args) do
82
+ # [:a, :b] to { a: a, b: b }, where a and b are method calls,
83
+ # evaluated in the instance's scope.
84
+ hsh = Hash[ args.map { |arg| [arg, send(arg)] } ]
85
+
86
+ # Mind the empty brackets, super throws an exception
87
+ # inside of define_method otherwise
88
+ super().merge(hsh)
89
+ end
90
+ end
91
+
92
+ include anonymous
93
+ end
94
+
95
+ # Defines which attributes shall be looked up in the lookup_class.
96
+ # Such values are automatically included in the validation process.
97
+ def look_up(*vars)
98
+ vars.each do |arg|
99
+ anon = Module.new do
100
+ define_method(:extensions_and_other_signs) do |args|
101
+ kl = self.class.lookup_class
102
+ val = kl.get(arg, args.merge(default_args))
103
+ args[arg] = val unless val.empty?
104
+ super(args)
105
+ end
106
+ end
107
+
108
+ include anon
109
+ end
110
+
111
+ validate(vars)
112
+ end
113
+
114
+ # Defines arguments that need to be validated.
115
+ def validate(*args)
116
+ validations << args
117
+ validations.flatten!
118
+ end
119
+
120
+ # Responds to has_*** methods and takes one argument.
121
+ # Defines default values for certain attributes,
122
+ # e.g. a Gerund's stem always has_extension "nd".
123
+ def method_missing(meth, *args, &blk)
124
+ if meth.to_s.match(/^has_(.*)/)
125
+ define_method($1) { args.first }
126
+ else
127
+ super
128
+ end
129
+ end
130
+
131
+ # Syntactic sugar to include modules with special behavior.
132
+ def builds_like_an(arg)
133
+ include FormBuilder.const_get("#{arg.capitalize}LikeBuilding")
134
+ end
135
+ alias :builds_like_a :builds_like_an
136
+ end
137
+
138
+ files = %w{ declinable noun ppp adjective ethnic
139
+ pronoun personal_pronoun
140
+ verb praesens perfectum ppa fp gerund gerundive supinum
141
+ infinitivum praesens_infinitivum perfectum_infinitivum
142
+ irregular_praesens irregular_ppa
143
+ irregular_gerundive irregular_gerund
144
+ irregular_praesens_infinitivum
145
+ adverb }
146
+ files.each do |file|
147
+ require "llt/form_builder/#{file}_builder"
148
+ end
149
+
150
+ attr_reader :impersonalium
151
+
152
+ def initialize(stem)
153
+ extract_normalized_args!(stem)
154
+
155
+ # Used to evaluate if metrical endings and extensions shall be used
156
+ evaluate_metrical_presence(@stem) if @stem # pronouns come without their stem
157
+
158
+ @options = stem[:options] || {}
159
+ @validate = @options[:validate] if @options
160
+ @lookup_indices = lookup_indices
161
+
162
+ # Use only downcased stem string in the following events,
163
+ # only persons and places are allowed to be capitalized.
164
+ downcase_all_stems unless stays_capitalized
165
+ end
166
+
167
+ def init_keys
168
+ # normalized values need to be used here!
169
+ # call a normalize method on this array, which needs to be built
170
+ %i{ type stem inflection_class nom deponens sexus impersonalium persona place }
171
+ end
172
+
173
+ # The method called by FormBuilder.build to run the building process.
174
+ # Subclasses overwrite this for more complex computations.
175
+ def compute
176
+ regular_forms
177
+ end
178
+
179
+ # Computes a one-dimensional array of indices.
180
+ #
181
+ # LLT::Constants::Endings provides endings for all valid
182
+ # Latin forms. Their index defines additional attributes.
183
+ #
184
+ # Contrived Example:
185
+ # The row %w{ o s t mus tis nt } presents personal endings
186
+ # for verbs. Index 0 (o) maps to persona: 1, numerus: 1,
187
+ # index 3 (mus) maps to persona: 1, numerus: 2.
188
+ #
189
+ # All FormBuilder subclasses need to implement #indices, consisting
190
+ # of a hash that reveals the meaning of an index.
191
+ #
192
+ # An implementation for the personal endings presented above would be
193
+ # { persona: [0, 1, 2], numerus: [0, 3] }
194
+ #
195
+ # This tells us that there are 3 different values for persona - changing
196
+ # on every first, second and third position - and 2 values for numerus -
197
+ # changing on every fourth position in the endings array.
198
+ #
199
+ # Depending on the presence of options in the given stem_hash, only
200
+ # selected indices are returned.
201
+ def lookup_indices
202
+ if ending = @options[:ending]
203
+ indices_by_ending(ending)
204
+ else
205
+ arr = indices.map do |attr, index_values|
206
+ if opt_val = @options[attr]
207
+ index = value_as_index(opt_val)
208
+ [index_values[index - 1]].compact
209
+ else
210
+ index_values.compact
211
+ end
212
+ end
213
+
214
+ cross_indices(arr)
215
+ end
216
+ end
217
+
218
+ def indices_by_ending(ending)
219
+ endings.select_indices { |x| endings_lookup(ending, x) }
220
+ end
221
+
222
+ # Can be overwritten by subclasses if special rules are needed.
223
+ def endings_lookup(ending, x)
224
+ x.to_s == ending
225
+ end
226
+
227
+ # LLT::Constants::Terminology provides a numeric representation of
228
+ # every valid value, e.g. tempus: :praesens == tempus: 1
229
+ def value_as_index(val)
230
+ if val.kind_of?(Fixnum)
231
+ val
232
+ else
233
+ t.send(val, :numeric)
234
+ end
235
+ end
236
+
237
+ def cross_indices(arr)
238
+ arr.inject(:product).map(&:flatten).map { |a| a.inject(:+) }.sort
239
+ end
240
+
241
+ # General purpose method to map indices to attributes using the
242
+ # #indices hash.
243
+ # Several subclasses use an easier algorithm due to computational
244
+ # efficiency.
245
+ def attributes_by_index(index)
246
+ attrs = {}
247
+ indices.to_a.reverse.each do |type, indices|
248
+ indices.reverse.each_with_index do |ind, i|
249
+ if (index - ind) >= 0
250
+ index -= ind
251
+ attrs[type] = reverse_lookup[type][i]
252
+ break
253
+ end
254
+ end
255
+ end
256
+ attrs.values.reverse
257
+ end
258
+
259
+ def reverse_lookup
260
+ @rl ||= indices.each_with_object({}) do |(type, values), h|
261
+ h[type] = t.norm_values_for(type).take(values.size).reverse
262
+ end
263
+ end
264
+
265
+ def new_form(args)
266
+ args = args.merge(default_args)
267
+ extensions_and_other_signs(args)
268
+ corrections(args)
269
+ form_class.new(args) if valid?(args)
270
+ end
271
+
272
+ def corrections(args)
273
+ end
274
+
275
+ def extensions_and_other_signs(args)
276
+ end
277
+
278
+ def validations
279
+ self.class.validations
280
+ end
281
+
282
+ # used by VerbBuilder, PppBuilder (for irregulars)
283
+ # GerundiveBuilder and GerundBuilder
284
+ def prefix
285
+ p = @options[:prefix].to_s
286
+ p unless p.empty?
287
+ end
288
+
289
+ def valid?(args)
290
+ if needs_validation?
291
+ validations.all? do |validator|
292
+ validation_rule(args, validator)
293
+ end
294
+ else
295
+ true
296
+ end
297
+ end
298
+
299
+ def needs_validation?
300
+ @validate && validations.any?
301
+ end
302
+
303
+ def validation_rule(args, validator)
304
+ args[validator].to_s == @options[validator].to_s
305
+ end
306
+
307
+ # Used especially with archaic forms, where a special validation rule
308
+ # is present, like audiundi. It enters the FB process with thematic u
309
+ # (archaic) which is looked up as e but passes the validation. Still
310
+ # we want to present the new forms like they were requested, with their
311
+ # archaic appearance.
312
+ # Only call this after you pass validation!
313
+ # @param args [Hash] - arguments used for form building
314
+ # @param validator [Symbol] - key that is used for validation
315
+ # @param classification [Symbol] - adds info why this value should be kept,
316
+ # e.g. an archaic form
317
+ # @return [true]
318
+ def keep_given_value(args, validator, classification = nil)
319
+ # work in the classification first, as it might be nil
320
+ # and we want the method to return true, as it will get
321
+ # most frequently called at the end of a passing validation!
322
+ args[:classification] = classification
323
+ args[validator] = @options[validator]
324
+ end
325
+
326
+ def default_args
327
+ { stem: stem_copy, inflection_class: @inflection_class }
328
+ end
329
+
330
+ def stem_copy
331
+ # solely needed for irregular verbs, they might come without
332
+ # a stem value, which will be set in the course of events
333
+ @stem ? @stem.clone : ""
334
+ end
335
+
336
+ def form_class
337
+ constant_by_type(namespace: LLT::Form)
338
+ end
339
+
340
+ def endings
341
+ endings_path.get(*endings_attributes)
342
+ end
343
+
344
+ def endings_attributes
345
+ []
346
+ end
347
+
348
+ def endings_container
349
+ @type
350
+ end
351
+
352
+ def endings_path
353
+ path = constant_by_type(endings_container, namespace: endings_namespace)
354
+ metrical? ? path::Metrical : path
355
+ end
356
+
357
+ def endings_namespace
358
+ LLT::Constants::Endings
359
+ end
360
+
361
+ def downcase_all_stems
362
+ @stem.downcase! if @stem
363
+ @options[:stem].downcase! if @options[:stem]
364
+ end
365
+
366
+ def stays_capitalized
367
+ false
368
+ end
369
+ end
370
+ end
@@ -0,0 +1,122 @@
1
+ module LLT
2
+ class Stem
3
+ class AdjectivePack < Pack
4
+ def initialize(type, args, source, extension = true)
5
+ # always extend
6
+ super
7
+ @lemma = @stems.first.nominative
8
+ end
9
+
10
+ def to_hash(use = nil, options = {})
11
+ selector = case options[:comparison_sign].to_s
12
+ when /^(|i?t?er)$/ then :positivus # regular pos or adverbs
13
+ when /(ior|ius)/ then :comparativus
14
+ else :superlativus
15
+ end
16
+
17
+ stem = @stems.find { |st| st.comparatio == selector }
18
+ stem.to_hash.merge(options: options)
19
+ end
20
+
21
+ def third_decl_with_possible_ne_abl?
22
+ super do
23
+ st = @stems.find { |stem| stem.comparatio == :positivus }
24
+ st ? st.third_decl_with_possible_ne_abl? : false
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def extended_stems(args)
31
+ @stems = []
32
+ @args = args
33
+
34
+ compute_comparatio_stems
35
+
36
+ @stems
37
+ end
38
+
39
+ STEMS = %i{ positivus comparativus superlativus }
40
+ def compute_comparatio_stems
41
+ STEMS.each do |level|
42
+ sc = (level != :positivus)
43
+ build_as(level, sc)
44
+ end
45
+ end
46
+
47
+ def build_as(level, stem_change = false)
48
+ new_args = @args.merge(comparatio: level)
49
+
50
+ if stem_change
51
+ new_stem = send("#{level}_sign")
52
+ new_args[:stem] = new_stem
53
+ new_args.delete(:nom)
54
+ end
55
+
56
+ check_irregularities(new_args)
57
+
58
+ add(create_stem(new_args))
59
+ end
60
+
61
+ # Creates Irregular Adverb stems like of bonus.
62
+ # If none such is built, later stages will just use
63
+ # the usual positivus stem.
64
+ def check_irregularities(args)
65
+ stem = args[:stem]
66
+ if stem.match(irregular_adverbs)
67
+ args[:irregular_adverb] = true
68
+ new_stem = select_adverb_stem($1)
69
+ add(create_stem(:adverb, args.merge(stem: new_stem)))
70
+ end
71
+ end
72
+
73
+ def select_adverb_stem(match)
74
+ case match
75
+ when "bon" then "ben"
76
+ when "difficil" then "difficul"
77
+ end
78
+ end
79
+
80
+ def irregular_adverbs
81
+ /^(bon|difficil)$/
82
+ end
83
+
84
+ def comparativus_sign
85
+ old_stem = @args[:stem].clone
86
+ old_stem << "ior"
87
+ end
88
+
89
+ def superlativus_sign
90
+ old_stem = @args[:stem].clone
91
+ ext = case old_stem
92
+ when /l$/ then "lim"
93
+ when /r$/ then "rim"
94
+ else "issim"
95
+ end
96
+
97
+ new_stem = send("#{ext}_sup_rules", old_stem)
98
+ new_stem << ext
99
+ end
100
+
101
+ def rim_sup_rules(stem)
102
+ if stem =~ /^(veter)$/
103
+ stem
104
+ else
105
+ @args[:nom].clone
106
+ end
107
+ end
108
+
109
+ def lim_sup_rules(stem)
110
+ stem
111
+ end
112
+
113
+ def issim_sup_rules(stem)
114
+ stem
115
+ end
116
+
117
+ def add(stem)
118
+ @stems << stem
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,23 @@
1
+ module LLT
2
+ class Stem
3
+ class AdjectiveStem < Stem
4
+ attr_reader :comparatio, :nom
5
+
6
+ def init_keys
7
+ %i{ nom stem inflection_class comparatio number_of_endings }
8
+ end
9
+
10
+ def to_s
11
+ "#{t.send(@type, :abbr)}#{@inflection_class} #{@stem}"
12
+ end
13
+
14
+ def nominative
15
+ @nom
16
+ end
17
+
18
+ def third_decl_with_possible_ne_abl?
19
+ @inflection_class == 3 && @nom.match(/nis$/) && @stem.match(/n$/)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ module LLT
2
+ class Stem
3
+ class EthnicStem < Stem
4
+ def init_keys
5
+ %i{ stem inflection_class }
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ module LLT
2
+ class Stem
3
+ class NounPack < Pack
4
+ def initialize(*args)
5
+ super(*args)
6
+ @lemma = @stems.first.nominative
7
+ end
8
+
9
+ def third_decl_with_possible_ne_abl?
10
+ super { @stems.any?(&:third_decl_with_possible_ne_abl?) }
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,26 @@
1
+ module LLT
2
+ class Stem
3
+ class NounStem < Stem
4
+ attr_reader :nom
5
+
6
+ def init_keys
7
+ %i{ nom stem inflection_class sexus persona place }
8
+ end
9
+
10
+ def to_s
11
+ "#{t.send(@type, :abbr)}#{@inflection_class} #{@stem}"
12
+ end
13
+
14
+ def nominative
15
+ @nom
16
+ end
17
+
18
+ def third_decl_with_possible_ne_abl?
19
+ if @inflection_class == 3
20
+ @nom.match(/[id]?on?$/) && @stem.match(/d?in$|i?on$/) ||
21
+ @nom.match(/men$/) && @stem.match(/min$/)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,46 @@
1
+ require 'llt/helpers'
2
+
3
+ module LLT
4
+ class Stem
5
+ class Pack
6
+ include Helpers::Transformer
7
+ include Helpers::Constantize
8
+ include Helpers::Normalizer
9
+
10
+ attr_reader :stems, :type, :lemma_key, :lemma
11
+
12
+ def initialize(type, args, source, extension = false)
13
+ @type = type
14
+ @source = source
15
+ @lemma_key = args[:lemma_key]
16
+ @stems = (extension ? extended_stems(args) : default_stem(args))
17
+ end
18
+
19
+ def lemma_with_key
20
+ "#{@lemma}##{@lemma_key}"
21
+ end
22
+
23
+ def to_hash(use = nil, options = {})
24
+ @stems.first.to_hash.merge(options: options)
25
+ end
26
+
27
+ def to_s
28
+ @stems.map(&:to_s) * ", "
29
+ end
30
+
31
+ private
32
+
33
+ def create_stem(stem_type = @type, args)
34
+ constant_by_type(suffix: "stem", namespace: LLT::Stem).new(stem_type, args)
35
+ end
36
+
37
+ def default_stem(args)
38
+ [create_stem(args)]
39
+ end
40
+
41
+ def third_decl_with_possible_ne_abl?
42
+ block_given? ? yield : false
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,53 @@
1
+ module LLT
2
+ class Stem
3
+ class VerbPack < Pack
4
+ attr_reader :direct_objects, :indirect_objects
5
+
6
+ def initialize(type, args, source, extension = true)
7
+ super
8
+ extract_valencies(args)
9
+
10
+ end
11
+
12
+ def to_hash(use = nil, options = {})
13
+ if use
14
+ stem = @stems.find { |st| st.type == use }
15
+ stem.to_hash.merge(options: options)
16
+ end
17
+ end
18
+
19
+ def extract_valencies(args)
20
+ d = args[:dir_objs]
21
+ i = args[:indir_objs]
22
+
23
+ @direct_objects, @indirect_objects = parse_valencies(d, i)
24
+ end
25
+
26
+ def parse_valencies(d, i)
27
+ if d.nil? || d == "not_set"
28
+ [[4, :aci, :infinitive], [3]]
29
+ else
30
+ [d, i].map { |val| convert_valencies(val)}
31
+ end
32
+ end
33
+
34
+ def convert_valencies(val)
35
+ val.split.map do |val_string|
36
+ meth = (val_string.match(/^\d$/) ? :to_i : :to_sym)
37
+ val_string.send(meth)
38
+ end
39
+ end
40
+
41
+ STEMS = %i{ praesens perfectum ppp }
42
+ def extended_stems(args)
43
+ STEMS.map do |type|
44
+ new_type = args[t.send(type, :abbr)]
45
+ next unless new_type
46
+ args[:stem] = new_type
47
+ create_stem(type, args)
48
+ end.compact
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,18 @@
1
+ module LLT
2
+ class Stem
3
+ class VerbStem < Stem
4
+ def init_keys
5
+ %i{ stem inflection_class deponens pf_composition }
6
+ end
7
+
8
+ def to_s
9
+ "#{@type}#{@inflection_class}#{dep_state.magenta} #{@stem}"
10
+ end
11
+
12
+ private
13
+ def dep_state
14
+ @deponens ? " dep" : ""
15
+ end
16
+ end
17
+ end
18
+ end