Actually just three programming languages in a trenchcoat
at main 227 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)] 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}