tiger_lib/block/
blockitem.rs1use crate::block::{BV, Block, Comparator, Eq::*, Field};
2use crate::report::{ErrorKey, err};
3use crate::token::Token;
4
5#[derive(Debug, Clone)]
6pub enum BlockItem {
7 Value(Token),
8 Block(Block),
9 Field(Field),
10}
11
12impl BlockItem {
13 pub fn expect_field(&self) -> Option<&Field> {
14 if let BlockItem::Field(field) = self {
15 Some(field)
16 } else {
17 let msg = format!("unexpected {}", self.describe());
18 err(ErrorKey::Structure).msg(msg).info("Did you forget an = ?").loc(self).push();
19 None
20 }
21 }
22
23 pub fn expect_into_field(self) -> Option<Field> {
24 if let BlockItem::Field(field) = self {
25 Some(field)
26 } else {
27 let msg = format!("unexpected {}", self.describe());
28 err(ErrorKey::Structure).msg(msg).info("Did you forget an = ?").loc(self).push();
29 None
30 }
31 }
32
33 pub fn get_field(&self) -> Option<&Field> {
34 if let BlockItem::Field(field) = self { Some(field) } else { None }
35 }
36
37 #[allow(dead_code)]
38 pub fn is_field(&self) -> bool {
39 matches!(self, BlockItem::Field(_))
40 }
41
42 pub fn get_value(&self) -> Option<&Token> {
43 if let BlockItem::Value(token) = self { Some(token) } else { None }
44 }
45
46 pub fn expect_value(&self) -> Option<&Token> {
47 if let BlockItem::Value(token) = self {
48 Some(token)
49 } else {
50 let msg = format!("expected value, found {}", self.describe());
51 err(ErrorKey::Structure).msg(msg).loc(self).push();
52 None
53 }
54 }
55
56 pub fn expect_into_value(self) -> Option<Token> {
57 if let BlockItem::Value(token) = self {
58 Some(token)
59 } else {
60 let msg = format!("expected value, found {}", self.describe());
61 err(ErrorKey::Structure).msg(msg).loc(self).push();
62 None
63 }
64 }
65
66 #[allow(dead_code)] pub fn get_block(&self) -> Option<&Block> {
68 if let BlockItem::Block(block) = self { Some(block) } else { None }
69 }
70
71 pub fn expect_block(&self) -> Option<&Block> {
72 if let BlockItem::Block(block) = self {
73 Some(block)
74 } else {
75 let msg = format!("expected block, found {}", self.describe());
76 err(ErrorKey::Structure).msg(msg).loc(self).push();
77 None
78 }
79 }
80
81 pub fn expect_into_block(self) -> Option<Block> {
82 if let BlockItem::Block(block) = self {
83 Some(block)
84 } else {
85 let msg = format!("expected block, found {}", self.describe());
86 err(ErrorKey::Structure).msg(msg).loc(self).push();
87 None
88 }
89 }
90
91 pub fn get_definition(&self) -> Option<(&Token, &Block)> {
92 if let Some(field) = self.get_field() { field.get_definition() } else { None }
93 }
94
95 pub fn expect_into_definition(self) -> Option<(Token, Block)> {
96 if let Some(field) = self.expect_into_field() {
97 field.expect_into_definition()
98 } else {
99 None
100 }
101 }
102
103 pub fn expect_definition(&self) -> Option<(&Token, &Block)> {
104 if let Some(field) = self.expect_field() { field.expect_definition() } else { None }
105 }
106
107 pub fn expect_into_assignment(self) -> Option<(Token, Token)> {
108 if let Some(field) = self.expect_into_field() {
109 field.expect_into_assignment()
110 } else {
111 None
112 }
113 }
114
115 pub fn expect_assignment(&self) -> Option<(&Token, &Token)> {
116 if let Some(field) = self.expect_field() {
117 #[allow(clippy::single_match_else)] match field {
119 Field(key, Comparator::Equals(Single | Question), BV::Value(token)) => {
120 return Some((key, token));
121 }
122 _ => {
123 let msg = format!("expected assignment, found {}", field.describe());
124 err(ErrorKey::Structure).msg(msg).loc(self).push();
125 }
126 }
127 }
128 None
129 }
130
131 pub fn get_assignment(&self) -> Option<(&Token, &Token)> {
132 #[allow(clippy::single_match_else)] match self {
134 BlockItem::Field(Field(
135 key,
136 Comparator::Equals(Single | Question),
137 BV::Value(token),
138 )) => Some((key, token)),
139 _ => None,
140 }
141 }
142
143 pub fn describe(&self) -> &'static str {
144 match self {
145 BlockItem::Value(_) => "value",
146 BlockItem::Block(_) => "block",
147 BlockItem::Field(field) => field.describe(),
148 }
149 }
150
151 pub fn equivalent(&self, other: &Self) -> bool {
152 match self {
153 BlockItem::Value(token) => {
154 if let BlockItem::Value(t) = other {
155 token == t
156 } else {
157 false
158 }
159 }
160 BlockItem::Block(block) => {
161 if let BlockItem::Block(b) = other {
162 block.equivalent(b)
163 } else {
164 false
165 }
166 }
167 BlockItem::Field(field) => {
168 if let BlockItem::Field(f) = other {
169 field.equivalent(f)
170 } else {
171 false
172 }
173 }
174 }
175 }
176}