Actually just three programming languages in a trenchcoat
1use super::{expression::Precedence, *};
2use crate::{Parser, Spanned};
3use source_span::Span;
4use trilogy_scanner::{Token, TokenType::*};
5
6/// A binary operation expression.
7///
8/// ```trilogy
9/// lhs + rhs
10/// ```
11#[derive(Clone, Debug, PrettyPrintSExpr)]
12pub struct BinaryOperation {
13 pub lhs: Expression,
14 pub operator: BinaryOperator,
15 pub rhs: Expression,
16 span: Span,
17}
18
19impl Spanned for BinaryOperation {
20 fn span(&self) -> Span {
21 self.span
22 }
23}
24
25impl BinaryOperation {
26 pub(crate) fn parse(
27 parser: &mut Parser,
28 lhs: Expression,
29 ) -> SyntaxResult<Result<Self, Pattern>> {
30 let operator = BinaryOperator::parse(parser);
31 let rhs = Expression::parse_or_pattern_precedence(parser, operator.precedence())?;
32 match rhs {
33 Ok(rhs) => Ok(Ok(BinaryOperation {
34 span: lhs.span().union(rhs.span()),
35 lhs,
36 operator,
37 rhs,
38 })),
39 Err(rhs) => match operator {
40 BinaryOperator::Glue(glue) => Ok(Err(Pattern::Glue(Box::new(GluePattern::new(
41 lhs.try_into().inspect_err(|err: &SyntaxError| {
42 parser.error(err.clone());
43 })?,
44 glue,
45 rhs,
46 ))))),
47 BinaryOperator::Cons(token) => {
48 Ok(Err(Pattern::Tuple(Box::new(TuplePattern::new(
49 lhs.try_into().inspect_err(|err: &SyntaxError| {
50 parser.error(err.clone());
51 })?,
52 token,
53 rhs,
54 )))))
55 }
56 _ => {
57 let err =
58 SyntaxError::new(rhs.span(), "expected an expression, but found a pattern");
59 parser.error(err.clone());
60 Err(err)
61 }
62 },
63 }
64 }
65}
66
67/// A binary operator, represented by a single token.
68#[derive(Clone, Debug, Spanned, PrettyPrintSExpr)]
69pub enum BinaryOperator {
70 Access(Token),
71 And(Token),
72 Or(Token),
73 Add(Token),
74 Subtract(Token),
75 Multiply(Token),
76 Divide(Token),
77 Remainder(Token),
78 Power(Token),
79 IntDivide(Token),
80 StructuralEquality(Token),
81 StructuralInequality(Token),
82 ReferenceEquality(Token),
83 ReferenceInequality(Token),
84 Lt(Token),
85 Gt(Token),
86 Leq(Token),
87 Geq(Token),
88 BitwiseAnd(Token),
89 BitwiseOr(Token),
90 BitwiseXor(Token),
91 LeftShift(Token),
92 RightShift(Token),
93 LeftShiftExtend(Token),
94 RightShiftExtend(Token),
95 LeftShiftContract(Token),
96 RightShiftContract(Token),
97 Sequence(Token),
98 Cons(Token),
99 Glue(Token),
100 Compose(Token),
101 RCompose(Token),
102 Pipe(Token),
103 RPipe(Token),
104}
105
106impl BinaryOperator {
107 fn parse(parser: &mut Parser) -> Self {
108 let token = parser.consume();
109 match token.token_type {
110 OpDot => Self::Access(token),
111 OpAmpAmp => Self::And(token),
112 OpPipePipe => Self::Or(token),
113 OpPlus => Self::Add(token),
114 OpMinus => Self::Subtract(token),
115 OpStar => Self::Multiply(token),
116 OpSlash => Self::Divide(token),
117 OpSlashSlash => Self::IntDivide(token),
118 OpPercent => Self::Remainder(token),
119 OpStarStar => Self::Power(token),
120 OpEqEq => Self::StructuralEquality(token),
121 OpBangEq => Self::StructuralInequality(token),
122 OpEqEqEq => Self::ReferenceEquality(token),
123 OpBangEqEq => Self::ReferenceInequality(token),
124 OpLt => Self::Lt(token),
125 OpGt => Self::Gt(token),
126 OpLtEq => Self::Leq(token),
127 OpGtEq => Self::Geq(token),
128 OpAmp => Self::BitwiseAnd(token),
129 OpPipe => Self::BitwiseOr(token),
130 OpCaret => Self::BitwiseXor(token),
131 OpShl => Self::LeftShift(token),
132 OpShr => Self::RightShift(token),
133 OpShlEx => Self::LeftShiftExtend(token),
134 OpShrEx => Self::RightShiftExtend(token),
135 OpShlCon => Self::LeftShiftContract(token),
136 OpShrCon => Self::RightShiftContract(token),
137 OpSemi => Self::Sequence(token),
138 OpColon => Self::Cons(token),
139 OpGlue => Self::Glue(token),
140 OpLtLt => Self::Compose(token),
141 OpGtGt => Self::RCompose(token),
142 OpPipeGt => Self::Pipe(token),
143 OpLtPipe => Self::RPipe(token),
144 _ => unreachable!(),
145 }
146 }
147
148 fn precedence(&self) -> Precedence {
149 match self {
150 BinaryOperator::Access(..) => Precedence::Access,
151 BinaryOperator::And(..) => Precedence::And,
152 BinaryOperator::Or(..) => Precedence::Or,
153 BinaryOperator::Add(..) | BinaryOperator::Subtract(..) => Precedence::Term,
154 BinaryOperator::Multiply(..)
155 | BinaryOperator::Divide(..)
156 | BinaryOperator::IntDivide(..)
157 | BinaryOperator::Remainder(..) => Precedence::Factor,
158 BinaryOperator::Power(..) => Precedence::Exponent,
159 BinaryOperator::StructuralEquality(..)
160 | BinaryOperator::ReferenceEquality(..)
161 | BinaryOperator::StructuralInequality(..)
162 | BinaryOperator::ReferenceInequality(..) => Precedence::Equality,
163 BinaryOperator::Lt(..)
164 | BinaryOperator::Gt(..)
165 | BinaryOperator::Geq(..)
166 | BinaryOperator::Leq(..) => Precedence::Comparison,
167 BinaryOperator::BitwiseAnd(..) => Precedence::BitwiseAnd,
168 BinaryOperator::BitwiseOr(..) => Precedence::BitwiseOr,
169 BinaryOperator::BitwiseXor(..) => Precedence::BitwiseXor,
170 BinaryOperator::LeftShift(..)
171 | BinaryOperator::RightShift(..)
172 | BinaryOperator::LeftShiftExtend(..)
173 | BinaryOperator::RightShiftExtend(..)
174 | BinaryOperator::LeftShiftContract(..)
175 | BinaryOperator::RightShiftContract(..) => Precedence::BitwiseShift,
176 BinaryOperator::Sequence(..) => Precedence::Sequence,
177 BinaryOperator::Cons(..) => Precedence::Cons,
178 BinaryOperator::Glue(..) => Precedence::Glue,
179 BinaryOperator::Compose(..) => Precedence::Compose,
180 BinaryOperator::RCompose(..) => Precedence::RCompose,
181 BinaryOperator::Pipe(..) => Precedence::Pipe,
182 BinaryOperator::RPipe(..) => Precedence::RPipe,
183 }
184 }
185}
186
187#[cfg(test)]
188mod test {
189 use super::*;
190
191 test_parse!(binop_access: "a . b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Access _) _))");
192 test_parse!(binop_and: "a && b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::And _) _))");
193 test_parse!(binop_or: "a || b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Or _) _))");
194 test_parse!(binop_plus: "a + b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Add _) _))");
195 test_parse!(binop_minus: "a - b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Subtract _) _))");
196 test_parse!(binop_multiply: "a * b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Multiply _) _))");
197 test_parse!(binop_divide: "a / b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Divide _) _))");
198 test_parse!(binop_int_divide: "a // b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::IntDivide _) _))");
199 test_parse!(binop_remainder: "a % b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Remainder _) _))");
200 test_parse!(binop_power: "a ** b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Power _) _))");
201 test_parse!(binop_equal: "a == b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::StructuralEquality _) _))");
202 test_parse!(binop_ref_equal: "a === b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::ReferenceEquality _) _))");
203 test_parse!(binop_not_equal: "a != b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::StructuralInequality _) _))");
204 test_parse!(binop_not_ref_equal: "a !== b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::ReferenceInequality _) _))");
205 test_parse!(binop_lt: "a < b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Lt _) _))");
206 test_parse!(binop_gt: "a > b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Gt _) _))");
207 test_parse!(binop_leq: "a <= b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Leq _) _))");
208 test_parse!(binop_geq: "a >= b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Geq _) _))");
209 test_parse!(binop_bitwise_and: "a & b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::BitwiseAnd _) _))");
210 test_parse!(binop_bitwise_or: "a | b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::BitwiseOr _) _))");
211 test_parse!(binop_bitwise_xor: "a ^ b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::BitwiseXor _) _))");
212 test_parse!(binop_bitwise_shl: "a <~ b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::LeftShift _) _))");
213 test_parse!(binop_bitwise_shr: "a ~> b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::RightShift _) _))");
214 test_parse!(binop_bitwise_shl_ex: "a <~~ b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::LeftShiftExtend _) _))");
215 test_parse!(binop_bitwise_shr_ex: "a ~~> b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::RightShiftExtend _) _))");
216 test_parse!(binop_bitwise_shl_con: "a <<~ b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::LeftShiftContract _) _))");
217 test_parse!(binop_bitwise_shr_con: "a ~>> b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::RightShiftContract _) _))");
218 test_parse!(binop_seq: "a ; b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Sequence _) _))");
219 test_parse!(binop_cons: "a : b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Cons _) _))");
220 test_parse!(binop_glue: "a <> b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Glue _) _))");
221 test_parse!(binop_compose: "a << b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Compose _) _))");
222 test_parse!(binop_rcompose: "a >> b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::RCompose _) _))");
223 test_parse!(binop_pipe: "a |> b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Pipe _) _))");
224 test_parse!(binop_rpipe: "a <| b" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::RPipe _) _))");
225
226 test_parse!(binop_with_unary: "a + -5" => Expression::parse => "(Expression::Binary (BinaryOperation _ (BinaryOperator::Add _) (Expression::Unary _)))");
227
228 test_parse_error!(binop_not_and_operator: "a and b" => Expression::parse);
229 test_parse_error!(binop_not_or_operator: "a or b" => Expression::parse);
230 test_parse_error!(binop_not_seq_operator: "a , b" => Expression::parse);
231}