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)] 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)] 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)] 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)] 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)] 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)] 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)] 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)] pub fn expect_assignment(&self) -> Option<(&Token, &Token)> {
139 #[allow(clippy::single_match_else)] 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)] match self {
156 Field(key, Comparator::Equals(Single | Question), BV::Value(value)) => {
157 Some((key, value))
158 }
159 _ => None,
160 }
161 }
162}