mod consts; mod utils; mod lex; use consts::SRC; use lex::{Stanza, StanzaLexError}; use utils::FromStaticStr; fn main() { let mut count = 0; let mut parse_state = ParseState::Ready; let mut current_entry = EntryBuilder::new(); let mut dict = Dictionary { entries: vec![], }; for l in SRC.split("\n\n") { count += 1; let stanza = match Stanza::from_str(l) { Ok(s) => { println!("{count} ok"); s }, Err(StanzaLexError { data }) => { eprintln!("stanza err: {data}\n\n"); continue; }, }; match stanza { Stanza::Entry(s) if parse_state == ParseState::Ready => { current_entry.set_name(s); parse_state = ParseState::InEntry; } Stanza::Defn(d) if parse_state == ParseState::InEntry => { current_entry.set_defn(d); match current_entry.build() { Ok(e) => dict.entries.push(e), Err(_) => eprintln!("failed to build entry"), } parse_state = ParseState::Ready; } _ => () } } dbg!(dict.entries.iter().find(|entry| entry.name.to_ascii_lowercase().starts_with("discursive"))); } #[derive(PartialEq, Eq, PartialOrd, Ord)] enum ParseState { Ready, InEntry } struct Dictionary { entries: Vec } #[derive(Debug)] struct Entry { name: &'static str, defn: Option<&'static str>, note: Option<&'static str>, synonym: Option<&'static str>, } #[derive(Default)] struct EntryBuilder { name: Option<&'static str>, defn: Option<&'static str>, note: Option<&'static str>, synonym: Option<&'static str>, } enum EntryBuilderError { MissingField(&'static str) } impl EntryBuilder { fn new() -> Self { Self::default() } fn set_name(&mut self, name: &'static str) { self.name = Some(name); } fn set_defn(&mut self, defn: &'static str) { self.defn = Some(defn); } fn build(&self) -> Result { Ok(Entry { name: self.name.ok_or(EntryBuilderError::MissingField("name"))?, defn: self.defn, note: self.note, synonym: self.synonym, }) } }