use std::collections::BTreeMap;
use std::iter::FromIterator;
use std::mem;
use std::ops::{Deref, DerefMut};
use crate::graph::{Iter, IterMut, Node, Sentence};
pub struct TokenBuilder {
token: Token,
}
impl TokenBuilder {
pub fn new(form: impl Into<String>) -> TokenBuilder {
TokenBuilder {
token: Token::new(form),
}
}
pub fn form(mut self, form: impl Into<String>) -> TokenBuilder {
self.token.set_form(form);
self
}
pub fn lemma(mut self, lemma: impl Into<String>) -> TokenBuilder {
self.token.set_lemma(Some(lemma));
self
}
pub fn upos(mut self, upos: impl Into<String>) -> TokenBuilder {
self.token.set_upos(Some(upos));
self
}
pub fn xpos(mut self, xpos: impl Into<String>) -> TokenBuilder {
self.token.set_xpos(Some(xpos));
self
}
pub fn features(mut self, features: Features) -> TokenBuilder {
self.token.set_features(features);
self
}
pub fn deps(mut self, deps: impl Into<String>) -> TokenBuilder {
self.token.set_deps(Some(deps.into()));
self
}
pub fn misc(mut self, misc: Misc) -> TokenBuilder {
self.token.set_misc(misc);
self
}
}
impl From<Token> for TokenBuilder {
fn from(token: Token) -> Self {
TokenBuilder { token }
}
}
impl From<TokenBuilder> for Token {
fn from(builder: TokenBuilder) -> Self {
builder.token
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Token {
form: String,
lemma: Option<String>,
upos: Option<String>,
xpos: Option<String>,
features: Features,
misc: Misc,
deps: Option<String>,
}
impl Token {
pub fn new(form: impl Into<String>) -> Token {
Token {
form: form.into(),
lemma: None,
upos: None,
xpos: None,
features: Features::new(),
misc: Misc::new(),
deps: None,
}
}
pub fn form(&self) -> &str {
self.form.as_ref()
}
pub fn lemma(&self) -> Option<&str> {
self.lemma.as_ref().map(String::as_ref)
}
pub fn upos(&self) -> Option<&str> {
self.upos.as_ref().map(String::as_ref)
}
pub fn xpos(&self) -> Option<&str> {
self.xpos.as_ref().map(String::as_ref)
}
pub fn features(&self) -> &Features {
&self.features
}
pub fn features_mut(&mut self) -> &mut Features {
&mut self.features
}
pub fn deps(&self) -> Option<&str> {
self.deps.as_deref()
}
pub fn misc(&self) -> &Misc {
&self.misc
}
pub fn misc_mut(&mut self) -> &mut Misc {
&mut self.misc
}
pub fn set_form(&mut self, form: impl Into<String>) -> String {
mem::replace(&mut self.form, form.into())
}
pub fn set_lemma<S>(&mut self, lemma: Option<S>) -> Option<String>
where
S: Into<String>,
{
mem::replace(&mut self.lemma, lemma.map(Into::into))
}
pub fn set_upos<S>(&mut self, upos: Option<S>) -> Option<String>
where
S: Into<String>,
{
mem::replace(&mut self.upos, upos.map(Into::into))
}
pub fn set_xpos<S>(&mut self, xpos: Option<S>) -> Option<String>
where
S: Into<String>,
{
mem::replace(&mut self.xpos, xpos.map(Into::into))
}
pub fn set_features(&mut self, features: Features) -> Features {
mem::replace(&mut self.features, features)
}
pub fn set_deps(&mut self, deps: Option<impl Into<String>>) -> Option<String> {
mem::replace(&mut self.deps, deps.map(Into::into))
}
pub fn set_misc(&mut self, misc: Misc) -> Misc {
mem::replace(&mut self.misc, misc)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Features {
inner: BTreeMap<String, String>,
}
impl Features {
pub fn new() -> Self {
Features {
inner: BTreeMap::new(),
}
}
pub fn into_inner(self) -> BTreeMap<String, String> {
self.inner
}
}
impl Default for Features {
fn default() -> Self {
Features::new()
}
}
impl Deref for Features {
type Target = BTreeMap<String, String>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for Features {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl From<BTreeMap<String, String>> for Features {
fn from(feature_map: BTreeMap<String, String>) -> Self {
Features { inner: feature_map }
}
}
impl<S, T> FromIterator<(S, T)> for Features
where
S: Into<String>,
T: Into<String>,
{
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = (S, T)>,
{
let features = iter
.into_iter()
.map(|(k, v)| (k.into(), v.into()))
.collect();
Features { inner: features }
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Misc {
inner: BTreeMap<String, Option<String>>,
}
impl Misc {
pub fn new() -> Self {
Misc {
inner: BTreeMap::new(),
}
}
pub fn into_inner(self) -> BTreeMap<String, Option<String>> {
self.inner
}
}
impl Default for Misc {
fn default() -> Self {
Misc::new()
}
}
impl Deref for Misc {
type Target = BTreeMap<String, Option<String>>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for Misc {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl From<BTreeMap<String, Option<String>>> for Misc {
fn from(misc_map: BTreeMap<String, Option<String>>) -> Self {
Misc { inner: misc_map }
}
}
impl<S, T> FromIterator<(S, Option<T>)> for Misc
where
S: Into<String>,
T: Into<String>,
{
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = (S, Option<T>)>,
{
let misc = iter
.into_iter()
.map(|(k, v)| (k.into(), v.map(Into::into)))
.collect();
Misc { inner: misc }
}
}
pub trait Tokens {
fn tokens(&self) -> TokenIter;
fn tokens_mut(&mut self) -> TokenIterMut;
}
impl Tokens for Sentence {
fn tokens(&self) -> TokenIter {
TokenIter { inner: self.iter() }
}
fn tokens_mut(&mut self) -> TokenIterMut {
TokenIterMut {
inner: self.iter_mut(),
}
}
}
pub struct TokenIter<'a> {
inner: Iter<'a>,
}
impl<'a> Iterator for TokenIter<'a> {
type Item = &'a Token;
fn next(&mut self) -> Option<Self::Item> {
for node in self.inner.by_ref() {
if let Node::Token(token) = node {
return Some(token);
}
}
None
}
}
pub struct TokenIterMut<'a> {
inner: IterMut<'a>,
}
impl<'a> Iterator for TokenIterMut<'a> {
type Item = &'a mut Token;
fn next(&mut self) -> Option<Self::Item> {
for node in self.inner.by_ref() {
if let Node::Token(token) = node {
return Some(token);
}
}
None
}
}
#[cfg(test)]
mod tests {
use std::iter::FromIterator;
use maplit::btreemap;
use super::{Features, Tokens};
use crate::tests::TEST_SENTENCES;
#[test]
fn features_from_iter() {
let feature_map = btreemap! {
"feature2".to_string() => "y".to_string(),
"feature1".to_string() => "x".to_string(),
};
assert_eq!(feature_map, *Features::from_iter(feature_map.clone()));
}
#[test]
fn tokens() {
let mut iter = TEST_SENTENCES[0].tokens();
assert_eq!(iter.next(), TEST_SENTENCES[0][1].token());
assert_eq!(iter.next(), TEST_SENTENCES[0][2].token());
assert_eq!(iter.next(), None);
}
#[test]
fn tokens_mut() {
let mut sentence = TEST_SENTENCES[0].clone();
{
let mut iter = sentence.tokens_mut();
let token = iter.next().unwrap();
assert_eq!(&*token, TEST_SENTENCES[0][1].token().unwrap());
token.set_upos(Some("mutable"));
assert_eq!(iter.next().map(|t| &*t), TEST_SENTENCES[0][2].token());
assert_eq!(iter.next(), None);
}
assert_eq!(sentence[1].token().unwrap().upos(), Some("mutable"));
}
}