Add BoundedSeparated with parser and printer
This type should be able to replace Separated (with a bit of effort). The hope is that this type is a better representation for table-like syntax with optional trailing delimiter that will let me remove_map elements without too much difficulty. This is necessary for desugaring table constructors.
This commit is contained in:
parent
9591b23082
commit
a1867fdc4e
3 changed files with 86 additions and 2 deletions
|
|
@ -96,3 +96,16 @@ impl<E, S1, S2> HasSpan for Separated<E, S1, S2> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
use chumsky::prelude::*;
|
use chumsky::prelude::*;
|
||||||
use chumsky::text::Character;
|
use chumsky::text::Character;
|
||||||
|
|
||||||
use crate::ast::{Ident, Line, Separated, Space};
|
use crate::ast::{BoundedSeparated, Ident, Line, Separated, Space};
|
||||||
use crate::span::Span;
|
use crate::span::Span;
|
||||||
|
|
||||||
pub type Error = Simple<char, Span>;
|
pub type Error = Simple<char, Span>;
|
||||||
|
|
@ -82,3 +82,43 @@ pub fn separated_by<E: 'static, S1: 'static, S2: 'static>(
|
||||||
})
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bounded_separated<E: 'static, R1, R2, R3>(
|
||||||
|
space: impl Parser<char, Space, Error = Error> + Clone + 'static,
|
||||||
|
start: impl Parser<char, R1, Error = Error> + 'static,
|
||||||
|
end: impl Parser<char, R2, Error = Error> + 'static,
|
||||||
|
separator: impl Parser<char, R3, Error = Error> + 'static,
|
||||||
|
elem: impl Parser<char, E, Error = Error> + Clone + 'static,
|
||||||
|
) -> EParser<BoundedSeparated<E>> {
|
||||||
|
start
|
||||||
|
.ignore_then(space.clone())
|
||||||
|
.then(
|
||||||
|
elem.clone()
|
||||||
|
.then(space.clone())
|
||||||
|
.then_ignore(separator)
|
||||||
|
.then(space.clone())
|
||||||
|
.repeated(),
|
||||||
|
)
|
||||||
|
.then(elem.then(space).or_not())
|
||||||
|
.then_ignore(end)
|
||||||
|
.map_with_span(|((s0, first_elems), last_elem), span| {
|
||||||
|
let mut space_before_elem = s0;
|
||||||
|
let mut elems = vec![];
|
||||||
|
for ((elem, s1), s2) in first_elems {
|
||||||
|
elems.push((space_before_elem, elem, s1));
|
||||||
|
space_before_elem = s2;
|
||||||
|
}
|
||||||
|
let trailing = if let Some((elem, s1)) = last_elem {
|
||||||
|
elems.push((space_before_elem, elem, s1));
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(space_before_elem)
|
||||||
|
};
|
||||||
|
BoundedSeparated {
|
||||||
|
elems,
|
||||||
|
trailing,
|
||||||
|
span,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.boxed()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
use pretty::{DocAllocator, DocBuilder, Pretty};
|
use pretty::{DocAllocator, DocBuilder, Pretty};
|
||||||
|
|
||||||
use crate::ast::{Ident, Separated};
|
use crate::ast::{BoundedSeparated, Ident, Separated};
|
||||||
|
|
||||||
|
use super::NEST_DEPTH;
|
||||||
|
|
||||||
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Ident {
|
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Ident {
|
||||||
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
|
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
|
||||||
|
|
@ -45,3 +47,32 @@ impl<E, S1, S2> Separated<E, S1, S2> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<E> BoundedSeparated<E> {
|
||||||
|
pub fn pretty<'a, D, FE>(
|
||||||
|
self,
|
||||||
|
allocator: &'a D,
|
||||||
|
start: DocBuilder<'a, D>,
|
||||||
|
end: DocBuilder<'a, D>,
|
||||||
|
separator: DocBuilder<'a, D>,
|
||||||
|
elem_pretty: FE,
|
||||||
|
) -> DocBuilder<'a, D>
|
||||||
|
where
|
||||||
|
D: DocAllocator<'a>,
|
||||||
|
D::Doc: Clone,
|
||||||
|
FE: Fn(E) -> DocBuilder<'a, D>,
|
||||||
|
{
|
||||||
|
allocator
|
||||||
|
.intersperse(
|
||||||
|
self.elems
|
||||||
|
.into_iter()
|
||||||
|
.map(|(s0, elem, s1)| allocator.line().append(elem_pretty(elem))),
|
||||||
|
separator.clone(),
|
||||||
|
)
|
||||||
|
.append(self.trailing.map(|s| separator))
|
||||||
|
.nest(NEST_DEPTH)
|
||||||
|
.append(allocator.line())
|
||||||
|
.enclose(start, end)
|
||||||
|
.group()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue