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