Compare commits
1 commit
master
...
separated2
| Author | SHA1 | Date | |
|---|---|---|---|
| 7748068be7 |
3 changed files with 163 additions and 0 deletions
|
|
@ -4,4 +4,5 @@ mod expr;
|
||||||
mod field;
|
mod field;
|
||||||
mod lit;
|
mod lit;
|
||||||
mod program;
|
mod program;
|
||||||
|
mod table_constr;
|
||||||
mod var;
|
mod var;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
use crate::ast::Separated;
|
use crate::ast::Separated;
|
||||||
|
use crate::span::Span;
|
||||||
|
|
||||||
impl<E, S1, S2> Separated<E, S1, S2> {
|
impl<E, S1, S2> Separated<E, S1, S2> {
|
||||||
pub fn desugar_elem(self, desugar_elem: impl Fn(E) -> (E, bool)) -> (Self, bool) {
|
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