#![cfg_attr(docsrs, feature(doc_cfg))]
#[doc(hidden)]
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
mod normalize_text;
pub use normalize_text::normalize_text_for_naist_jdic;
pub use jpreprocess_core::error;
use jpreprocess_core::{token::Tokenizer, *};
pub use jpreprocess_njd::NJD;
pub struct JPreprocess<T: Tokenizer> {
tokenizer: T,
}
impl<T: Tokenizer> JPreprocess<T> {
pub fn from_tokenizer(tokenizer: T) -> Self {
Self { tokenizer }
}
pub fn text_to_njd(&self, text: &str) -> JPreprocessResult<NJD> {
let normalized_input_text = normalize_text_for_naist_jdic(text);
let tokens = self.tokenizer.tokenize(normalized_input_text.as_str())?;
NJD::from_tokens(tokens)
}
pub fn run_frontend(&self, text: &str) -> JPreprocessResult<Vec<String>> {
let mut njd = Self::text_to_njd(self, text)?;
njd.preprocess();
Ok(njd.into())
}
pub fn make_label(&self, njd_features: Vec<String>) -> Vec<jlabel::Label> {
let njd = NJD::from_strings(njd_features);
jpreprocess_jpcommon::njdnodes_to_features(&njd.nodes)
}
pub fn extract_fullcontext(&self, text: &str) -> JPreprocessResult<Vec<jlabel::Label>> {
let mut njd = Self::text_to_njd(self, text)?;
njd.preprocess();
Ok(jpreprocess_jpcommon::njdnodes_to_features(&njd.nodes))
}
}
#[cfg(feature = "tokenizer")]
mod dictionary;
#[cfg(feature = "tokenizer")]
pub use default_tokenizer_impl::*;
#[cfg(feature = "tokenizer")]
mod default_tokenizer_impl {
pub use crate::dictionary::*;
pub use jpreprocess_dictionary::tokenizer::default::DefaultTokenizer;
pub use lindera_dictionary::dictionary::{Dictionary, UserDictionary};
use crate::JPreprocess;
use jpreprocess_core::{error::DictionaryError, JPreprocessError, JPreprocessResult};
pub struct JPreprocessConfig {
pub dictionary: SystemDictionaryConfig,
pub user_dictionary: Option<lindera::dictionary::UserDictionaryConfig>,
}
impl JPreprocess<DefaultTokenizer> {
#[deprecated(since = "0.13.0", note = "Use `with_dictionaries` instead")]
pub fn from_config(config: JPreprocessConfig) -> JPreprocessResult<Self> {
let dictionary = config.dictionary.load()?;
let user_dictionary = match config.user_dictionary {
Some(user_dict_conf) => {
let path = user_dict_conf
.get("path")
.and_then(|path_value| path_value.as_str())
.map(std::path::PathBuf::from)
.ok_or_else(|| {
JPreprocessError::DictionaryError(
DictionaryError::UserDictionaryNotProvided,
)
})?;
match path.extension().and_then(|ext| ext.to_str()) {
Some("bin") => {
Some(lindera::dictionary::load_user_dictionary_from_bin(&path)?)
}
_ => {
eprintln!("CSV-type user dictionary can no longer be loaded with `JPreprocess::from_config` since JPreprocess v0.13.0. Please use `JPreprocess::with_dictionaries` instead.");
eprintln!("Skipping user dictionary loading.");
None
}
}
}
None => None,
};
Ok(Self::with_dictionaries(dictionary, user_dictionary))
}
pub fn with_dictionaries(
dictionary: Dictionary,
user_dictionary: Option<UserDictionary>,
) -> Self {
let tokenizer = lindera::tokenizer::Tokenizer::new(lindera::segmenter::Segmenter::new(
lindera_dictionary::mode::Mode::Normal,
dictionary,
user_dictionary,
));
let tokenizer = DefaultTokenizer::new(tokenizer);
Self::from_tokenizer(tokenizer)
}
}
#[cfg(test)]
mod tests {
#[test]
fn multithread() {
use crate::JPreprocess;
use jpreprocess_dictionary::tokenizer::default::DefaultTokenizer;
fn tester<T: Send + Sync>() {}
tester::<JPreprocess<DefaultTokenizer>>();
}
}
}