1use crate::ast::error::pattern::Pattern;
2use crate::ast::lexer::Token;
3use crate::ast::utils::whitespace;
4use crate::ast::{DatexExpression, DatexParserTrait};
5use chumsky::prelude::*;
6
7#[derive(Clone, Debug, PartialEq)]
8pub enum ApplyOperation {
9 FunctionCall(DatexExpression),
11
12 PropertyAccess(DatexExpression),
15
16 GenericAccess(DatexExpression),
18}
19
20pub fn chain_without_whitespace_apply<'a>(
21 unary: impl DatexParserTrait<'a>,
22 key: impl DatexParserTrait<'a>,
23 any: impl DatexParserTrait<'a>,
24) -> impl DatexParserTrait<'a> {
25 unary
26 .clone()
27 .then(
28 choice((
29 just(Token::LeftAngle)
31 .ignore_then(any.clone())
32 .then_ignore(just(Token::RightAngle))
33 .map(ApplyOperation::GenericAccess),
34 just(Token::Dot)
36 .padded_by(whitespace())
37 .ignore_then(key)
38 .map(ApplyOperation::PropertyAccess),
39 ))
40 .repeated()
41 .collect::<Vec<_>>(),
42 )
43 .labelled(Pattern::Custom("chain_no_whitespace_atom"))
44 .map(|(val, args)| {
45 if args.is_empty() {
46 val
47 } else {
48 DatexExpression::ApplyChain(Box::new(val), args)
49 }
50 })
51}
52
53pub fn keyed_parameters<'a>(
54 key: impl DatexParserTrait<'a>,
55 expression: impl DatexParserTrait<'a>,
56) -> impl DatexParserTrait<'a> {
57 key.then_ignore(just(Token::Colon).padded_by(whitespace()))
58 .then(expression.clone())
59 .separated_by(just(Token::Comma).padded_by(whitespace()))
60 .at_least(0)
61 .allow_trailing()
62 .collect()
63 .padded_by(whitespace())
64 .delimited_by(just(Token::LeftParen), just(Token::RightParen))
65 .padded_by(whitespace())
66 .map(DatexExpression::Map)
67}
68
69pub fn indexed_parameters<'a>(
70 expression: impl DatexParserTrait<'a>,
71) -> impl DatexParserTrait<'a> {
72 expression
73 .clone()
74 .separated_by(just(Token::Comma).padded_by(whitespace()))
75 .at_least(0)
76 .allow_trailing()
77 .collect()
78 .padded_by(whitespace())
79 .delimited_by(just(Token::LeftParen), just(Token::RightParen))
80 .padded_by(whitespace())
81 .map(DatexExpression::List)
82}
83
84pub fn chain<'a>(
85 unary: impl DatexParserTrait<'a>,
86 key: impl DatexParserTrait<'a>,
87 atom: impl DatexParserTrait<'a>,
88 expression: impl DatexParserTrait<'a>,
89) -> impl DatexParserTrait<'a> {
90 unary
91 .clone()
92 .then(
93 choice((
94 just(Token::LeftAngle)
96 .ignore_then(expression.clone())
97 .then_ignore(just(Token::RightAngle))
98 .map(ApplyOperation::GenericAccess),
99 choice((
102 keyed_parameters(key.clone(), expression.clone()),
103 indexed_parameters(expression.clone()),
104 ))
105 .map(ApplyOperation::FunctionCall),
106 just(Token::Whitespace)
109 .repeated()
110 .at_least(1)
111 .ignore_then(atom.padded_by(whitespace()))
112 .map(ApplyOperation::FunctionCall),
113 just(Token::Dot)
124 .padded_by(whitespace())
125 .ignore_then(key)
126 .map(ApplyOperation::PropertyAccess),
127 ))
128 .repeated()
129 .collect::<Vec<_>>(),
130 )
131 .labelled(Pattern::Custom("chain"))
132 .map(|(val, args)| {
133 if args.is_empty() {
135 val
136 } else {
137 DatexExpression::ApplyChain(Box::new(val), args)
138 }
139 })
140}