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
use super::{filter::filter, Delim, Token};
use alloc::vec::Vec;
use chumsky::prelude::*;
use jaq_syn::{Arg, Call, Def, Main};

/// A (potentially empty) parenthesised and `;`-separated sequence of arguments.
fn args<T, P>(arg: P) -> impl Parser<Token, Vec<T>, Error = P::Error> + Clone
where
    P: Parser<Token, T> + Clone,
{
    Delim::Paren
        .around(arg.separated_by(just(Token::Semicolon)))
        .or_not()
        .map(Option::unwrap_or_default)
}

pub fn call<T, P>(expr: P) -> impl Parser<Token, Call<T>, Error = P::Error> + Clone
where
    P: Parser<Token, T, Error = Simple<Token>> + Clone,
{
    select! {
        Token::Ident(ident) => ident,
    }
    .labelled("filter name")
    .then(args(expr).labelled("filter args"))
    .map(|(name, args)| Call { name, args })
}

/// Parser for a single definition.
fn def<P>(def: P) -> impl Parser<Token, Def, Error = Simple<Token>> + Clone
where
    P: Parser<Token, Def, Error = Simple<Token>> + Clone,
{
    let arg = select! {
        Token::Ident(name) => Arg::new_filter(name),
        Token::Var(name) => Arg::new_var(name),
    };

    let defs = def.repeated().collect();

    just(Token::Def)
        .ignore_then(call(arg))
        .then_ignore(just(Token::Colon))
        .then(defs.then(filter()).map(|(defs, body)| Main { defs, body }))
        .then_ignore(just(Token::Semicolon))
        .map(|(lhs, rhs)| Def { lhs, rhs })
        .labelled("definition")
}

/// Parser for a sequence of definitions.
pub fn defs() -> impl Parser<Token, Vec<Def>, Error = Simple<Token>> + Clone {
    recursive(def).repeated().collect()
}

/// Parser for a (potentially empty) sequence of definitions, followed by a filter.
pub fn main() -> impl Parser<Token, Main, Error = Simple<Token>> + Clone {
    defs()
        .then(filter())
        .map(|(defs, body)| Main { defs, body })
}