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