Compare commits

...

2 commits

Author SHA1 Message Date
2cbe8462ae remove redundant dict entries 2022-11-21 00:34:43 +01:00
9ec50677d9 coversion working, but no spaces 2022-11-20 21:42:06 +01:00
6 changed files with 406 additions and 33 deletions

View file

@ -8317,7 +8317,6 @@
おうようじょう 応用上 おうようじょう 応用上
おうようじょうほう 応用情報 おうようじょうほう 応用情報
おうようじょうほうがく 応用情報学 おうようじょうほうがく 応用情報学
おうじょうけん 応用情報学研究センター
おうようすいしんか 応用推進課 おうようすいしんか 応用推進課
おうようすうがく 応用数学 おうようすうがく 応用数学
おうようすうがっか 応用数学科 おうようすうがっか 応用数学科
@ -14908,7 +14907,6 @@
かんいしんぱん 簡易新版 かんいしんぱん 簡易新版
かんいてき 簡易的 かんいてき 簡易的
かんいほけん 簡易保険 かんいほけん 簡易保険
かんいほけんほーる 簡易保険ホール
かんいほうしき 簡易方式 かんいほうしき 簡易方式
かんいむせん 簡易無線 かんいむせん 簡易無線
かんけつ 簡潔 かんけつ 簡潔
@ -42588,7 +42586,6 @@
しょせきるい 書籍類 しょせきるい 書籍類
しょせん 書泉 しょせん 書泉
しょせんぐらんで 書泉グランデ しょせんぐらんで 書泉グランデ
しょせんぶっくまーと 書泉ブックマート
しょたい 書体 しょたい 書体
しょだな 書棚 しょだな 書棚
かきおき 書置 かきおき 書置
@ -46961,7 +46958,6 @@
しんにっぽん 新日本 しんにっぽん 新日本
しんにほんしょうけん 新日本証券 しんにほんしょうけん 新日本証券
しんにほんせいてつ 新日本製鉄 しんにほんせいてつ 新日本製鉄
しんにってつ 新日本製鉄株式会社
しんにほんせいてつ 新日本製鐵 しんにほんせいてつ 新日本製鐵
しんにっぽんせいてつ 新日本製鐵 しんにっぽんせいてつ 新日本製鐵
しんにってつ 新日鐵 しんにってつ 新日鐵
@ -54141,7 +54137,6 @@
せんこうちゅう 選考中 せんこうちゅう 選考中
せんこうび 選考日 せんこうび 選考日
せんこう 選鉱 せんこう 選鉱
せんけん 選鉱精錬研究所
せんじゃ 選者 せんじゃ 選者
せんしゅ 選手 せんしゅ 選手
せんしゅいちらん 選手一覧 せんしゅいちらん 選手一覧
@ -62107,7 +62102,6 @@
ちゅうがくせいばん 中学生版 ちゅうがくせいばん 中学生版
ちゅうがくにゅうしもんだい 中学入試問題 ちゅうがくにゅうしもんだい 中学入試問題
ちゅうかっこ 中括弧 ちゅうかっこ 中括弧
なかま 中間
ちゅうかんれべるがくしゅう 中間レベル学習 ちゅうかんれべるがくしゅう 中間レベル学習
ちゅうかんえき 中間駅 ちゅうかんえき 中間駅
ちゅうかんえきしはつ 中間駅始発 ちゅうかんえきしはつ 中間駅始発
@ -66471,7 +66465,6 @@
でんしききぶ 電子機器部 でんしききぶ 電子機器部
でんしぎじゅつ 電子技術 でんしぎじゅつ 電子技術
でんしぎじゅつしゃ 電子技術者 でんしぎじゅつしゃ 電子技術者
でんそうけん 電子技術総合研究所
でんしきょう 電子協 でんしきょう 電子協
でんしけいじばん 電子掲示板 でんしけいじばん 電子掲示板
でんしけい 電子系 でんしけい 電子系
@ -66486,7 +66479,6 @@
でんしこうがくきょうしつ 電子工学教室 でんしこうがくきょうしつ 電子工学教室
でんしこうがくせんこう 電子工学専攻 でんしこうがくせんこう 電子工学専攻
でんしこうぎょう 電子工業 でんしこうぎょう 電子工業
でんしきょう 電子工業振興協会
でんしこうさく 電子工作 でんしこうさく 電子工作
でんしざいりょう 電子材料 でんしざいりょう 電子材料
でんししき 電子式 でんししき 電子式
@ -67641,7 +67633,6 @@
とうきょうがす 東京ガス とうきょうがす 東京ガス
とうきょうすたいる 東京スタイル とうきょうすたいる 東京スタイル
とうきょうてあとる 東京テアトル とうきょうてあとる 東京テアトル
とうきょうべいえぬけーほーる 東京ベイNKホール
とうきょういがい 東京以外 とうきょういがい 東京以外
とうきょういち 東京一 とうきょういち 東京一
とうきょうえき 東京駅 とうきょうえき 東京駅
@ -68467,7 +68458,6 @@
とうけいしょり 統計処理 とうけいしょり 統計処理
とうけいじょうほう 統計情報 とうけいじょうほう 統計情報
とうけいすうがく 統計数学 とうけいすうがく 統計数学
とうすうけん 統計数理研究所
とうけいち 統計値 とうけいち 統計値
とうけいてき 統計的 とうけいてき 統計的
とうけいてきぱたあん 統計的パターン とうけいてきぱたあん 統計的パターン
@ -71469,12 +71459,10 @@
にっぽんとむそん 日本トムソン にっぽんとむそん 日本トムソン
にっぽんはむ 日本ハム にっぽんはむ 日本ハム
にほんはむ 日本ハム にほんはむ 日本ハム
にっぽんひゅーむかん 日本ヒューム管
にっぽんびくたー 日本ビクター にっぽんびくたー 日本ビクター
にっぽんぺいんと 日本ペイント にっぽんぺいんと 日本ペイント
にっぽんゆにばっく 日本ユニバック にっぽんゆにばっく 日本ユニバック
にっぽんれーす 日本レース にっぽんれーす 日本レース
にほんろぼっとがっかい 日本ロボット学会
にほんいがい 日本以外 にほんいがい 日本以外
にほんいじょう 日本以上 にほんいじょう 日本以上
にほんいち 日本一 にほんいち 日本一
@ -72032,8 +72020,6 @@
にゅうしゅつりょく 入出力 にゅうしゅつりょく 入出力
にゅうしゅつりょくh 入出力 にゅうしゅつりょくh 入出力
にゅうしゅつりょくせっと 入出力セット にゅうしゅつりょくせっと 入出力セット
にゅうしゅつりょくぱ 入出力パターン
にゅうしゅつりょくぱたーん 入出力パターン
にゅうしゅつりょくかんけい 入出力関係 にゅうしゅつりょくかんけい 入出力関係
にゅうしゅつりょくけい 入出力系 にゅうしゅつりょくけい 入出力系
にゅうしゅつりょくそうち 入出力装置 にゅうしゅつりょくそうち 入出力装置
@ -79676,7 +79662,6 @@
ぶんいちそうごうしゅっぱん 文一総合出版 ぶんいちそうごうしゅっぱん 文一総合出版
ぶんえんどう 文苑堂 ぶんえんどう 文苑堂
ぶんか 文化 ぶんか 文化
ぶんかしゃったー 文化シャッター
ぶんかかい 文化会 ぶんかかい 文化会
ぶんかかいかん 文化会館 ぶんかかいかん 文化会館
ぶんかかいかん 文化会舘 ぶんかかいかん 文化会舘
@ -80078,7 +80063,6 @@
へいおん 平温 へいおん 平温
へいおん 平穏 へいおん 平穏
ひらかな 平仮名 ひらかな 平仮名
ひらかなかくていにゅうりょく 平仮名確定入力
へいか 平価 へいか 平価
へいけ 平家 へいけ 平家
へいけものがたり 平家物語 へいけものがたり 平家物語
@ -110778,7 +110762,6 @@
せんせいよう 先生用 せんせいよう 先生用
せんせんげつ 先先月 せんせんげつ 先先月
せんたんいりょう 先端医療 せんたんいりょう 先端医療
せんたんかがくぎじゅつけんきゅうせんたー 先端科学技術研究センター
せんたんぎじゅつけんきゅう 先端技術研究 せんたんぎじゅつけんきゅう 先端技術研究
せんたんきょうふしょう 先端恐怖症 せんたんきょうふしょう 先端恐怖症
せんたんけん 先端研 せんたんけん 先端研
@ -114513,7 +114496,6 @@
でんしききるい 電子機器類 でんしききるい 電子機器類
でんしきどう 電子軌道 でんしきどう 電子軌道
でんしぎじゅつかんけい 電子技術関係 でんしぎじゅつかんけい 電子技術関係
でんしぎじゅつそうごうけんきゅうしょ 電子技術総合研究所
でんしけいじばん 電子掲示版 でんしけいじばん 電子掲示版
でんしけいさんきしつ 電子計算機室 でんしけいさんきしつ 電子計算機室
でんしこうさくよう 電子工作用 でんしこうさくよう 電子工作用
@ -116022,7 +116004,6 @@
にほんちんぼつ 日本沈没 にほんちんぼつ 日本沈没
にほんていえん 日本庭園 にほんていえん 日本庭園
にほんてつどう 日本鉄道 にほんてつどう 日本鉄道
にほんにんちかがくかい 日本認知科学会
にほんねこ 日本猫 にほんねこ 日本猫
にほんばんじまく 日本版字幕 にほんばんじまく 日本版字幕
にほんぶっきょう 日本仏教 にほんぶっきょう 日本仏教
@ -116115,7 +116096,6 @@
にゅうよくざい 入浴剤 にゅうよくざい 入浴剤
にゅうよくはっぽうき 入浴発泡器 にゅうよくはっぽうき 入浴発泡器
にゅうらい 入来 にゅうらい 入来
にゅうりょくぱらめーた 入力パラメータ
にゅうりょくかんじ 入力漢字 にゅうりょくかんじ 入力漢字
にゅうりょくかんきょう 入力環境 にゅうりょくかんきょう 入力環境
にゅうりょくじたい 入力自体 にゅうりょくじたい 入力自体

View file

@ -1,4 +1,5 @@
mod phfbin_gen; mod phfbin_gen;
mod testconv;
use std::{borrow::Cow, collections::HashMap, path::Path}; use std::{borrow::Cow, collections::HashMap, path::Path};
@ -66,12 +67,13 @@ fn parse_dict_ln(records: &mut Records, line: &str, ln: usize) {
.or_else(|| context.map(str::to_owned)) .or_else(|| context.map(str::to_owned))
.unwrap_or_default(), .unwrap_or_default(),
) { ) {
std::collections::hash_map::Entry::Occupied(mut e) => { std::collections::hash_map::Entry::Occupied(_) => {
// Replace reading if the new one is longer /*
// Replace reading if the new one is shorter
let val = e.get_mut(); let val = e.get_mut();
if val.len() < reading.len() { if val.len() > reading.len() {
*val = reading.to_owned(); *val = reading.to_owned();
} }*/
} }
std::collections::hash_map::Entry::Vacant(e) => { std::collections::hash_map::Entry::Vacant(e) => {
e.insert(reading.to_owned()); e.insert(reading.to_owned());
@ -198,9 +200,63 @@ impl Encodable for Readings {
} }
} }
fn find_redundant_compounds(dict: &Records) -> Records {
let mut wdict = dict.clone();
for (kanji, readings) in dict {
if kanji.chars().count() <= 3 {
continue;
}
if readings.len() != 1 {
continue;
}
if let Some(reading) = readings.get("") {
// Try to convert the entry without it being present
let entry = wdict.remove_entry(kanji).unwrap();
let res = testconv::convert(kanji, &wdict);
if &res == reading || to_romaji_nodc(&res) == to_romaji_nodc(reading) {
println!("Redundant: {} - {}", kanji, reading);
} else {
// Put the entry back if it is necessary
wdict.insert(entry.0, entry.1);
}
}
}
wdict
}
/// Romanize and remove double consonants
fn to_romaji_nodc(text: &str) -> String {
let rom = wana_kana::to_romaji::to_romaji(text);
let mut buf = String::new();
let mut citer = rom.chars().peekable();
while let Some(c) = citer.next() {
if matches!(c, 'a' | 'e' | 'i' | 'o' | 'u') {
match citer.peek() {
Some(nc) => {
if &c != nc {
buf.push(c);
}
}
None => buf.push(c),
}
} else {
buf.push(c);
}
}
buf
}
fn generate_kanji_dict() -> Vec<u8> { fn generate_kanji_dict() -> Vec<u8> {
let mut records = Records::default(); let mut records = Records::default();
parse_dict(&mut records, Path::new("dict/kakasidict.utf8")); parse_dict(&mut records, Path::new("dict/kakasidict.utf8"));
records = find_redundant_compounds(&records);
println!("kanji_dict: {} entries", records.len());
let mut phfmap = phfbin_gen::Map::<KanjiString, Readings>::default(); let mut phfmap = phfbin_gen::Map::<KanjiString, Readings>::default();
for (kanji, readings) in records { for (kanji, readings) in records {

196
codegen/src/testconv.rs Normal file
View file

@ -0,0 +1,196 @@
use crate::{Records, CLETTERS};
const ENDMARK: [char; 11] = [
')', ']', '!', '.', ',', '\u{3001}', '\u{3002}', '\u{ff1f}', '\u{ff10}', '\u{ff1e}', '\u{ff1c}',
];
const DASH_SYMBOLS: [char; 4] = ['\u{30FC}', '\u{2015}', '\u{2212}', '\u{FF70}'];
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum CharType {
Kanji,
Katakana,
Hiragana,
Symbol,
Alpha,
}
pub fn convert(text: &str, dict: &Records) -> String {
// TODO: char conversion should be done with iterators
let mut char_indices = text.char_indices();
let mut kana_text = String::new();
let mut hiragana = String::new();
let mut prev_type = CharType::Kanji;
// output_flag
// means (output buffer?, output text[i]?, copy to buffer and increment i?)
// possible (False, True, True), (True, False, False), (True, True, True)
// (False, False, True)
while let Some((i, c)) = char_indices.next() {
let output_flag = if ENDMARK.contains(&c) {
(CharType::Symbol, true, true, true)
} else if DASH_SYMBOLS.contains(&c) {
(prev_type, false, false, true)
} else if is_sym(c) {
if prev_type != CharType::Symbol {
(CharType::Symbol, true, false, true)
} else {
(CharType::Symbol, false, true, true)
}
} else if wana_kana::utils::is_char_katakana(c) {
(
CharType::Katakana,
prev_type != CharType::Katakana,
false,
true,
)
} else if wana_kana::utils::is_char_hiragana(c) {
(
CharType::Hiragana,
prev_type != CharType::Hiragana,
false,
true,
)
} else if c.is_ascii() {
(CharType::Alpha, prev_type != CharType::Alpha, false, true)
} else if wana_kana::utils::is_char_kanji(c) {
if !kana_text.is_empty() {
hiragana.push_str(&convert_kana(&kana_text));
}
let (t, n) = convert_kanji(&text[i..], &kana_text, &dict);
if n > 0 {
kana_text = t;
for _ in 1..n {
char_indices.next();
}
(CharType::Kanji, false, false, false)
} else {
// Unknown kanji
kana_text.clear();
// TODO: FOR TESTING
hiragana.push_str("🯄");
(CharType::Kanji, true, false, false)
}
} else if matches!(c as u32, 0xf000..=0xfffd | 0x10000..=0x10ffd) {
// PUA: ignore and drop
if !kana_text.is_empty() {
hiragana.push_str(&convert_kana(&kana_text));
}
(prev_type, false, false, false)
} else {
(prev_type, true, true, true)
};
prev_type = output_flag.0;
if output_flag.1 && output_flag.2 {
kana_text.push(c);
hiragana.push_str(&convert_kana(&kana_text));
kana_text.clear()
} else if output_flag.1 && output_flag.3 {
if !kana_text.is_empty() {
hiragana.push_str(&convert_kana(&kana_text));
}
kana_text = c.to_string();
} else if output_flag.3 {
kana_text.push(c);
}
}
// Convert last word
if !kana_text.is_empty() {
hiragana.push_str(&convert_kana(&kana_text));
}
hiragana
}
fn is_sym(c: char) -> bool {
matches!(c as u32,
0x3000..=0x3020 |
0x3030..=0x303F |
0x0391..=0x03A1 |
0x03A3..=0x03A9 |
0x03B1..=0x03C9 |
0x0410..= 0x044F |
0xFF01..=0xFF1A |
0x00A1..=0x00FF |
0xFF20..=0xFF5E |
0x0451 |
0x0401
)
}
fn convert_kana(text: &str) -> String {
wana_kana::to_hiragana::to_hiragana_with_opt(
text,
wana_kana::Options {
use_obsolete_kana: false,
pass_romaji: true,
upcase_katakana: false,
imemode: false,
},
)
}
/// Convert the leading kanji from the input string to hiragana
fn convert_kanji(text: &str, btext: &str, dict: &Records) -> (String, usize) {
let mut translation: Option<String> = None;
let mut i_c = 0;
let mut n_c = 0;
let mut char_indices = text.char_indices().peekable();
while let Some((i, c)) = char_indices.next() {
let kanji = &text[0..i + c.len_utf8()];
let this_tl = dict.get(kanji).and_then(|readings| {
readings
.iter()
.find_map(|(k, reading)| {
if k.is_empty() {
None
} else if let Some(cltr) = CLETTERS.get(&k.chars().next().unwrap_or_default()) {
char_indices.peek().and_then(|(_, next_c)| {
// Shortcut if the next character is not hiragana
if wana_kana::utils::is_char_hiragana(*next_c) {
if cltr.contains(&&next_c.to_string().as_str()) {
// Add the next character to the char count
i_c += 1;
let mut hira = reading.to_owned();
hira.push(*next_c);
return Some(hira);
} else {
None
}
} else {
None
}
})
} else if wana_kana::is_hiragana::is_hiragana(&k) {
if btext.contains(reading) {
Some(reading.to_owned())
} else {
None
}
} else {
panic!("invalid reading key")
}
})
.or_else(|| readings.get("").cloned())
});
i_c += 1;
if let Some(tl) = this_tl {
translation = Some(tl);
n_c = i_c;
}
if i_c >= 12 {
break;
}
}
translation
.map(|tl| (tl.to_owned(), n_c))
.unwrap_or_default()
}

Binary file not shown.

View file

@ -12,6 +12,7 @@ use phfbin::PhfMap;
use types::{KanjiString, Readings}; use types::{KanjiString, Readings};
const KANJI_DICT: &[u8] = include_bytes!("./kanji_dict.bin"); const KANJI_DICT: &[u8] = include_bytes!("./kanji_dict.bin");
const MAX_KANJI_LEN: usize = 7;
static CLETTERS: phf::Map<u8, &[char]> = phf::phf_map!( static CLETTERS: phf::Map<u8, &[char]> = phf::phf_map!(
b'a' => &['あ', 'ぁ', 'っ', 'わ', 'ゎ'], b'a' => &['あ', 'ぁ', 'っ', 'わ', 'ゎ'],
@ -39,6 +40,20 @@ static CLETTERS: phf::Map<u8, &[char]> = phf::phf_map!(
b'v' => &['ゔ'], b'v' => &['ゔ'],
); );
const ENDMARK: [char; 11] = [
')', ']', '!', '.', ',', '\u{3001}', '\u{3002}', '\u{ff1f}', '\u{ff10}', '\u{ff1e}', '\u{ff1c}',
];
const DASH_SYMBOLS: [char; 4] = ['\u{30FC}', '\u{2015}', '\u{2212}', '\u{FF70}'];
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum CharType {
Kanji,
Katakana,
Hiragana,
Symbol,
Alpha,
}
pub fn convert(text: &str) -> KakasiResult { pub fn convert(text: &str) -> KakasiResult {
let dict = PhfMap::new(KANJI_DICT); let dict = PhfMap::new(KANJI_DICT);
@ -46,12 +61,131 @@ pub fn convert(text: &str) -> KakasiResult {
let text = text.nfkc().collect::<String>(); let text = text.nfkc().collect::<String>();
let text = convert_syn(&text); let text = convert_syn(&text);
let hiragana = convert_kanji(&text, "", &dict).0; let mut char_indices = text.char_indices();
let romaji = wana_kana::to_romaji::to_romaji(&hiragana); let mut kana_text = String::new();
let mut prev_type = CharType::Kanji;
let mut hiragana = String::new();
let mut romaji = String::new();
let conv_kana_txt = |kana_text: &mut String, hiragana: &mut String, romaji: &mut String| {
if !kana_text.is_empty() {
let h = convert_kana(&kana_text);
hiragana.push_str(&h);
romaji.push_str(&wana_kana::to_romaji::to_romaji(&h));
romaji.push(' ');
}
};
// output_flag
// means (output buffer?, output text[i]?, copy to buffer and increment i?)
// possible (False, True, True), (True, False, False), (True, True, True)
// (False, False, True)
while let Some((i, c)) = char_indices.next() {
let output_flag = if ENDMARK.contains(&c) {
(CharType::Symbol, true, true, true)
} else if DASH_SYMBOLS.contains(&c) {
(prev_type, false, false, true)
} else if is_sym(c) {
if prev_type != CharType::Symbol {
(CharType::Symbol, true, false, true)
} else {
(CharType::Symbol, false, true, true)
}
} else if wana_kana::utils::is_char_katakana(c) {
(
CharType::Katakana,
prev_type != CharType::Katakana,
false,
true,
)
} else if wana_kana::utils::is_char_hiragana(c) {
(
CharType::Hiragana,
prev_type != CharType::Hiragana,
false,
true,
)
} else if c.is_ascii() {
(CharType::Alpha, prev_type != CharType::Alpha, false, true)
} else if wana_kana::utils::is_char_kanji(c) {
conv_kana_txt(&mut kana_text, &mut hiragana, &mut romaji);
let (t, n) = convert_kanji(&text[i..], &kana_text, &dict);
if n > 0 {
kana_text = t;
for _ in 1..n {
char_indices.next();
}
(CharType::Kanji, false, false, false)
} else {
// Unknown kanji
kana_text.clear();
// TODO: FOR TESTING
hiragana.push_str("🯄");
romaji.push_str("🯄");
(CharType::Kanji, true, false, false)
}
} else if matches!(c as u32, 0xf000..=0xfffd | 0x10000..=0x10ffd) {
// PUA: ignore and drop
conv_kana_txt(&mut kana_text, &mut hiragana, &mut romaji);
kana_text.clear();
(prev_type, false, false, false)
} else {
(prev_type, true, true, true)
};
prev_type = output_flag.0;
if output_flag.1 && output_flag.2 {
kana_text.push(c);
conv_kana_txt(&mut kana_text, &mut hiragana, &mut romaji);
kana_text.clear()
} else if output_flag.1 && output_flag.3 {
conv_kana_txt(&mut kana_text, &mut hiragana, &mut romaji);
kana_text = c.to_string();
} else if output_flag.3 {
kana_text.push(c);
}
}
// Convert last word
conv_kana_txt(&mut kana_text, &mut hiragana, &mut romaji);
// Remove trailing space
romaji.pop();
KakasiResult { hiragana, romaji } KakasiResult { hiragana, romaji }
} }
fn is_sym(c: char) -> bool {
matches!(c as u32,
0x3000..=0x3020 |
0x3030..=0x303F |
0x0391..=0x03A1 |
0x03A3..=0x03A9 |
0x03B1..=0x03C9 |
0x0410..= 0x044F |
0xFF01..=0xFF1A |
0x00A1..=0x00FF |
0xFF20..=0xFF5E |
0x0451 |
0x0401
)
}
fn convert_kana(text: &str) -> String {
wana_kana::to_hiragana::to_hiragana_with_opt(
text,
wana_kana::Options {
use_obsolete_kana: false,
pass_romaji: true,
upcase_katakana: false,
imemode: false,
},
)
}
/// Convert the leading kanji from the input string to hiragana /// Convert the leading kanji from the input string to hiragana
/// ///
/// # Arguments /// # Arguments
@ -61,7 +195,7 @@ pub fn convert(text: &str) -> KakasiResult {
/// The input needs to be NFKC-normalized and synonymous kanji need to be /// The input needs to be NFKC-normalized and synonymous kanji need to be
/// replaced using [`convert_syn`]. /// replaced using [`convert_syn`].
/// ///
/// * `btext` - /// * `btext` - Buffer string (leading kana)
/// ///
/// # Return /// # Return
/// ///
@ -69,6 +203,7 @@ pub fn convert(text: &str) -> KakasiResult {
/// * `1` - Number of converted chars from the input string /// * `1` - Number of converted chars from the input string
fn convert_kanji(text: &str, btext: &str, dict: &PhfMap) -> (String, usize) { fn convert_kanji(text: &str, btext: &str, dict: &PhfMap) -> (String, usize) {
let mut translation = None; let mut translation = None;
let mut i_c = 0;
let mut n_c = 0; let mut n_c = 0;
let mut char_indices = text.char_indices().peekable(); let mut char_indices = text.char_indices().peekable();
@ -87,7 +222,7 @@ fn convert_kanji(text: &str, btext: &str, dict: &PhfMap) -> (String, usize) {
CLETTERS.get(&ch).and_then(|cltr| { CLETTERS.get(&ch).and_then(|cltr| {
if cltr.contains(next_c) { if cltr.contains(next_c) {
// Add the next character to the char count // Add the next character to the char count
n_c += 1; i_c += 1;
hira.push(*next_c); hira.push(*next_c);
Some(hira) Some(hira)
} else { } else {
@ -109,11 +244,14 @@ fn convert_kanji(text: &str, btext: &str, dict: &PhfMap) -> (String, usize) {
}) })
}); });
match this_tl { i_c += 1;
Some(this_tl) => translation = Some(this_tl), if let Some(tl) = this_tl {
None => break, translation = Some(tl);
n_c = i_c;
}
if i_c >= MAX_KANJI_LEN {
break;
} }
n_c += 1;
} }
translation translation
@ -165,6 +303,9 @@ mod tests {
#[rstest] #[rstest]
#[case("会っAbc", "あっ", 2)] #[case("会っAbc", "あっ", 2)]
#[case("渋谷", "しぶや", 2)]
// #[case("渋谷公会堂", "しぶやこうかいどう", 5)]
// #[case("家畜衛生試験場", "かちくえいせいしけんじょう", 7)]
fn t_convert_kanji(#[case] text: &str, #[case] expect: &str, #[case] expect_n: usize) { fn t_convert_kanji(#[case] text: &str, #[case] expect: &str, #[case] expect_n: usize) {
let dict = PhfMap::new(KANJI_DICT); let dict = PhfMap::new(KANJI_DICT);
let (res, n) = convert_kanji(text, "", &dict); let (res, n) = convert_kanji(text, "", &dict);

View file

@ -1,6 +1,6 @@
fn main() { fn main() {
for line in std::io::stdin().lines() { for line in std::io::stdin().lines() {
let res = kakasi::convert(&line.unwrap()); let res = kakasi::convert(&line.unwrap());
println!("{} - {}", res.hiragana, res.romaji); println!("{}\n{}\n\n", res.hiragana, res.romaji);
} }
} }