module BoggleMorph
BoggleMorph — inflected-form → lemma resolution for WordNet lexicon checks. Public: lemma_for, load_exceptions, inflected_forms, singular_candidates Depends: Dictionary (optional, for default exception files) Tests: test/lib/boggle_morph_test.rb, test/lib/boggle_lexicon_test.rb
Constants
- EXCEPTION_FILES
- PLURAL_ES_ENDINGS
Public Instance Methods
Source
# File lib/boggle_morph.rb, line 48 def inflected_forms(lemma, exceptions:) forms = [] reverse = reverse_exceptions(exceptions) Array(reverse[lemma]).each { |form| forms << form } token = lemma.to_s.downcase if token.end_with?("y") && token.length > 2 && token[-2] !~ /[aeiou]/ forms << token.sub(/y\z/, "ies") elsif PLURAL_ES_ENDINGS.any? { |ending| token.end_with?(ending) } forms << "#{token}es" elsif token.end_with?("f") forms << token.sub(/f\z/, "ves") elsif token.end_with?("fe") forms << token.sub(/fe\z/, "ves") elsif !token.end_with?("s") forms << "#{token}s" end forms.map(&:downcase).uniq end
Source
# File lib/boggle_morph.rb, line 34 def lemma_for(word, lexicon:, exceptions:) token = word.to_s.strip.downcase return token if lexicon.key?(token) base = exceptions[token] return base if base && lexicon.key?(base) singular_candidates(token).each do |candidate| return candidate if lexicon.key?(candidate) end nil end
Source
# File lib/boggle_morph.rb, line 16 def load_exceptions(dict_dir: Dictionary::WN_DICT_DIR) exceptions = {} EXCEPTION_FILES.each do |filename| path = File.join(dict_dir.to_s, filename) next unless File.file?(path) File.foreach(path) do |line| inflected, base = line.split(/\s+/, 2) next if inflected.nil? || base.nil? inflected = inflected.downcase base = base.downcase exceptions[inflected] = base unless exceptions.key?(inflected) end end exceptions end
Source
# File lib/boggle_morph.rb, line 90 def reverse_exceptions(exceptions) reverse = {} exceptions.each do |inflected, base| reverse[base] ||= [] reverse[base] << inflected unless reverse[base].include?(inflected) end reverse end
Source
# File lib/boggle_morph.rb, line 69 def singular_candidates(word) token = word.to_s.downcase candidates = [] if token.end_with?("ies") && token.length > 4 candidates << token.sub(/ies\z/, "y") end if token.end_with?("ves") && token.length > 4 candidates << token.sub(/ves\z/, "f") candidates << token.sub(/ves\z/, "fe") end if token.end_with?("es") && token.length > 4 candidates << token.sub(/es\z/, "") end if token.end_with?("s") && !token.end_with?("ss") && token.length > 3 candidates << token.sub(/s\z/, "") end candidates.uniq end