1use crate::key::Key;
2use crate::parser::error::CustomError;
3use crate::repr::Decor;
4use crate::table::TableKeyValue;
5use crate::{ArrayOfTables, ImDocument, InternalString, Item, RawString, Table};
6
7pub(crate) struct ParseState {
8 root: Table,
9 trailing: Option<std::ops::Range<usize>>,
10 current_table_position: usize,
11 current_table: Table,
12 current_is_array: bool,
13 current_table_path: Vec<Key>,
14}
15
16impl ParseState {
17 pub(crate) fn new() -> Self {
18 let mut root = Table::new();
19 root.span = Some(0..0);
20 Self {
21 root: Table::new(),
22 trailing: None,
23 current_table_position: 0,
24 current_table: root,
25 current_is_array: false,
26 current_table_path: Vec::new(),
27 }
28 }
29
30 pub(crate) fn into_document<S>(mut self, raw: S) -> Result<ImDocument<S>, CustomError> {
31 self.finalize_table()?;
32 let trailing = self.trailing.map(RawString::with_span).unwrap_or_default();
33 Ok(ImDocument {
34 root: Item::Table(self.root),
35 trailing,
36 raw,
37 })
38 }
39
40 pub(crate) fn on_ws(&mut self, span: std::ops::Range<usize>) {
41 if let Some(old) = self.trailing.take() {
42 self.trailing = Some(old.start..span.end);
43 } else {
44 self.trailing = Some(span);
45 }
46 }
47
48 pub(crate) fn on_comment(&mut self, span: std::ops::Range<usize>) {
49 if let Some(old) = self.trailing.take() {
50 self.trailing = Some(old.start..span.end);
51 } else {
52 self.trailing = Some(span);
53 }
54 }
55
56 pub(crate) fn on_keyval(
57 &mut self,
58 path: Vec<Key>,
59 mut kv: TableKeyValue,
60 ) -> Result<(), CustomError> {
61 {
62 let mut prefix = self.trailing.take();
63 let prefix = match (
64 prefix.take(),
65 kv.key.leaf_decor.prefix().and_then(|d| d.span()),
66 ) {
67 (Some(p), Some(k)) => Some(p.start..k.end),
68 (Some(p), None) | (None, Some(p)) => Some(p),
69 (None, None) => None,
70 };
71 kv.key
72 .leaf_decor
73 .set_prefix(prefix.map(RawString::with_span).unwrap_or_default());
74 }
75
76 if let (Some(existing), Some(value)) = (self.current_table.span(), kv.value.span()) {
77 self.current_table.span = Some((existing.start)..(value.end));
78 }
79 let table = &mut self.current_table;
80 let table = Self::descend_path(table, &path, true)?;
81
82 // "Likewise, using dotted keys to redefine tables already defined in [table] form is not allowed"
83 let mixed_table_types = table.is_dotted() == path.is_empty();
84 if mixed_table_types {
85 return Err(CustomError::DuplicateKey {
86 key: kv.key.get().into(),
87 table: None,
88 });
89 }
90
91 let key: InternalString = kv.key.get_internal().into();
92 match table.items.entry(key) {
93 indexmap::map::Entry::Vacant(o) => {
94 o.insert(kv);
95 }
96 indexmap::map::Entry::Occupied(o) => {
97 // "Since tables cannot be defined more than once, redefining such tables using a [table] header is not allowed"
98 return Err(CustomError::DuplicateKey {
99 key: o.key().as_str().into(),
100 table: Some(self.current_table_path.clone()),
101 });
102 }
103 }
104
105 Ok(())
106 }
107
108 pub(crate) fn start_array_table(
109 &mut self,
110 path: Vec<Key>,
111 decor: Decor,
112 span: std::ops::Range<usize>,
113 ) -> Result<(), CustomError> {
114 debug_assert!(!path.is_empty());
115 debug_assert!(self.current_table.is_empty());
116 debug_assert!(self.current_table_path.is_empty());
117
118 // Look up the table on start to ensure the duplicate_key error points to the right line
119 let root = &mut self.root;
120 let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?;
121 let key = &path[path.len() - 1];
122 let entry = parent_table
123 .entry_format(key)
124 .or_insert(Item::ArrayOfTables(ArrayOfTables::new()));
125 entry
126 .as_array_of_tables()
127 .ok_or_else(|| CustomError::duplicate_key(&path, path.len() - 1))?;
128
129 self.current_table_position += 1;
130 self.current_table.decor = decor;
131 self.current_table.set_implicit(false);
132 self.current_table.set_dotted(false);
133 self.current_table.set_position(self.current_table_position);
134 self.current_table.span = Some(span);
135 self.current_is_array = true;
136 self.current_table_path = path;
137
138 Ok(())
139 }
140
141 pub(crate) fn start_table(
142 &mut self,
143 path: Vec<Key>,
144 decor: Decor,
145 span: std::ops::Range<usize>,
146 ) -> Result<(), CustomError> {
147 debug_assert!(!path.is_empty());
148 debug_assert!(self.current_table.is_empty());
149 debug_assert!(self.current_table_path.is_empty());
150
151 // 1. Look up the table on start to ensure the duplicate_key error points to the right line
152 // 2. Ensure any child tables from an implicit table are preserved
153 let root = &mut self.root;
154 let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?;
155 let key = &path[path.len() - 1];
156 if let Some(entry) = parent_table.remove(key.get()) {
157 match entry {
158 Item::Table(t) if t.implicit && !t.is_dotted() => {
159 self.current_table = t;
160 }
161 // Since tables cannot be defined more than once, redefining such tables using a [table] header is not allowed. Likewise, using dotted keys to redefine tables already defined in [table] form is not allowed.
162 _ => return Err(CustomError::duplicate_key(&path, path.len() - 1)),
163 }
164 }
165
166 self.current_table_position += 1;
167 self.current_table.decor = decor;
168 self.current_table.set_implicit(false);
169 self.current_table.set_dotted(false);
170 self.current_table.set_position(self.current_table_position);
171 self.current_table.span = Some(span);
172 self.current_is_array = false;
173 self.current_table_path = path;
174
175 Ok(())
176 }
177
178 pub(crate) fn finalize_table(&mut self) -> Result<(), CustomError> {
179 let mut table = std::mem::take(&mut self.current_table);
180 let path = std::mem::take(&mut self.current_table_path);
181
182 let root = &mut self.root;
183 if path.is_empty() {
184 assert!(root.is_empty());
185 std::mem::swap(&mut table, root);
186 } else if self.current_is_array {
187 let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?;
188 let key = &path[path.len() - 1];
189
190 let entry = parent_table
191 .entry_format(key)
192 .or_insert(Item::ArrayOfTables(ArrayOfTables::new()));
193 let array = entry
194 .as_array_of_tables_mut()
195 .ok_or_else(|| CustomError::duplicate_key(&path, path.len() - 1))?;
196 array.push(table);
197 let span = if let (Some(first), Some(last)) = (
198 array.values.first().and_then(|t| t.span()),
199 array.values.last().and_then(|t| t.span()),
200 ) {
201 Some((first.start)..(last.end))
202 } else {
203 None
204 };
205 array.span = span;
206 } else {
207 let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?;
208 let key = &path[path.len() - 1];
209
210 let entry = parent_table.entry_format(key);
211 match entry {
212 crate::Entry::Occupied(entry) => {
213 match entry.into_mut() {
214 // if [a.b.c] header preceded [a.b]
215 Item::Table(ref mut t) if t.implicit => {
216 std::mem::swap(t, &mut table);
217 }
218 _ => return Err(CustomError::duplicate_key(&path, path.len() - 1)),
219 }
220 }
221 crate::Entry::Vacant(entry) => {
222 let item = Item::Table(table);
223 entry.insert(item);
224 }
225 }
226 }
227
228 Ok(())
229 }
230
231 pub(crate) fn descend_path<'t>(
232 mut table: &'t mut Table,
233 path: &[Key],
234 dotted: bool,
235 ) -> Result<&'t mut Table, CustomError> {
236 for (i, key) in path.iter().enumerate() {
237 let entry = table.entry_format(key).or_insert_with(|| {
238 let mut new_table = Table::new();
239 new_table.set_implicit(true);
240 new_table.set_dotted(dotted);
241
242 Item::Table(new_table)
243 });
244 match *entry {
245 Item::Value(ref v) => {
246 return Err(CustomError::extend_wrong_type(path, i, v.type_name()));
247 }
248 Item::ArrayOfTables(ref mut array) => {
249 debug_assert!(!array.is_empty());
250
251 let index = array.len() - 1;
252 let last_child = array.get_mut(index).unwrap();
253
254 table = last_child;
255 }
256 Item::Table(ref mut sweet_child_of_mine) => {
257 // Since tables cannot be defined more than once, redefining such tables using a
258 // [table] header is not allowed. Likewise, using dotted keys to redefine tables
259 // already defined in [table] form is not allowed.
260 if dotted && !sweet_child_of_mine.is_implicit() {
261 return Err(CustomError::DuplicateKey {
262 key: key.get().into(),
263 table: None,
264 });
265 }
266 table = sweet_child_of_mine;
267 }
268 _ => unreachable!(),
269 }
270 }
271 Ok(table)
272 }
273
274 pub(crate) fn on_std_header(
275 &mut self,
276 path: Vec<Key>,
277 trailing: std::ops::Range<usize>,
278 span: std::ops::Range<usize>,
279 ) -> Result<(), CustomError> {
280 debug_assert!(!path.is_empty());
281
282 self.finalize_table()?;
283 let leading = self
284 .trailing
285 .take()
286 .map(RawString::with_span)
287 .unwrap_or_default();
288 self.start_table(
289 path,
290 Decor::new(leading, RawString::with_span(trailing)),
291 span,
292 )?;
293
294 Ok(())
295 }
296
297 pub(crate) fn on_array_header(
298 &mut self,
299 path: Vec<Key>,
300 trailing: std::ops::Range<usize>,
301 span: std::ops::Range<usize>,
302 ) -> Result<(), CustomError> {
303 debug_assert!(!path.is_empty());
304
305 self.finalize_table()?;
306 let leading = self
307 .trailing
308 .take()
309 .map(RawString::with_span)
310 .unwrap_or_default();
311 self.start_array_table(
312 path,
313 Decor::new(leading, RawString::with_span(trailing)),
314 span,
315 )?;
316
317 Ok(())
318 }
319}
320