Skip to content

Commit a97dce1

Browse files
committed
bugfix end anchor behavior
1 parent e187fd0 commit a97dce1

File tree

4 files changed

+64
-28
lines changed

4 files changed

+64
-28
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
*.mod

project/fortran-regex.depend

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# depslib dependency file v1.0
2-
1671311068 source:/Users/federico/code/fortran-regex/src/regex.f90
2+
1671351900 source:/Users/federico/code/fortran-regex/src/regex.f90
33

44
1671276031 source:/Users/federico/code/fortran-regex/test/test_1.f90
55

@@ -11,5 +11,5 @@
1111

1212
1671123384 source:i:\fortran-regex\test\test_1.f90
1313

14-
1671275983 source:/Users/federico/code/fortran-regex/test/test_2.f90
14+
1671311161 source:/Users/federico/code/fortran-regex/test/test_2.f90
1515

src/regex.f90

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ module regex_module
2121
private
2222

2323
public :: parse_pattern
24+
public :: check_pattern
2425
public :: regex
2526

2627
! Character kind
@@ -108,6 +109,29 @@ module regex_module
108109

109110
contains
110111

112+
! Check that a pattern matches the expected result
113+
logical function check_pattern(string,pattern,expected) result(success)
114+
character(len=*,kind=RCK), intent(in) :: string
115+
character(len=*,kind=RCK), intent(in) :: pattern
116+
character(len=*,kind=RCK), intent(in) :: expected
117+
118+
integer :: idx,length
119+
120+
idx = regex(string,pattern,length)
121+
122+
if (idx>0) then
123+
success = length==len(expected)
124+
if (success) success = string(idx:idx+length-1)==expected
125+
else
126+
success = len(expected)<=0
127+
end if
128+
129+
if (DEBUG .and. .not.success) &
130+
print "('[regex] test FAILED: text=',a,' pattern=',a,' index=',i0,' len=',i0)", &
131+
string,pattern,idx,length
132+
133+
end function check_pattern
134+
111135
! Clean up a pattern
112136
elemental subroutine pat_destroy(this)
113137
class(regex_pattern), intent(inout) :: this
@@ -332,7 +356,6 @@ logical function matchstar(p, pattern, text, it0, matchlength)
332356
it = it-1
333357
if (matchstar) return
334358
matchlength = matchlength-1
335-
336359
end do
337360

338361
matchlength = prelen
@@ -586,24 +609,24 @@ integer function re_matchp_nolength(string, pattern) result(index)
586609
end function re_matchp_nolength
587610

588611

589-
integer function re_matchp(string, pattern, matchlength) result(index)
612+
integer function re_matchp(string, pattern, length) result(index)
590613
type(regex_op), intent(in) :: pattern
591614
character(len=*,kind=RCK), intent(in) :: string
592-
integer, intent(out) :: matchlength
593-
594-
matchlength = 0
615+
integer, intent(out) :: length
595616

596617
if (pattern%n>0) then
597618

598619
if (pattern%pattern(1)%type == BEGIN_WITH) then
599620

600621
! String must begin with this pattern
601-
index = merge(1,0,matchpattern(pattern%pattern(2:), string, matchlength))
622+
length = 0
623+
index = merge(1,0,matchpattern(pattern%pattern(2:), string, length))
602624

603625
else
604626

605627
do index=1,len(string)
606-
if (matchpattern(pattern%pattern,string(index:),matchlength)) return
628+
length = 0
629+
if (matchpattern(pattern%pattern,string(index:),length)) goto 1
607630
end do
608631

609632
index = 0
@@ -616,6 +639,13 @@ integer function re_matchp(string, pattern, matchlength) result(index)
616639

617640
end if
618641

642+
1 if (DEBUG) then
643+
if (index==0) then
644+
print "('[regex] end: pattern not found. ')"
645+
else
646+
print "('[regex] end: pattern found at ',i0,': ',a)", index,string(index:)
647+
end if
648+
end if
619649

620650
end function re_matchp
621651

@@ -651,16 +681,17 @@ logical function matchpattern(pattern, text, matchlength) result(match)
651681

652682
elseif (pattern(ip)%type == END_WITH .and. pattern(ip+1)%type == UNUSED) then
653683

684+
if (DEBUG .and. len(text(it:))>0) print *, '[regex] at end: remaining = ',text(it:),' len=',matchlength
654685

655-
match = len(text(it:))<=1
686+
match = it>len(text)
656687
return
657688

658689
end if
659690

660-
matchlength = matchlength+1
661-
662691
if (it>len(text)) exit iterate
663692

693+
matchlength = matchlength+1
694+
664695
if (DEBUG) print "('[regex] matching ',i0,'-th pattern on chunk <',i0,':',i0,'>')", ip,it,len(text)
665696
if (.not. pat_match(pattern(ip), text(it:it))) exit iterate
666697
ip = ip+1

test/tests.f90

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ program tests
2323
call add_test(test_invalid())
2424
call add_test(test_main())
2525
call add_test(test_bracket_space())
26+
call add_test(test_end_anchor())
2627

2728
! Test #2
2829
call add_test(run_test2())
@@ -66,39 +67,41 @@ logical function test_main() result(success)
6667
use regex_module
6768
implicit none
6869

69-
integer :: idx,ln
7070
character(*), parameter :: text = 'table football'
7171

72-
idx = REGEX(string=text,pattern='foo*',length=ln);
73-
74-
! Prints "football"
75-
success = idx>0; if (.not.success) return
76-
success = text(idx:idx+ln-1) == "foo"
72+
success = check_pattern(text,'foo*',expected="foo")
73+
if (.not.success) return
7774

7875
end function test_main
7976

8077
logical function test_bracket_space() result(success)
8178
use regex_module
8279
implicit none
8380

84-
integer :: idx,ln
8581
character(*), parameter :: text = 'table football'
8682

87-
idx = REGEX(string=text,pattern='e[ ]f',length=ln);
88-
89-
! Prints "football"
90-
success = idx>0; if (.not.success) return
91-
success = text(idx:idx+ln-1) == "e f"
83+
success = check_pattern(text,'e[ ]f',expected="e f")
84+
if (.not.success) return
9285

93-
idx = REGEX(string=text,pattern='e[ ]+f',length=ln);
86+
success = check_pattern(text,'e[ ]+f',expected="e f")
87+
if (.not.success) return
9488

95-
! Prints "football"
96-
success = idx>0; if (.not.success) return
97-
success = text(idx:idx+ln-1) == "e f"
9889

9990
end function test_bracket_space
10091

92+
logical function test_end_anchor() result(success)
93+
use regex_module
94+
implicit none
95+
96+
character(*), parameter :: text = 'table football'
97+
98+
success = check_pattern(text,'ll$',expected="ll")
99+
if (.not.success) return
100+
101+
success = check_pattern(text,'l$',expected="l")
102+
if (.not.success) return
101103

104+
end function test_end_anchor
102105

103106

104107
end program tests

0 commit comments

Comments
 (0)