diff options
author | Alex Crichton <alex@alexcrichton.com> | 2016-01-24 10:50:39 -0800 |
---|---|---|
committer | Alex Crichton <alex@alexcrichton.com> | 2016-01-24 10:50:39 -0800 |
commit | 6b0a1362a161a2fe5574f66843e11ee54af28b7d (patch) | |
tree | ef87e4570d16c4b3382039f1a3ff76ab894bcf24 | |
parent | 5431cade31dc754786ccce329d2db1e6ec14d4e1 (diff) | |
download | milf-rs-6b0a1362a161a2fe5574f66843e11ee54af28b7d.tar.gz milf-rs-6b0a1362a161a2fe5574f66843e11ee54af28b7d.zip |
Support literal strings in table names
Closes #85
-rw-r--r-- | src/parser.rs | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/src/parser.rs b/src/parser.rs index 38edd20..185f325 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -294,7 +294,9 @@ impl<'a> Parser<'a> { fn key_name(&mut self) -> Option<String> { let start = self.next_pos(); 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 { let mut ret = String::new(); while let Some((_, ch)) = self.cur.clone().next() { @@ -363,7 +365,7 @@ impl<'a> Parser<'a> { fn value(&mut self) -> Option<Value> { self.ws(); match self.cur.clone().next() { - Some((pos, '"')) => self.string(pos), + Some((pos, '"')) => self.basic_string(pos), Some((pos, '\'')) => self.literal_string(pos), Some((pos, 't')) | Some((pos, 'f')) => self.boolean(pos), @@ -387,7 +389,7 @@ impl<'a> Parser<'a> { } // 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 } let mut multiline = false; @@ -403,13 +405,13 @@ 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 - fn finish_string(&mut self, - start: usize, - multiline: bool) -> Option<String> { + fn finish_basic_string(&mut self, + start: usize, + multiline: bool) -> Option<String> { let mut ret = String::new(); loop { while multiline && self.newline() { ret.push('\n') } @@ -516,7 +518,6 @@ impl<'a> Parser<'a> { fn literal_string(&mut self, start: usize) -> Option<Value> { if !self.expect('\'') { return None } let mut multiline = false; - let mut ret = String::new(); // detect multiline literals if self.eat('\'') { @@ -524,10 +525,16 @@ impl<'a> Parser<'a> { multiline = true; self.newline(); } 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 { if !multiline && self.newline() { 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 } } - break + return Some(ret) } Some((_, ch)) => ret.push(ch), None => { @@ -557,8 +564,6 @@ impl<'a> Parser<'a> { } } } - - Some(Value::String(ret)) } fn number_or_datetime(&mut self, start: usize) -> Option<Value> { @@ -1231,7 +1236,7 @@ trimmed in raw strings. \"a^b\" = 3 \"\\\"\" = 3 \"character encoding\" = \"value\" - \"ʎǝʞ\" = \"value\" + 'ʎǝʞ' = \"value\" "); let table = Table(p.parse().unwrap()); assert!(table.lookup("foo").is_some()); @@ -1269,6 +1274,11 @@ trimmed in raw strings. assert!(Parser::new("[!]").parse().is_none()); assert!(Parser::new("[\"\n\"]").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] @@ -1278,11 +1288,14 @@ trimmed in raw strings. [\"f f\"] [\"f.f\"] [\"\\\"\"] + ['a.a'] + ['\"\"'] "); let table = Table(p.parse().unwrap()); assert!(table.lookup("a.b").is_some()); assert!(table.lookup("f f").is_some()); assert!(table.lookup("\"").is_some()); + assert!(table.lookup("\"\"").is_some()); } #[test] |