67 character,
save :: C_ESCAPE =
'#'
68 integer,
parameter :: SYM_EOL = -128
69 integer,
parameter :: SYM_ANYCHAR = 500
70 integer,
parameter :: SYM_QUESTION = 501
71 integer,
parameter :: SYM_PLUS = 502
72 integer,
parameter :: SYM_STAR = 503
73 integer,
parameter :: SYM_NORMAL_SET = 520
74 integer,
parameter :: SYM_REVERSED_SET = 521
75 integer,
parameter :: SYM_HEADFIX = 540
76 integer,
parameter :: SYM_TAILFIX = 541
77 integer,
parameter :: SYM_ISDIGIT = 560
78 integer,
parameter :: SYM_ISALPHA = 561
79 integer,
parameter :: SYM_ISWORD = 562
80 integer,
parameter :: SYM_ISSPACE = 563
81 integer,
parameter :: SYM_ISXDIGIT = 564
82 integer,
parameter :: SYM_COUNT_BASE = 1000
105 subroutine preprocess_pattern(pattern, symbols)
106 character(len = *),
intent(in):: pattern
107 integer,
intent(out):: symbols(:)
108 integer:: i, j, code, imax, j_last_set
109 integer:: status, stat_return
110 integer,
parameter:: &
113 & STAT_OPEN_SET = 3, &
115 & STAT_HEXADECIMAL = 5
119 stat_return = stat_init
122 imax = len_trim(pattern)
129 if (c == c_escape)
then
132 else if (c ==
"[")
then
133 symbols(j) = sym_normal_set
134 status = stat_open_set
135 else if (c ==
".")
then
136 symbols(j) = sym_anychar
137 else if (c ==
"?")
then
138 symbols(j) = sym_question
139 else if (c ==
"+")
then
140 symbols(j) = sym_plus
141 else if (c ==
"*")
then
142 symbols(j) = sym_star
143 else if (c ==
"^" .and. i == 1)
then
144 symbols(j) = sym_headfix
145 else if (c ==
"$" .and. i == imax)
then
146 symbols(j) = sym_tailfix
148 symbols(j) = ichar(c)
151 if (c ==
'd' .or. c ==
'D')
then
152 symbols(j) = sym_isdigit
153 else if (c ==
'a' .or. c ==
'A')
then
154 symbols(j) = sym_isalpha
155 else if (c ==
'w' .or. c ==
'W')
then
156 symbols(j) = sym_isword
157 else if (c ==
's' .or. c ==
'S')
then
158 symbols(j) = sym_isspace
159 else if (c ==
'z' .or. c ==
'Z')
then
160 symbols(j) = sym_isxdigit
161 else if (c ==
'x' .or. c ==
'X')
then
163 status = stat_hexadecimal
166 symbols(j) = ichar(c)
169 case(stat_hexadecimal)
170 code = index(
"123456789ABCDEFabcdef", c)
171 if (code >= 16) code = code - 6
172 if (symbols(j) == -1)
then
176 symbols(j) = symbols(j) * 16 + code
180 symbols(j) = sym_count_base
182 stat_return = stat_in_set
184 symbols(j - 1) = sym_reversed_set
186 else if (c == c_escape)
then
190 symbols(j) = ichar(c)
195 symbols(j_last_set) = sym_count_base + j - j_last_set - 1
196 stat_return = stat_init
199 else if (c == c_escape)
then
203 symbols(j) = ichar(c)
210 symbols(j) = ichar(
' ')
212 symbols(j) = sym_count_base
214 symbols(j_last_set) = sym_count_base + j - j_last_set - 1
216 end subroutine preprocess_pattern
246 recursive subroutine match_here(ipat, text, length)
247 integer,
intent(in):: ipat(:)
248 character(len = *),
intent(in):: text
249 integer,
intent(out):: length
250 integer:: s1, s2, remain, i, hitmax, hitcount, hit_at_least
254 if (
size(ipat) == 0 .or. ipat(1) == sym_eol)
then
259 if (ipat(1) == sym_tailfix)
then
267 if (len(text) == 0)
then
272 if (ipat(1) == sym_normal_set)
then
274 s2 = 2 + ipat(2) - sym_count_base
276 else if (ipat(1) == sym_reversed_set)
then
278 s2 = 2 + ipat(2) - sym_count_base
287 select case (ipat(s2 + 1))
305 if (hit(ipat(s1:s2), text(i:i)) .neqv. normal_hit)
then
311 if (hitcount < hit_at_least)
then
317 do, i = 1 + hitcount, 1 + hit_at_least, -1
318 call match_here(ipat(remain: ), text(i: ), length)
319 if (length >= 0)
then
320 length = length + i - 1
325 end subroutine match_here
350 logical function hit(ipat, c)
result(result)
351 integer,
intent(in) :: ipat(:)
352 character(len=*),
intent(in) :: c
353 character(len=*),
parameter :: &
354 & DIGIT =
"0123456789", &
355 & XDIGIT =
"ABCDEFabcdef", &
356 & ALPHA =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
359 do, i = 1,
size(ipat)
364 result = (index(alpha, c) > 0)
366 result = (index(digit, c) > 0)
368 result = (index(digit, c) > 0 .or. index(alpha, c) > 0 .or. &
371 result = (index(digit, c) > 0 .or. index(xdigit, c) > 0)
373 result = (c ==
' ' .or. (iachar(c) >= 8 .and. iachar(c) <= 13))
375 result = (ipat(i) == ichar(c))
468 subroutine match(pattern, text, start, length)
470 character(len = *),
intent(in) :: pattern, text
471 integer,
intent(out) :: start, length
472 integer,
allocatable :: ipattern(:)
473 integer :: text_length
476 if (len(pattern) <= 0)
then
482 allocate(ipattern(len(pattern) + 2))
483 call preprocess_pattern(pattern, ipattern)
485 if (ipattern(1) == sym_headfix)
then
487 call match_here(ipattern(2: ), text, length)
488 if (length < 0)
goto 995
492 text_length = len(text)
493 do, start = 1, text_length + 1
494 call match_here(ipattern, text(start:text_length), length)
495 if (length >= 0)
goto 999
シンプルな正規表現関数 'match' を提供します.
subroutine, public match(pattern, text, start, length)