Compare commits
4 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a18532a23a | |||
| b21619dabd | |||
| 969570fc4b | |||
| b009a9c4ec |
15 changed files with 231 additions and 94 deletions
|
|
@ -47,3 +47,23 @@ impl HasSpan for Ident {
|
||||||
self.span
|
self.span
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Separated<E, S1, S2> {
|
||||||
|
Empty(Span),
|
||||||
|
NonEmpty {
|
||||||
|
first_elem: E,
|
||||||
|
last_elems: Vec<(S1, E)>,
|
||||||
|
trailing: Option<S2>,
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E, S1, S2> HasSpan for Separated<E, S1, S2> {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
match self {
|
||||||
|
Separated::Empty(span) => *span,
|
||||||
|
Separated::NonEmpty { span, .. } => *span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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, Space};
|
use super::{Expr, Ident, Separated, Space};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum NumLitStr {
|
pub enum NumLitStr {
|
||||||
|
|
@ -126,11 +126,13 @@ impl HasSpan for TableLitElem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `'{ a, foo: b }`
|
/// `'{ a, foo: b }`
|
||||||
|
///
|
||||||
|
/// Structure: `'{ s0 elems s1 }`
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TableLit {
|
pub struct TableLit {
|
||||||
pub elems: Vec<(Space, TableLitElem, Space)>,
|
pub s0: Space,
|
||||||
/// `Some` if there is a trailing comma, `None` otherwise.
|
pub elems: Separated<TableLitElem, (Space, Space), Space>,
|
||||||
pub trailing_comma: Option<Space>,
|
pub s1: Space,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::span::{HasSpan, Span};
|
use crate::span::{HasSpan, Span};
|
||||||
|
|
||||||
use super::{Expr, Space, TableLitElem};
|
use super::{Expr, Separated, Space, TableLitElem};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Program {
|
pub enum Program {
|
||||||
|
|
@ -12,12 +12,12 @@ pub enum Program {
|
||||||
span: Span,
|
span: Span,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Structure: `s0 module elems trailing_comma`
|
/// Structure: `s0 module s1 elems s2`
|
||||||
Module {
|
Module {
|
||||||
s0: Space,
|
s0: Space,
|
||||||
elems: Vec<(Space, TableLitElem, Space)>,
|
s1: Space,
|
||||||
/// `Some` if there is a trailing comma, `None` otherwise.
|
elems: Separated<TableLitElem, (Space, Space), Space>,
|
||||||
trailing_comma: Option<Space>,
|
s2: Space,
|
||||||
span: Span,
|
span: Span,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::span::{HasSpan, Span};
|
use crate::span::{HasSpan, Span};
|
||||||
|
|
||||||
use super::{Expr, Space, TableLitElem};
|
use super::{Expr, Separated, Space, TableLitElem};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TableConstrElem {
|
pub enum TableConstrElem {
|
||||||
|
|
@ -31,11 +31,13 @@ impl HasSpan for TableConstrElem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `{ a, b, foo: c, [d]: e }`
|
/// `{ a, b, foo: c, [d]: e }`
|
||||||
|
///
|
||||||
|
/// Structure: `{ s0 elems s1 }`
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TableConstr {
|
pub struct TableConstr {
|
||||||
pub elems: Vec<(Space, TableConstrElem, Space)>,
|
pub s0: Space,
|
||||||
/// `Some` if there is a trailing comma, `None` otherwise.
|
pub elems: Separated<TableConstrElem, (Space, Space), Space>,
|
||||||
pub trailing_comma: Option<Space>,
|
pub s1: Space,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::span::{HasSpan, Span};
|
use crate::span::{HasSpan, Span};
|
||||||
|
|
||||||
use super::{Expr, Ident, Space};
|
use super::{Expr, Ident, Separated, Space};
|
||||||
|
|
||||||
// TODO Make table patterns recursive
|
// TODO Make table patterns recursive
|
||||||
|
|
||||||
|
|
@ -30,12 +30,14 @@ impl HasSpan for TablePatternElem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `'{ foo, bar: baz }`
|
/// `{ foo, bar: baz }`
|
||||||
|
///
|
||||||
|
/// Structure: `{ s0 elems s1 }`
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TablePattern {
|
pub struct TablePattern {
|
||||||
pub elems: Vec<(Space, TablePatternElem, Space)>,
|
pub s0: Space,
|
||||||
/// `Some` if there is a trailing comma, `None` otherwise.
|
pub elems: Separated<TablePatternElem, (Space, Space), Space>,
|
||||||
pub trailing_comma: Option<Space>,
|
pub s1: Space,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
12
src/main.rs
12
src/main.rs
|
|
@ -1,7 +1,6 @@
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use ::pretty::{Pretty, RcAllocator};
|
|
||||||
use chumsky::Parser as _;
|
use chumsky::Parser as _;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
|
|
@ -48,17 +47,14 @@ fn main() -> anyhow::Result<()> {
|
||||||
let stream = span::stream_from_str(&content);
|
let stream = span::stream_from_str(&content);
|
||||||
match parser::parser().parse(stream) {
|
match parser::parser().parse(stream) {
|
||||||
Ok(program) => {
|
Ok(program) => {
|
||||||
println!("Successful parse");
|
|
||||||
let doc = program.pretty(&RcAllocator);
|
|
||||||
let mut out = vec![];
|
let mut out = vec![];
|
||||||
doc.render(100, &mut out)?;
|
program.to_doc().render(100, &mut out)?;
|
||||||
let str = String::from_utf8(out)?;
|
println!("{}", String::from_utf8(out)?);
|
||||||
println!("{str}");
|
|
||||||
}
|
}
|
||||||
Err(errs) => {
|
Err(errs) => {
|
||||||
println!("Parsing failed");
|
eprintln!("Parsing failed");
|
||||||
for err in errs {
|
for err in errs {
|
||||||
println!("{err:?}");
|
eprintln!("{err:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
//!
|
//!
|
||||||
//! # Rules
|
//! # Rules
|
||||||
//!
|
//!
|
||||||
|
//! - Parsers must not consume surrounding whitespace.
|
||||||
//! - Public parser functions must return [`basic::EParser`].
|
//! - Public parser functions must return [`basic::EParser`].
|
||||||
//! - Public parser functions must receive public subparsers via their arguments.
|
//! - Public parser functions must receive public subparsers via their arguments.
|
||||||
//! - Each public parser function must be called exactly once, inside this file.
|
//! - Each public parser function must be called exactly once, inside this file.
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
use chumsky::prelude::*;
|
use chumsky::prelude::*;
|
||||||
use chumsky::text::Character;
|
use chumsky::text::Character;
|
||||||
|
|
||||||
use crate::ast::{Ident, Line, Space};
|
use crate::ast::{Ident, Line, Separated, Space};
|
||||||
use crate::span::Span;
|
use crate::span::Span;
|
||||||
|
|
||||||
pub type Error = Simple<char, Span>;
|
pub type Error = Simple<char, Span>;
|
||||||
|
|
@ -58,3 +58,27 @@ pub fn ident() -> EParser<Ident> {
|
||||||
pub fn local(space: EParser<Space>) -> EParser<Option<Space>> {
|
pub fn local(space: EParser<Space>) -> EParser<Option<Space>> {
|
||||||
text::keyword("local").ignore_then(space).or_not().boxed()
|
text::keyword("local").ignore_then(space).or_not().boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function is more of a utility function. Because of this and to keep the
|
||||||
|
// code nicer, I have decided that the rules specified in the `parser` module
|
||||||
|
// don't apply to it.
|
||||||
|
pub fn separated_by<E: 'static, S1: 'static, S2: 'static>(
|
||||||
|
elem: impl Parser<char, E, Error = Error> + Clone + 'static,
|
||||||
|
separator: impl Parser<char, S1, Error = Error> + 'static,
|
||||||
|
trailing_separator: impl Parser<char, S2, Error = Error> + 'static,
|
||||||
|
) -> EParser<Separated<E, S1, S2>> {
|
||||||
|
elem.clone()
|
||||||
|
.then(separator.then(elem).repeated())
|
||||||
|
.then(trailing_separator.or_not())
|
||||||
|
.or_not()
|
||||||
|
.map_with_span(|s, span| match s {
|
||||||
|
Some(((first_elem, last_elems), trailing)) => Separated::NonEmpty {
|
||||||
|
first_elem,
|
||||||
|
last_elems,
|
||||||
|
trailing,
|
||||||
|
span,
|
||||||
|
},
|
||||||
|
None => Separated::Empty(span),
|
||||||
|
})
|
||||||
|
.boxed()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use crate::ast::{
|
||||||
};
|
};
|
||||||
use crate::builtin::Builtin;
|
use crate::builtin::Builtin;
|
||||||
|
|
||||||
use super::basic::{EParser, Error};
|
use super::basic::{separated_by, 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,22 +154,18 @@ 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 elem = space
|
let separator = space.clone().then_ignore(just(',')).then(space.clone());
|
||||||
|
let trailing_separator = space.clone().then_ignore(just(','));
|
||||||
|
|
||||||
|
space
|
||||||
.clone()
|
.clone()
|
||||||
.then(table_lit_elem)
|
.then(separated_by(table_lit_elem, separator, trailing_separator))
|
||||||
.then(space.clone())
|
.then(space)
|
||||||
.map(|((s0, elem), s1)| (s0, elem, s1));
|
.delimited_by(just("'{"), just('}'))
|
||||||
|
.map_with_span(|((s0, elems), s1), span| TableLit {
|
||||||
let trailing_comma = just(',').ignore_then(space).or_not();
|
s0,
|
||||||
|
|
||||||
let elems = elem.separated_by(just(',')).then(trailing_comma);
|
|
||||||
|
|
||||||
just("'{")
|
|
||||||
.ignore_then(elems)
|
|
||||||
.then_ignore(just('}'))
|
|
||||||
.map_with_span(|(elems, trailing_comma), span| TableLit {
|
|
||||||
elems,
|
elems,
|
||||||
trailing_comma,
|
s1,
|
||||||
span,
|
span,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use chumsky::prelude::*;
|
||||||
|
|
||||||
use crate::ast::{Expr, Program, Space, TableLitElem};
|
use crate::ast::{Expr, Program, Space, TableLitElem};
|
||||||
|
|
||||||
use super::basic::EParser;
|
use super::basic::{separated_by, EParser};
|
||||||
|
|
||||||
pub fn program(
|
pub fn program(
|
||||||
space: EParser<Space>,
|
space: EParser<Space>,
|
||||||
|
|
@ -17,20 +17,19 @@ 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 elem = space
|
let separator = space.clone().then_ignore(just(',')).then(space.clone());
|
||||||
.clone()
|
let trailing_separator = space.clone().then_ignore(just(','));
|
||||||
.then(table_lit_elem)
|
|
||||||
.then(space.clone())
|
|
||||||
.map(|((s0, elem), s1)| (s0, elem, s1));
|
|
||||||
let trailing_comma = just(',').ignore_then(space.clone()).or_not();
|
|
||||||
let module = space
|
let module = space
|
||||||
|
.clone()
|
||||||
.then_ignore(text::keyword("module"))
|
.then_ignore(text::keyword("module"))
|
||||||
.then(elem.separated_by(just(',')))
|
.then(space.clone())
|
||||||
.then(trailing_comma)
|
.then(separated_by(table_lit_elem, separator, trailing_separator))
|
||||||
.map_with_span(|((s0, elems), trailing_comma), span| Program::Module {
|
.then(space.clone())
|
||||||
|
.map_with_span(|(((s0, s1), elems), s2), span| Program::Module {
|
||||||
s0,
|
s0,
|
||||||
|
s1,
|
||||||
elems,
|
elems,
|
||||||
trailing_comma,
|
s2,
|
||||||
span,
|
span,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,13 @@ use chumsky::prelude::*;
|
||||||
|
|
||||||
use crate::ast::{Expr, Space, TableConstr, TableConstrElem, TableLitElem};
|
use crate::ast::{Expr, Space, TableConstr, TableConstrElem, TableLitElem};
|
||||||
|
|
||||||
use super::basic::{EParser, Error};
|
use super::basic::{separated_by, EParser, Error};
|
||||||
|
|
||||||
fn table_constr_elem(
|
fn table_constr_elem(
|
||||||
space: EParser<Space>,
|
space: EParser<Space>,
|
||||||
table_lit_elem: EParser<TableLitElem>,
|
table_lit_elem: EParser<TableLitElem>,
|
||||||
expr: EParser<Expr>,
|
expr: EParser<Expr>,
|
||||||
) -> impl Parser<char, TableConstrElem, Error = Error> {
|
) -> impl Parser<char, TableConstrElem, Error = Error> + Clone {
|
||||||
let lit = table_lit_elem.map(TableConstrElem::Lit);
|
let lit = table_lit_elem.map(TableConstrElem::Lit);
|
||||||
|
|
||||||
let indexed = just('[')
|
let indexed = just('[')
|
||||||
|
|
@ -42,22 +42,19 @@ pub fn table_constr(
|
||||||
table_lit_elem: EParser<TableLitElem>,
|
table_lit_elem: EParser<TableLitElem>,
|
||||||
expr: EParser<Expr>,
|
expr: EParser<Expr>,
|
||||||
) -> EParser<TableConstr> {
|
) -> EParser<TableConstr> {
|
||||||
let elem = space
|
let elem = table_constr_elem(space.clone(), table_lit_elem, expr);
|
||||||
|
let separator = space.clone().then_ignore(just(',')).then(space.clone());
|
||||||
|
let trailing_separator = space.clone().then_ignore(just(','));
|
||||||
|
|
||||||
|
space
|
||||||
.clone()
|
.clone()
|
||||||
.then(table_constr_elem(space.clone(), table_lit_elem, expr))
|
.then(separated_by(elem, separator, trailing_separator))
|
||||||
.then(space.clone())
|
.then(space)
|
||||||
.map(|((s0, elem), s1)| (s0, elem, s1));
|
.delimited_by(just('{'), just('}'))
|
||||||
|
.map_with_span(|((s0, elems), s1), span| TableConstr {
|
||||||
let trailing_comma = just(',').ignore_then(space).or_not();
|
s0,
|
||||||
|
|
||||||
let elems = elem.separated_by(just(',')).then(trailing_comma);
|
|
||||||
|
|
||||||
just('{')
|
|
||||||
.ignore_then(elems)
|
|
||||||
.then_ignore(just('}'))
|
|
||||||
.map_with_span(|(elems, trailing_comma), span| TableConstr {
|
|
||||||
elems,
|
elems,
|
||||||
trailing_comma,
|
s1,
|
||||||
span,
|
span,
|
||||||
})
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ use chumsky::prelude::*;
|
||||||
|
|
||||||
use crate::ast::{Expr, Ident, Space, TableDestr, TablePattern, TablePatternElem};
|
use crate::ast::{Expr, Ident, Space, TableDestr, TablePattern, TablePatternElem};
|
||||||
|
|
||||||
use super::basic::{EParser, Error};
|
use super::basic::{separated_by, EParser, Error};
|
||||||
|
|
||||||
fn table_pattern_elem(
|
fn table_pattern_elem(
|
||||||
space: EParser<Space>,
|
space: EParser<Space>,
|
||||||
ident: EParser<Ident>,
|
ident: EParser<Ident>,
|
||||||
) -> impl Parser<char, TablePatternElem, Error = Error> {
|
) -> impl Parser<char, TablePatternElem, Error = Error> + Clone {
|
||||||
let positional = ident.clone().map(TablePatternElem::Positional);
|
let positional = ident.clone().map(TablePatternElem::Positional);
|
||||||
|
|
||||||
let named = ident
|
let named = ident
|
||||||
|
|
@ -30,22 +30,19 @@ fn table_pattern_elem(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn table_pattern(space: EParser<Space>, ident: EParser<Ident>) -> EParser<TablePattern> {
|
pub fn table_pattern(space: EParser<Space>, ident: EParser<Ident>) -> EParser<TablePattern> {
|
||||||
let elem = space
|
let elem = table_pattern_elem(space.clone(), ident);
|
||||||
|
let separator = space.clone().then_ignore(just(',')).then(space.clone());
|
||||||
|
let trailing_separator = space.clone().then_ignore(just(','));
|
||||||
|
|
||||||
|
space
|
||||||
.clone()
|
.clone()
|
||||||
.then(table_pattern_elem(space.clone(), ident))
|
.then(separated_by(elem, separator, trailing_separator))
|
||||||
.then(space.clone())
|
.then(space)
|
||||||
.map(|((s0, elem), s1)| (s0, elem, s1));
|
.delimited_by(just('{'), just('}'))
|
||||||
|
.map_with_span(|((s0, elems), s1), span| TablePattern {
|
||||||
let trailing_comma = just(',').ignore_then(space).or_not();
|
s0,
|
||||||
|
|
||||||
let elems = elem.separated_by(just(',')).then(trailing_comma);
|
|
||||||
|
|
||||||
just('{')
|
|
||||||
.ignore_then(elems)
|
|
||||||
.then_ignore(just('}'))
|
|
||||||
.map_with_span(|(elems, trailing_comma), span| TablePattern {
|
|
||||||
elems,
|
elems,
|
||||||
trailing_comma,
|
s1,
|
||||||
span,
|
span,
|
||||||
})
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1 @@
|
||||||
use pretty::{DocAllocator, DocBuilder, Pretty};
|
mod program;
|
||||||
|
|
||||||
use crate::ast::Program;
|
|
||||||
|
|
||||||
impl<'a, A: DocAllocator<'a>> Pretty<'a, A> for Program {
|
|
||||||
fn pretty(self, allocator: &'a A) -> DocBuilder<'a, A, ()> {
|
|
||||||
allocator.text("Hello world")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
86
src/pretty/basic.rs
Normal file
86
src/pretty/basic.rs
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
use pretty::{DocAllocator, DocBuilder, Pretty, RcAllocator, RcDoc};
|
||||||
|
|
||||||
|
use crate::ast::{Ident, Line, Space};
|
||||||
|
|
||||||
|
pub enum Group<'a> {
|
||||||
|
EmptyLine,
|
||||||
|
CommentBlock(Vec<&'a str>),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Group comments and deduplicate empty lines
|
||||||
|
fn group_comments(lines: &[Line]) -> Vec<Group> {
|
||||||
|
let mut result = vec![];
|
||||||
|
|
||||||
|
let mut current_block = vec![];
|
||||||
|
let mut last_line_was_empty = false;
|
||||||
|
for line in lines {
|
||||||
|
match line {
|
||||||
|
Line::Empty if last_line_was_empty => {}
|
||||||
|
Line::Empty => {
|
||||||
|
last_line_was_empty = true;
|
||||||
|
if !current_block.is_empty() {
|
||||||
|
result.push(Group::CommentBlock(mem::take(&mut current_block)));
|
||||||
|
}
|
||||||
|
result.push(Group::EmptyLine);
|
||||||
|
}
|
||||||
|
Line::Comment(comment) => {
|
||||||
|
last_line_was_empty = false;
|
||||||
|
current_block.push(comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !current_block.is_empty() {
|
||||||
|
result.push(Group::CommentBlock(current_block));
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_leading_empty_line(groups: &mut Vec<Group>) {
|
||||||
|
if let Some(Group::EmptyLine) = groups.first() {
|
||||||
|
groups.remove(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_trailing_empty_line(groups: &mut Vec<Group>) {
|
||||||
|
if let Some(Group::EmptyLine) = groups.last() {
|
||||||
|
groups.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn comment_group_to_doc(comment: Vec<&str>) -> RcDoc {
|
||||||
|
RcAllocator
|
||||||
|
.concat(comment.into_iter().map(|c| {
|
||||||
|
RcDoc::text("# ")
|
||||||
|
.append(RcDoc::text(c))
|
||||||
|
.append(RcDoc::hardline())
|
||||||
|
}))
|
||||||
|
.indent(0)
|
||||||
|
.into_doc()
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Space {
|
||||||
|
/// Format as document for inline use, prefering nil if possible.
|
||||||
|
pub fn to_doc_inline_nospace(&self) -> RcDoc {
|
||||||
|
RcDoc::nil()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Format as document, prefering a single space if possible.
|
||||||
|
pub fn to_doc_inline_space(&self) -> RcDoc {
|
||||||
|
RcDoc::space()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Format as document, prefering a newline if possible.
|
||||||
|
pub fn to_doc_newline(&self) -> RcDoc {
|
||||||
|
RcDoc::line()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ident {
|
||||||
|
pub fn to_doc(&self) -> RcDoc {
|
||||||
|
RcDoc::text(&self.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/pretty/program.rs
Normal file
23
src/pretty/program.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
use pretty::RcDoc;
|
||||||
|
|
||||||
|
use crate::ast::Program;
|
||||||
|
|
||||||
|
impl Program {
|
||||||
|
pub fn to_doc(&self) -> RcDoc {
|
||||||
|
match self {
|
||||||
|
Program::Expr {
|
||||||
|
s0,
|
||||||
|
expr,
|
||||||
|
s1,
|
||||||
|
span: _,
|
||||||
|
} => RcDoc::nil(),
|
||||||
|
Program::Module {
|
||||||
|
s0,
|
||||||
|
s1,
|
||||||
|
elems,
|
||||||
|
s2,
|
||||||
|
span: _,
|
||||||
|
} => RcDoc::text("module"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue