Raw string literals
diff --git a/src/escape.rs b/src/escape.rs
index c3b208a..3ff52e3 100644
--- a/src/escape.rs
+++ b/src/escape.rs
@@ -3,7 +3,7 @@
use std::{char, str};
use nom::IResult;
-pub fn escaped_string(input: &str) -> IResult<&str, String> {
+pub fn cooked_string(input: &str) -> IResult<&str, String> {
let mut s = String::new();
let mut chars = input.char_indices().peekable();
while let Some((byte_offset, ch)) = chars.next() {
@@ -48,6 +48,29 @@
IResult::Error
}
+pub fn raw_string(input: &str) -> IResult<&str, (String, usize)> {
+ let mut chars = input.char_indices();
+ let mut n = 0;
+ while let Some((byte_offset, ch)) = chars.next() {
+ match ch {
+ '"' => {
+ n = byte_offset;
+ break;
+ }
+ '#' => {},
+ _ => return IResult::Error,
+ }
+ }
+ while let Some((byte_offset, ch)) = chars.next() {
+ if ch == '"' && input[byte_offset + 1..].starts_with(&input[..n]) {
+ let rest = &input[byte_offset + 1 + n..];
+ let value = &input[n + 1 .. byte_offset];
+ return IResult::Done(rest, (value.to_owned(), n));
+ }
+ }
+ IResult::Error
+}
+
macro_rules! next_char {
($chars:ident @ $pat:pat $(| $rest:pat)*) => {
match $chars.next() {
@@ -101,8 +124,8 @@
}
#[test]
-fn test_escaped_string() {
+fn test_cooked_string() {
let input = r#"\x62 \u{7} \u{64} \u{bf5} \u{12ba} \u{1F395} \u{102345}""#;
let expected = "\x62 \u{7} \u{64} \u{bf5} \u{12ba} \u{1F395} \u{102345}";
- assert_eq!(escaped_string(input), IResult::Done("\"", expected.to_string()));
+ assert_eq!(cooked_string(input), IResult::Done("\"", expected.to_string()));
}
diff --git a/src/lit.rs b/src/lit.rs
index 3cc773f..456b3c6 100644
--- a/src/lit.rs
+++ b/src/lit.rs
@@ -54,12 +54,12 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
- use escape::escaped_string;
+ use escape::{cooked_string, raw_string};
use helper::eat_spaces;
use nom::IResult;
named!(pub lit -> Lit, alt!(
- quoted => { |q| Lit::Str(q, StrStyle::Cooked) }
+ string
// TODO: ByteStr
// TODO: Byte
// TODO: Char
@@ -69,10 +69,17 @@
// TODO: Bool
));
- named!(quoted -> String, delimited!(
- punct!("\""),
- escaped_string,
- tag!("\"")
+ named!(string -> Lit, alt!(
+ delimited!(
+ punct!("\""),
+ cooked_string,
+ tag!("\"")
+ ) => { |s| Lit::Str(s, StrStyle::Cooked) }
+ |
+ preceded!(
+ punct!("r"),
+ raw_string
+ ) => { |(s, n)| Lit::Str(s, StrStyle::Raw(n)) }
));
named!(pub int -> (u64, IntTy), tuple!(