Actually just three programming languages in a trenchcoat
at main 179 lines 7.1 kB view raw
1use super::*; 2use crate::{Parser, Spanned}; 3use trilogy_scanner::{ 4 Token, 5 TokenType::{self, *}, 6}; 7 8#[derive(Clone, Debug, Spanned)] 9pub enum Pattern { 10 Conjunction(Box<PatternConjunction>), 11 Disjunction(Box<PatternDisjunction>), 12 Number(Box<NumberLiteral>), 13 Character(Box<CharacterLiteral>), 14 String(Box<StringLiteral>), 15 Bits(Box<BitsLiteral>), 16 Boolean(Box<BooleanLiteral>), 17 Unit(Box<UnitLiteral>), 18 Atom(Box<AtomLiteral>), 19 Wildcard(Box<Token>), 20 Negative(Box<NegativePattern>), 21 Glue(Box<GluePattern>), 22 Typeof(Box<TypeofPattern>), 23 Struct(Box<StructPattern>), 24 Tuple(Box<TuplePattern>), 25 Array(Box<ArrayPattern>), 26 Set(Box<SetPattern>), 27 Record(Box<RecordPattern>), 28 Pinned(Box<PinnedPattern>), 29 Binding(Box<BindingPattern>), 30 Parenthesized(Box<ParenthesizedPattern>), 31} 32 33#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] 34pub(crate) enum Precedence { 35 None, 36 Disjunction, 37 Conjunction, 38 Cons, 39 Glue, 40 Unary, 41} 42 43impl Pattern { 44 pub(crate) const PREFIX: [TokenType; 17] = [ 45 Numeric, String, Bits, KwTrue, KwFalse, Atom, Character, KwUnit, OParen, OpMinus, OpCaret, 46 OBrack, OBrackPipe, OBracePipe, Discard, Identifier, KwMut, 47 ]; 48 49 pub(crate) fn parse_follow( 50 parser: &mut Parser, 51 precedence: Precedence, 52 lhs: Pattern, 53 ) -> SyntaxResult<Result<Self, Self>> { 54 let token = parser.peek(); 55 match token.token_type { 56 KwAnd if precedence < Precedence::Conjunction => Ok(Ok(Self::Conjunction(Box::new( 57 PatternConjunction::parse(parser, lhs)?, 58 )))), 59 KwOr if precedence < Precedence::Disjunction => Ok(Ok(Self::Disjunction(Box::new( 60 PatternDisjunction::parse(parser, lhs)?, 61 )))), 62 OpGlue if precedence < Precedence::Glue => { 63 Ok(Ok(Self::Glue(Box::new(GluePattern::parse(parser, lhs)?)))) 64 } 65 OpColon if precedence <= Precedence::Cons => { 66 Ok(Ok(Self::Tuple(Box::new(TuplePattern::parse(parser, lhs)?)))) 67 } 68 _ => Ok(Err(lhs)), 69 } 70 } 71 72 fn parse_prefix(parser: &mut Parser) -> SyntaxResult<Self> { 73 let token = parser.peek(); 74 match token.token_type { 75 Numeric => Ok(Self::Number(Box::new(NumberLiteral::parse(parser)?))), 76 String => Ok(Self::String(Box::new(StringLiteral::parse(parser)?))), 77 Bits => Ok(Self::Bits(Box::new(BitsLiteral::parse(parser)?))), 78 KwTrue | KwFalse => Ok(Self::Boolean(Box::new(BooleanLiteral::parse(parser)?))), 79 Atom => { 80 let atom = AtomLiteral::parse(parser)?; 81 if parser.check(OParen).is_ok() { 82 Ok(Self::Struct(Box::new(StructPattern::parse(parser, atom)?))) 83 } else { 84 Ok(Self::Atom(Box::new(atom))) 85 } 86 } 87 Character => Ok(Self::Character(Box::new(CharacterLiteral::parse(parser)?))), 88 KwUnit => Ok(Self::Unit(Box::new(UnitLiteral::parse(parser)?))), 89 OParen => Ok(Self::Parenthesized(Box::new(ParenthesizedPattern::parse( 90 parser, 91 )?))), 92 OpMinus => Ok(Self::Negative(Box::new(NegativePattern::parse(parser)?))), 93 KwTypeof => Ok(Self::Typeof(Box::new(TypeofPattern::parse(parser)?))), 94 OpCaret => Ok(Self::Pinned(Box::new(PinnedPattern::parse(parser)?))), 95 OBrack => Ok(Self::Array(Box::new(ArrayPattern::parse(parser)?))), 96 OBrackPipe => Ok(Self::Set(Box::new(SetPattern::parse(parser)?))), 97 OBracePipe => Ok(Self::Record(Box::new(RecordPattern::parse(parser)?))), 98 Discard => Ok(Self::Wildcard(Box::new(parser.expect(Discard).unwrap()))), 99 KwMut | Identifier => Ok(Self::Binding(Box::new(BindingPattern::parse(parser)?))), 100 _ => { 101 let error = SyntaxError::new(token.span, "unexpected token in pattern"); 102 parser.error(error.clone()); 103 Err(error) 104 } 105 } 106 } 107 108 pub(crate) fn parse_suffix( 109 parser: &mut Parser, 110 precedence: Precedence, 111 mut lhs: Pattern, 112 ) -> SyntaxResult<Self> { 113 loop { 114 match Self::parse_follow(parser, precedence, lhs)? { 115 Ok(updated) => lhs = updated, 116 Err(lhs) => return Ok(lhs), 117 } 118 } 119 } 120 121 pub(crate) fn parse_precedence( 122 parser: &mut Parser, 123 precedence: Precedence, 124 ) -> SyntaxResult<Self> { 125 let lhs = Self::parse_prefix(parser)?; 126 Self::parse_suffix(parser, precedence, lhs) 127 } 128 129 pub(crate) fn parse(parser: &mut Parser) -> SyntaxResult<Self> { 130 Self::parse_precedence(parser, Precedence::None) 131 } 132} 133 134impl TryFrom<Expression> for Pattern { 135 type Error = SyntaxError; 136 137 fn try_from(value: Expression) -> Result<Self, Self::Error> { 138 match value { 139 Expression::Reference(identifier) => Ok(Pattern::Binding(Box::new(BindingPattern { 140 r#mut: None, 141 span: identifier.span, 142 identifier: *identifier, 143 }))), 144 Expression::Atom(val) => Ok(Pattern::Atom(val)), 145 Expression::Number(val) => Ok(Pattern::Number(val)), 146 Expression::Boolean(val) => Ok(Pattern::Boolean(val)), 147 Expression::Unit(val) => Ok(Pattern::Unit(val)), 148 Expression::Bits(val) => Ok(Pattern::Bits(val)), 149 Expression::String(val) => Ok(Pattern::String(val)), 150 Expression::Character(val) => Ok(Pattern::Character(val)), 151 Expression::Unary(op) if matches!(op.operator, UnaryOperator::Negate(..)) => { 152 Ok(Pattern::Negative(Box::new(NegativePattern::try_from(*op)?))) 153 } 154 Expression::Binary(op) if matches!(op.operator, BinaryOperator::Glue(..)) => { 155 Ok(Pattern::Glue(Box::new(GluePattern::try_from(*op)?))) 156 } 157 Expression::Binary(op) if matches!(op.operator, BinaryOperator::Cons(..)) => { 158 Ok(Pattern::Tuple(Box::new(TuplePattern::try_from(*op)?))) 159 } 160 Expression::Struct(inner) => { 161 Ok(Pattern::Struct(Box::new(StructPattern::try_from(*inner)?))) 162 } 163 Expression::Array(array) => { 164 Ok(Pattern::Array(Box::new(ArrayPattern::try_from(*array)?))) 165 } 166 Expression::Set(set) => Ok(Pattern::Set(Box::new(SetPattern::try_from(*set)?))), 167 Expression::Record(record) => { 168 Ok(Pattern::Record(Box::new(RecordPattern::try_from(*record)?))) 169 } 170 Expression::Parenthesized(paren) => Ok(Pattern::Parenthesized(Box::new( 171 ParenthesizedPattern::try_from(*paren)?, 172 ))), 173 _ => Err(SyntaxError::new( 174 value.span(), 175 "expression is not valid in pattern context", 176 )), 177 } 178 } 179}