1515! http://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html
1616!
1717! *************************************************************************************************
18- module regex
18+ module regex_module
1919 implicit none
2020 private
2121
2222 public :: parse_pattern
2323 ! public :: re_matchp
24- ! public :: re_match
24+ public :: regex
2525
2626 ! Character kind
2727 integer , parameter , public :: RCK = selected_char_kind(" ascii" )
@@ -88,14 +88,20 @@ module regex
8888
8989 contains
9090
91- procedure :: parse = > parse_pattern
91+ ! procedure :: parse => parse_pattern
9292 procedure :: write = > write_pattern
9393 procedure :: nrules
9494 procedure :: destroy
9595 final :: finalize
9696
9797 end type regex_op
9898
99+ ! Public interface
100+ interface regex
101+ module procedure re_match
102+ module procedure re_matchp
103+ end interface regex
104+
99105 contains
100106
101107 ! Clean up a pattern
@@ -252,19 +258,91 @@ elemental logical function matchcharclass(c,str)
252258
253259 end function matchcharclass
254260
261+ logical function matchquestion (p , pattern , text , matchlength )
262+ type (regex_pattern), intent (in ) :: p, pattern(:)
263+ character (len=* ,kind= RCK), intent (in ) :: text
264+ integer , intent (inout ) :: matchlength
265+
266+ matchquestion = .false.
267+
268+ if (p% type == UNUSED .or. matchpattern(pattern, text, matchlength)) then
269+ matchquestion = .true.
270+ return
271+ elseif (len (text)>0 .and. pat_match(p,text(2 :))) then
272+ if (matchpattern(pattern,text(2 :),matchlength)) then
273+ matchlength = matchlength+1
274+ matchquestion = .true.
275+ return
276+ end if
277+ end if
278+
279+ end function matchquestion
280+
281+ logical function matchstar (p , pattern , text , matchlength )
282+ type (regex_pattern), intent (in ) :: p, pattern(:)
283+ character (len=* ,kind= RCK), intent (in ) :: text
284+ integer , intent (inout ) :: matchlength
285+
286+ integer :: prelen,it
287+
288+ ! Save input variables
289+ prelen = matchlength
290+ it = 1
291+
292+ do while (it<= len (text) .and. pat_match(p, text(it:)))
293+ it = it+1
294+ matchlength = matchlength+1
295+ end do
296+
297+ do while (it>= 1 )
298+ matchstar = matchpattern(pattern, text(it:), matchlength)
299+ if (matchstar) return
300+
301+ it = it-1
302+ matchlength = matchlength-1
303+
304+ end do
305+
306+ matchlength = prelen
307+ matchstar = .false.
308+
309+ end function matchstar
310+
311+ logical function matchplus (p , pattern , text , matchlength )
312+ type (regex_pattern), intent (in ) :: p, pattern(:)
313+ character (len=* ,kind= RCK), intent (in ) :: text
314+ integer , intent (inout ) :: matchlength
315+
316+ integer :: it
317+
318+ it = 1
319+ do while (it<= len (text) .and. pat_match(p, text(it:)))
320+ it = it+1
321+ matchlength = matchlength+1
322+ end do
323+
324+ do while (it> 1 )
325+ matchplus = matchpattern(pattern, text(it:), matchlength)
326+ if (matchplus) return
327+ it = it-1
328+ matchlength = matchlength-1
329+ end do
330+
331+ matchplus = .false.
332+
333+ end function matchplus
334+
255335 ! Find matches of the given pattern in the string
256- integer function re_match (pattern , text , length )
336+ integer function re_match (pattern , text , length ) result(index)
257337 character (* ,kind= RCK), intent (in ) :: pattern
258338 character (* ,kind= RCK), intent (in ) :: text
259339 integer , intent (out ) :: length
260340
261- ! re_match = re_matchp(parse_pattern(pattern),text,length)
262- stop ' re_match not impl'
341+ index = re_matchp(parse_pattern(pattern),text,length)
263342
264343 end function re_match
265344
266- subroutine parse_pattern (this , pattern )
267- class(regex_op), intent (inout ) :: this
345+ type (regex_op) function parse_pattern(pattern) result(this)
268346 character (* ,kind= RCK), intent (in ) :: pattern
269347
270348 ! Local variables
@@ -381,7 +459,7 @@ subroutine parse_pattern(this, pattern)
381459 ! Save number of patterns
382460 this% n = j-1
383461
384- end subroutine parse_pattern
462+ end function parse_pattern
385463
386464 function print_pattern (pattern ) result(msg)
387465 class(regex_pattern), intent (in ) :: pattern
@@ -434,19 +512,24 @@ integer function re_matchp(pattern, text, matchlength) result(index)
434512
435513 ! String must begin with this pattern
436514 index = merge (1 ,0 ,matchpattern([pattern% pattern(2 )], text, matchlength))
515+ ! print *, 'begin with? index = ',index
437516
438517 else
439518
440519 do index= 1 ,len (text)
441- if (matchpattern(pattern% pattern,text,matchlength)) return
520+ if (matchpattern(pattern% pattern,text(index:) ,matchlength)) return
442521 end do
443522
523+ ! print *, 'all patterns not matched'
524+
444525 index = 0
445526
446527 end if
447528
448529 else
449530
531+ ! print *, 'pattern has no patterns'
532+
450533 index = 0
451534
452535 end if
@@ -456,124 +539,62 @@ end function re_matchp
456539
457540
458541
459- !
460- ! static int matchstar(regex_pattern p, regex_pattern* pattern, const char* text, int* matchlength)
461- ! {
462- ! int prelen = *matchlength;
463- ! const char* prepoint = text;
464- ! while ((text[0] != '\0') && pat_match(p, *text))
465- ! {
466- ! text++;
467- ! (*matchlength)++;
468- ! }
469- ! while (text >= prepoint)
470- ! {
471- ! if (matchpattern(pattern, text--, matchlength))
472- ! return 1;
473- ! (*matchlength)--;
474- ! }
475- !
476- ! *matchlength = prelen;
477- ! return 0;
478- ! }
479- !
480- ! static int matchplus(regex_pattern p, regex_pattern* pattern, const char* text, int* matchlength)
481- ! {
482- ! const char* prepoint = text;
483- ! while ((text[0] != '\0') && pat_match(p, *text))
484- ! {
485- ! text++;
486- ! (*matchlength)++;
487- ! }
488- ! while (text > prepoint)
489- ! {
490- ! if (matchpattern(pattern, text--, matchlength))
491- ! return 1;
492- ! (*matchlength)--;
493- ! }
494- !
495- ! return 0;
496- ! }
497- !
498- ! static int matchquestion(regex_pattern p, regex_pattern* pattern, const char* text, int* matchlength)
499- ! {
500- ! if (p.type == UNUSED)
501- ! return 1;
502- ! if (matchpattern(pattern, text, matchlength))
503- ! return 1;
504- ! if (*text && pat_match(p, *text++))
505- ! {
506- ! if (matchpattern(pattern, text, matchlength))
507- ! {
508- ! (*matchlength)++;
509- ! return 1;
510- ! }
511- ! }
512- ! return 0;
513- ! }
514- !
515- !
542+
543+
544+
516545
517546 ! Iterative matching
518547 logical function matchpattern (pattern , text , matchlength ) result(match)
519548 class(regex_pattern), intent (in ) :: pattern(:)
520549 character (kind= RCK,len=* ), intent (in ) :: text
521- integer , intent (in ) :: matchlength
550+ integer , intent (inout ) :: matchlength
522551
523- integer :: pre
552+ integer :: pre,ip,it
524553
525554 pre = matchlength
555+ ip = 1
556+ it = 1
557+
558+ iterate: do while (ip<= size (pattern))
559+
560+ if (pattern(ip)% type == UNUSED .or. pattern(ip+1 )% type == QUESTIONMARK) then
561+
562+ match = matchquestion(pattern(ip),pattern(ip+2 :),text(it:),matchlength)
563+ return
564+
565+ elseif (pattern(ip+1 )% type == STAR) then
566+
567+ match = matchstar(pattern(ip),pattern(ip+2 :), text(it:), matchlength)
568+ return
569+
570+ elseif (pattern(ip+1 )% type == PLUS) then
571+
572+ match = matchplus(pattern(ip),pattern(ip+2 :), text(it:), matchlength)
573+ return
574+
575+ elseif (pattern(ip)% type == END_WITH .and. pattern(ip+1 )% type == UNUSED) then
576+
577+ match = len (text(it:))<= 0
578+ return
579+
580+ end if
581+
582+ matchlength = matchlength+1
583+
584+ ip = ip+1
585+ it = it+1
586+ if (it> len (text)) exit iterate
587+ if (.not. pat_match(pattern(ip), text(it:it))) exit iterate
588+
589+ end do iterate
590+
591+ matchlength = pre
592+ match = .false.
593+ return
526594
527- !
528- ! iterate: do
529- !
530- !
531- ! do
532- ! {
533- ! if ((pattern[0].type == UNUSED) || (pattern[1].type == QUESTIONMARK))
534- ! {
535- ! return matchquestion(pattern[0], &pattern[2], text, matchlength);
536- ! }
537- ! else if (pattern[1].type == STAR)
538- ! {
539- ! return matchstar(pattern[0], &pattern[2], text, matchlength);
540- ! }
541- ! else if (pattern[1].type == PLUS)
542- ! {
543- ! return matchplus(pattern[0], &pattern[2], text, matchlength);
544- ! }
545- ! else if ((pattern[0].type == END) && pattern[1].type == UNUSED)
546- ! {
547- ! return (text[0] == '\0');
548- ! }
549- ! /* Branching is not working properly
550- ! else if (pattern[1].type == BRANCH)
551- ! {
552- ! return (matchpattern(pattern, text) || matchpattern(&pattern[2], text));
553- ! }
554- ! */
555- ! (*matchlength)++;
556- ! }
557- ! while ((text[0] != '\0') && pat_match(*pattern++, *text++));
558- !
559- ! *matchlength = pre;
560- !
561- ! ierr = 0
562- !
563- ! end function matchpattern
564- !
565- ! static int matchpattern(regex_pattern* pattern, const char* text, int* matchlength)
566- ! {
567- ! int pre = *matchlength;
568- !
569- ! }
570- !
571- ! #endif
572- !
573- !
574595 end function matchpattern
575596
576597
577598
578599
579- end module regex
600+ end module regex_module
0 commit comments