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