1use super::{filter::filter, Delim, Token};
2use alloc::vec::Vec;
3use chumsky::prelude::*;
4use jaq_syn::{Arg, Call, Def, Main};
5
6fn args<T, P>(arg: P) -> impl Parser<Token, Vec<T>, Error = P::Error> + Clone
8where
9 P: Parser<Token, T> + Clone,
10{
11 Delim::Paren
12 .around(arg.separated_by(just(Token::Semicolon)))
13 .or_not()
14 .map(Option::unwrap_or_default)
15}
16
17pub fn call<T, P>(expr: P) -> impl Parser<Token, Call<T>, Error = P::Error> + Clone
18where
19 P: Parser<Token, T, Error = Simple<Token>> + Clone,
20{
21 select! {
22 Token::Ident(ident) => ident,
23 }
24 .labelled("filter name")
25 .then(args(expr).labelled("filter args"))
26 .map(|(name, args)| Call { name, args })
27}
28
29fn def<P>(def: P) -> impl Parser<Token, Def, Error = Simple<Token>> + Clone
31where
32 P: Parser<Token, Def, Error = Simple<Token>> + Clone,
33{
34 let arg = select! {
35 Token::Ident(name) => Arg::new_filter(name),
36 Token::Var(name) => Arg::new_var(name),
37 };
38
39 let defs = def.repeated().collect();
40
41 just(Token::Def)
42 .ignore_then(call(arg))
43 .then_ignore(just(Token::Colon))
44 .then(defs.then(filter()).map(|(defs, body)| Main { defs, body }))
45 .then_ignore(just(Token::Semicolon))
46 .map(|(lhs, rhs)| Def { lhs, rhs })
47 .labelled("definition")
48}
49
50pub fn defs() -> impl Parser<Token, Vec<Def>, Error = Simple<Token>> + Clone {
52 recursive(def).repeated().collect()
53}
54
55pub fn main() -> impl Parser<Token, Main, Error = Simple<Token>> + Clone {
57 defs()
58 .then(filter())
59 .map(|(defs, body)| Main { defs, body })
60}