datex_core/ast/
comparison_operation.rs

1use std::fmt::Display;
2
3use crate::ast::DatexExpression;
4use crate::ast::DatexParserTrait;
5use crate::ast::lexer::Token;
6use crate::ast::utils::operation;
7use crate::global::instruction_codes::InstructionCode;
8use crate::global::protocol_structures::instructions::Instruction;
9use chumsky::prelude::*;
10
11#[derive(Clone, Debug, PartialEq, Copy)]
12pub enum ComparisonOperator {
13    Is,                 // is
14    Matches,            // matches
15    StructuralEqual,    // ==
16    NotStructuralEqual, // !=
17    Equal,              // ===
18    NotEqual,           // !==
19    LessThan,           // <
20    GreaterThan,        // >
21    LessThanOrEqual,    // <=
22    GreaterThanOrEqual, // >=
23}
24
25impl Display for ComparisonOperator {
26    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27        write!(
28            f,
29            "{}",
30            match self {
31                ComparisonOperator::Is => "is",
32                ComparisonOperator::Matches => "matches",
33                ComparisonOperator::StructuralEqual => "==",
34                ComparisonOperator::NotStructuralEqual => "!=",
35                ComparisonOperator::Equal => "===",
36                ComparisonOperator::NotEqual => "!==",
37                ComparisonOperator::LessThan => "<",
38                ComparisonOperator::GreaterThan => ">",
39                ComparisonOperator::LessThanOrEqual => "<=",
40                ComparisonOperator::GreaterThanOrEqual => ">=",
41            }
42        )
43    }
44}
45
46fn comparison_op(
47    op: ComparisonOperator,
48) -> impl Fn(Box<DatexExpression>, Box<DatexExpression>) -> DatexExpression + Clone
49{
50    move |lhs, rhs| DatexExpression::ComparisonOperation(op, lhs, rhs)
51}
52
53pub fn comparison_operation<'a>(
54    union: impl DatexParserTrait<'a>,
55) -> impl DatexParserTrait<'a> {
56    union
57        .clone()
58        .foldl(
59            choice((
60                operation(Token::StructuralEqual)
61                    .to(comparison_op(ComparisonOperator::StructuralEqual)),
62                operation(Token::Equal)
63                    .to(comparison_op(ComparisonOperator::Equal)),
64                operation(Token::NotStructuralEqual)
65                    .to(comparison_op(ComparisonOperator::NotStructuralEqual)),
66                operation(Token::NotEqual)
67                    .to(comparison_op(ComparisonOperator::NotEqual)),
68                operation(Token::Is).to(comparison_op(ComparisonOperator::Is)),
69                operation(Token::Matches)
70                    .to(comparison_op(ComparisonOperator::Matches)),
71            ))
72            .then(union.clone())
73            .repeated(),
74            |lhs, (op, rhs)| op(Box::new(lhs), Box::new(rhs)),
75        )
76        .boxed()
77}
78
79impl From<&ComparisonOperator> for InstructionCode {
80    fn from(op: &ComparisonOperator) -> Self {
81        match op {
82            ComparisonOperator::StructuralEqual => {
83                InstructionCode::STRUCTURAL_EQUAL
84            }
85            ComparisonOperator::NotStructuralEqual => {
86                InstructionCode::NOT_STRUCTURAL_EQUAL
87            }
88            ComparisonOperator::Equal => InstructionCode::EQUAL,
89            ComparisonOperator::NotEqual => InstructionCode::NOT_EQUAL,
90            ComparisonOperator::Is => InstructionCode::IS,
91            ComparisonOperator::Matches => InstructionCode::MATCHES,
92            operator => todo!(
93                "Comparison operator {:?} not implemented for InstructionCode",
94                operator
95            ),
96        }
97    }
98}
99
100impl From<ComparisonOperator> for InstructionCode {
101    fn from(op: ComparisonOperator) -> Self {
102        InstructionCode::from(&op)
103    }
104}
105impl From<&Instruction> for ComparisonOperator {
106    fn from(instruction: &Instruction) -> Self {
107        match instruction {
108            Instruction::StructuralEqual => ComparisonOperator::StructuralEqual,
109            Instruction::Equal => ComparisonOperator::Equal,
110            Instruction::NotStructuralEqual => {
111                ComparisonOperator::NotStructuralEqual
112            }
113            Instruction::NotEqual => ComparisonOperator::NotEqual,
114            Instruction::Is => ComparisonOperator::Is,
115            Instruction::Matches => ComparisonOperator::Matches,
116            _ => {
117                todo!(
118                    "Comparison operator for instruction {:?} not implemented",
119                    instruction
120                );
121            }
122        }
123    }
124}
125
126impl From<Instruction> for ComparisonOperator {
127    fn from(instruction: Instruction) -> Self {
128        ComparisonOperator::from(&instruction)
129    }
130}