Actually just three programming languages in a trenchcoat
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}