tada/src/ast/basic.rs

155 lines
3.2 KiB
Rust

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<Line>,
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<S: ToString>(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<E> {
pub elems: Vec<(Space, E, Space)>,
pub trailing: Option<Space>,
pub span: Span,
}
impl<E> HasSpan for BoundedSeparated<E> {
fn span(&self) -> Span {
self.span
}
}
impl<E> BoundedSeparated<E> {
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<E2>(self, f: impl Fn(E) -> E2) -> BoundedSeparated<E2> {
let elems = self
.elems
.into_iter()
.map(|(s0, e, s1)| (s0, f(e), s1))
.collect::<Vec<_>>();
BoundedSeparated {
elems,
trailing: self.trailing,
span: self.span,
}
}
pub fn remove_map<E1, E2>(
self,
f: impl Fn(E) -> Result<E1, E2>,
) -> (BoundedSeparated<E1>, 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<TableLitElem> {
pub fn table_lit(self) -> TableLit {
TableLit(self)
}
}
impl BoundedSeparated<TableConstrElem> {
pub fn table_constr(self) -> TableConstr {
TableConstr(self)
}
}