Actually just three programming languages in a trenchcoat
at main 201 lines 7.4 kB view raw
1use super::*; 2use crate::{Parser, Spanned}; 3use source_span::Span; 4use trilogy_scanner::{Token, TokenType::*}; 5 6#[derive(Clone, Debug)] 7pub struct SetPattern { 8 pub open_bracket_pipe: Token, 9 pub elements: Vec<Pattern>, 10 pub rest: Option<RestPattern>, 11 pub close_bracket_pipe: Token, 12 pub span: Span, 13} 14 15impl SetPattern { 16 pub(crate) fn parse(parser: &mut Parser) -> SyntaxResult<Self> { 17 let open_bracket_pipe = parser.expect(OBrackPipe).unwrap(); 18 Self::parse_elements(parser, open_bracket_pipe, vec![]) 19 } 20 21 pub(crate) fn parse_elements( 22 parser: &mut Parser, 23 open_bracket_pipe: Token, 24 mut elements: Vec<Pattern>, 25 ) -> SyntaxResult<Self> { 26 let rest = loop { 27 if parser.check(CBrackPipe).is_ok() { 28 break None; 29 }; 30 if let Ok(spread) = parser.expect(OpDotDot) { 31 if let Ok(dot) = parser.expect(OpDot) { 32 parser.error(ErrorKind::TripleDot { dot: dot.span }.at(spread.span)); 33 } 34 break Some(RestPattern::parse(parser, spread)?); 35 } 36 elements.push(Pattern::parse(parser)?); 37 if parser.check(CBrackPipe).is_ok() { 38 break None; 39 }; 40 parser.expect(OpComma).map_err(|token| { 41 parser.expected(token, "expected `,` between set pattern elements") 42 })?; 43 }; 44 45 if let Some(rest) = rest { 46 return Self::parse_rest(parser, open_bracket_pipe, elements, rest); 47 } 48 let close_bracket_pipe = parser 49 .expect(CBrackPipe) 50 .map_err(|token| parser.expected(token, "expected `|]` to end set pattern"))?; 51 52 Ok(Self { 53 span: open_bracket_pipe.span.union(close_bracket_pipe.span), 54 open_bracket_pipe, 55 elements, 56 rest, 57 close_bracket_pipe, 58 }) 59 } 60 61 pub(crate) fn parse_rest( 62 parser: &mut Parser, 63 open_bracket_pipe: Token, 64 elements: Vec<Pattern>, 65 rest: RestPattern, 66 ) -> SyntaxResult<Self> { 67 // We'll consume this trailing comma anyway as if it was going to work, 68 // and report an appropriate error. One of few attempts at smart error 69 // handling in this parser so far! 70 if let Ok(comma) = parser.expect(OpComma) { 71 let Ok(close_bracket_pipe) = parser.expect(CBrackPipe) else { 72 let error = 73 SyntaxError::new(comma.span, "a rest (`..`) element must end a set pattern"); 74 parser.error(error.clone()); 75 return Err(error); 76 }; 77 parser.error(SyntaxError::new( 78 comma.span, 79 "no trailing comma is permitted after the rest (`..`) element in a set pattern", 80 )); 81 return Ok(Self { 82 span: open_bracket_pipe.span.union(close_bracket_pipe.span), 83 open_bracket_pipe, 84 elements, 85 rest: Some(rest), 86 close_bracket_pipe, 87 }); 88 } 89 let close_bracket_pipe = parser 90 .expect(CBrackPipe) 91 .map_err(|token| parser.expected(token, "expected `|]` to close set pattern"))?; 92 Ok(Self { 93 span: open_bracket_pipe.span.union(close_bracket_pipe.span), 94 open_bracket_pipe, 95 elements, 96 rest: Some(rest), 97 close_bracket_pipe, 98 }) 99 } 100 101 pub(crate) fn parse_from_expression( 102 parser: &mut Parser, 103 open_bracket_pipe: Token, 104 elements: Vec<SetElement>, 105 (spread, next): (Option<Token>, Pattern), 106 ) -> SyntaxResult<Self> { 107 let (mut elements, rest) = elements 108 .into_iter() 109 .try_fold( 110 (vec![], None::<Pattern>), 111 |(mut elements, mut spread), element| { 112 match element { 113 SetElement::Element(element) if spread.is_none() => { 114 elements.push(element.try_into()?) 115 } 116 SetElement::Element(element) => { 117 return Err(SyntaxError::new( 118 element.span(), 119 "no elements may follow the rest element of a set pattern, you might have meant this to be an expression", 120 )); 121 } 122 SetElement::Spread(_, element) if spread.is_none() => { 123 spread = Some(element.try_into()?); 124 } 125 SetElement::Spread(token, element) => { 126 return Err(SyntaxError::new( 127 token.span.union(element.span()), 128 "a set pattern may contain only one rest element, you might have meant this to be an expression", 129 )); 130 } 131 } 132 Ok((elements, spread)) 133 }) 134 .inspect_err(|error| { 135 parser.error(error.clone()); 136 })?; 137 match rest { 138 None if spread.is_none() => { 139 elements.push(next); 140 Self::parse_elements(parser, open_bracket_pipe, elements) 141 } 142 None => Self::parse_rest( 143 parser, 144 open_bracket_pipe, 145 elements, 146 RestPattern::new(spread.unwrap(), next), 147 ), 148 Some(..) if spread.is_none() => Err(SyntaxError::new( 149 next.span().union(spread.unwrap().span()), 150 "no elements may follow the rest element of a set pattern, you might have meant this to be an expression", 151 )), 152 Some(rest) => Err(SyntaxError::new( 153 rest.span().union(spread.unwrap().span()), 154 "a set pattern may contain only one rest element, you might have meant this to be an expression", 155 )), 156 } 157 } 158} 159 160impl Spanned for SetPattern { 161 fn span(&self) -> Span { 162 self.open_bracket_pipe 163 .span 164 .union(self.close_bracket_pipe.span) 165 } 166} 167 168impl TryFrom<SetLiteral> for SetPattern { 169 type Error = SyntaxError; 170 171 fn try_from(value: SetLiteral) -> Result<Self, Self::Error> { 172 let mut head = vec![]; 173 let mut rest = None; 174 175 for element in value.elements { 176 match element { 177 SetElement::Element(val) if rest.is_none() => head.push(val.try_into()?), 178 SetElement::Spread(token, val) if rest.is_none() => { 179 rest = Some(RestPattern::try_from((token, val))?) 180 } 181 SetElement::Element(val) | SetElement::Spread(_, val) => { 182 return Err(SyntaxError::new( 183 val.span(), 184 "no elements may follow the rest (`..`) element in a set pattern", 185 )); 186 } 187 } 188 } 189 190 Ok(Self { 191 span: value 192 .open_bracket_pipe 193 .span 194 .union(value.close_bracket_pipe.span), 195 open_bracket_pipe: value.open_bracket_pipe, 196 elements: head, 197 rest, 198 close_bracket_pipe: value.close_bracket_pipe, 199 }) 200 } 201}