diff --git a/src/config.rs b/src/config.rs index ba39bc5..ed00a29 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, iter::FromIterator}; use super::*; use anyhow::*; @@ -54,13 +54,15 @@ pub struct Definitional { impl FromExpr for Definitional { fn from_expr(e: Expr) -> Result { if let Expr::List(list) = e { - let mut iter = list.into_iter(); + let mut iter = SExpIterator::new(list); - let def_type = DefType::from_sp(iter.next().unwrap())?; - let name = iter.next().unwrap().1.str()?; - let attrs = parse_key_values(&mut iter); + let def_type = DefType::from_sp(iter.next().unwrap().as_single().unwrap())?; + let name = iter.next().unwrap().as_single().unwrap().1.str()?; + let attrs = iter.next().unwrap().as_key_value().unwrap(); - let children = iter.map(T::from_sp).collect::, AstError>>()?; + let children = iter + .map(|elem| T::from_sp(elem.as_single()?)) + .collect::, AstError>>()?; Ok(Definitional { def_type, name, @@ -78,40 +80,43 @@ pub struct WidgetDefinition { argnames: Vec, } -pub fn parse_key_values(iter: impl Iterator>) -> HashMap> { - let mut attrs = HashMap::new(); - let mut iter = iter.multipeek(); - loop { - let next = iter.peek(); - let next2 = iter.peek(); - iter.reset_peek(); - if let (Some(Sp(_, Expr::Keyword(_), _)), Some(_)) = (next, next2) { - if let Some(Sp(_, Expr::Keyword(x), _)) = iter.next() { - attrs.insert(x.to_string(), iter.next().unwrap()); - } else { - unreachable!(); - } - } else { - break; - } - } - attrs -} - struct SExpIterator { elements: LinkedList>, } +impl SExpIterator { + fn new(elements: Vec>) -> Self { + SExpIterator { + elements: LinkedList::from_iter(elements.into_iter()), + } + } +} + enum ExpressionElement { Single(Sp), - KeyValue(Vec<(String, Sp)>), + KeyValue(HashMap>), +} + +impl ExpressionElement { + fn as_single(self) -> Option> { + match self { + ExpressionElement::Single(x) => Some(x), + ExpressionElement::KeyValue(_) => None, + } + } + fn as_key_value(self) -> Option>> { + match self { + ExpressionElement::Single(_) => None, + ExpressionElement::KeyValue(x) => Some(x), + } + } } impl Iterator for SExpIterator { type Item = ExpressionElement; fn next(&mut self) -> Option { - let mut data = vec![]; + let mut data = HashMap::new(); loop { let first_is_kw = self.elements.front().map_or(false, |x| x.1.is_keyword()); if first_is_kw { @@ -120,7 +125,7 @@ impl Iterator for SExpIterator { _ => unreachable!(), }; if let Some(value) = self.elements.pop_front() { - data.push((kw, value)); + data.insert(kw, value); } else { return if data.is_empty() { Some(ExpressionElement::Single(Sp(l, Expr::Keyword(kw), r))) @@ -138,12 +143,3 @@ impl Iterator for SExpIterator { } } } - -/* - ( - foo - bar - :baz "hi" :bat "ho" - [rst arst arst rst]) - -*/