kotlin_parser/parse/expression/
call.rs

1use crate::{
2    ast::*,
3    parse::ty::{
4        simple::{simple_type_parser, type_args_parser},
5        type_parser,
6    },
7};
8use chumsky::prelude::*;
9
10use super::{label::before_label_parser, path::path_parser};
11
12pub fn call_parser(
13    stmt_parser: impl Parser<char, Statement, Error = Simple<char>>,
14    expr_parser: impl Parser<char, Expression, Error = Simple<char>>,
15) -> impl Parser<char, Expression, Error = Simple<char>> {
16    path_parser()
17        .padded()
18        .then(type_args_parser(simple_type_parser()).or_not())
19        .then(call_args_parser(expr_parser).or_not())
20        .then(lambda_parser(stmt_parser).or_not())
21        .map(|(((path, type_args), args), block)| {
22            Expression::Call(CallExpression {
23                path,
24                args: args.unwrap_or_default(),
25                type_args: type_args.unwrap_or_default(),
26                lambda: block.map(Box::new),
27            })
28        })
29}
30
31pub fn call_arg_parser(
32    expr_parser: impl Parser<char, Expression, Error = Simple<char>>,
33) -> impl Parser<char, CallArg, Error = Simple<char>> {
34    text::ident()
35        .padded()
36        .then_ignore(just('='))
37        .or_not()
38        .then(just('*').or_not())
39        .then(expr_parser)
40        .map(|((name, is_spread), expr)| CallArg {
41            name,
42            value: Box::new(expr),
43            is_spread: is_spread.is_some(),
44        })
45}
46
47pub fn call_args_parser(
48    expr_parser: impl Parser<char, Expression, Error = Simple<char>>,
49) -> impl Parser<char, Vec<CallArg>, Error = Simple<char>> {
50    call_arg_parser(expr_parser)
51        .separated_by(just(',').padded())
52        .delimited_by(just('(').padded(), just(')').padded())
53}
54
55pub fn invocation_args_parser(
56    expr_parser: impl Parser<char, Expression, Error = Simple<char>>,
57) -> impl Parser<char, Vec<InvocationArg>, Error = Simple<char>> {
58    text::ident()
59        .padded()
60        .then_ignore(just('='))
61        .or_not()
62        .then(expr_parser)
63        .separated_by(just(',').padded())
64        .delimited_by(just('(').padded(), just(')').padded())
65        .map(|args| {
66            args.into_iter()
67                .map(|(name, expr)| InvocationArg {
68                    name,
69                    value: Box::new(expr),
70                })
71                .collect()
72        })
73}
74
75pub fn lambda_parser(
76    stmt_parser: impl Parser<char, Statement, Error = Simple<char>>,
77) -> impl Parser<char, LambdaBlock, Error = Simple<char>> {
78    before_label_parser()
79        .or_not()
80        .then(
81            just('{')
82                .ignore_then(vars_parser().then_ignore(just("->")).or_not())
83                .then(inner_block_parser(stmt_parser).or_not())
84                .then_ignore(just('}')),
85        )
86        .map(|(label, (vars, body))| LambdaBlock { label, vars, body })
87}
88
89pub fn vars_parser() -> impl Parser<char, Vars, Error = Simple<char>> {
90    let params = text::ident()
91        .padded()
92        .then(just(':').padded().ignore_then(type_parser()).or_not())
93        .separated_by(just(',').padded());
94
95    params
96        .delimited_by(just('(').padded(), just(')').padded())
97        .map(|params| {
98            let vars = params
99                .into_iter()
100                .map(|(name, ty)| Var { name, ty })
101                .collect();
102
103            Vars {
104                is_destructured: true,
105                vars,
106            }
107        })
108}
109
110pub fn block_parser(
111    stmt_parser: impl Parser<char, Statement, Error = Simple<char>>,
112) -> impl Parser<char, Block, Error = Simple<char>> {
113    stmt_parser
114        .repeated()
115        .delimited_by(just('{').padded(), just('}').padded())
116        .map(|statements| Block { statements })
117}
118
119pub fn inner_block_parser(
120    stmt_parser: impl Parser<char, Statement, Error = Simple<char>>,
121) -> impl Parser<char, Block, Error = Simple<char>> {
122    stmt_parser
123        .repeated()
124        .map(|statements| Block { statements })
125}
126
127pub fn expr_block_parser(
128    stmt_parser: impl Parser<char, Statement, Error = Simple<char>> + Clone,
129) -> impl Parser<char, Block, Error = Simple<char>> {
130    choice((
131        just('{')
132            .padded()
133            .ignore_then(stmt_parser.clone().repeated())
134            .then_ignore(just('}').padded())
135            .or_not()
136            .map(|stmts| Block {
137                statements: stmts.unwrap_or_default(),
138            }),
139        stmt_parser.or_not().map(|stmt| Block {
140            statements: stmt.map_or_else(Vec::new, |stmt| vec![stmt]),
141        }),
142    ))
143}