Parsing the affiliated keywords.

This commit is contained in:
Tom Alexander
2023-10-11 12:06:05 -04:00
parent a5129199c7
commit c4cc40f5e1
3 changed files with 92 additions and 37 deletions

View File

@@ -1,11 +1,17 @@
use std::collections::BTreeMap;
use nom::combinator::all_consuming;
use nom::multi::many0;
use super::object_parser::standard_set_object;
use crate::context::parser_with_context;
use crate::context::Context;
use crate::context::ContextElement;
use crate::context::GlobalSettings;
use crate::context::List;
use crate::types::AffiliatedKeywordValue;
use crate::types::AffiliatedKeywords;
use crate::types::Keyword;
use crate::types::Object;
use crate::types::PlainList;
pub(crate) fn parse_affiliated_keywords<'g, 's>(
global_settings: &'g GlobalSettings<'g, 's>,
@@ -13,42 +19,70 @@ pub(crate) fn parse_affiliated_keywords<'g, 's>(
) -> AffiliatedKeywords<'s> {
let mut ret = BTreeMap::new();
for kw in input.into_iter() {
// foo
let translated_name = translate_name(global_settings, kw.key);
if is_single_string_keyword(global_settings, translated_name) {
ret.insert(
translated_name,
AffiliatedKeywordValue::SingleString(kw.value),
);
} else if is_list_of_objects_keyword(global_settings, translated_name) {
let initial_context = ContextElement::document_context();
let initial_context = Context::new(global_settings, List::new(&initial_context));
// TODO: This should be omitting footnote references
let (_remaining, objects) = all_consuming(many0(parser_with_context!(
standard_set_object
)(&initial_context)))(kw.value.into())
.expect("Object parser should always succeed.");
let list_of_lists = ret.entry(translated_name).or_insert_with(|| {
AffiliatedKeywordValue::ListOfListsOfObjects(Vec::with_capacity(1))
});
match list_of_lists {
AffiliatedKeywordValue::ListOfListsOfObjects(list_of_lists) => {
list_of_lists.push(objects);
}
_ => panic!("Invalid AffiliatedKeywordValue type."),
}
} else {
let list_of_strings = ret
.entry(translated_name)
.or_insert_with(|| AffiliatedKeywordValue::ListOfStrings(Vec::with_capacity(1)));
match list_of_strings {
AffiliatedKeywordValue::ListOfStrings(list_of_strings) => {
list_of_strings.push(kw.value);
}
_ => panic!("Invalid AffiliatedKeywordValue type."),
}
}
}
AffiliatedKeywords { keywords: ret }
}
// pub struct AffiliatedKeyword<'s> {
// name: &'s str,
// }
fn translate_name<'g, 's>(global_settings: &'g GlobalSettings<'g, 's>, name: &'s str) -> &'s str {
for (src, dst) in global_settings.element_keyword_translation_alist {
if name.eq_ignore_ascii_case(src) {
return *dst;
}
}
name
}
// pub enum AffiliatedKeywordValue<'s> {
// SingleString(&'s str),
// ListOfStrings(Vec<&'s str>),
// ListOfObjects(Vec<Object<'s>>),
// }
fn is_single_string_keyword<'g, 's>(
_global_settings: &'g GlobalSettings<'g, 's>,
name: &'s str,
) -> bool {
// TODO: Is this defined by an elisp variable? I'm only seeing this done for plot.
name.eq_ignore_ascii_case("plot")
}
// pub trait GetAffiliatedKeywords<'s> {
// type ItemIterator: Iterator<Item = &'s Keyword<'s>>;
// fn get_affiliated_keywords<'r: 's>(&'r self) -> Self::ItemIterator;
// }
// pub trait HandleAffiliatedKeywords<'s> {
// fn get_stuff(&self) -> &'s str;
// }
// impl<'s> GetAffiliatedKeywords<'s> for PlainList<'s> {
// type ItemIterator = std::slice::Iter<'s, Keyword<'s>>;
// fn get_affiliated_keywords<'r: 's>(&'r self) -> Self::ItemIterator {
// self.affiliated_keywords.iter()
// }
// }
// impl<'s, I: GetAffiliatedKeywords<'s>> HandleAffiliatedKeywords<'s> for I {
// fn get_stuff(&self) -> &'s str {
// self.get_affiliated_keywords().count();
// todo!()
// }
// }
fn is_list_of_objects_keyword<'g, 's>(
global_settings: &'g GlobalSettings<'g, 's>,
name: &'s str,
) -> bool {
for parsed_keyword in global_settings.element_parsed_keywords {
if name.eq_ignore_ascii_case(parsed_keyword) {
return true;
}
}
false
}