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 literal expression.
7///
8/// ```trilogy
9/// [..prefix, 1, 2, 3, ..suffix]
10/// ```
11#[derive(Clone, Debug)]
12pub struct ArrayLiteral {
13 pub open_bracket: Token,
14 pub elements: Punctuated<ArrayElement>,
15 pub close_bracket: Token,
16 pub span: Span,
17}
18
19impl Spanned for ArrayLiteral {
20 fn span(&self) -> Span {
21 self.span
22 }
23}
24
25impl ArrayLiteral {
26 pub(crate) fn new_empty(open_bracket: Token, close_bracket: Token) -> Self {
27 Self {
28 span: open_bracket.span.union(close_bracket.span),
29 open_bracket,
30 elements: Punctuated::default(),
31 close_bracket,
32 }
33 }
34
35 pub(crate) fn parse_rest(
36 parser: &mut Parser,
37 open_bracket: Token,
38 first: ArrayElement,
39 ) -> SyntaxResult<Result<Self, ArrayPattern>> {
40 let mut elements = Punctuated::init(first);
41 if let Ok(close_bracket) = parser.expect(CBrack) {
42 return Ok(Ok(Self {
43 span: open_bracket.span.union(close_bracket.span),
44 open_bracket,
45 elements,
46 close_bracket,
47 }));
48 }
49
50 let close_bracket = loop {
51 let comma = parser.expect(OpComma).map_err(|token| {
52 parser.expected(
53 token,
54 "expected `]` to end or `,` to continue array literal",
55 )
56 })?;
57 if let Ok(end) = parser.expect(CBrack) {
58 elements.finish(comma);
59 break end;
60 };
61 match ArrayElement::parse(parser)? {
62 Ok(element) => elements.follow(comma, element),
63 Err(next) => {
64 return Ok(Err(ArrayPattern::parse_from_expression(
65 parser,
66 open_bracket,
67 elements,
68 next,
69 )?));
70 }
71 }
72 if let Ok(token) = parser.check(KwFor) {
73 let error = SyntaxError::new(
74 token.span,
75 "only one element may precede the `for` keyword in a comprehension",
76 );
77 parser.error(error.clone());
78 return Err(error);
79 }
80 if let Ok(close_bracket) = parser.expect(CBrack) {
81 break close_bracket;
82 };
83 };
84 Ok(Ok(Self {
85 span: open_bracket.span.union(close_bracket.span),
86 open_bracket,
87 elements,
88 close_bracket,
89 }))
90 }
91}
92
93#[derive(Clone, Debug, Spanned)]
94pub enum ArrayElement {
95 Element(Expression),
96 Spread(Token, Expression),
97}
98
99impl ArrayElement {
100 pub(crate) fn parse(
101 parser: &mut Parser,
102 ) -> SyntaxResult<Result<Self, (Option<Token>, Pattern)>> {
103 let spread = parser.expect(OpDotDot).ok();
104 if let Some(spread) = &spread
105 && let Ok(dot) = parser.expect(OpDot)
106 {
107 parser.error(ErrorKind::TripleDot { dot: dot.span }.at(spread.span));
108 }
109 let expression = Expression::parse_or_pattern(parser)?;
110 match expression {
111 Ok(expression) => match spread {
112 None => Ok(Ok(Self::Element(expression))),
113 Some(spread) => Ok(Ok(Self::Spread(spread, expression))),
114 },
115 Err(pattern) => Ok(Err((spread, pattern))),
116 }
117 }
118}
119
120#[cfg(test)]
121mod test {
122 use super::*;
123
124 test_parse!(arraylit_empty: "[]" => Expression::parse => Expression::Array(ArrayLiteral { .. }));
125 test_parse!(arraylit_one: "[1]" => Expression::parse => Expression::Array(ArrayLiteral { .. }));
126 test_parse!(arraylit_one_tc: "[1, ]" => Expression::parse => Expression::Array(ArrayLiteral { .. }));
127 test_parse!(arraylit_many: "[1, 2, 3, ]" => Expression::parse => Expression::Array(ArrayLiteral { elements: Punctuated { elements: [_, _, _], .. }, .. }));
128 test_parse!(arraylit_many_tc: "[1, 2, 3, ]" => Expression::parse => Expression::Array(ArrayLiteral { elements: Punctuated { elements: [_, _, _], .. }, .. }));
129 test_parse!(arraylit_nested: "[[1, 2], [3, 4], [5, 6], ]" => Expression::parse => Expression::Array(ArrayLiteral { elements: Punctuated { elements: [_, _, _], .. }, .. }));
130 test_parse!(arraylit_no_comma: "[f 2]" => Expression::parse => Expression::Array(ArrayLiteral { elements: Punctuated { elements: [], last: Some(ArrayElement::Element(Expression::Application(..))) }, .. }));
131 test_parse!(arraylit_spread: "[..a, b, ]" => Expression::parse => Expression::Array(ArrayLiteral { elements: Punctuated { elements: [(ArrayElement::Spread(..), _), (ArrayElement::Element(..), _)], .. }, .. }));
132
133 test_parse_error!(arraylit_empty_tc: "[,]" => Expression::parse);
134 test_parse_error!(arraylit_missing_item: "[1,,]" => Expression::parse);
135 test_parse_error!(arraylit_missing_end: "[1,2," => Expression::parse);
136 test_parse_error!(arraylit_incomplete: "[1, 2" => Expression::parse => "expected `]` to end or `,` to continue array literal");
137 test_parse_error!(arraylit_mismatched: "[1, 2)" => Expression::parse => "expected `]` to end or `,` to continue array literal");
138}