// Ported from: https://github.com/michel-kraemer/citeproc-java/blob/master/citeproc-java/grammars/InternalName.g4 // Michel Kraemer // Apache License 2.0 use citeproc_io::{Name, PersonName}; use itertools::Itertools; grammar; pub Names: Vec = And; And: Vec = { "and")*> => match e { None => v, Some(e) => { let mut v = v; v.push(e); v } } }; Name: Name = { "," => { let (fst1, fst2) = fst; let name = PersonName { family: Some(fam.join(" ")), given: fst2, non_dropping_particle: Some(format!("{} {}", np1.join(" "), np2)), dropping_particle: None, suffix: fst1, }; Name::Person(name) }, "," => { let (fst1, fst2) = fst; let name = PersonName { family: Some(fam.join(" ")), given: fst2, non_dropping_particle: Some(np), dropping_particle: None, suffix: fst1, }; Name::Person(name) }, "," => { let (fst1, fst2) = fst; let first_text = format!( "{} {}", fst1.as_ref().map(|s| s.as_str()).unwrap_or_default(), fst2.as_ref().map(|s| s.as_str()).unwrap_or_default(), ).trim().to_owned(); let name = if first_text == "Jr." { if last.len() == 1 { PersonName { family: Some(last.join(" ")), given: None, non_dropping_particle: None, dropping_particle: None, suffix: Some(first_text), } } else { let mut last = last.into_iter(); let given = last.next().map(ToOwned::to_owned); PersonName { family: Some(last.join(" ")), given, non_dropping_particle: None, dropping_particle: None, suffix: Some(first_text), } } } else { PersonName { family: Some(last.join(" ")), given: fst2, non_dropping_particle: None, dropping_particle: None, suffix: fst1, } }; Name::Person(name) }, => { let name = PersonName { family: Some(fam.join(" ")), given: None, non_dropping_particle: Some(np), dropping_particle: None, suffix: None, }; Name::Person(name) }, => { let name = PersonName { family: Some(fam.join(" ")), given: Some(giv.join(" ")), non_dropping_particle: Some(np), dropping_particle: None, suffix: None, }; Name::Person(name) }, => { let name = PersonName { family: Some(fam.into()), given: Some(giv.join(" ")), non_dropping_particle: None, dropping_particle: None, suffix: None, }; Name::Person(name) }, => { let name = PersonName { family: Some(fam.into()), given: None, non_dropping_particle: None, dropping_particle: None, suffix: None, }; Name::Person(name) }, }; First: (Option, Option) = { "," => (Some(a.join(" ")), Some(b.join(" "))), => (None, Some(a.join(" "))), }; Last: Vec<&'input str> = { LWord => vec![(<>)], UWord+ => (<>), }; Von: String = { LWord => String::from(<>), => format!("{} {}", a, b), => format!("{} {} {}", a, b.join(" "), c), }; Word: &'input str = { UWord => (<>), LWord => (<>), }; UWord: &'input str = r"[A-Z\u00C0-\uFFFF(?][A-Z\u00C0-\uFFFF(?a-z\-)&/.]+" => (<>); LWord: &'input str = r"[a-z\-)&/.][A-Z\u00C0-\uFFFF(?a-z\-)&/.]+" => (<>);