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)]
12pub struct BinaryOperation {
13 pub lhs: Expression,
14 pub operator: BinaryOperator,
15 pub rhs: Expression,
16 pub 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)]
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 Cons(Token),
98 Glue(Token),
99 Compose(Token),
100 RCompose(Token),
101 Pipe(Token),
102 RPipe(Token),
103}
104
105impl BinaryOperator {
106 fn parse(parser: &mut Parser) -> Self {
107 let token = parser.consume();
108 match token.token_type {
109 OpDot => Self::Access(token),
110 OpAmpAmp => Self::And(token),
111 OpPipePipe => Self::Or(token),
112 OpPlus => Self::Add(token),
113 OpMinus => Self::Subtract(token),
114 OpStar => Self::Multiply(token),
115 OpSlash => Self::Divide(token),
116 OpSlashSlash => Self::IntDivide(token),
117 OpPercent => Self::Remainder(token),
118 OpStarStar => Self::Power(token),
119 OpEqEq => Self::StructuralEquality(token),
120 OpBangEq => Self::StructuralInequality(token),
121 OpEqEqEq => Self::ReferenceEquality(token),
122 OpBangEqEq => Self::ReferenceInequality(token),
123 OpLt => Self::Lt(token),
124 OpGt => Self::Gt(token),
125 OpLtEq => Self::Leq(token),
126 OpGtEq => Self::Geq(token),
127 OpAmp => Self::BitwiseAnd(token),
128 OpPipe => Self::BitwiseOr(token),
129 OpCaret => Self::BitwiseXor(token),
130 OpShl => Self::LeftShift(token),
131 OpShr => Self::RightShift(token),
132 OpShlEx => Self::LeftShiftExtend(token),
133 OpShrEx => Self::RightShiftExtend(token),
134 OpShlCon => Self::LeftShiftContract(token),
135 OpShrCon => Self::RightShiftContract(token),
136 OpColon => Self::Cons(token),
137 OpGlue => Self::Glue(token),
138 OpLtLt => Self::Compose(token),
139 OpGtGt => Self::RCompose(token),
140 OpPipeGt => Self::Pipe(token),
141 OpLtPipe => Self::RPipe(token),
142 _ => unreachable!(),
143 }
144 }
145
146 fn precedence(&self) -> Precedence {
147 match self {
148 BinaryOperator::Access(..) => Precedence::Access,
149 BinaryOperator::And(..) => Precedence::And,
150 BinaryOperator::Or(..) => Precedence::Or,
151 BinaryOperator::Add(..) | BinaryOperator::Subtract(..) => Precedence::Term,
152 BinaryOperator::Multiply(..)
153 | BinaryOperator::Divide(..)
154 | BinaryOperator::IntDivide(..)
155 | BinaryOperator::Remainder(..) => Precedence::Factor,
156 BinaryOperator::Power(..) => Precedence::Exponent,
157 BinaryOperator::StructuralEquality(..)
158 | BinaryOperator::ReferenceEquality(..)
159 | BinaryOperator::StructuralInequality(..)
160 | BinaryOperator::ReferenceInequality(..) => Precedence::Equality,
161 BinaryOperator::Lt(..)
162 | BinaryOperator::Gt(..)
163 | BinaryOperator::Geq(..)
164 | BinaryOperator::Leq(..) => Precedence::Comparison,
165 BinaryOperator::BitwiseAnd(..) => Precedence::BitwiseAnd,
166 BinaryOperator::BitwiseOr(..) => Precedence::BitwiseOr,
167 BinaryOperator::BitwiseXor(..) => Precedence::BitwiseXor,
168 BinaryOperator::LeftShift(..)
169 | BinaryOperator::RightShift(..)
170 | BinaryOperator::LeftShiftExtend(..)
171 | BinaryOperator::RightShiftExtend(..)
172 | BinaryOperator::LeftShiftContract(..)
173 | BinaryOperator::RightShiftContract(..) => Precedence::BitwiseShift,
174 BinaryOperator::Cons(..) => Precedence::Cons,
175 BinaryOperator::Glue(..) => Precedence::Glue,
176 BinaryOperator::Compose(..) => Precedence::Compose,
177 BinaryOperator::RCompose(..) => Precedence::RCompose,
178 BinaryOperator::Pipe(..) => Precedence::Pipe,
179 BinaryOperator::RPipe(..) => Precedence::RPipe,
180 }
181 }
182}
183
184#[cfg(test)]
185mod test {
186 use super::*;
187
188 test_parse!(binop_access: "a . b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Access(_), .. }));
189 test_parse!(binop_and: "a && b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::And(_), .. }));
190 test_parse!(binop_or: "a || b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Or(_), .. }));
191 test_parse!(binop_plus: "a + b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Add(_), .. }));
192 test_parse!(binop_minus: "a - b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Subtract(_), .. }));
193 test_parse!(binop_multiply: "a * b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Multiply(_), .. }));
194 test_parse!(binop_divide: "a / b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Divide(_), .. }));
195 test_parse!(binop_int_divide: "a // b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::IntDivide(_), .. }));
196 test_parse!(binop_remainder: "a % b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Remainder(_), .. }));
197 test_parse!(binop_power: "a ** b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Power(_), .. }));
198 test_parse!(binop_equal: "a == b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::StructuralEquality(_), .. }));
199 test_parse!(binop_ref_equal: "a === b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::ReferenceEquality(_), .. }));
200 test_parse!(binop_not_equal: "a != b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::StructuralInequality(_), .. }));
201 test_parse!(binop_not_ref_equal: "a !== b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::ReferenceInequality(_), .. }));
202 test_parse!(binop_lt: "a < b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Lt(_), .. }));
203 test_parse!(binop_gt: "a > b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Gt(_), .. }));
204 test_parse!(binop_leq: "a <= b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Leq(_), .. }));
205 test_parse!(binop_geq: "a >= b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Geq(_), .. }));
206 test_parse!(binop_bitwise_and: "a & b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::BitwiseAnd(_), .. }));
207 test_parse!(binop_bitwise_or: "a | b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::BitwiseOr(_), .. }));
208 test_parse!(binop_bitwise_xor: "a ^ b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::BitwiseXor(_), .. }));
209 test_parse!(binop_bitwise_shl: "a <~ b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::LeftShift(_), .. }));
210 test_parse!(binop_bitwise_shr: "a ~> b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::RightShift(_), .. }));
211 test_parse!(binop_bitwise_shl_ex: "a <~~ b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::LeftShiftExtend(_), .. }));
212 test_parse!(binop_bitwise_shr_ex: "a ~~> b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::RightShiftExtend(_), .. }));
213 test_parse!(binop_bitwise_shl_con: "a <<~ b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::LeftShiftContract(_), .. }));
214 test_parse!(binop_bitwise_shr_con: "a ~>> b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::RightShiftContract(_), .. }));
215 test_parse!(binop_cons: "a : b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Cons(_), .. }));
216 test_parse!(binop_glue: "a <> b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Glue(_), .. }));
217 test_parse!(binop_compose: "a << b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Compose(_), .. }));
218 test_parse!(binop_rcompose: "a >> b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::RCompose(_), .. }));
219 test_parse!(binop_pipe: "a |> b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Pipe(_), .. }));
220 test_parse!(binop_rpipe: "a <| b" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::RPipe(_), .. }));
221
222 test_parse!(binop_with_unary: "a + -5" => Expression::parse => Expression::Binary(BinaryOperation { operator: BinaryOperator::Add(_), rhs: Expression::Unary(_), .. }));
223
224 test_parse_error!(binop_not_and_operator: "a and b" => Expression::parse);
225 test_parse_error!(binop_not_or_operator: "a or b" => Expression::parse);
226 test_parse_error!(binop_not_seq_operator: "a , b" => Expression::parse);
227}