jaq_parse/
def.rs

1use super::{filter::filter, Delim, Token};
2use alloc::vec::Vec;
3use chumsky::prelude::*;
4use jaq_syn::{Arg, Call, Def, Main};
5
6/// A (potentially empty) parenthesised and `;`-separated sequence of arguments.
7fn 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
29/// Parser for a single definition.
30fn 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
50/// Parser for a sequence of definitions.
51pub fn defs() -> impl Parser<Token, Vec<Def>, Error = Simple<Token>> + Clone {
52    recursive(def).repeated().collect()
53}
54
55/// Parser for a (potentially empty) sequence of definitions, followed by a filter.
56pub fn main() -> impl Parser<Token, Main, Error = Simple<Token>> + Clone {
57    defs()
58        .then(filter())
59        .map(|(defs, body)| Main { defs, body })
60}