aiken_lang/parser/expr/
pair.rs

1use crate::{
2    ast::well_known,
3    builtins::PRELUDE,
4    expr::UntypedExpr,
5    parser::{error::ParseError, token::Token},
6};
7use chumsky::prelude::*;
8
9pub fn parser(
10    r: Recursive<'_, Token, UntypedExpr, ParseError>,
11) -> impl Parser<Token, UntypedExpr, Error = ParseError> + '_ {
12    select! {Token::Name { name } if name == PRELUDE => name}
13        .then_ignore(just(Token::Dot))
14        .or_not()
15        .then_ignore(select! {Token::UpName { name } if name == well_known::PAIR => name})
16        .ignore_then(
17            r.clone()
18                .separated_by(just(Token::Comma))
19                .exactly(2)
20                .allow_trailing()
21                .delimited_by(
22                    choice((just(Token::LeftParen), just(Token::NewLineLeftParen))),
23                    just(Token::RightParen),
24                )
25                .map_with_span(|elems, location| UntypedExpr::Pair {
26                    location,
27                    fst: elems
28                        .first()
29                        .expect("Pair should have exactly 2 elements")
30                        .to_owned()
31                        .into(),
32                    snd: elems
33                        .last()
34                        .expect("Pair should have exactly 2 elements")
35                        .to_owned()
36                        .into(),
37                }),
38        )
39}
40
41#[cfg(test)]
42mod tests {
43    use crate::assert_expr;
44
45    #[test]
46    fn basic_pair() {
47        assert_expr!(r#"Pair(1, 2)"#);
48    }
49
50    #[test]
51    fn pair_from_prelude() {
52        assert_expr!(r#"aiken.Pair(1, 2)"#);
53    }
54}