1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
pub mod types;
use crate::lexer::{Lexer, Token};
use chumsky::{
    input::{SpannedInput, Stream},
    prelude::*,
    Parser,
};
pub mod fun;
pub mod util;
use types::*;
use util::*;

use self::fun::Function;

impl<'s> Value<'s> {
    pub fn parse() -> parser![Self] {
        select! {
            Token::Int(x) => Value::Int(x),
            Token::Float(x) => Value::Float(x),
            Token::String(s) => Value::String(s),
        }
        .labelled("value")
    }
}

impl<'s> Expr<'s> {
    pub fn parse() -> parser![Self] {
        recursive::<_, Expr, _, _, _>(|expr| {
            let inline_expr = recursive(|inline_expr| {
                let val = select! {
                    Token::Int(x) => Expr::Value(Value::Int(x)),
                    Token::Float(x) => Expr::Value(Value::Float(x)),
                    Token::String(s) => Expr::Value(Value::String(s)),
                }
                .labelled("value");

                choice((t![ident].map(Expr::Ident), val)).boxed()
            });

            let λ = Λ::parse(expr.clone());

            let decl = t![ident]
                .then_ignore(t![<-])
                .then(inline_expr.clone().or(λ.clone().map(Expr::Lambda)))
                .map(|(name, body)| Expr::Let {
                    name,
                    rhs: Box::new(body),
                })
                .labelled("declare")
                .boxed();

            let r#if = t![if]
                .ignore_then(
                    expr.clone()
                        .then(t![else].or_not().ignore_then(expr.clone().or_not()))
                        .delimited_by(t!['('], t![')']),
                )
                .map(|(a, b)| Expr::If {
                    then: Box::new(a),
                    or: Box::new(b.unwrap_or_else(|| Expr::Value(Value::Unit))),
                })
                .labelled("🐋")
                .boxed();
            choice((
                decl,
                r#if,
                inline_expr,
                λ.clone().map(Expr::Lambda),
                Function::parse(λ).map(Expr::Function),
            ))
            .labelled("expr")
        })
    }
}

#[test]
fn parse_expr() {
    parse_s("a ← λ ( +- 🍴 )", Expr::parse());
    // dbg!(Expr::parse().parse(code("a ← λ ( +- 🍴 )")).unwrap());
}

pub fn stream(lexer: Lexer<'_>, len: usize) -> SpannedInput<Token<'_>, Span, Stream<Lexer<'_>>> {
    Stream::from_iter(lexer).spanned((len..len).into())
}

#[cfg(test)]
pub fn code<'s>(x: &'s str) -> SpannedInput<Token<'s>, Span, Stream<Lexer<'s>>> {
    stream(crate::lexer::lex(x), x.len())
}

#[cfg(test)]
pub fn parse_s<'s, T: std::fmt::Debug>(x: &'s str, p: parser![T]) -> T {
    match crate::ui::display(p.parse(code(x)).into_result(), x) {
        Ok(x) => dbg!(x),
        Err(()) => panic!(),
    }
}

pub fn parse(tokens: Lexer<'_>, len: usize) -> Result<Ast<'_>, Vec<Error<'_>>> {
    parser().parse(stream(tokens, len)).into_result()
}

fn parser<'s>() -> parser![Ast<'s>] {
    Expr::parse().repeated().collect().map(Ast::Module)
}