tiger_lib/block/
field.rs

1use crate::block::{BV, Block, Comparator, Eq::*};
2use crate::report::{ErrorKey, err};
3use crate::token::Token;
4
5#[derive(Debug, Clone)]
6pub struct Field(pub Token, pub Comparator, pub BV);
7
8impl Field {
9    pub fn into_key(self) -> Token {
10        self.0
11    }
12
13    pub fn key(&self) -> &Token {
14        &self.0
15    }
16
17    pub fn cmp(&self) -> Comparator {
18        self.1
19    }
20
21    #[allow(dead_code)] // It's here for symmetry
22    pub fn into_bv(self) -> BV {
23        self.2
24    }
25
26    pub fn bv(&self) -> &BV {
27        &self.2
28    }
29
30    pub fn is_eq(&self) -> bool {
31        matches!(self.1, Comparator::Equals(Single))
32    }
33
34    pub fn is_eq_qeq(&self) -> bool {
35        matches!(self.1, Comparator::Equals(Single | Question))
36    }
37
38    pub fn expect_eq(&self) -> bool {
39        let Self(key, cmp, _) = self;
40        if matches!(cmp, Comparator::Equals(Single)) {
41            true
42        } else {
43            let msg = &format!("expected `{key} =`, found `{cmp}`");
44            err(ErrorKey::Validation).msg(msg).loc(self).push();
45            false
46        }
47    }
48
49    pub fn describe(&self) -> &'static str {
50        if self.is_eq_qeq() {
51            match self.2 {
52                BV::Value(_) => "assignment",
53                BV::Block(_) => "definition",
54            }
55        } else {
56            "comparison"
57        }
58    }
59
60    pub fn equivalent(&self, other: &Self) -> bool {
61        self.0 == other.0 && self.1 == other.1 && self.2.equivalent(&other.2)
62    }
63
64    pub fn expect_definition(&self) -> Option<(&Token, &Block)> {
65        #[allow(clippy::single_match_else)] // too complicated for a `let`
66        match self {
67            Field(key, Comparator::Equals(Single | Question), BV::Block(block)) => {
68                return Some((key, block));
69            }
70            _ => {
71                let msg = format!("expected definition, found {}", self.describe());
72                err(ErrorKey::Structure).msg(msg).loc(self).push();
73            }
74        }
75        None
76    }
77
78    pub fn expect_into_definition(self) -> Option<(Token, Block)> {
79        #[allow(clippy::single_match_else)] // too complicated for a `let`
80        match self {
81            Field(key, Comparator::Equals(Single | Question), BV::Block(block)) => {
82                return Some((key, block));
83            }
84            _ => {
85                let msg = format!("expected definition, found {}", self.describe());
86                err(ErrorKey::Structure).msg(msg).loc(self).push();
87            }
88        }
89        None
90    }
91
92    pub fn get_definition(&self) -> Option<(&Token, &Block)> {
93        #[allow(clippy::single_match_else)] // too complicated for a `let`
94        match self {
95            Field(key, Comparator::Equals(Single | Question), BV::Block(block)) => {
96                Some((key, block))
97            }
98            _ => None,
99        }
100    }
101
102    #[allow(dead_code)]
103    pub fn into_definition(self) -> Option<(Token, Block)> {
104        #[allow(clippy::single_match_else)] // too complicated for a `let`
105        match self {
106            Field(key, Comparator::Equals(Single | Question), BV::Block(block)) => {
107                Some((key, block))
108            }
109            _ => None,
110        }
111    }
112
113    pub fn get_assignment(&self) -> Option<(&Token, &Token)> {
114        #[allow(clippy::single_match_else)] // too complicated for a `let`
115        match self {
116            Field(key, Comparator::Equals(Single | Question), BV::Value(token)) => {
117                Some((key, token))
118            }
119            _ => None,
120        }
121    }
122
123    pub fn expect_into_assignment(self) -> Option<(Token, Token)> {
124        #[allow(clippy::single_match_else)] // too complicated for a `let`
125        match self {
126            Field(key, Comparator::Equals(Single | Question), BV::Value(token)) => {
127                return Some((key, token));
128            }
129            _ => {
130                let msg = format!("expected assignment, found {}", self.describe());
131                err(ErrorKey::Structure).msg(msg).loc(self).push();
132            }
133        }
134        None
135    }
136
137    #[allow(dead_code)] // It's here for symmetry
138    pub fn expect_assignment(&self) -> Option<(&Token, &Token)> {
139        #[allow(clippy::single_match_else)] // too complicated for a `let`
140        match self {
141            Field(key, Comparator::Equals(Single | Question), BV::Value(token)) => {
142                return Some((key, token));
143            }
144            _ => {
145                let msg = format!("expected assignment, found {}", self.describe());
146                err(ErrorKey::Structure).msg(msg).loc(self).push();
147            }
148        }
149        None
150    }
151
152    #[allow(dead_code)]
153    pub fn into_assignment(self) -> Option<(Token, Token)> {
154        #[allow(clippy::single_match_else)] // too complicated for a `let`
155        match self {
156            Field(key, Comparator::Equals(Single | Question), BV::Value(value)) => {
157                Some((key, value))
158            }
159            _ => None,
160        }
161    }
162}