11package cc.wordview.gengolex.languages.japanese
22
33import cc.wordview.gengolex.languages.Tokenizer
4+ import cc.wordview.gengolex.languages.japanese.JapaneseKanjiStrategy.*
45import cc.wordview.gengolex.word.DerivatableWord
56import cc.wordview.gengolex.word.Word
67import java.util.HashMap
7- import java.util.regex.Pattern
88
99object JapaneseTokenizer : Tokenizer {
1010 override var dictionary: ArrayList <DerivatableWord > = arrayListOf ()
11+ private val wordMap: HashMap <String , DerivatableWord > = HashMap ()
1112
1213 @Suppress(" MemberVisibilityCanBePrivate" )
13- var kanjiStrategy = JapaneseKanjiStrategy .PREFER_DERIVATION
14-
15- private val kanjiPattern: Pattern = Pattern .compile(" [一-龯]" )
14+ var kanjiStrategy = PREFER_DERIVATION
1615
1716 override fun tokenize (words : List <String >): ArrayList <Word > {
18- val wordsByChars = words.joinToString().replace(" 、" , " " ).replace(" 。" , " " ).split(" " )
19- val joinedWordsString = wordsByChars.joinToString(" " )
20-
21- val wordsFound = ArrayList <Word >()
22- var charsToSkipNext = 0
17+ val input = words.joinToString()
18+ .replace(" 、" , " " )
19+ .replace(" 。" , " " )
2320
24- for (i in wordsByChars.indices) {
25- if (charsToSkipNext > 0 ) {
26- charsToSkipNext--
27- continue
28- }
21+ val chars = input.toCharArray()
2922
30- val char = wordsByChars[i]
31-
32- val currentWordsString =
33- wordsFound.fold(joinedWordsString) { acc, foundWord -> acc.replace(foundWord.word, " " ) }
23+ val wordsFound = ArrayList <Word >()
24+ var i = 0
3425
35- tokenizeKanji(char, currentWordsString)?.let {
26+ while (i < chars.size) {
27+ val char = chars[i].toString()
28+ tokenizeKanji(char, input.substring(i))?.let {
3629 wordsFound.add(it)
37- charsToSkipNext = it.word.length - 1
38- }
30+ i + = it.word.length // Skip characters based on the word's length
31+ } ? : i ++
3932 }
4033
4134 return wordsFound
4235 }
4336
4437 private fun tokenizeKanji (char : String , original : String ): Word ? {
45- if (! kanjiPattern.matcher( char).matches() ) return null
38+ if (char.isEmpty() || char[ 0 ].code !in 0x4E00 .. 0x9FFF ) return null
4639
47- dictionary.firstOrNull { it.word == char } ?.let { kanjiWord ->
40+ wordMap[ char] ?.let { kanjiWord ->
4841 return when (kanjiStrategy) {
49- // TODO: Properly address this by removing all derivations that is not present in the phrase.
50- JapaneseKanjiStrategy .PREFER_PARENT -> kanjiWord
51- JapaneseKanjiStrategy .PREFER_DERIVATION -> {
42+ PREFER_PARENT -> kanjiWord
43+ PREFER_DERIVATION -> {
5244 @Suppress(" UNNECESSARY_SAFE_CALL" )
53- kanjiWord.derivations?.firstOrNull { original.contains (it.word) } ? : kanjiWord
45+ kanjiWord.derivations?.find { original.startsWith (it.word) } ? : kanjiWord
5446 }
5547 }
5648 }
@@ -60,9 +52,11 @@ object JapaneseTokenizer : Tokenizer {
6052
6153 override fun initializeDictionary (path : String ) {
6254 super .initializeDictionary(path, " kanji" )
55+ dictionary.forEach { wordMap[it.word] = it }
6356 }
6457
6558 override fun initializeDictionary (dictionaries : HashMap <String , String >) {
6659 super .initializeDictionary(dictionaries, " kanji" )
60+ dictionary.forEach { wordMap[it.word] = it }
6761 }
6862}
0 commit comments