llt-form_builder 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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