Skip to main content

zen_expression/parser/
constants.rs

1use nohash_hasher::BuildNoHashHasher;
2use once_cell::sync::Lazy;
3use std::collections::HashMap;
4
5use crate::lexer::{ArithmeticOperator, ComparisonOperator, LogicalOperator, Operator};
6use Associativity::{Left, Right};
7
8type NoHasher = BuildNoHashHasher<Operator>;
9
10#[derive(Debug, PartialEq, Eq, Clone, Copy)]
11pub enum Associativity {
12    Left,
13    Right,
14}
15
16#[derive(Debug, PartialEq)]
17pub struct ParserOperator {
18    pub precedence: u8,
19    pub associativity: Associativity,
20}
21
22impl ParserOperator {
23    pub fn binary(operator: &Operator) -> Option<&'static ParserOperator> {
24        BINARY_OPERATORS.get(operator)
25    }
26
27    pub fn unary(operator: &Operator) -> Option<&'static ParserOperator> {
28        UNARY_OPERATORS.get(operator)
29    }
30}
31
32macro_rules! hashmap {
33    (@single $($x:tt)*) => (());
34    (@count $($rest:expr),*) => (<[()]>::len(&[$(hashmap!(@single $rest)),*]));
35
36    ($($key:expr => $value:expr,)+) => { hashmap!($($key => $value),+) };
37    ($($key:expr => $value:expr),*) => {
38        {
39            let _cap = hashmap!(@count $($key),*);
40            let mut _map = ::std::collections::HashMap::default();
41            _map.reserve(_cap);
42            $(
43                let _ = _map.insert($key, $value);
44            )*
45            _map
46        }
47    };
48}
49
50pub(crate) static BINARY_OPERATORS: Lazy<HashMap<Operator, ParserOperator, NoHasher>> = Lazy::new(
51    || {
52        hashmap! {
53            Operator::Logical(LogicalOperator::Or) => ParserOperator { precedence: 10, associativity: Left },
54            Operator::Logical(LogicalOperator::And) => ParserOperator { precedence: 15, associativity: Left },
55            Operator::Comparison(ComparisonOperator::Equal) => ParserOperator { precedence: 20, associativity: Left },
56            Operator::Comparison(ComparisonOperator::NotEqual) => ParserOperator { precedence: 20, associativity: Left },
57            Operator::Comparison(ComparisonOperator::LessThan) => ParserOperator { precedence: 20, associativity: Left },
58            Operator::Comparison(ComparisonOperator::GreaterThan) => ParserOperator { precedence: 20, associativity: Left },
59            Operator::Comparison(ComparisonOperator::LessThanOrEqual) => ParserOperator { precedence: 20, associativity: Left },
60            Operator::Comparison(ComparisonOperator::GreaterThanOrEqual) => ParserOperator { precedence: 20, associativity: Left },
61            Operator::Comparison(ComparisonOperator::NotIn) => ParserOperator { precedence: 20, associativity: Left },
62            Operator::Comparison(ComparisonOperator::In) => ParserOperator { precedence: 20, associativity: Left },
63            Operator::Arithmetic(ArithmeticOperator::Add) => ParserOperator { precedence: 30, associativity: Left },
64            Operator::Arithmetic(ArithmeticOperator::Subtract) => ParserOperator { precedence: 30, associativity: Left },
65            Operator::Arithmetic(ArithmeticOperator::Multiply) => ParserOperator { precedence: 60, associativity: Left },
66            Operator::Arithmetic(ArithmeticOperator::Divide) => ParserOperator { precedence: 60, associativity: Left },
67            Operator::Arithmetic(ArithmeticOperator::Modulus) => ParserOperator { precedence: 60, associativity: Left },
68            Operator::Arithmetic(ArithmeticOperator::Power) => ParserOperator { precedence: 70, associativity: Right },
69            Operator::Logical(LogicalOperator::NullishCoalescing) => ParserOperator { precedence: 80, associativity: Left },
70        }
71    },
72);
73
74pub(crate) static UNARY_OPERATORS: Lazy<HashMap<Operator, ParserOperator, NoHasher>> = Lazy::new(
75    || {
76        hashmap! {
77            Operator::Logical(LogicalOperator::Not) => ParserOperator { precedence: 50, associativity: Left },
78            Operator::Arithmetic(ArithmeticOperator::Add) => ParserOperator { precedence: 200, associativity: Left },
79            Operator::Arithmetic(ArithmeticOperator::Subtract) => ParserOperator { precedence: 200, associativity: Left },
80        }
81    },
82);