@@ -416,10 +416,20 @@ where
416416 if eq ( & self . 0 , "int" ) {
417417 Left ( r#"((?:-?\d+)|(?:\d+))"# . chars ( ) . map ( Ok ) )
418418 } else if eq ( & self . 0 , "float" ) {
419+ // Regex in other implementations has lookaheads. As `regex` crate
420+ // doesn't support them, we use `f32`/`f64` grammar instead:
421+ // https://doc.rust-lang.org/stable/std/primitive.f64.html#grammar
422+ // Provided grammar is a superset of the original one:
423+ // - supports `e` as exponent in addition to `E`
424+ // - supports trailing comma: `1.`
425+ // - supports `inf` and `NaN`
419426 Left (
420- r#"((?=.*\d.*)[-+]?\d*(?:\.(?=\d.*))?\d*(?:\d+[E][+-]?\d+)?)"#
421- . chars ( )
422- . map ( Ok ) ,
427+ "([+-]?(?:inf\
428+ |NaN\
429+ |(?:\\ d+|\\ d+\\ .\\ d*|\\ d*\\ .\\ d+)(?:[eE][+-]?\\ d+)?\
430+ ))"
431+ . chars ( )
432+ . map ( Ok ) ,
423433 )
424434 } else if eq ( & self . 0 , "word" ) {
425435 Left ( r#"([^\s]+)"# . chars ( ) . map ( Ok ) )
@@ -592,6 +602,11 @@ mod spec {
592602 . unwrap_or_else ( |e| panic ! ( "failed: {}" , e) ) ;
593603
594604 assert_eq ! ( expr. as_str( ) , "^(?:a|b) (?:c|d|e)$" ) ;
605+ assert ! ( expr. is_match( "a c" ) ) ;
606+ assert ! ( expr. is_match( "b e" ) ) ;
607+ assert ! ( !expr. is_match( "c e" ) ) ;
608+ assert ! ( !expr. is_match( "a" ) ) ;
609+ assert ! ( !expr. is_match( "a " ) ) ;
595610 }
596611
597612 #[ test]
@@ -600,14 +615,17 @@ mod spec {
600615 Expression :: regex ( "" ) . unwrap_or_else ( |e| panic ! ( "failed: {}" , e) ) ;
601616
602617 assert_eq ! ( expr. as_str( ) , "^$" ) ;
618+ assert ! ( expr. is_match( "" ) ) ;
619+ assert ! ( !expr. is_match( "a" ) ) ;
603620 }
604621
605622 #[ test]
606623 fn escape_regex_characters ( ) {
607- let expr = Expression :: regex ( r"^$[]\(\) {}\\.|?*+" )
624+ let expr = Expression :: regex ( r"^$[]\()\ {}\\.|?*+" )
608625 . unwrap_or_else ( |e| panic ! ( "failed: {}" , e) ) ;
609626
610- assert_eq ! ( expr. as_str( ) , r"^\^\$\[\]\(\)(.*)\\\.\|\?\*\+$" ) ;
627+ assert_eq ! ( expr. as_str( ) , r"^\^\$\[\]\(\)\{\}\\\.\|\?\*\+$" ) ;
628+ assert ! ( expr. is_match( "^$[](){}\\ .|?*+" ) ) ;
611629 }
612630
613631 #[ test]
@@ -616,14 +634,80 @@ mod spec {
616634 . unwrap_or_else ( |e| panic ! ( "failed: {}" , e) ) ;
617635
618636 assert_eq ! ( expr. as_str( ) , "^(?:a)?$" ) ;
637+ assert ! ( expr. is_match( "" ) ) ;
638+ assert ! ( expr. is_match( "a" ) ) ;
639+ assert ! ( !expr. is_match( "b" ) ) ;
619640 }
620641
621642 #[ test]
622- fn parameter ( ) {
643+ fn parameter_int ( ) {
623644 let expr = Expression :: regex ( "{int}" )
624645 . unwrap_or_else ( |e| panic ! ( "failed: {}" , e) ) ;
625646
626647 assert_eq ! ( expr. as_str( ) , "^((?:-?\\ d+)|(?:\\ d+))$" ) ;
648+ assert ! ( expr. is_match( "123" ) ) ;
649+ assert ! ( expr. is_match( "-123" ) ) ;
650+ assert ! ( !expr. is_match( "+123" ) ) ;
651+ assert ! ( !expr. is_match( "123." ) ) ;
652+ }
653+
654+ #[ test]
655+ fn parameter_float ( ) {
656+ let expr = Expression :: regex ( "{float}" )
657+ . unwrap_or_else ( |e| panic ! ( "failed: {}" , e) ) ;
658+
659+ assert_eq ! (
660+ expr. as_str( ) ,
661+ "^([+-]?(?:inf\
662+ |NaN\
663+ |(?:\\ d+|\\ d+\\ .\\ d*|\\ d*\\ .\\ d+)(?:[eE][+-]?\\ d+)?\
664+ ))$",
665+ ) ;
666+ assert ! ( expr. is_match( "+1" ) ) ;
667+ assert ! ( expr. is_match( ".1" ) ) ;
668+ assert ! ( expr. is_match( "-.1" ) ) ;
669+ assert ! ( expr. is_match( "-1." ) ) ;
670+ assert ! ( expr. is_match( "-1.1E+1" ) ) ;
671+ assert ! ( expr. is_match( "-inf" ) ) ;
672+ assert ! ( expr. is_match( "NaN" ) ) ;
673+ }
674+
675+ #[ test]
676+ fn parameter_word ( ) {
677+ let expr = Expression :: regex ( "{word}" )
678+ . unwrap_or_else ( |e| panic ! ( "failed: {}" , e) ) ;
679+
680+ assert_eq ! ( expr. as_str( ) , "^([^\\ s]+)$" ) ;
681+ assert ! ( expr. is_match( "test" ) ) ;
682+ assert ! ( expr. is_match( "\" test\" " ) ) ;
683+ assert ! ( !expr. is_match( "with space" ) ) ;
684+ }
685+
686+ #[ test]
687+ fn parameter_string ( ) {
688+ let expr = Expression :: regex ( "{string}" )
689+ . unwrap_or_else ( |e| panic ! ( "failed: {}" , e) ) ;
690+
691+ assert_eq ! (
692+ expr. as_str( ) ,
693+ r#"^("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)')$"# ,
694+ ) ;
695+ assert ! ( expr. is_match( "\" \" " ) ) ;
696+ assert ! ( expr. is_match( "''" ) ) ;
697+ assert ! ( expr. is_match( "'with \" '" ) ) ;
698+ assert ! ( expr. is_match( "\" with '\" " ) ) ;
699+ assert ! ( expr. is_match( "\" with \\ \" escaped\" " ) ) ;
700+ assert ! ( expr. is_match( "'with \\ ' escaped'" ) ) ;
701+ assert ! ( !expr. is_match( "word" ) ) ;
702+ }
703+
704+ #[ test]
705+ fn parameter_all ( ) {
706+ let expr =
707+ Expression :: regex ( "{}" ) . unwrap_or_else ( |e| panic ! ( "failed: {}" , e) ) ;
708+
709+ assert_eq ! ( expr. as_str( ) , "^(.*)$" ) ;
710+ assert ! ( expr. is_match( "anything matches" ) ) ;
627711 }
628712
629713 #[ test]
@@ -632,6 +716,9 @@ mod spec {
632716 Expression :: regex ( "a" ) . unwrap_or_else ( |e| panic ! ( "failed: {}" , e) ) ;
633717
634718 assert_eq ! ( expr. as_str( ) , "^a$" ) ;
719+ assert ! ( expr. is_match( "a" ) ) ;
720+ assert ! ( !expr. is_match( "b" ) ) ;
721+ assert ! ( !expr. is_match( "ab" ) ) ;
635722 }
636723
637724 #[ allow( clippy:: non_ascii_literal) ]
@@ -641,6 +728,9 @@ mod spec {
641728 . unwrap_or_else ( |e| panic ! ( "failed: {}" , e) ) ;
642729
643730 assert_eq ! ( expr. as_str( ) , "^Привет, Мир(?:ы)?!$" ) ;
731+ assert ! ( expr. is_match( "Привет, Мир!" ) ) ;
732+ assert ! ( expr. is_match( "Привет, Миры!" ) ) ;
733+ assert ! ( !expr. is_match( "Hello world" ) ) ;
644734 }
645735
646736 #[ test]
0 commit comments