Actually just three programming languages in a trenchcoat
1use super::*;
2use crate::{Parser, Spanned};
3use source_span::Span;
4use trilogy_scanner::{Token, TokenType::*};
5
6/// An array comprehension expression.
7///
8/// ```trilogy
9/// [x for query(x)]
10/// ```
11#[derive(Clone, Debug, PrettyPrintSExpr)]
12pub struct ArrayComprehension {
13 pub open_bracket: Token,
14 pub expression: Expression,
15 pub r#for: Token,
16 pub query: Query,
17 pub close_bracket: Token,
18}
19
20impl Spanned for ArrayComprehension {
21 fn span(&self) -> Span {
22 self.open_bracket.span.union(self.close_bracket.span)
23 }
24}
25
26impl ArrayComprehension {
27 pub(crate) fn parse_rest(
28 parser: &mut Parser,
29 open_bracket: Token,
30 expression: Expression,
31 ) -> SyntaxResult<Self> {
32 let r#for = parser
33 .expect(KwFor)
34 .map_err(|token| parser.expected(token, "expected `for` in array comprehension"))?;
35 let query = Query::parse(parser)?;
36 let end = parser
37 .expect(CBrack)
38 .map_err(|token| parser.expected(token, "expected `]` to end array comprehension"))?;
39 Ok(Self {
40 open_bracket,
41 expression,
42 r#for,
43 query,
44 close_bracket: end,
45 })
46 }
47}
48
49#[cfg(test)]
50mod test {
51 use super::*;
52
53 test_parse!(arraycomp_simple: "[x for x in array]" => Expression::parse => "(Expression::ArrayComprehension (ArrayComprehension _ _ _ _ _))");
54 test_parse!(arraycomp_complex: "[x:y for lookup(x) and another(y)]" => Expression::parse => "(Expression::ArrayComprehension (ArrayComprehension _ _ _ _ _))");
55 test_parse!(array_comp_seq: "[(x; y) for lookup(x, y)]" => Expression::parse => "(Expression::ArrayComprehension (ArrayComprehension _ _ _ _ _))");
56
57 test_parse_error!(arraycomp_no_commas: "[x, y for lookup(x, y)]" => Expression::parse => "only one element may precede the `for` keyword in a comprehension");
58 test_parse_error!(arraycomp_no_end: "[x for x in array" => Expression::parse => "expected `]` to end array comprehension");
59 test_parse_error!(arraycomp_no_expression: "[for y]" => Expression::parse);
60
61 test_parse_error!(arraycomp_invalid_query: "[x for y]" => Expression::parse);
62 test_parse_error!(arraycomp_invalid_expr: "[() for x in y]" => Expression::parse);
63}