Switch TableLit and Program to BoundedSeparated

This commit is contained in:
Joscha 2022-11-21 23:37:36 +01:00
parent a1867fdc4e
commit e3fa3500d4
18 changed files with 146 additions and 129 deletions

View file

@ -3,7 +3,7 @@ use std::fmt;
use crate::builtin::Builtin;
use crate::span::{HasSpan, Span};
use super::{Expr, Ident, Separated, Space};
use super::{BoundedSeparated, Expr, Ident, Space};
#[derive(Clone)]
pub enum NumLitStr {
@ -129,16 +129,11 @@ impl HasSpan for TableLitElem {
///
/// Structure: `'{ s0 elems s1 }`
#[derive(Debug, Clone)]
pub struct TableLit {
pub s0: Space,
pub elems: Separated<TableLitElem, (Space, Space), Space>,
pub s1: Space,
pub span: Span,
}
pub struct TableLit(pub BoundedSeparated<TableLitElem>);
impl HasSpan for TableLit {
fn span(&self) -> Span {
self.span
self.0.span()
}
}

View file

@ -1,6 +1,6 @@
use crate::span::{HasSpan, Span};
use super::{Expr, Separated, Space, TableLitElem};
use super::{BoundedSeparated, Expr, Space, TableLitElem};
#[derive(Debug, Clone)]
pub enum Program {
@ -12,12 +12,10 @@ pub enum Program {
span: Span,
},
/// Structure: `s0 module s1 elems s2`
/// Structure: `s0 module elems`
Module {
s0: Space,
s1: Space,
elems: Separated<TableLitElem, (Space, Space), Space>,
s2: Space,
elems: BoundedSeparated<TableLitElem>,
span: Span,
},
}

View file

@ -1,4 +1,4 @@
use crate::ast::Separated;
use crate::ast::{BoundedSeparated, Separated};
impl<E, S1, S2> Separated<E, S1, S2> {
pub fn desugar_elem(self, desugar_elem: impl Fn(E) -> (E, bool)) -> (Self, bool) {
@ -34,3 +34,26 @@ impl<E, S1, S2> Separated<E, S1, S2> {
}
}
}
impl<E> BoundedSeparated<E> {
pub fn desugar(self, desugar_elem: impl Fn(E) -> (E, bool)) -> (Self, bool) {
let mut desugared = false;
let mut elems = vec![];
for (s0, elem, s1) in self.elems {
if desugared {
elems.push((s0, elem, s1));
} else {
let (elem, elem_desugared) = desugar_elem(elem);
desugared = desugared || elem_desugared;
elems.push((s0, elem, s1));
}
}
let new = Self {
elems,
trailing: self.trailing,
span: self.span,
};
(new, desugared)
}
}

View file

@ -1,4 +1,4 @@
use crate::ast::{Call, Expr, Ident, Lit, Separated, Space, TableLit, TableLitElem};
use crate::ast::{BoundedSeparated, Call, Expr, Ident, Lit, Space, TableLit, TableLitElem};
// TODO Add span for just the parentheses to ast, or limit span to parentheses
@ -29,18 +29,15 @@ impl Call {
value: arg,
span,
};
let elems = Separated::NonEmpty {
first_elem: call,
last_elems: vec![((Space::empty(span), Space::empty(span)), arg)],
let elems = vec![
(s0, call, Space::empty(span)),
(Space::empty(span), arg, s2),
];
let new = Expr::Lit(Lit::Table(TableLit(BoundedSeparated {
elems,
trailing: None,
span,
};
let new = Expr::Lit(Lit::Table(TableLit {
s0,
elems,
s1: s2,
span,
}));
})));
(new, true)
}

View file

@ -31,21 +31,8 @@ impl TableLitElem {
impl TableLit {
pub fn desugar(self) -> (Self, bool) {
let Self {
s0,
elems,
s1,
span,
} = self;
let (elems, desugared) = elems.desugar_elem(|e| e.desugar());
let new = Self {
s0,
elems,
s1,
span,
};
(new, desugared)
let (elems, desugared) = self.0.desugar(|e| e.desugar());
(Self(elems), desugared)
}
}

View file

@ -9,24 +9,12 @@ impl Program {
(new, desugared)
}
Self::Module {
s0,
s1,
elems,
s2,
span,
} => {
// `s0 module s1 elems s2`
// -> `s0 '{ s1 elems s2 } empty`
let table = TableLit {
s0: s1,
elems,
s1: s2,
span,
};
Self::Module { s0, elems, span } => {
// `s0 module elems`
// -> `s0 table`
let new = Self::Expr {
s0,
expr: Expr::Lit(Lit::Table(table)),
expr: Expr::Lit(Lit::Table(TableLit(elems))),
s1: Space::empty(span),
span,
};

View file

@ -83,11 +83,11 @@ pub fn separated_by<E: 'static, S1: 'static, S2: 'static>(
.boxed()
}
pub fn bounded_separated<E: 'static, R1, R2, R3>(
pub fn bounded_separated<E: 'static>(
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,
start: impl Parser<char, (), Error = Error> + 'static,
end: impl Parser<char, (), Error = Error> + 'static,
separator: impl Parser<char, (), Error = Error> + 'static,
elem: impl Parser<char, E, Error = Error> + Clone + 'static,
) -> EParser<BoundedSeparated<E>> {
start

View file

@ -7,7 +7,7 @@ use crate::ast::{
};
use crate::builtin::Builtin;
use super::basic::{separated_by, EParser, Error};
use super::basic::{bounded_separated, EParser, Error};
fn builtin_lit() -> impl Parser<char, Builtin, Error = Error> {
just('\'').ignore_then(choice((
@ -154,20 +154,14 @@ fn table_lit(
space: EParser<Space>,
table_lit_elem: EParser<TableLitElem>,
) -> impl Parser<char, TableLit, Error = Error> {
let separator = space.clone().then_ignore(just(',')).then(space.clone());
let trailing_separator = space.clone().then_ignore(just(','));
space
.clone()
.then(separated_by(table_lit_elem, separator, trailing_separator))
.then(space)
.delimited_by(just("'{"), just('}'))
.map_with_span(|((s0, elems), s1), span| TableLit {
s0,
elems,
s1,
span,
})
bounded_separated(
space,
just("'{").to(()),
just('}').to(()),
just(',').to(()),
table_lit_elem,
)
.map(TableLit)
}
pub fn lit(space: EParser<Space>, table_lit_elem: EParser<TableLitElem>) -> EParser<Lit> {

View file

@ -4,7 +4,7 @@ use chumsky::prelude::*;
use crate::ast::{Expr, Program, Space, TableLitElem};
use super::basic::{separated_by, EParser};
use super::basic::{bounded_separated, EParser};
pub fn program(
space: EParser<Space>,
@ -17,21 +17,17 @@ pub fn program(
.then(space.clone())
.map_with_span(|((s0, expr), s1), span| Program::Expr { s0, expr, s1, span });
let separator = space.clone().then_ignore(just(',')).then(space.clone());
let trailing_separator = space.clone().then_ignore(just(','));
let module = space
.clone()
.then_ignore(text::keyword("module"))
.then(space.clone())
.then(separated_by(table_lit_elem, separator, trailing_separator))
.then(space.clone())
.map_with_span(|(((s0, s1), elems), s2), span| Program::Module {
s0,
s1,
elems,
s2,
span,
});
.then(bounded_separated(
space,
empty(),
empty(),
just(',').to(()),
table_lit_elem,
))
.map_with_span(|(s0, elems), span| Program::Module { s0, elems, span });
module.or(lit).boxed()
}

View file

@ -2,7 +2,11 @@ use pretty::{DocAllocator, DocBuilder, Pretty};
use crate::ast::Call;
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Call {
impl<'a, D> Pretty<'a, D> for Call
where
D: DocAllocator<'a>,
D::Doc: Clone,
{
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self {
Self::Arg {

View file

@ -22,7 +22,11 @@ impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for BinOp {
}
}
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Expr {
impl<'a, D> Pretty<'a, D> for Expr
where
D: DocAllocator<'a>,
D::Doc: Clone,
{
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self {
Self::Lit(lit) => lit.pretty(allocator),

View file

@ -2,7 +2,11 @@ use pretty::{DocAllocator, DocBuilder, Pretty};
use crate::ast::Field;
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Field {
impl<'a, D> Pretty<'a, D> for Field
where
D: DocAllocator<'a>,
D::Doc: Clone,
{
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self {
Self::Access {

View file

@ -2,7 +2,11 @@ use pretty::{DocAllocator, DocBuilder, Pretty};
use crate::ast::FuncDef;
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for FuncDef {
impl<'a, D> Pretty<'a, D> for FuncDef
where
D: DocAllocator<'a>,
D::Doc: Clone,
{
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self {
Self::AnonNoArg {

View file

@ -2,8 +2,6 @@ use pretty::{DocAllocator, DocBuilder, Pretty};
use crate::ast::{Lit, NumLit, StringLit, StringLitElem, TableLit, TableLitElem};
use super::NEST_DEPTH;
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for NumLit {
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
allocator.text(format!("{self:?}"))
@ -32,7 +30,11 @@ impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for StringLit {
}
}
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TableLitElem {
impl<'a, D> Pretty<'a, D> for TableLitElem
where
D: DocAllocator<'a>,
D::Doc: Clone,
{
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self {
Self::Positional(expr) => expr.pretty(allocator),
@ -50,23 +52,27 @@ impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TableLitElem {
}
}
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TableLit {
impl<'a, D> Pretty<'a, D> for TableLit
where
D: DocAllocator<'a>,
D::Doc: Clone,
{
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
self.elems
.pretty(
self.0.pretty(
allocator,
|e| allocator.line().append(e.pretty(allocator)),
|(s0, s1)| allocator.text(","),
|s| allocator.text(","),
allocator.text("'{"),
allocator.text("}"),
allocator.text(","),
|e| e.pretty(allocator),
)
.nest(NEST_DEPTH)
.append(allocator.line())
.enclose(allocator.text("'{"), allocator.text("}"))
.group()
}
}
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Lit {
impl<'a, D> Pretty<'a, D> for Lit
where
D: DocAllocator<'a>,
D::Doc: Clone,
{
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self {
Self::Nil(_) => allocator.text("nil"),

View file

@ -2,7 +2,11 @@ use pretty::{DocAllocator, DocBuilder, Pretty};
use crate::ast::Program;
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Program {
impl<'a, D> Pretty<'a, D> for Program
where
D: DocAllocator<'a>,
D::Doc: Clone,
{
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self {
Self::Expr {
@ -11,22 +15,19 @@ impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Program {
s1,
span: _,
} => expr.pretty(allocator),
Self::Module {
s0,
s1,
elems,
s2,
span: _,
} => allocator
.text("module")
.append(allocator.line())
.append(allocator.line())
.append(elems.pretty(
allocator,
|e| e.pretty(allocator),
|(s0, s1)| allocator.text(",").append(allocator.line()),
|s| allocator.text(","),
)),
Self::Module { s0, elems, span: _ } => {
allocator.text("module").append(allocator.line()).append(
allocator
.intersperse(
elems.elems.into_iter().map(|(s0, elem, s1)| {
allocator.line().append(elem.pretty(allocator))
}),
allocator.text(","),
)
.append(elems.trailing.map(|s| allocator.text(","))),
)
}
}
}
}

View file

@ -4,7 +4,11 @@ use crate::ast::{TableConstr, TableConstrElem};
use super::NEST_DEPTH;
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TableConstrElem {
impl<'a, D> Pretty<'a, D> for TableConstrElem
where
D: DocAllocator<'a>,
D::Doc: Clone,
{
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self {
Self::Lit(lit) => lit.pretty(allocator),
@ -25,7 +29,11 @@ impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TableConstrElem {
}
}
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TableConstr {
impl<'a, D> Pretty<'a, D> for TableConstr
where
D: DocAllocator<'a>,
D::Doc: Clone,
{
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
self.elems
.pretty(

View file

@ -38,7 +38,11 @@ impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TablePattern {
}
}
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TableDestr {
impl<'a, D> Pretty<'a, D> for TableDestr
where
D: DocAllocator<'a>,
D::Doc: Clone,
{
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
// TODO Handle spaces
self.local

View file

@ -2,7 +2,11 @@ use pretty::{DocAllocator, DocBuilder, Pretty};
use crate::ast::Var;
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Var {
impl<'a, D> Pretty<'a, D> for Var
where
D: DocAllocator<'a>,
D::Doc: Clone,
{
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self {
Self::Access {