use std::fmt; use crate::span::{HasSpan, Span}; use super::{TableConstr, TableConstrElem, TableLit, TableLitElem}; #[derive(Clone)] pub enum Line { Empty, Comment(String), } #[derive(Clone)] pub struct Space { pub lines: Vec, pub span: Span, } impl fmt::Debug for Space { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.lines.iter().any(|l| matches!(l, Line::Comment(_))) { write!(f, "space with comments") } else { write!(f, "space") } } } impl HasSpan for Space { fn span(&self) -> Span { self.span } } impl Space { pub fn empty(span: Span) -> Self { Self { lines: vec![], span, } } pub fn then(mut self, other: Self) -> Self { self.lines.extend(other.lines); self.span = self.span.join(other.span); self } pub fn then_line(mut self, line: Line) -> Self { self.lines.push(line); self } } #[derive(Clone)] pub struct Ident { pub name: String, pub span: Span, } impl Ident { pub fn new(name: S, span: Span) -> Self { Self { name: name.to_string(), span, } } } impl fmt::Debug for Ident { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "i#{}", self.name) } } impl HasSpan for Ident { fn span(&self) -> Span { self.span } } #[derive(Debug, Clone)] pub struct BoundedSeparated { pub elems: Vec<(Space, E, Space)>, pub trailing: Option, pub span: Span, } impl HasSpan for BoundedSeparated { fn span(&self) -> Span { self.span } } impl BoundedSeparated { pub fn new(span: Span) -> Self { Self { elems: vec![], trailing: None, span, } } pub fn then(mut self, elem: E) -> Self { self.elems .push((Space::empty(self.span), elem, Space::empty(self.span))); self } pub fn map(self, f: impl Fn(E) -> E2) -> BoundedSeparated { let elems = self .elems .into_iter() .map(|(s0, e, s1)| (s0, f(e), s1)) .collect::>(); BoundedSeparated { elems, trailing: self.trailing, span: self.span, } } pub fn remove_map( self, f: impl Fn(E) -> Result, ) -> (BoundedSeparated, Vec<(Space, E2, Space)>) { let mut kept = vec![]; let mut removed = vec![]; for (s0, elem, s1) in self.elems { match f(elem) { Ok(elem) => kept.push((s0, elem, s1)), Err(elem) => removed.push((s0, elem, s1)), } } let new = BoundedSeparated { elems: kept, trailing: self.trailing, span: self.span, }; (new, removed) } } impl BoundedSeparated { pub fn table_lit(self) -> TableLit { TableLit(self) } } impl BoundedSeparated { pub fn table_constr(self) -> TableConstr { TableConstr(self) } }