From acdb24ba5debeff0efe0a6be8279e953d5f3c102 Mon Sep 17 00:00:00 2001 From: Caleb Jones Date: Sat, 24 Dec 2016 21:06:10 -0500 Subject: [PATCH] Parse strings --- src/lib.rs | 63 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 85c3594..b4aba8c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -77,6 +77,7 @@ use ParseResult::*; pub enum ParseError where Loc: Span { /// We can't explain how the parsing failed. UnexpectedEof, + String(Box, Loc), Symbol(Box, Loc), Number(Box, Loc), Unexpected(char, Loc::Begin), @@ -144,7 +145,7 @@ pub fn parse_number(input: &str, start_loc: usize) -> ParseResult { return Error(ParseError::Number( - Box::new(ParseError::Unexpected(c, 0)), + Box::new(ParseError::Unexpected(c, start_loc)), (0, c.len_utf8()).offset(start_loc))); } None => return Error(ParseError::Number( @@ -171,7 +172,7 @@ pub fn parse_number(input: &str, start_loc: usize) -> ParseResult ParseResult ParseResult ParseResult { + let end_of_white = if let Some(pos) = input.find(|c: char| !c.is_whitespace()) { + pos + } else { + return Error(ParseError::String( + Box::new(ParseError::UnexpectedEof), + (input.len(), input.len()).offset(start_loc))); + }; + + let input = &input[end_of_white..]; + let start_loc = start_loc + end_of_white; + + match input.chars().next() { + Some('"') => (), + Some(c) => + return Error(ParseError::String( + Box::new(ParseError::Unexpected(c, start_loc)), + (0, 0).offset(start_loc))), + None => unreachable!(), + } + + for (i, c) in input[1..].char_indices() { + if c == '"' { + return Done(&input[2+i..], + Sexp::Str(input[1..i+1].into(), (0, i+2).offset(start_loc))); + } + } + + Error(ParseError::String( + Box::new(ParseError::UnexpectedEof), + (0, input.len()).offset(start_loc))) +} + // Tests /////////////////////////////////////////////////////////////////////// @@ -281,20 +315,17 @@ mod test { assert_eq!(parse_symbol("0", 0), Error(ParseError::Symbol(Box::new(ParseError::Unexpected('0', 0)), (0, 0)))); assert_eq!(parse_symbol("()", 0), Error(ParseError::Symbol(Box::new(ParseError::Unexpected('(', 0)), (0, 0)))); } -} - -// #[cfg(test)] - -// #[cfg(test)] -// #[test] -// fn test_parse_string() { -// assert_eq!(string(r#""hello""#), IResult::Done("", Sexp::Str("hello".into()))); -// assert_eq!(string(r#" "this is a nice string -// with 0123 things in it""#), -// IResult::Done("", Sexp::Str("this is a nice string\nwith 0123 things in it".into()))); -// assert!(string(r#""hi"#).is_err()); -// } + #[test] + fn test_parse_string() { + assert_eq!(parse_string(r#""""#, 0), Done("", Sexp::Str("".into(), (0, 2)))); + assert_eq!(parse_string(r#""hello""#, 0), Done("", Sexp::Str("hello".into(), (0, 7)))); + assert_eq!(parse_string(r#" "this is a nice string +with 0123 things in it""#, 0), + Done("", Sexp::Str("this is a nice string\nwith 0123 things in it".into(), (2, 48)))); + assert_eq!(parse_string(r#""hi"#, 0), Error(ParseError::String(Box::new(ParseError::UnexpectedEof), (0, 3)))); + } +} // #[cfg(test)] // #[test] -- 2.47.0