aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-02-07 22:01:13 -0800
committerAlex Crichton <alex@alexcrichton.com>2015-02-07 22:02:32 -0800
commit95085dba9a98a8e9ff2280945d6aede5e7de9fec (patch)
tree9648de6120d3c2330c2f84e67aa5440995f7f0aa /src
parent00420259044e9e961b9d8a80e5482ffc58250145 (diff)
downloadmilf-rs-95085dba9a98a8e9ff2280945d6aede5e7de9fec.tar.gz
milf-rs-95085dba9a98a8e9ff2280945d6aede5e7de9fec.zip
Implement parsing of inline tables
Diffstat (limited to 'src')
-rw-r--r--src/parser.rs48
1 files changed, 46 insertions, 2 deletions
diff --git a/src/parser.rs b/src/parser.rs
index 723ac3a..13044e3 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -257,8 +257,7 @@ impl<'a> Parser<'a> {
Some(s) => s,
None => return false
};
- self.ws();
- if !self.expect('=') { return false }
+ if !self.keyval_sep() { return false }
let value = match self.value() {
Some(value) => value,
None => return false,
@@ -271,6 +270,13 @@ impl<'a> Parser<'a> {
return true
}
+ fn keyval_sep(&mut self) -> bool {
+ self.ws();
+ if !self.expect('=') { return false }
+ self.ws();
+ true
+ }
+
// Parses a value
fn value(&mut self) -> Option<Value> {
self.ws();
@@ -280,6 +286,7 @@ impl<'a> Parser<'a> {
Some((pos, 't')) |
Some((pos, 'f')) => self.boolean(pos),
Some((pos, '[')) => self.array(pos),
+ Some((pos, '{')) => self.inline_table(pos),
Some((pos, '-')) |
Some((pos, '+')) => self.number_or_datetime(pos),
Some((pos, ch)) if is_digit(ch) => self.number_or_datetime(pos),
@@ -667,6 +674,26 @@ impl<'a> Parser<'a> {
return Some(Array(ret))
}
+ fn inline_table(&mut self, _start: usize) -> Option<Value> {
+ if !self.expect('{') { return None }
+ self.ws();
+ let mut ret = BTreeMap::new();
+ if self.eat('}') { return Some(Table(ret)) }
+ loop {
+ let lo = self.next_pos();
+ let key = match self.key_name() { Some(s) => s, None => return None };
+ if !self.keyval_sep() { return None }
+ let value = match self.value() { Some(v) => v, None => return None };
+ self.insert(&mut ret, key, value, lo);
+
+ self.ws();
+ if self.eat('}') { break }
+ if !self.expect(',') { return None }
+ self.ws();
+ }
+ return Some(Table(ret))
+ }
+
fn insert(&mut self, into: &mut TomlTable, key: String, value: Value,
key_lo: usize) {
if into.contains_key(&key) {
@@ -1149,4 +1176,21 @@ trimmed in raw strings.
fn invalid_bare_numeral() {
assert!(Parser::new("4").parse().is_none());
}
+
+ #[test]
+ fn inline_tables() {
+ assert!(Parser::new("a = {}").parse().is_some());
+ assert!(Parser::new("a = {b=1}").parse().is_some());
+ assert!(Parser::new("a = { b = 1 }").parse().is_some());
+ assert!(Parser::new("a = {a=1,b=2}").parse().is_some());
+ assert!(Parser::new("a = {a=1,b=2,c={}}").parse().is_some());
+ assert!(Parser::new("a = {a=1,}").parse().is_none());
+ assert!(Parser::new("a = {,}").parse().is_none());
+ assert!(Parser::new("a = {a=1,a=1}").parse().is_none());
+ assert!(Parser::new("a = {\n}").parse().is_none());
+ assert!(Parser::new("a = {").parse().is_none());
+ assert!(Parser::new("a = {a=[\n]}").parse().is_some());
+ assert!(Parser::new("a = {\"a\"=[\n]}").parse().is_some());
+ assert!(Parser::new("a = [\n{},\n{},\n]").parse().is_some());
+ }
}