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

View file

@ -1,6 +1,6 @@
use crate::span::{HasSpan, Span}; use crate::span::{HasSpan, Span};
use super::{Expr, Separated, Space, TableLitElem}; use super::{BoundedSeparated, Expr, Space, TableLitElem};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Program { pub enum Program {
@ -12,12 +12,10 @@ pub enum Program {
span: Span, span: Span,
}, },
/// Structure: `s0 module s1 elems s2` /// Structure: `s0 module elems`
Module { Module {
s0: Space, s0: Space,
s1: Space, elems: BoundedSeparated<TableLitElem>,
elems: Separated<TableLitElem, (Space, Space), Space>,
s2: Space,
span: Span, 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> { 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 +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 // TODO Add span for just the parentheses to ast, or limit span to parentheses
@ -29,18 +29,15 @@ impl Call {
value: arg, value: arg,
span, span,
}; };
let elems = Separated::NonEmpty { let elems = vec![
first_elem: call, (s0, call, Space::empty(span)),
last_elems: vec![((Space::empty(span), Space::empty(span)), arg)], (Space::empty(span), arg, s2),
];
let new = Expr::Lit(Lit::Table(TableLit(BoundedSeparated {
elems,
trailing: None, trailing: None,
span, span,
}; })));
let new = Expr::Lit(Lit::Table(TableLit {
s0,
elems,
s1: s2,
span,
}));
(new, true) (new, true)
} }

View file

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

View file

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

View file

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

View file

@ -7,7 +7,7 @@ use crate::ast::{
}; };
use crate::builtin::Builtin; 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> { fn builtin_lit() -> impl Parser<char, Builtin, Error = Error> {
just('\'').ignore_then(choice(( just('\'').ignore_then(choice((
@ -154,20 +154,14 @@ fn table_lit(
space: EParser<Space>, space: EParser<Space>,
table_lit_elem: EParser<TableLitElem>, table_lit_elem: EParser<TableLitElem>,
) -> impl Parser<char, TableLit, Error = Error> { ) -> impl Parser<char, TableLit, Error = Error> {
let separator = space.clone().then_ignore(just(',')).then(space.clone()); bounded_separated(
let trailing_separator = space.clone().then_ignore(just(',')); space,
just("'{").to(()),
space just('}').to(()),
.clone() just(',').to(()),
.then(separated_by(table_lit_elem, separator, trailing_separator)) table_lit_elem,
.then(space) )
.delimited_by(just("'{"), just('}')) .map(TableLit)
.map_with_span(|((s0, elems), s1), span| TableLit {
s0,
elems,
s1,
span,
})
} }
pub fn lit(space: EParser<Space>, table_lit_elem: EParser<TableLitElem>) -> EParser<Lit> { 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 crate::ast::{Expr, Program, Space, TableLitElem};
use super::basic::{separated_by, EParser}; use super::basic::{bounded_separated, EParser};
pub fn program( pub fn program(
space: EParser<Space>, space: EParser<Space>,
@ -17,21 +17,17 @@ pub fn program(
.then(space.clone()) .then(space.clone())
.map_with_span(|((s0, expr), s1), span| Program::Expr { s0, expr, s1, span }); .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 let module = space
.clone() .clone()
.then_ignore(text::keyword("module")) .then_ignore(text::keyword("module"))
.then(space.clone()) .then(bounded_separated(
.then(separated_by(table_lit_elem, separator, trailing_separator)) space,
.then(space.clone()) empty(),
.map_with_span(|(((s0, s1), elems), s2), span| Program::Module { empty(),
s0, just(',').to(()),
s1, table_lit_elem,
elems, ))
s2, .map_with_span(|(s0, elems), span| Program::Module { s0, elems, span });
span,
});
module.or(lit).boxed() module.or(lit).boxed()
} }

View file

@ -2,7 +2,11 @@ use pretty::{DocAllocator, DocBuilder, Pretty};
use crate::ast::Call; 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> { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self { match self {
Self::Arg { 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> { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self { match self {
Self::Lit(lit) => lit.pretty(allocator), Self::Lit(lit) => lit.pretty(allocator),

View file

@ -2,7 +2,11 @@ use pretty::{DocAllocator, DocBuilder, Pretty};
use crate::ast::Field; 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> { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self { match self {
Self::Access { Self::Access {

View file

@ -2,7 +2,11 @@ use pretty::{DocAllocator, DocBuilder, Pretty};
use crate::ast::FuncDef; 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> { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self { match self {
Self::AnonNoArg { Self::AnonNoArg {

View file

@ -2,8 +2,6 @@ use pretty::{DocAllocator, DocBuilder, Pretty};
use crate::ast::{Lit, NumLit, StringLit, StringLitElem, TableLit, TableLitElem}; use crate::ast::{Lit, NumLit, StringLit, StringLitElem, TableLit, TableLitElem};
use super::NEST_DEPTH;
impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for NumLit { impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for NumLit {
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
allocator.text(format!("{self:?}")) 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> { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self { match self {
Self::Positional(expr) => expr.pretty(allocator), 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> { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
self.elems self.0.pretty(
.pretty( allocator,
allocator, allocator.text("'{"),
|e| allocator.line().append(e.pretty(allocator)), allocator.text("}"),
|(s0, s1)| allocator.text(","), allocator.text(","),
|s| 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> { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self { match self {
Self::Nil(_) => allocator.text("nil"), Self::Nil(_) => allocator.text("nil"),

View file

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

View file

@ -4,7 +4,11 @@ use crate::ast::{TableConstr, TableConstrElem};
use super::NEST_DEPTH; 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> { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self { match self {
Self::Lit(lit) => lit.pretty(allocator), 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> { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
self.elems self.elems
.pretty( .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> { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
// TODO Handle spaces // TODO Handle spaces
self.local self.local

View file

@ -2,7 +2,11 @@ use pretty::{DocAllocator, DocBuilder, Pretty};
use crate::ast::Var; 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> { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> {
match self { match self {
Self::Access { Self::Access {