Actually just three programming languages in a trenchcoat
at main 138 lines 5.3 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)] 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}