Name the fields of the custom table AST

This commit is contained in:
Alex Crichton 2015-06-08 00:03:36 -07:00
parent 00baf76107
commit 27a70d4024

View file

@ -9,8 +9,8 @@ macro_rules! try {
($e:expr) => (match $e { Some(s) => s, None => return None }) ($e:expr) => (match $e { Some(s) => s, None => return None })
} }
// We redefine Array, Table and Value, because we need to keep track of // We redefine Value because we need to keep track of encountered table
// encountered table definitions, eg when parsing: // definitions, eg when parsing:
// //
// [a] // [a]
// [a.b] // [a.b]
@ -19,11 +19,14 @@ macro_rules! try {
// we have to error out on redefinition of [a]. This bit of data is difficult to // we have to error out on redefinition of [a]. This bit of data is difficult to
// track in a side table so we just have a "stripped down" AST to work with // track in a side table so we just have a "stripped down" AST to work with
// which has the relevant metadata fields in it. // which has the relevant metadata fields in it.
struct TomlTable(BTreeMap<String, Value>, bool); struct TomlTable {
values: BTreeMap<String, Value>,
defined: bool,
}
impl TomlTable { impl TomlTable {
fn convert(self) -> super::Table { fn convert(self) -> super::Table {
self.0.into_iter().map(|(k,v)| (k,v.convert())).collect() self.values.into_iter().map(|(k,v)| (k, v.convert())).collect()
} }
} }
@ -230,7 +233,7 @@ impl<'a> Parser<'a> {
/// If an error occurs, the `errors` field of this parser can be consulted /// If an error occurs, the `errors` field of this parser can be consulted
/// to determine the cause of the parse failure. /// to determine the cause of the parse failure.
pub fn parse(&mut self) -> Option<super::Table> { pub fn parse(&mut self) -> Option<super::Table> {
let mut ret = TomlTable(BTreeMap::new(), false); let mut ret = TomlTable { values: BTreeMap::new(), defined: false };
while self.peek(0).is_some() { while self.peek(0).is_some() {
self.ws(); self.ws();
if self.newline() { continue } if self.newline() { continue }
@ -256,7 +259,10 @@ impl<'a> Parser<'a> {
if keys.len() == 0 { return None } if keys.len() == 0 { return None }
// Build the section table // Build the section table
let mut table = TomlTable(BTreeMap::new(), true); let mut table = TomlTable {
values: BTreeMap::new(),
defined: true,
};
if !self.values(&mut table) { return None } if !self.values(&mut table) { return None }
if array { if array {
self.insert_array(&mut ret, &keys, Value::Table(table), self.insert_array(&mut ret, &keys, Value::Table(table),
@ -771,7 +777,7 @@ impl<'a> Parser<'a> {
fn inline_table(&mut self, _start: usize) -> Option<Value> { fn inline_table(&mut self, _start: usize) -> Option<Value> {
if !self.expect('{') { return None } if !self.expect('{') { return None }
self.ws(); self.ws();
let mut ret = TomlTable(BTreeMap::new(), true); let mut ret = TomlTable { values: BTreeMap::new(), defined: true };
if self.eat('}') { return Some(Value::Table(ret)) } if self.eat('}') { return Some(Value::Table(ret)) }
loop { loop {
let lo = self.next_pos(); let lo = self.next_pos();
@ -790,14 +796,14 @@ impl<'a> Parser<'a> {
fn insert(&mut self, into: &mut TomlTable, key: String, value: Value, fn insert(&mut self, into: &mut TomlTable, key: String, value: Value,
key_lo: usize) { key_lo: usize) {
if into.0.contains_key(&key) { if into.values.contains_key(&key) {
self.errors.push(ParserError { self.errors.push(ParserError {
lo: key_lo, lo: key_lo,
hi: key_lo + key.len(), hi: key_lo + key.len(),
desc: format!("duplicate key: `{}`", key), desc: format!("duplicate key: `{}`", key),
}) })
} else { } else {
into.0.insert(key, value); into.values.insert(key, value);
} }
} }
@ -807,8 +813,8 @@ impl<'a> Parser<'a> {
for part in keys[..keys.len() - 1].iter() { for part in keys[..keys.len() - 1].iter() {
let tmp = cur; let tmp = cur;
if tmp.0.contains_key(part) { if tmp.values.contains_key(part) {
match *tmp.0.get_mut(part).unwrap() { match *tmp.values.get_mut(part).unwrap() {
Value::Table(ref mut table) => cur = table, Value::Table(ref mut table) => cur = table,
Value::Array(ref mut array) => { Value::Array(ref mut array) => {
match array.last_mut() { match array.last_mut() {
@ -838,8 +844,11 @@ impl<'a> Parser<'a> {
} }
// Initialize an empty table as part of this sub-key // Initialize an empty table as part of this sub-key
tmp.0.insert(part.clone(), Value::Table(TomlTable(BTreeMap::new(), false))); tmp.values.insert(part.clone(), Value::Table(TomlTable {
match *tmp.0.get_mut(part).unwrap() { values: BTreeMap::new(),
defined: false,
}));
match *tmp.values.get_mut(part).unwrap() {
Value::Table(ref mut inner) => cur = inner, Value::Table(ref mut inner) => cur = inner,
_ => unreachable!(), _ => unreachable!(),
} }
@ -848,25 +857,25 @@ impl<'a> Parser<'a> {
} }
fn insert_table(&mut self, into: &mut TomlTable, keys: &[String], fn insert_table(&mut self, into: &mut TomlTable, keys: &[String],
value: TomlTable, key_lo: usize) { table: TomlTable, key_lo: usize) {
let (into, key) = match self.recurse(into, keys, key_lo) { let (into, key) = match self.recurse(into, keys, key_lo) {
Some(pair) => pair, Some(pair) => pair,
None => return, None => return,
}; };
if !into.0.contains_key(key) { if !into.values.contains_key(key) {
into.0.insert(key.to_owned(), Value::Table(value)); into.values.insert(key.to_owned(), Value::Table(table));
return return
} }
if let Value::Table(ref mut table) = *into.0.get_mut(key).unwrap() { if let Value::Table(ref mut into) = *into.values.get_mut(key).unwrap() {
if table.1 { if into.defined {
self.errors.push(ParserError { self.errors.push(ParserError {
lo: key_lo, lo: key_lo,
hi: key_lo + key.len(), hi: key_lo + key.len(),
desc: format!("redefinition of table `{}`", key), desc: format!("redefinition of table `{}`", key),
}); });
} }
for (k, v) in value.0 { for (k, v) in table.values {
if table.0.insert(k.clone(), v).is_some() { if into.values.insert(k.clone(), v).is_some() {
self.errors.push(ParserError { self.errors.push(ParserError {
lo: key_lo, lo: key_lo,
hi: key_lo + key.len(), hi: key_lo + key.len(),
@ -889,10 +898,10 @@ impl<'a> Parser<'a> {
Some(pair) => pair, Some(pair) => pair,
None => return, None => return,
}; };
if !into.0.contains_key(key) { if !into.values.contains_key(key) {
into.0.insert(key.to_owned(), Value::Array(Vec::new())); into.values.insert(key.to_owned(), Value::Array(Vec::new()));
} }
match *into.0.get_mut(key).unwrap() { match *into.values.get_mut(key).unwrap() {
Value::Array(ref mut vec) => { Value::Array(ref mut vec) => {
match vec.first() { match vec.first() {
Some(ref v) if !v.same_type(&value) => { Some(ref v) if !v.same_type(&value) => {