Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion crates/nameparser/src/pipeline/preflight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,15 @@ static PLACEHOLDER_KEYWORDS: LazyLock<Regex> = LazyLock::new(|| {
/// Casey, 1911`, it is a note on the species, before an author, `(unknown) C. Agardh`, the basionym
/// author unknown. `unnamed` counts only here: an
/// `Unnamed clade` names nothing.
/// Dyntaxa and LPSN put a comma after the taxon and a rank word in Latin or English, singular or
/// plural, before the keyword (`Hacrobia, classes incertae sedis`, `Insecta, ordines incertae
/// sedis`) or `to <rank>` after it (`Bacillota, not assigned to class`); the comma is in neither
/// group, and a plural rank word is no epithet (`Hacrobia classes incertae sedis`, #202).
static ANCHORED_PLACEHOLDER: LazyLock<Regex> = LazyLock::new(|| {
let keyword = r"(?i:incertae(?-u:\s+)sedis|inc\.(?-u:\s*)sed\.?|unknown|unnamed|unassigned|not(?-u:\s+)assigned|unidentified|undetermined|indeterminate)";
let rank_word = r"(?:sub|super|infra)?(?:species|genus|genera|family|families|familia|familiae|ordo|ordines|orders?|classis|classes|class|phylum|phyla|divisio|divisions?|kingdoms?|regnum|tribus|tribes?|sectio|sections?)|variety|form|hybrid|cultivar";
Regex::new(&format!(
r"^(\p{{Lu}}\p{{Ll}}+(?:(?-u:\s+)\(\p{{Lu}}\p{{Ll}}+\))?(?:(?-u:\s+)\p{{Ll}}[\p{{Ll}}\-]+){{0,2}}?)(?-u:\s+)((?:(?:\p{{Ll}}{{1,8}}\.|species|genus|family|subspecies|variety|form|hybrid|cultivar)(?-u:\s+)){{0,2}}(?:[(\[]{keyword}[)\]]|{keyword}\b.*))$"
r"^(\p{{Lu}}\p{{Ll}}+(?:(?-u:\s+)\(\p{{Lu}}\p{{Ll}}+\))?(?:(?-u:\s+)\p{{Ll}}[\p{{Ll}}\-]+){{0,2}}?),?(?-u:\s+)((?:(?:\p{{Ll}}{{1,8}}\.|{rank_word})(?-u:\s+)){{0,2}}(?:[(\[]{keyword}[)\]]|{keyword}\b.*))$"
))
.unwrap()
});
Expand Down
110 changes: 110 additions & 0 deletions crates/nameparser/tests/worms_temporary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,116 @@ fn incertae_sedis_variants_are_placeholders() {
}
}

#[test]
fn comma_style_placeholders_are_anchored() {
// Dyntaxa and LPSN put a comma after the taxon and a rank word, Latin or English, singular or
// plural, before the keyword or `to <rank>` after it (#202). The comma is no part of the phrase.
for (name, taxon, phrase) in [
(
"Hacrobia, classes incertae sedis",
"Hacrobia",
"classes incertae sedis",
),
(
"Acoelomorpha, classis incertae sedis",
"Acoelomorpha",
"classis incertae sedis",
),
(
"Protozoa, phylum incertae sedis",
"Protozoa",
"phylum incertae sedis",
),
(
"Coleoptera, genera incertae sedis",
"Coleoptera",
"genera incertae sedis",
),
(
"Diptera, families incertae sedis",
"Diptera",
"families incertae sedis",
),
(
"Insecta, ordo incertae sedis",
"Insecta",
"ordo incertae sedis",
),
(
"Hemiptera, familia incertae sedis",
"Hemiptera",
"familia incertae sedis",
),
(
"Insecta, ordines incertae sedis",
"Insecta",
"ordines incertae sedis",
),
(
"Insecta, orders incertae sedis",
"Insecta",
"orders incertae sedis",
),
(
"Anthozoa, subclassis incertae sedis",
"Anthozoa",
"subclassis incertae sedis",
),
(
"Hemiptera, subordines incertae sedis",
"Hemiptera",
"subordines incertae sedis",
),
("Mollusca, incertae sedis", "Mollusca", "incertae sedis"),
(
"Bacteria, not assigned to kingdom",
"Bacteria",
"not assigned to kingdom",
),
(
"Anaerolineae, not assigned to order",
"Anaerolineae",
"not assigned to order",
),
// the comma-less form: a plural rank word is no epithet
(
"Hacrobia classes incertae sedis",
"Hacrobia",
"classes incertae sedis",
),
(
"Coleoptera genera incertae sedis",
"Coleoptera",
"genera incertae sedis",
),
] {
assert_placeholder(name)
.taxon(taxon)
.taxon_rank(Rank::Unranked)
.rank(Rank::Unranked)
.phrase(phrase)
.nothing_else();
}
// a rank hint does not change the anchor
for (name, rank) in [
("Ascomycota, classes incertae sedis", Rank::Subphylum),
("Bacillota, not assigned to class", Rank::Class),
] {
let result = nameparser::parse(name, None, Some(rank), None);
let pn = result
.parsed()
.unwrap_or_else(|| panic!("{name}: a parsed placeholder"));
assert_eq!(pn.type_, NameType::Placeholder, "{name}");
assert_eq!(
pn.uninomial.as_deref(),
Some(&name[..name.find(',').unwrap()]),
"{name}"
);
}
// a taxon that is no name leaves the placeholder unparsable, as without the comma (#185)
assert_unparsable("Viruses, phylum not assigned", NameType::Placeholder);
}

#[test]
fn fish_suborders_are_scientific_monomials() {
assert_name("Acanthistioidei")
Expand Down
6 changes: 3 additions & 3 deletions testdata/golden/expected-format.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -822,9 +822,9 @@ Xylosma quichensis var. subalpina Donn.Sm. true Xylosma quichensis var. subalpin
Zexmenia guatemalensis Donn.Sm. true Zexmenia guatemalensis Donn.Sm. Zexmenia guatemalensis Zexmenia guatemalensis Zexmenia guatemalensis Donn.Sm. Donn.Sm.
Zinnia jugistyla Paul G.Wilson true Zinnia jugistyla Paul G.Wilson Zinnia jugistyla Zinnia jugistyla Zinnia jugistyla Paul G.Wilson Paul G.Wilson
Poa indeterminate true Poa indeterminate Poa indeterminate Poa Poa indeterminate
Pezizomycotina, ordines incertae sedis false
Ascomycota, families incertae sedis false
Heterokontophyta, genera incertae sedis false
Pezizomycotina, ordines incertae sedis true Pezizomycotina ordines incertae sedis Pezizomycotina ordines incertae sedis Pezizomycotina Pezizomycotina ordines incertae sedis
Ascomycota, families incertae sedis true Ascomycota families incertae sedis Ascomycota families incertae sedis Ascomycota Ascomycota families incertae sedis
Heterokontophyta, genera incertae sedis true Heterokontophyta genera incertae sedis Heterokontophyta genera incertae sedis Heterokontophyta Heterokontophyta genera incertae sedis
Oxypoda ((incertae sedis)) inimica Casey, 1911 false
Undescribed genus false
? unclassed false
Expand Down
6 changes: 3 additions & 3 deletions testdata/golden/expected-parse.jsonl
Original file line number Diff line number Diff line change
Expand Up @@ -821,9 +821,9 @@
{"line":822,"input":"Zexmenia guatemalensis Donn.Sm.","parsed":{"rank":"SPECIES","genus":"Zexmenia","specificEpithet":"guatemalensis","candidatus":false,"graftChimaera":false,"type":"SCIENTIFIC","extinct":false,"doubtful":false,"manuscript":false,"state":"COMPLETE","warnings":[],"combinationAuthorship":{"authors":["Donn.Sm."],"exAuthors":[],"bracketedYear":false,"anonymous":false},"basionymAuthorship":{"authors":[],"exAuthors":[],"bracketedYear":false,"anonymous":false}}}
{"line":823,"input":"Zinnia jugistyla Paul G.Wilson","parsed":{"rank":"SPECIES","genus":"Zinnia","specificEpithet":"jugistyla","candidatus":false,"graftChimaera":false,"type":"SCIENTIFIC","extinct":false,"doubtful":false,"manuscript":false,"state":"COMPLETE","warnings":[],"combinationAuthorship":{"authors":["Paul G.Wilson"],"exAuthors":[],"bracketedYear":false,"anonymous":false},"basionymAuthorship":{"authors":[],"exAuthors":[],"bracketedYear":false,"anonymous":false}}}
{"line":824,"input":"Poa indeterminate","parsed":{"rank":"UNRANKED","uninomial":"Poa","phrase":"indeterminate","candidatus":false,"graftChimaera":false,"type":"PLACEHOLDER","extinct":false,"doubtful":false,"manuscript":false,"state":"COMPLETE","warnings":[],"combinationAuthorship":{"authors":[],"exAuthors":[],"bracketedYear":false,"anonymous":false},"basionymAuthorship":{"authors":[],"exAuthors":[],"bracketedYear":false,"anonymous":false}}}
{"line":825,"input":"Pezizomycotina, ordines incertae sedis","error":{"type":"PLACEHOLDER","message":"Unparsable PLACEHOLDER name: Pezizomycotina, ordines incertae sedis"}}
{"line":826,"input":"Ascomycota, families incertae sedis","error":{"type":"PLACEHOLDER","message":"Unparsable PLACEHOLDER name: Ascomycota, families incertae sedis"}}
{"line":827,"input":"Heterokontophyta, genera incertae sedis","error":{"type":"PLACEHOLDER","message":"Unparsable PLACEHOLDER name: Heterokontophyta, genera incertae sedis"}}
{"line":825,"input":"Pezizomycotina, ordines incertae sedis","parsed":{"rank":"UNRANKED","uninomial":"Pezizomycotina","phrase":"ordines incertae sedis","candidatus":false,"graftChimaera":false,"type":"PLACEHOLDER","extinct":false,"doubtful":false,"manuscript":false,"state":"COMPLETE","warnings":[],"combinationAuthorship":{"authors":[],"exAuthors":[],"bracketedYear":false,"anonymous":false},"basionymAuthorship":{"authors":[],"exAuthors":[],"bracketedYear":false,"anonymous":false}}}
{"line":826,"input":"Ascomycota, families incertae sedis","parsed":{"rank":"UNRANKED","uninomial":"Ascomycota","phrase":"families incertae sedis","candidatus":false,"graftChimaera":false,"type":"PLACEHOLDER","extinct":false,"doubtful":false,"manuscript":false,"state":"COMPLETE","warnings":[],"combinationAuthorship":{"authors":[],"exAuthors":[],"bracketedYear":false,"anonymous":false},"basionymAuthorship":{"authors":[],"exAuthors":[],"bracketedYear":false,"anonymous":false}}}
{"line":827,"input":"Heterokontophyta, genera incertae sedis","parsed":{"rank":"UNRANKED","uninomial":"Heterokontophyta","phrase":"genera incertae sedis","candidatus":false,"graftChimaera":false,"type":"PLACEHOLDER","extinct":false,"doubtful":false,"manuscript":false,"state":"COMPLETE","warnings":[],"combinationAuthorship":{"authors":[],"exAuthors":[],"bracketedYear":false,"anonymous":false},"basionymAuthorship":{"authors":[],"exAuthors":[],"bracketedYear":false,"anonymous":false}}}
{"line":828,"input":"Oxypoda ((incertae sedis)) inimica Casey, 1911","error":{"type":"PLACEHOLDER","message":"Unparsable PLACEHOLDER name: Oxypoda ((incertae sedis)) inimica Casey, 1911"}}
{"line":829,"input":"Undescribed genus","error":{"type":"PLACEHOLDER","message":"Unparsable PLACEHOLDER name: Undescribed genus"}}
{"line":830,"input":"? unclassed","error":{"type":"PLACEHOLDER","message":"Unparsable PLACEHOLDER name: ? unclassed"}}
Expand Down
Loading