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