diff --git a/src/lib.rs b/src/lib.rs index 2c8163d..be76c50 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,4 +3,5 @@ pub mod comments; pub mod identifiers; pub mod numbers; pub mod operators; +pub mod strings; pub mod util; diff --git a/src/strings.rs b/src/strings.rs new file mode 100644 index 0000000..21cccc3 --- /dev/null +++ b/src/strings.rs @@ -0,0 +1,54 @@ +use nom::bytes::complete::*; +use nom::combinator::*; +use nom::multi::*; +use nom::sequence::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +#[derive(Debug)] +pub struct StringLiteral<'a> { + pub raw: Vec<&'a str>, +} + +// ----------------------------------------------------------------------------- + +pub fn string_literal(s: &str) -> IResult<&str, StringLiteral> { + let (s, _) = tag("\"")(s)?; + let (s, x) = many1(pair(is_not("\\\""), opt(pair(tag("\\"), take(1usize)))))(s)?; + let (s, _) = tag("\"")(s)?; + + let mut raw = Vec::new(); + for (x, y) in x { + raw.push(x); + if let Some((y, z)) = y { + raw.push(y); + raw.push(z); + } + } + + Ok((s, StringLiteral { raw })) +} + +// ----------------------------------------------------------------------------- + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + assert_eq!( + format!("{:?}", all_consuming(string_literal)("\"aaa aaaa\"")), + "Ok((\"\", StringLiteral { raw: [\"aaa aaaa\"] }))" + ); + assert_eq!( + format!("{:?}", all_consuming(string_literal)(r#""aaa\" aaaa""#)), + "Ok((\"\", StringLiteral { raw: [\"aaa\", \"\\\\\", \"\\\"\", \" aaaa\"] }))" + ); + assert_eq!( + format!("{:?}", all_consuming(string_literal)(r#""aaa\"""#)), + "Ok((\"\", StringLiteral { raw: [\"aaa\", \"\\\\\", \"\\\"\"] }))" + ); + } +}