blob: 5299cc4e6c62857e1fc62a1ff98d93bf92c757bf [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use nom::{self, IResult};
2
3macro_rules! punct {
4 ($i:expr, $punct:expr) => {
5 tuple!($i, opt!(call!(::nom::multispace)), tag_s!($punct))
6 };
7}
8
9macro_rules! opt_vec (
10 ($i:expr, $submac:ident!( $($args:tt)* )) => ({
11 match $submac!($i, $($args)*) {
12 ::nom::IResult::Done(i, o) => ::nom::IResult::Done(i, o),
13 ::nom::IResult::Error(_) => ::nom::IResult::Done($i, Vec::new()),
14 ::nom::IResult::Incomplete(i) => ::nom::IResult::Incomplete(i)
15 }
16 });
17);
18
19macro_rules! epsilon {
20 ($i:expr,) => {
21 call!($i, {
22 fn epsilon<T>(input: T) -> ::nom::IResult<T, ()> {
23 ::nom::IResult::Done(input, ())
24 }
25 epsilon
26 })
27 };
28}
29
30pub fn escaped_string(input: &str) -> IResult<&str, String> {
31 let mut s = String::new();
32 let mut chars = input.char_indices().peekable();
33 while let Some((byte_offset, ch)) = chars.next() {
34 match ch {
35 '"' => {
36 return IResult::Done(&input[byte_offset..], s);
37 }
38 '\\' => {
39 match chars.next() {
40 Some((_, 'x')) => unimplemented!(),
41 Some((_, 'u')) => unimplemented!(),
42 Some((_, 'n')) => s.push('\n'),
43 Some((_, 'r')) => s.push('\r'),
44 Some((_, 't')) => s.push('\t'),
45 Some((_, '0')) => s.push('\0'),
46 Some((_, '\\')) => s.push('\\'),
47 Some((_, '\n')) => {
48 while let Some(&(_, ch)) = chars.peek() {
49 if ch.is_whitespace() {
50 chars.next();
51 } else {
52 break;
53 }
54 }
55 }
56 _ => break,
57 }
58 }
59 ch => {
60 s.push(ch);
61 }
62 }
63 }
64 IResult::Error(nom::Err::Position(nom::ErrorKind::Escaped, input))
65}