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