Actually just three programming languages in a trenchcoat
at string-repr-callable 231 lines 12 kB view raw
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}