• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::key::Key;
2 use crate::parser::error::CustomError;
3 use crate::repr::Decor;
4 use crate::table::TableKeyValue;
5 use crate::{ArrayOfTables, ImDocument, InternalString, Item, RawString, Table};
6 
7 pub(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 
16 impl ParseState {
new() -> Self17     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 
into_document<S>(mut self, raw: S) -> Result<ImDocument<S>, CustomError>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 
on_ws(&mut self, span: std::ops::Range<usize>)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 
on_comment(&mut self, span: std::ops::Range<usize>)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 
on_keyval( &mut self, path: Vec<Key>, mut kv: TableKeyValue, ) -> Result<(), CustomError>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 
start_array_table( &mut self, path: Vec<Key>, decor: Decor, span: std::ops::Range<usize>, ) -> Result<(), CustomError>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 
start_table( &mut self, path: Vec<Key>, decor: Decor, span: std::ops::Range<usize>, ) -> Result<(), CustomError>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 
finalize_table(&mut self) -> Result<(), CustomError>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 
descend_path<'t>( mut table: &'t mut Table, path: &[Key], dotted: bool, ) -> Result<&'t mut Table, CustomError>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                 Item::None => unreachable!(),
269             }
270         }
271         Ok(table)
272     }
273 
on_std_header( &mut self, path: Vec<Key>, trailing: std::ops::Range<usize>, span: std::ops::Range<usize>, ) -> Result<(), CustomError>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 
on_array_header( &mut self, path: Vec<Key>, trailing: std::ops::Range<usize>, span: std::ops::Range<usize>, ) -> Result<(), CustomError>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