// Copyright (c) 2022 Kaushik Kulkarni // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. use crate::primitives::{Expression, BinaryOpType, UnaryOpType, LiteralT, SmallVecExprT}; use std::rc::Rc; use std::str::FromStr; use smallvec::{smallvec}; grammar; pub Expr: Rc = { IfExpr, }; IfExpr: Rc = { "if" "else" => Rc::new(Expression::If(cond_expr.clone(), then_expr.clone(), else_expr.clone())), OrExpr, } OrExpr: Rc = { "or" => Rc::new(Expression::BinaryOp(left_op.clone(), BinaryOpType::LogicalOr, right_op.clone())), AndExpr, }; AndExpr: Rc = { "and" => Rc::new(Expression::BinaryOp(left_op.clone(), BinaryOpType::LogicalAnd, right_op.clone())), NotExpr, }; NotExpr: Rc = { "not" => Rc::new(Expression::UnaryOp(UnaryOpType::LogicalNot, op.clone())), CmpExpr, }; CmpExpr: Rc = { => Rc::new(Expression::BinaryOp(left_op.clone(), operator, right_op.clone())), BitwiseOrExpr, }; BitwiseOrExpr: Rc = { "|" => Rc::new(Expression::BinaryOp(left_op.clone(), BinaryOpType::BitwiseOr, right_op.clone())), BitwiseXorExpr, }; BitwiseXorExpr: Rc = { "^" => Rc::new(Expression::BinaryOp(left_op.clone(), BinaryOpType::BitwiseXor, right_op.clone())), BitwiseAndExpr, }; BitwiseAndExpr: Rc = { "&" => Rc::new(Expression::BinaryOp(left_op.clone(), BinaryOpType::BitwiseAnd, right_op.clone())), ShiftExpr, }; ShiftExpr: Rc = { => Rc::new(Expression::BinaryOp(left_op.clone(), operator, right_op.clone())), SumExpr, }; SumExpr: Rc = { "+" => Rc::new(Expression::BinaryOp(left_op.clone(), BinaryOpType::Sum, right_op.clone())), "-" => Rc::new(Expression::BinaryOp(left_op.clone(), BinaryOpType::Subtract, right_op.clone())), ProdExpr, }; ProdExpr: Rc = { "*" => Rc::new(Expression::BinaryOp(left_op.clone(), BinaryOpType::Product, right_op.clone())), "/" => Rc::new(Expression::BinaryOp(left_op.clone(), BinaryOpType::Divide, right_op.clone())), "//" => Rc::new(Expression::BinaryOp(left_op.clone(), BinaryOpType::FloorDiv, right_op.clone())), "%" => Rc::new(Expression::BinaryOp(left_op.clone(), BinaryOpType::Modulo, right_op.clone())), UnaryExpr, }; UnaryExpr: Rc = { "-" => Rc::new(Expression::UnaryOp(UnaryOpType::Minus, op.clone())), "~" => Rc::new(Expression::UnaryOp(UnaryOpType::BitwiseNot, op.clone())), "+" => op, ExponentExpr, }; ExponentExpr: Rc = { "**" => Rc::new(Expression::BinaryOp(left_op.clone(), BinaryOpType::Exponent, right_op.clone())), AtomExpr, }; AtomExpr: Rc = { => Rc::new(Expression::Variable(identifier)), "(" ")" => Rc::new(Expression::Call(call.clone(), commaed_exprs)), "(" ")" => Rc::new(Expression::Call(call.clone(), smallvec![])), "[" "]" => Rc::new(Expression::Subscript(agg.clone(), commaed_exprs)), "[" "]" => Rc::new(Expression::Subscript(agg.clone(), smallvec![])), "(" ")" => expr, => Rc::new(Expression::Scalar(LiteralT::I32(int_literal))), => Rc::new(Expression::Scalar(LiteralT::F64(float_literal))), }; CommaedExprs: Vec> = { "," => [commaed_exprs.as_slice(), vec![expr].as_slice()].concat(), => vec![expr], } CommaedExprsFinal: SmallVecExprT = { => SmallVecExprT::from_vec(commaed_exprs), "," => SmallVecExprT::from_vec(commaed_exprs), }; CmpOperator: BinaryOpType = { "==" => BinaryOpType::Equal, "!=" => BinaryOpType::NotEqual, ">" => BinaryOpType::Greater, ">=" => BinaryOpType::GreaterEqual, "<" => BinaryOpType::Less, "<=" => BinaryOpType::LessEqual, }; ShiftOperator: BinaryOpType = { ">>" => BinaryOpType::RightShift, "<<" => BinaryOpType::LeftShift, }; Identifier: String = { => s.to_string(), }; IntLiteral: i32 = { => i32::from_str(s).unwrap(), } FloatLiteral: f64 = { // f64 with the decimal point => f64::from_str(s).unwrap(), // f64 without the decimal point => f64::from_str(s).unwrap(), } // vim:syntax=rust