parent
5431cade31
commit
6b0a1362a1
|
@ -294,7 +294,9 @@ impl<'a> Parser<'a> {
|
||||||
fn key_name(&mut self) -> Option<String> {
|
fn key_name(&mut self) -> Option<String> {
|
||||||
let start = self.next_pos();
|
let start = self.next_pos();
|
||||||
let key = if self.eat('"') {
|
let key = if self.eat('"') {
|
||||||
self.finish_string(start, false)
|
self.finish_basic_string(start, false)
|
||||||
|
} else if self.eat('\'') {
|
||||||
|
self.finish_literal_string(start, false)
|
||||||
} else {
|
} else {
|
||||||
let mut ret = String::new();
|
let mut ret = String::new();
|
||||||
while let Some((_, ch)) = self.cur.clone().next() {
|
while let Some((_, ch)) = self.cur.clone().next() {
|
||||||
|
@ -363,7 +365,7 @@ impl<'a> Parser<'a> {
|
||||||
fn value(&mut self) -> Option<Value> {
|
fn value(&mut self) -> Option<Value> {
|
||||||
self.ws();
|
self.ws();
|
||||||
match self.cur.clone().next() {
|
match self.cur.clone().next() {
|
||||||
Some((pos, '"')) => self.string(pos),
|
Some((pos, '"')) => self.basic_string(pos),
|
||||||
Some((pos, '\'')) => self.literal_string(pos),
|
Some((pos, '\'')) => self.literal_string(pos),
|
||||||
Some((pos, 't')) |
|
Some((pos, 't')) |
|
||||||
Some((pos, 'f')) => self.boolean(pos),
|
Some((pos, 'f')) => self.boolean(pos),
|
||||||
|
@ -387,7 +389,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses a single or multi-line string
|
// Parses a single or multi-line string
|
||||||
fn string(&mut self, start: usize) -> Option<Value> {
|
fn basic_string(&mut self, start: usize) -> Option<Value> {
|
||||||
if !self.expect('"') { return None }
|
if !self.expect('"') { return None }
|
||||||
let mut multiline = false;
|
let mut multiline = false;
|
||||||
|
|
||||||
|
@ -403,11 +405,11 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.finish_string(start, multiline).map(Value::String)
|
self.finish_basic_string(start, multiline).map(Value::String)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish parsing a basic string after the opening quote has been seen
|
// Finish parsing a basic string after the opening quote has been seen
|
||||||
fn finish_string(&mut self,
|
fn finish_basic_string(&mut self,
|
||||||
start: usize,
|
start: usize,
|
||||||
multiline: bool) -> Option<String> {
|
multiline: bool) -> Option<String> {
|
||||||
let mut ret = String::new();
|
let mut ret = String::new();
|
||||||
|
@ -516,7 +518,6 @@ impl<'a> Parser<'a> {
|
||||||
fn literal_string(&mut self, start: usize) -> Option<Value> {
|
fn literal_string(&mut self, start: usize) -> Option<Value> {
|
||||||
if !self.expect('\'') { return None }
|
if !self.expect('\'') { return None }
|
||||||
let mut multiline = false;
|
let mut multiline = false;
|
||||||
let mut ret = String::new();
|
|
||||||
|
|
||||||
// detect multiline literals
|
// detect multiline literals
|
||||||
if self.eat('\'') {
|
if self.eat('\'') {
|
||||||
|
@ -524,10 +525,16 @@ impl<'a> Parser<'a> {
|
||||||
multiline = true;
|
multiline = true;
|
||||||
self.newline();
|
self.newline();
|
||||||
} else {
|
} else {
|
||||||
return Some(Value::String(ret)) // empty
|
return Some(Value::String(String::new())) // empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.finish_literal_string(start, multiline).map(Value::String)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish_literal_string(&mut self, start: usize, multiline: bool)
|
||||||
|
-> Option<String> {
|
||||||
|
let mut ret = String::new();
|
||||||
loop {
|
loop {
|
||||||
if !multiline && self.newline() {
|
if !multiline && self.newline() {
|
||||||
let next = self.next_pos();
|
let next = self.next_pos();
|
||||||
|
@ -544,7 +551,7 @@ impl<'a> Parser<'a> {
|
||||||
if !self.eat('\'') { ret.push_str("'"); continue }
|
if !self.eat('\'') { ret.push_str("'"); continue }
|
||||||
if !self.eat('\'') { ret.push_str("''"); continue }
|
if !self.eat('\'') { ret.push_str("''"); continue }
|
||||||
}
|
}
|
||||||
break
|
return Some(ret)
|
||||||
}
|
}
|
||||||
Some((_, ch)) => ret.push(ch),
|
Some((_, ch)) => ret.push(ch),
|
||||||
None => {
|
None => {
|
||||||
|
@ -557,8 +564,6 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Value::String(ret))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn number_or_datetime(&mut self, start: usize) -> Option<Value> {
|
fn number_or_datetime(&mut self, start: usize) -> Option<Value> {
|
||||||
|
@ -1231,7 +1236,7 @@ trimmed in raw strings.
|
||||||
\"a^b\" = 3
|
\"a^b\" = 3
|
||||||
\"\\\"\" = 3
|
\"\\\"\" = 3
|
||||||
\"character encoding\" = \"value\"
|
\"character encoding\" = \"value\"
|
||||||
\"ʎǝʞ\" = \"value\"
|
'ʎǝʞ' = \"value\"
|
||||||
");
|
");
|
||||||
let table = Table(p.parse().unwrap());
|
let table = Table(p.parse().unwrap());
|
||||||
assert!(table.lookup("foo").is_some());
|
assert!(table.lookup("foo").is_some());
|
||||||
|
@ -1269,6 +1274,11 @@ trimmed in raw strings.
|
||||||
assert!(Parser::new("[!]").parse().is_none());
|
assert!(Parser::new("[!]").parse().is_none());
|
||||||
assert!(Parser::new("[\"\n\"]").parse().is_none());
|
assert!(Parser::new("[\"\n\"]").parse().is_none());
|
||||||
assert!(Parser::new("[a.b]\n[a.\"b\"]").parse().is_none());
|
assert!(Parser::new("[a.b]\n[a.\"b\"]").parse().is_none());
|
||||||
|
assert!(Parser::new("[']").parse().is_none());
|
||||||
|
assert!(Parser::new("[''']").parse().is_none());
|
||||||
|
assert!(Parser::new("['''''']").parse().is_none());
|
||||||
|
assert!(Parser::new("['\n']").parse().is_none());
|
||||||
|
assert!(Parser::new("['\r\n']").parse().is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1278,11 +1288,14 @@ trimmed in raw strings.
|
||||||
[\"f f\"]
|
[\"f f\"]
|
||||||
[\"f.f\"]
|
[\"f.f\"]
|
||||||
[\"\\\"\"]
|
[\"\\\"\"]
|
||||||
|
['a.a']
|
||||||
|
['\"\"']
|
||||||
");
|
");
|
||||||
let table = Table(p.parse().unwrap());
|
let table = Table(p.parse().unwrap());
|
||||||
assert!(table.lookup("a.b").is_some());
|
assert!(table.lookup("a.b").is_some());
|
||||||
assert!(table.lookup("f f").is_some());
|
assert!(table.lookup("f f").is_some());
|
||||||
assert!(table.lookup("\"").is_some());
|
assert!(table.lookup("\"").is_some());
|
||||||
|
assert!(table.lookup("\"\"").is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue