Start creating Separated2 type for easier manipulation
This commit is contained in:
parent
9591b23082
commit
7748068be7
3 changed files with 163 additions and 0 deletions
|
|
@ -4,4 +4,5 @@ mod expr;
|
|||
mod field;
|
||||
mod lit;
|
||||
mod program;
|
||||
mod table_constr;
|
||||
mod var;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
use std::mem;
|
||||
|
||||
use crate::ast::Separated;
|
||||
use crate::span::Span;
|
||||
|
||||
impl<E, S1, S2> Separated<E, S1, S2> {
|
||||
pub fn desugar_elem(self, desugar_elem: impl Fn(E) -> (E, bool)) -> (Self, bool) {
|
||||
|
|
@ -34,3 +37,145 @@ impl<E, S1, S2> Separated<E, S1, S2> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A version of [`Separated`] that includes its leading and trailing
|
||||
/// whitespace.
|
||||
enum Separated2<E, S> {
|
||||
// In theory, all of the second space would've already been consumed by the
|
||||
// first space parser, but we still need to keep track of it because I
|
||||
// haven't yet found a nicer way to model this data.
|
||||
Empty(S, S, Span),
|
||||
NonEmpty {
|
||||
elems: Vec<(S, E, S)>,
|
||||
trailing: Option<S>,
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
impl<E, S> Separated2<E, S> {
|
||||
pub fn from_separated(before: S, separated: Separated<E, (S, S), S>, after: S) -> Self {
|
||||
match separated {
|
||||
Separated::Empty(span) => Self::Empty(before, after, span),
|
||||
|
||||
Separated::NonEmpty {
|
||||
first_elem,
|
||||
last_elems,
|
||||
trailing,
|
||||
span,
|
||||
} => {
|
||||
let mut next_before = before;
|
||||
let mut next_elem = first_elem;
|
||||
let mut elems = vec![];
|
||||
|
||||
for ((prev_after, this_before), elem) in last_elems {
|
||||
elems.push((next_before, next_elem, prev_after));
|
||||
next_before = this_before;
|
||||
next_elem = elem;
|
||||
}
|
||||
|
||||
let trailing = if let Some(trailing) = trailing {
|
||||
elems.push((next_before, next_elem, trailing));
|
||||
Some(after)
|
||||
} else {
|
||||
elems.push((next_before, next_elem, after));
|
||||
None
|
||||
};
|
||||
|
||||
Self::NonEmpty {
|
||||
elems,
|
||||
trailing,
|
||||
span,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_separated(self) -> (S, Separated<E, (S, S), S>, S) {
|
||||
match self {
|
||||
Self::Empty(before, after, span) => (before, Separated::Empty(span), after),
|
||||
|
||||
Self::NonEmpty {
|
||||
elems,
|
||||
trailing,
|
||||
span,
|
||||
} => {
|
||||
let mut elems = elems.into_iter();
|
||||
|
||||
let (before, first_elem, mut after) = elems
|
||||
.next()
|
||||
.expect("non-empty Separated2 must have elements");
|
||||
|
||||
let mut last_elems = vec![];
|
||||
for (this_before, elem, this_after) in elems {
|
||||
last_elems.push(((after, this_before), elem));
|
||||
after = this_after;
|
||||
}
|
||||
|
||||
let trailing = if let Some(mut trailing) = trailing {
|
||||
mem::swap(&mut after, &mut trailing);
|
||||
Some(trailing)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let separated = Separated::NonEmpty {
|
||||
first_elem,
|
||||
last_elems,
|
||||
trailing,
|
||||
span,
|
||||
};
|
||||
|
||||
(before, separated, after)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Decision<A, B> {
|
||||
Keep(A),
|
||||
Remove(B),
|
||||
}
|
||||
|
||||
impl<E, S> Separated2<E, S> {
|
||||
pub fn remove<E1, E2>(
|
||||
self,
|
||||
decide: impl Fn(E) -> Decision<E1, E2>,
|
||||
) -> (Separated2<E1, S>, Vec<(S, E2, S)>) {
|
||||
match self {
|
||||
Self::Empty(s0, s1, span) => (Separated2::Empty(s0, s1, span), vec![]),
|
||||
Self::NonEmpty {
|
||||
elems,
|
||||
trailing,
|
||||
span,
|
||||
} => {
|
||||
let mut kept = vec![];
|
||||
let mut removed = vec![];
|
||||
for (s0, elem, s1) in elems {
|
||||
match decide(elem) {
|
||||
Decision::Keep(elem) => kept.push((s0, elem, s1)),
|
||||
Decision::Remove(elem) => removed.push((s0, elem, s1)),
|
||||
}
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Removed<A, B, S> {
|
||||
before: S,
|
||||
separated: Separated<A, (S, S), S>,
|
||||
after: S,
|
||||
removed: Vec<(S, B, S)>,
|
||||
}
|
||||
|
||||
impl<E, S> Separated<E, (S, S), S> {
|
||||
pub fn remove_elems<E2, E3>(
|
||||
self,
|
||||
before: S,
|
||||
after: S,
|
||||
separate: impl Fn(E) -> Decision<E2, E3>,
|
||||
) -> Removed<E2, E3, S> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
17
src/desugar/table_constr.rs
Normal file
17
src/desugar/table_constr.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
use crate::ast::{Expr, Lit, TableConstr, TableLit};
|
||||
|
||||
impl TableConstr {
|
||||
pub fn desugar(self) -> (Expr, bool) {
|
||||
let Self {
|
||||
s0,
|
||||
elems,
|
||||
s1,
|
||||
span,
|
||||
} = self;
|
||||
|
||||
// `{ s0 elems s1 }`
|
||||
// -> `'{ raw: '{ s0 lit_elems s1 } }` surrounded by 'set calls
|
||||
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue