Name the fields of the custom table AST
This commit is contained in:
parent
00baf76107
commit
27a70d4024
|
@ -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) => {
|
||||||
|
|
Loading…
Reference in a new issue