@@ -379,68 +379,46 @@ pub fn try_read_string(input: &str) -> IResult<&str, Value> {
379379
380380 let ( rest_input, _) = quotation ( input) ?;
381381
382+ named ! ( escaped_string_parser<& str , String >, escaped_transform!( take_till1!( |ch| { ch == '\\' || ch == '\"' } ) , '\\' , alt!(
383+ tag!( "t" ) => { |_| "\t " } |
384+ tag!( "b" ) => { |_| "\x08 " } |
385+ tag!( "n" ) => { |_| "\n " } |
386+ tag!( "r" ) => { |_| "\r " } |
387+ tag!( "f" ) => { |_| "\x0C " } |
388+ tag!( "'" ) => { |_| "'" } |
389+ tag!( "\" " ) => { |_| "\" " } |
390+ tag!( "\\ " ) => { |_| "\\ " }
391+ ) ) ) ;
392+
382393 named ! (
383394 string_parser<& str , String >,
384395 map!(
385- terminated!( take_until! ( " \" " ) , tag( "\" " ) ) ,
396+ terminated!( escaped_string_parser , tag( "\" " ) ) ,
386397 |v| String :: from( v)
387398 )
388399 ) ;
389400
390401 to_value_parser ( string_parser) ( rest_input)
391402}
392403
393- /// Tries to parse &str into Value::Pattern
394- /// Reader Macro for Regex
395- /// Example Successes:
396- /// #"this is pretty straightforward" => Value::Pattern("this is pretty straightforward")
397404pub fn try_read_pattern ( input : & str ) -> IResult < & str , Value > {
398- named ! ( hash_quotation<& str , & str >, preceded!( consume_clojure_whitespaces_parser, tag!( "#\" " ) ) ) ;
399-
400- let ( rest_input, _) = hash_quotation ( input) ?;
401-
402- // println!("regexquoted: {:#?}", regex::Regex::quote(rest_input));
403- let mut iterator = rest_input. escape_default ( ) ;
404- let mut prev: char = iterator. next ( ) . unwrap ( ) ;
405- let mut prev_prev_was_escape = false ;
406- let mut is_escaping = false ;
407- let mut till_quote: String = String :: from ( prev. to_string ( ) ) ;
408- println ! ( "first char: {:#?}" , till_quote) ;
409- while let ch = iterator. next ( ) . unwrap ( ) {
410- if ch == '\\' && prev == '\\' {
411- is_escaping = true ;
412- }
413- println ! (
414- "LOOP: next char to handle: {:#?} prev: {:#?} is escaping {} and prev prev was escaping {}" ,
415- ch, prev, is_escaping, prev_prev_was_escape
416- ) ;
417- if ch == '\"' && prev == '\\' && !prev_prev_was_escape {
418- println ! (
419- "GONNA END: next char to handle: {:#?} prev: {:#?} is escaping {}" ,
420- ch, prev, is_escaping
421- ) ;
422- till_quote = till_quote. trim_end_matches ( "\" " ) . to_string ( ) ;
423- break ;
424- } ;
425- if ch == '\"' && is_escaping {
426- till_quote = String :: from ( till_quote + ch. to_string ( ) . as_str ( ) ) ;
427- } else if ch != '\\' {
428- till_quote = String :: from ( till_quote + ch. to_string ( ) . as_str ( ) ) ;
429- //is_escaping = false;
430- prev_prev_was_escape = false ;
431- }
432- prev_prev_was_escape = is_escaping;
433- prev = ch;
405+ named ! ( hash_parser<& str , & str >, preceded!( consume_clojure_whitespaces_parser, tag!( "#" ) ) ) ;
406+
407+ let ( rest_input, _) = hash_parser ( input) ?;
408+ let ( rest_input, regex_string_val) = try_read_string ( rest_input) ?;
409+
410+ let mut regex_string = String :: from ( "" ) ;
411+
412+ // @TODO separate try_read_string into a parser, so we don't have to read a Value
413+ // and then unwrap it
414+ match regex_string_val {
415+ Value :: String ( reg_str) => { regex_string = reg_str; } ,
416+ _ => { panic ! ( "try_read_string returned something that wasn't string" ) ; }
434417 }
435- println ! ( "till quote: {} {:#?}" , till_quote, till_quote) ;
436- let to_trim = till_quote. to_owned ( ) + "\" " ;
437- println ! (
438- "rest input trimmed: {}" ,
439- rest_input. trim_start_matches( & to_trim)
440- ) ;
441- let regex = regex:: Regex :: new ( till_quote. as_str ( ) ) . unwrap ( ) ;
418+
419+ let regex = regex:: Regex :: new ( regex_string. as_str ( ) ) . unwrap ( ) ;
442420 Ok ( (
443- rest_input. trim_start_matches ( & to_trim ) ,
421+ rest_input,
444422 Value :: Pattern ( regex) ,
445423 ) )
446424}
@@ -921,7 +899,50 @@ mod tests {
921899 }
922900 }
923901 }
902+ mod regex_tests {
903+ use crate :: reader:: try_read;
904+ use crate :: value:: Value ;
905+
906+ #[ test]
907+ fn try_read_simple_regex_pattern_test ( ) {
908+ assert_eq ! (
909+ Value :: Pattern ( regex:: Regex :: new( "a" ) . unwrap( ) ) ,
910+ try_read( r###"#"a" "### ) . ok( ) . unwrap( ) . 1
911+ ) ;
912+ }
913+
914+ #[ test]
915+ fn try_read_regex_pattern_test ( ) {
916+ assert_eq ! (
917+ Value :: Pattern ( regex:: Regex :: new( "hello" ) . unwrap( ) ) ,
918+ try_read( "#\" hello\" " ) . ok( ) . unwrap( ) . 1
919+ ) ;
920+ }
921+
922+ #[ test]
923+ fn try_read_regex_pattern_escaped_quote_test ( ) {
924+ assert_eq ! (
925+ Value :: Pattern ( regex:: Regex :: new( "h\" e\" l\" l\" o\" " ) . unwrap( ) ) ,
926+ try_read( r#"#"h\"e\"l\"l\"o\"" something"# ) . ok( ) . unwrap( ) . 1
927+ ) ;
928+ }
929+
930+ #[ test]
931+ fn try_read_regex_pattern_escaped_quote_prefixed_by_whitespace_test ( ) {
932+ assert_eq ! (
933+ Value :: Pattern ( regex:: Regex :: new( "h\" e\" l\" l \" o" ) . unwrap( ) ) ,
934+ try_read( r#"#"h\"e\"l\"l \"o""# ) . ok( ) . unwrap( ) . 1
935+ ) ;
936+ }
924937
938+ #[ test]
939+ fn try_read_regex_pattern_escaped_quote_suffixed_by_whitespace_test ( ) {
940+ assert_eq ! (
941+ Value :: Pattern ( regex:: Regex :: new( "h\" e\" l\" l \" o" ) . unwrap( ) ) ,
942+ try_read( r#"#"h\"e\"l\" l \"o" something"# ) . ok( ) . unwrap( ) . 1
943+ ) ;
944+ }
945+ }
925946 mod consume_clojure_whitespaces_tests {
926947 use crate :: reader:: consume_clojure_whitespaces_parser;
927948 #[ test]
0 commit comments