Module: Daidai

Defined in:
lib/daidai.rb,
lib/daidai/word.rb,
lib/daidai/kabosu.rb,
lib/daidai/tables.rb,
lib/daidai/version.rb,
lib/daidai/conjugator.rb,
lib/daidai/deinflector.rb

Overview

Daidai (橙) — Japanese verb and adjective conjugation in pure Ruby.

The conjugation knowledge comes from the JMdictDB tables developed by Jim Breen’s EDRDG project (via jconj); Daidai ports the table-driven algorithm and exposes a small, app-friendly API. Named after the bitter orange, a sibling of sudachi and kabosu.

Daidai.conjugate(kanji: "書く", reading: "かく", pos: "v5k")
#=> Daidai::Result

Daidai.conjugatable?("n")   #=> false
Daidai.conjugatable?("v1")  #=> true

Defined Under Namespace

Modules: Conjugator, Deinflector, Kabosu, Tables Classes: Deinflection, Error, Form, View, Word

Constant Summary collapse

FORMS =

The conjugation forms daidai generates, in table order, with display labels. These names replace the numeric conjugation ids of the underlying tables.

{
  non_past: "Non-past",
  past: "Past",
  te: "Te-form",
  provisional: "Provisional (~eba)",
  potential: "Potential",
  passive: "Passive",
  causative: "Causative",
  causative_passive: "Causative-passive",
  volitional: "Volitional",
  imperative: "Imperative",
  conditional: "Conditional (~tara)",
  alternative: "Alternative (~tari)",
  stem: "Continuative (~i)"
}.freeze
FORM_BY_ID =

conjo.csv conjugation id (1..13) => form name, in the same order as FORMS.

FORMS.keys.each_with_index.to_h { |name, i| [ i + 1, name ] }.freeze
VERSION =
"0.1.1"

Class Method Summary collapse

Class Method Details

.conjugatable?(pos) ⇒ Boolean

Whether ‘pos` (a code or array of codes) describes a conjugatable word.

Returns:

  • (Boolean)


53
54
55
# File 'lib/daidai.rb', line 53

def conjugatable?(pos)
  Conjugator.conjugatable?(pos)
end

.conjugate(word, pos = nil, reading: nil) ⇒ Object

Conjugate a dictionary-form word.

Daidai.conjugate("書く", "v5k")                 # kanji surface forms
Daidai.conjugate("書く", "v5k", reading: "かく")  # + the kana of each form
Daidai.conjugate("する", "vs-i")                # kana word (is its own reading)

‘word` is the dictionary form (kanji surface or kana). `pos` is a JMdict part-of-speech code (“v5k”, “adj-i”, …) or an array of them — the first conjugatable one wins. `reading` is optional: pass it only when you also want each form’s kana (conjugation rewrites the okurigana, which is already in the surface, so the kanji forms need no reading). Returns a Daidai::Word, or nil when nothing is conjugatable.

‘pos` may be omitted, in which case the optional `kabosu` gem (Sudachi) resolves the dictionary form, POS and reading from `word` — even when `word` is itself inflected (“食べている” → conjugations of 食べる). This raises Daidai::Kabosu::MissingDependency if kabosu/a dictionary isn’t installed.



39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/daidai.rb', line 39

def conjugate(word, pos = nil, reading: nil)
  return nil if word.nil? || word.to_s.empty?

  if pos.nil?
    resolved = Kabosu.resolve(word) or return nil
    word, pos, reading = resolved.values_at(:word, :pos, :reading)
  end

  kanji = word.match?(/\p{Han}/) ? word : nil
  reading ||= kanji ? nil : word
  Conjugator.conjugate(kanji: kanji, reading: reading, pos: pos)
end

.deinflect(text) ⇒ Object

Deinflect an inflected surface form back to its dictionary form(s), naming each inflection along the way (the inverse of #conjugate):

# each result has a `term` and its named `inflections` (surface -> dictionary):
Daidai.deinflect("食べてる")    # includes #<Daidai::Deinflection 食べる [-いる, -て]>
Daidai.deinflect("読まなかった") # includes #<Daidai::Deinflection 読む [-た, negative]>

Returns every candidate the rules can reach (each a Daidai::Deinflection); the rules are string-based and dictionary-free, so many candidates are not real words. A caller with a dictionary looks up each ‘term`; one without can keep only `dictionary_form?` candidates. Pure and offline — unlike the POS-less #conjugate, it needs no kabosu.



69
70
71
72
73
# File 'lib/daidai.rb', line 69

def deinflect(text)
  return [] if text.nil? || text.to_s.empty?

  Deinflector.deinflect(text)
end