Class regex
In: regex.f90

正規表現モジュール

サブルーチン match により正規表現を用いた文字列マッチを行うことが 可能です。

Methods

match  

Public Instance methods

Subroutine :
pattern :character(len = *), intent(in)
text :character(len = *), intent(in)
start :integer, intent(out)
length :integer, intent(out)

pattern には正規表現を与えます。 text には正規表現によって探査したい文字列を与えます。

patterntext にマッチした場合、 start には文字列の何文字目からマッチしたのかを示す数値 (正の整数) が返ります。 length には何文字分マッチしたのかを示す数値 (正の整数) が返ります。

マッチしない場合、 length == -1, start == 0 となります。

     program regex_test
       use regex,    only: match
       use dc_types, only: TOKEN
       implicit none

       integer:: start, length
       character(TOKEN) :: pattern, text
     continue
       pattern = "->"
       text    = "time->0.0,x->hoge"
       call match(trim(pattern), trim(text), start, length)
       call formatted_print

       pattern = "^##+"
       text    = "####### hoge"
       call match(trim(pattern), trim(text), start, length)
       call formatted_print

       pattern = "@+$"
       text    = "# hoge @@@"
       call match(trim(pattern), trim(text), start, length)
       call formatted_print

     contains
       subroutine formatted_print
         use dc_string, only: Printf
         call Printf(fmt='pattern= %c : text= %c : start= %d : length= %d', &
           & c1=trim(pattern), c2=trim(text), i=(/start, length/))
       end subroutine formatted_print

     end program regex_test

このプログラムを実行することで以下の出力が得られるはずです。

     pattern= -> : text= time->0.0,x->hoge : start= 5 : length= 2
     pattern= ^##+ : text= ####### hoge : start= 1 : length= 7
     pattern= @+$ : text= # hoge @@@ : start= 8 : length= 3

[Source]

  subroutine match(pattern, text, start, length)
    !
    ! _pattern_ には正規表現を与えます。
    ! _text_ には正規表現によって探査したい文字列を与えます。
    !
    ! _pattern_ が _text_ にマッチした場合、
    ! _start_ には文字列の何文字目からマッチしたのかを示す数値 (正の整数)
    ! が返ります。
    ! _length_ には何文字分マッチしたのかを示す数値 (正の整数)
    ! が返ります。
    !
    ! マッチしない場合、 length == -1, start == 0 となります。
    !
    !
    !=== 例
    !
    !      program regex_test
    !        use regex,    only: match
    !        use dc_types, only: TOKEN
    !        implicit none
    !      
    !        integer:: start, length
    !        character(TOKEN) :: pattern, text
    !      continue
    !        pattern = "->"
    !        text    = "time->0.0,x->hoge"
    !        call match(trim(pattern), trim(text), start, length)
    !        call formatted_print
    !      
    !        pattern = "^##+"
    !        text    = "####### hoge"
    !        call match(trim(pattern), trim(text), start, length)
    !        call formatted_print
    !      
    !        pattern = "@+$"
    !        text    = "# hoge @@@"
    !        call match(trim(pattern), trim(text), start, length)
    !        call formatted_print
    !      
    !      contains
    !        subroutine formatted_print
    !          use dc_string, only: Printf
    !          call Printf(fmt='pattern= %c : text= %c : start= %d : length= %d', &
    !            & c1=trim(pattern), c2=trim(text), i=(/start, length/))
    !        end subroutine formatted_print
    !      
    !      end program regex_test
    !
    ! このプログラムを実行することで以下の出力が得られるはずです。
    !
    !      pattern= -> : text= time->0.0,x->hoge : start= 5 : length= 2
    !      pattern= ^##+ : text= ####### hoge : start= 1 : length= 7
    !      pattern= @+$ : text= # hoge @@@ : start= 8 : length= 3
    !
    implicit none
    character(len = *), intent(in):: pattern, text
    integer, intent(out):: start, length
    integer, allocatable:: ipattern(:)
    integer:: text_length
  continue
    ! 空 pattern は空文字列に適合
    if (len(pattern) <= 0) then
      length = 0
      start = 1
      return
    endif
    ! メタキャラクタの認識
    allocate(ipattern(len(pattern) + 2))
    call preprocess_pattern(pattern, ipattern)
    ! 頭寄せ指定のある場合
    if (ipattern(1) == SYM_HEADFIX) then
      start = 1
      call match_here(ipattern(2: ), text, length)
      if (length < 0) goto 995
      goto 999
    endif
    ! 最左原理
    text_length = len(text)
    do, start = 1, text_length + 1
      call match_here(ipattern, text(start:text_length), length)
      if (length >= 0) goto 999
    end do
    ! みつからない場合
995 continue
    start = 0
    length = -1
999 continue
    deallocate(ipattern)
  end subroutine match

[Validate]