kotlin_parser/parse/expression/
call.rs1use 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}