blob: eec26d69559dea88f8b3a9350e53aa8722cedc33 [file] [log] [blame]
David Tolnay86eca752016-09-04 11:26:41 -07001#![cfg(feature = "parsing")]
2
David Tolnayb79ee962016-09-04 09:39:20 -07003use nom::{self, IResult};
4
5macro_rules! punct {
6 ($i:expr, $punct:expr) => {
David Tolnayf6ccb832016-09-04 15:00:56 -07007 complete!($i, preceded!(opt!(call!(::nom::multispace)), tag_s!($punct)))
David Tolnayb79ee962016-09-04 09:39:20 -07008 };
9}
10
David Tolnayf6ccb832016-09-04 15:00:56 -070011macro_rules! option (
12 ($i:expr, $submac:ident!( $($args:tt)* )) => ({
13 match $submac!($i, $($args)*) {
14 ::nom::IResult::Done(i, o) => ::nom::IResult::Done(i, Some(o)),
15 ::nom::IResult::Error(_) => ::nom::IResult::Done($i, None),
16 ::nom::IResult::Incomplete(_) => ::nom::IResult::Done($i, None),
17 }
18 });
19 ($i:expr, $f:expr) => (
20 option!($i, call!($f));
21 );
22);
23
David Tolnayb79ee962016-09-04 09:39:20 -070024macro_rules! opt_vec (
25 ($i:expr, $submac:ident!( $($args:tt)* )) => ({
26 match $submac!($i, $($args)*) {
27 ::nom::IResult::Done(i, o) => ::nom::IResult::Done(i, o),
28 ::nom::IResult::Error(_) => ::nom::IResult::Done($i, Vec::new()),
David Tolnayf6ccb832016-09-04 15:00:56 -070029 ::nom::IResult::Incomplete(_) => ::nom::IResult::Done($i, Vec::new()),
David Tolnayb79ee962016-09-04 09:39:20 -070030 }
31 });
32);
33
34macro_rules! epsilon {
35 ($i:expr,) => {
36 call!($i, {
37 fn epsilon<T>(input: T) -> ::nom::IResult<T, ()> {
38 ::nom::IResult::Done(input, ())
39 }
40 epsilon
41 })
42 };
43}
44
45pub fn escaped_string(input: &str) -> IResult<&str, String> {
46 let mut s = String::new();
47 let mut chars = input.char_indices().peekable();
48 while let Some((byte_offset, ch)) = chars.next() {
49 match ch {
50 '"' => {
51 return IResult::Done(&input[byte_offset..], s);
52 }
53 '\\' => {
54 match chars.next() {
55 Some((_, 'x')) => unimplemented!(),
56 Some((_, 'u')) => unimplemented!(),
57 Some((_, 'n')) => s.push('\n'),
58 Some((_, 'r')) => s.push('\r'),
59 Some((_, 't')) => s.push('\t'),
60 Some((_, '0')) => s.push('\0'),
61 Some((_, '\\')) => s.push('\\'),
62 Some((_, '\n')) => {
63 while let Some(&(_, ch)) = chars.peek() {
64 if ch.is_whitespace() {
65 chars.next();
66 } else {
67 break;
68 }
69 }
70 }
71 _ => break,
72 }
73 }
74 ch => {
75 s.push(ch);
76 }
77 }
78 }
79 IResult::Error(nom::Err::Position(nom::ErrorKind::Escaped, input))
80}