@@ -379,68 +379,46 @@ pub fn try_read_string(input: &str) -> IResult<&str, Value> {
379
379
380
380
let ( rest_input, _) = quotation ( input) ?;
381
381
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
+
382
393
named ! (
383
394
string_parser<& str , String >,
384
395
map!(
385
- terminated!( take_until! ( " \" " ) , tag( "\" " ) ) ,
396
+ terminated!( escaped_string_parser , tag( "\" " ) ) ,
386
397
|v| String :: from( v)
387
398
)
388
399
) ;
389
400
390
401
to_value_parser ( string_parser) ( rest_input)
391
402
}
392
403
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")
397
404
pub 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" ) ; }
434
417
}
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 ( ) ;
442
420
Ok ( (
443
- rest_input. trim_start_matches ( & to_trim ) ,
421
+ rest_input,
444
422
Value :: Pattern ( regex) ,
445
423
) )
446
424
}
@@ -921,7 +899,50 @@ mod tests {
921
899
}
922
900
}
923
901
}
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
+ }
924
937
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
+ }
925
946
mod consume_clojure_whitespaces_tests {
926
947
use crate :: reader:: consume_clojure_whitespaces_parser;
927
948
#[ test]
0 commit comments