re_expand 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/Generator.rb +191 -187
- data/lib/Node.rb +51 -49
- data/lib/Scanner.rb +45 -43
- data/lib/re_expand.rb +2 -2
- data/test/test_generator.rb +28 -32
- data/test/test_scanner.rb +24 -23
- metadata +3 -3
    
        data/lib/Generator.rb
    CHANGED
    
    | @@ -17,217 +17,221 @@ require 'Scanner' | |
| 17 17 | 
             
            require 'Node'
         | 
| 18 18 | 
             
            require 'Asearch'
         | 
| 19 19 |  | 
| 20 | 
            -
             | 
| 21 | 
            -
               | 
| 22 | 
            -
                 | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
            class Generator
         | 
| 37 | 
            -
              def initialize(s = nil)
         | 
| 38 | 
            -
                @s = (s ? [s] : [])
         | 
| 39 | 
            -
                @matchedlist = []
         | 
| 40 | 
            -
                @par = 0
         | 
| 41 | 
            -
                @commands = []
         | 
| 42 | 
            -
              end
         | 
| 43 | 
            -
             | 
| 44 | 
            -
              def add(pat,command)
         | 
| 45 | 
            -
                @s << pat
         | 
| 46 | 
            -
                @commands << command
         | 
| 47 | 
            -
              end
         | 
| 48 | 
            -
             | 
| 49 | 
            -
              def delete
         | 
| 50 | 
            -
                @s.pop
         | 
| 51 | 
            -
                @commands.pop
         | 
| 20 | 
            +
            module ReExpand
         | 
| 21 | 
            +
              class GenNode
         | 
| 22 | 
            +
                def initialize(id, state=[], s="", substrings=[], accept=false)
         | 
| 23 | 
            +
                  @id = id
         | 
| 24 | 
            +
                  @s = s
         | 
| 25 | 
            +
                  @substrings = substrings
         | 
| 26 | 
            +
                  @accept = accept
         | 
| 27 | 
            +
                  @state = state
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
                
         | 
| 30 | 
            +
                attr :id, true
         | 
| 31 | 
            +
                attr :s, true
         | 
| 32 | 
            +
                attr :substrings, true
         | 
| 33 | 
            +
                attr :accept, true
         | 
| 34 | 
            +
                attr :state, true
         | 
| 52 35 | 
             
              end
         | 
| 53 | 
            -
             | 
| 54 | 
            -
               | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
                 | 
| 62 | 
            -
                 | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
                 | 
| 66 | 
            -
                 | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
                 | 
| 71 | 
            -
                 | 
| 72 | 
            -
                #
         | 
| 73 | 
            -
                lists = []
         | 
| 74 | 
            -
                listed = [{},{},{}]
         | 
| 75 | 
            -
                #
         | 
| 76 | 
            -
                # 初期状態
         | 
| 36 | 
            +
              
         | 
| 37 | 
            +
              class Generator
         | 
| 38 | 
            +
                def initialize(s = nil)
         | 
| 39 | 
            +
                  @s = (s ? [s] : [])
         | 
| 40 | 
            +
                  @matchedlist = []
         | 
| 41 | 
            +
                  @par = 0
         | 
| 42 | 
            +
                  @commands = []
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
                
         | 
| 45 | 
            +
                def add(pat,command)
         | 
| 46 | 
            +
                  @s << pat
         | 
| 47 | 
            +
                  @commands << command
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
                
         | 
| 50 | 
            +
                def delete
         | 
| 51 | 
            +
                  @s.pop
         | 
| 52 | 
            +
                  @commands.pop
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
                
         | 
| 77 55 | 
             
                #
         | 
| 78 | 
            -
                 | 
| 79 | 
            -
                list[0] = GenNode.new(startnode.id, @asearch.initstate)
         | 
| 80 | 
            -
                lists[0] = list
         | 
| 56 | 
            +
                # ルールを解析して状態遷移機械を作成し、patにマッチするもののリストを返す
         | 
| 81 57 | 
             
                #
         | 
| 82 | 
            -
                ( | 
| 83 | 
            -
                   | 
| 84 | 
            -
                   | 
| 85 | 
            -
                   | 
| 86 | 
            -
                   | 
| 87 | 
            -
                   | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 108 | 
            -
             | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 58 | 
            +
                def generate(pat, app = nil)
         | 
| 59 | 
            +
                  res = [[],[],[]] # 曖昧度0,1,2のマッチ結果
         | 
| 60 | 
            +
                  patterns = pat.split.map { |p| p.downcase }
         | 
| 61 | 
            +
                  
         | 
| 62 | 
            +
                  @asearch = Asearch.new(pat)
         | 
| 63 | 
            +
                  scanner = Scanner.new(@s.join('|'))
         | 
| 64 | 
            +
                  
         | 
| 65 | 
            +
                  # HelpDataで指定した状態遷移機械全体を生成
         | 
| 66 | 
            +
                  # (少し時間がかかる)
         | 
| 67 | 
            +
                  (startnode, endnode) = regexp(scanner,true) # top level
         | 
| 68 | 
            +
                  
         | 
| 69 | 
            +
                  #
         | 
| 70 | 
            +
                  # 状態遷移機械からDepth-Firstで文字列を生成する
         | 
| 71 | 
            +
                  # n個のノードを経由して生成される状態の集合をlists[n]に入れる
         | 
| 72 | 
            +
                  # 生成しながらマッチングも計算する
         | 
| 73 | 
            +
                  #
         | 
| 74 | 
            +
                  lists = []
         | 
| 75 | 
            +
                  listed = [{},{},{}]
         | 
| 76 | 
            +
                  #
         | 
| 77 | 
            +
                  # 初期状態
         | 
| 78 | 
            +
                  #
         | 
| 79 | 
            +
                  list = []
         | 
| 80 | 
            +
                  list[0] = GenNode.new(startnode.id, @asearch.initstate)
         | 
| 81 | 
            +
                  lists[0] = list
         | 
| 82 | 
            +
                  #
         | 
| 83 | 
            +
                  (0..1000).each { |length|
         | 
| 84 | 
            +
                    break if app && app.inputPending
         | 
| 85 | 
            +
                    list = lists[length]
         | 
| 86 | 
            +
                    newlist = []
         | 
| 87 | 
            +
                    # puts "#{length} - #{list.length}"
         | 
| 88 | 
            +
                    list.each { |entry|
         | 
| 89 | 
            +
                      srcnode = Node.node(entry.id)
         | 
| 90 | 
            +
                      if list.length * srcnode.trans.length < 10000 then
         | 
| 91 | 
            +
                        srcnode.trans.each { |trans|
         | 
| 92 | 
            +
                          ss = entry.substrings.dup
         | 
| 93 | 
            +
                          srcnode.pars.each { |i|
         | 
| 94 | 
            +
                            ss[i-1] = ss[i-1].to_s + trans.arg
         | 
| 95 | 
            +
                          }
         | 
| 96 | 
            +
                          newstate = @asearch.state(entry.state, trans.str) # 新しいマッチング状態を計算してノードに保存
         | 
| 97 | 
            +
                          s = entry.s + trans.str
         | 
| 98 | 
            +
                          acceptno = trans.dest.accept
         | 
| 99 | 
            +
                          newlist << GenNode.new(trans.dest.id, newstate, s, ss, acceptno)
         | 
| 100 | 
            +
                          #
         | 
| 101 | 
            +
                          # この時点で、マッチしているかどうかをstateとacceptpatで判断できる
         | 
| 102 | 
            +
                          # マッチしてたら出力リストに加える
         | 
| 103 | 
            +
                          #
         | 
| 104 | 
            +
                          if acceptno then
         | 
| 105 | 
            +
                            maxambig = 2
         | 
| 106 | 
            +
                            (0..maxambig).each { |ambig|
         | 
| 107 | 
            +
                              if !listed[ambig][s] then
         | 
| 108 | 
            +
                                if (newstate[ambig] & @asearch.acceptpat) != 0 then # マッチ
         | 
| 109 | 
            +
                                  maxambig = ambig if ambig < maxambig # 曖昧度0でマッチすれば曖昧度1の検索は不要
         | 
| 110 | 
            +
                                  listed[ambig][s] = true
         | 
| 111 | 
            +
                                  sslen = ss.length
         | 
| 112 | 
            +
                                  if sslen > 0 then
         | 
| 113 | 
            +
                                    # patstr = "(.*)\t" * (sslen-1) + "(.*)"
         | 
| 114 | 
            +
                                    patstr = (["(.*)"] * sslen).join("\t")
         | 
| 115 | 
            +
                                    /#{patstr}/ =~ ss.join("\t")
         | 
| 116 | 
            +
                                  end
         | 
| 117 | 
            +
                                  ##                    next if $1 == $2
         | 
| 118 | 
            +
                                  # 'set date #{$2}' のような記述の$変数にsubstringの値を代入
         | 
| 119 | 
            +
                                  File.open("/tmp/log","a"){ |f|
         | 
| 120 | 
            +
                                    f.puts "#{s}-----" + eval('%('+@commands[acceptno]+')')
         | 
| 121 | 
            +
                                  }
         | 
| 122 | 
            +
                                  res[ambig] << [s, eval('%('+@commands[acceptno]+')')]
         | 
| 115 123 | 
             
                                end
         | 
| 116 | 
            -
            ##                    next if $1 == $2
         | 
| 117 | 
            -
                                # 'set date #{$2}' のような記述の$変数にsubstringの値を代入
         | 
| 118 | 
            -
                            File.open("/tmp/log","a"){ |f|
         | 
| 119 | 
            -
                              f.puts "#{s}-----" + eval('%('+@commands[acceptno]+')')
         | 
| 120 | 
            -
                            }
         | 
| 121 | 
            -
                                res[ambig] << [s, eval('%('+@commands[acceptno]+')')]
         | 
| 122 124 | 
             
                              end
         | 
| 123 | 
            -
                             | 
| 124 | 
            -
                           | 
| 125 | 
            -
                         | 
| 126 | 
            -
                       | 
| 127 | 
            -
                     | 
| 125 | 
            +
                            }
         | 
| 126 | 
            +
                          end
         | 
| 127 | 
            +
                        }
         | 
| 128 | 
            +
                      end
         | 
| 129 | 
            +
                    }
         | 
| 130 | 
            +
                    break if newlist.length == 0
         | 
| 131 | 
            +
                    lists << newlist
         | 
| 132 | 
            +
                    break if res[0].length > 100
         | 
| 128 133 | 
             
                  }
         | 
| 129 | 
            -
                   | 
| 130 | 
            -
                  lists << newlist
         | 
| 131 | 
            -
                  break if res[0].length > 100
         | 
| 132 | 
            -
                }
         | 
| 133 | 
            -
                [res[0], res[1], res[2]]
         | 
| 134 | 
            -
              end
         | 
| 135 | 
            -
             | 
| 136 | 
            -
              #
         | 
| 137 | 
            -
              # 正規表現をパースして状態遷移機械を作る
         | 
| 138 | 
            -
              #
         | 
| 139 | 
            -
              private
         | 
| 140 | 
            -
              #            n1     n2
         | 
| 141 | 
            -
              #        +-->□.....□--+
         | 
| 142 | 
            -
              # start /                \  end
         | 
| 143 | 
            -
              #     □ --->□.....□---> □
         | 
| 144 | 
            -
              #       \                /
         | 
| 145 | 
            -
              #        +-->□.....□--+
         | 
| 146 | 
            -
              #
         | 
| 147 | 
            -
              def regexp(s,toplevel=false) # regcat { '|' regcat }
         | 
| 148 | 
            -
                startnode = Node.new
         | 
| 149 | 
            -
                endnode = Node.new
         | 
| 150 | 
            -
                if toplevel then
         | 
| 151 | 
            -
                  @pars = []
         | 
| 152 | 
            -
                  @parno = 0
         | 
| 153 | 
            -
                  @ruleid = 0
         | 
| 134 | 
            +
                  [res[0], res[1], res[2]]
         | 
| 154 135 | 
             
                end
         | 
| 155 | 
            -
                 | 
| 156 | 
            -
                 | 
| 157 | 
            -
                 | 
| 158 | 
            -
                 | 
| 159 | 
            -
                 | 
| 160 | 
            -
             | 
| 161 | 
            -
                 | 
| 162 | 
            -
                 | 
| 163 | 
            -
                 | 
| 136 | 
            +
                
         | 
| 137 | 
            +
                #
         | 
| 138 | 
            +
                # 正規表現をパースして状態遷移機械を作る
         | 
| 139 | 
            +
                #
         | 
| 140 | 
            +
                private
         | 
| 141 | 
            +
                #            n1     n2
         | 
| 142 | 
            +
                #        +-->□.....□--+
         | 
| 143 | 
            +
                # start /                \  end
         | 
| 144 | 
            +
                #     □ --->□.....□---> □
         | 
| 145 | 
            +
                #       \                /
         | 
| 146 | 
            +
                #        +-->□.....□--+
         | 
| 147 | 
            +
                #
         | 
| 148 | 
            +
                def regexp(s,toplevel=false) # regcat { '|' regcat }
         | 
| 149 | 
            +
                  startnode = Node.new
         | 
| 150 | 
            +
                  endnode = Node.new
         | 
| 164 151 | 
             
                  if toplevel then
         | 
| 165 152 | 
             
                    @pars = []
         | 
| 166 153 | 
             
                    @parno = 0
         | 
| 167 | 
            -
                    @ruleid  | 
| 154 | 
            +
                    @ruleid = 0
         | 
| 168 155 | 
             
                  end
         | 
| 156 | 
            +
                  startnode.pars = @pars
         | 
| 157 | 
            +
                  endnode.pars = @pars
         | 
| 169 158 | 
             
                  (n1, n2) = regcat(s)
         | 
| 170 159 | 
             
                  startnode.addTrans('',n1)
         | 
| 171 160 | 
             
                  if toplevel then
         | 
| 172 161 | 
             
                    n2.accept = @ruleid
         | 
| 173 162 | 
             
                  end
         | 
| 174 163 | 
             
                  n2.addTrans('',endnode)
         | 
| 175 | 
            -
             | 
| 176 | 
            -
             | 
| 177 | 
            -
             | 
| 178 | 
            -
             | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 181 | 
            -
             | 
| 182 | 
            -
             | 
| 164 | 
            +
                  while s.gettoken == '|' && s.nexttoken != '' do
         | 
| 165 | 
            +
                    if toplevel then
         | 
| 166 | 
            +
                      @pars = []
         | 
| 167 | 
            +
                      @parno = 0
         | 
| 168 | 
            +
                      @ruleid += 1
         | 
| 169 | 
            +
                    end
         | 
| 170 | 
            +
                    (n1, n2) = regcat(s)
         | 
| 171 | 
            +
                    startnode.addTrans('',n1)
         | 
| 172 | 
            +
                    if toplevel then
         | 
| 173 | 
            +
                      n2.accept = @ruleid
         | 
| 174 | 
            +
                    end
         | 
| 175 | 
            +
                    n2.addTrans('',endnode)
         | 
| 176 | 
            +
                  end
         | 
| 183 177 | 
             
                  s.ungettoken
         | 
| 184 | 
            -
                   | 
| 185 | 
            -
                  endnode.addTrans('',n1)
         | 
| 186 | 
            -
                  endnode = n2
         | 
| 178 | 
            +
                  return [startnode, endnode]
         | 
| 187 179 | 
             
                end
         | 
| 188 | 
            -
                 | 
| 189 | 
            -
                 | 
| 190 | 
            -
             | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 194 | 
            -
             | 
| 195 | 
            -
             | 
| 196 | 
            -
                   | 
| 197 | 
            -
                elsif t =~ /^[\+]$/ then
         | 
| 198 | 
            -
                  endnode.addTrans('',startnode)
         | 
| 199 | 
            -
                elsif t =~ /^[\*]$/ then
         | 
| 200 | 
            -
                  startnode.addTrans('',endnode)
         | 
| 201 | 
            -
                  endnode.addTrans('',startnode)
         | 
| 202 | 
            -
                else
         | 
| 180 | 
            +
                
         | 
| 181 | 
            +
                def regcat(s) # regfactor { regfactor }
         | 
| 182 | 
            +
                  (startnode, endnode) = regfactor(s)
         | 
| 183 | 
            +
                  while s.gettoken !~ /^[\)\]\|]$/ && s.nexttoken != '' do
         | 
| 184 | 
            +
                    s.ungettoken
         | 
| 185 | 
            +
                    (n1, n2) = regfactor(s)
         | 
| 186 | 
            +
                    endnode.addTrans('',n1)
         | 
| 187 | 
            +
                    endnode = n2
         | 
| 188 | 
            +
                  end
         | 
| 203 189 | 
             
                  s.ungettoken
         | 
| 190 | 
            +
                  return [startnode, endnode]
         | 
| 204 191 | 
             
                end
         | 
| 205 | 
            -
                 | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 208 | 
            -
              def regterm(s) # '(' regexp ')' | token
         | 
| 209 | 
            -
                t = s.gettoken
         | 
| 210 | 
            -
                if t == '(' then
         | 
| 211 | 
            -
                  @parno += 1
         | 
| 212 | 
            -
                  @pars.push(@parno)
         | 
| 213 | 
            -
                  (n1, n2) = regexp(s)
         | 
| 214 | 
            -
                  n1.pars = @pars.dup
         | 
| 192 | 
            +
                
         | 
| 193 | 
            +
                def regfactor(s) # regterm [ '?' | '+' | '*' ]
         | 
| 194 | 
            +
                  (startnode, endnode) = regterm(s)
         | 
| 215 195 | 
             
                  t = s.gettoken
         | 
| 216 | 
            -
                  if t  | 
| 217 | 
            -
                     | 
| 218 | 
            -
             | 
| 219 | 
            -
                     | 
| 196 | 
            +
                  if t =~ /^[\?]$/ then
         | 
| 197 | 
            +
                    startnode.addTrans('',endnode)
         | 
| 198 | 
            +
                  elsif t =~ /^[\+]$/ then
         | 
| 199 | 
            +
                    endnode.addTrans('',startnode)
         | 
| 200 | 
            +
                  elsif t =~ /^[\*]$/ then
         | 
| 201 | 
            +
                    startnode.addTrans('',endnode)
         | 
| 202 | 
            +
                    endnode.addTrans('',startnode)
         | 
| 220 203 | 
             
                  else
         | 
| 221 | 
            -
                     | 
| 222 | 
            -
             | 
| 204 | 
            +
                    s.ungettoken
         | 
| 205 | 
            +
                  end
         | 
| 206 | 
            +
                  return [startnode,endnode]
         | 
| 207 | 
            +
                end
         | 
| 208 | 
            +
                
         | 
| 209 | 
            +
                def regterm(s) # '(' regexp ')' | token
         | 
| 210 | 
            +
                  t = s.gettoken
         | 
| 211 | 
            +
                  if t == '(' then
         | 
| 212 | 
            +
                    @parno += 1
         | 
| 213 | 
            +
                    @pars.push(@parno)
         | 
| 214 | 
            +
                    (n1, n2) = regexp(s)
         | 
| 215 | 
            +
                    n1.pars = @pars.dup
         | 
| 216 | 
            +
                    t = s.gettoken
         | 
| 217 | 
            +
                    if t == ')' then
         | 
| 218 | 
            +
                      @pars.pop
         | 
| 219 | 
            +
                      n2.pars = @pars.dup
         | 
| 220 | 
            +
                      return [n1, n2]
         | 
| 221 | 
            +
                    else
         | 
| 222 | 
            +
                      puts 'missing )'
         | 
| 223 | 
            +
                      exit
         | 
| 224 | 
            +
                    end
         | 
| 225 | 
            +
                  else
         | 
| 226 | 
            +
                    startnode = Node.new
         | 
| 227 | 
            +
                    startnode.pars = @pars.dup
         | 
| 228 | 
            +
                    endnode = Node.new
         | 
| 229 | 
            +
                    endnode.pars = @pars.dup
         | 
| 230 | 
            +
                    startnode.addTrans(t,endnode)
         | 
| 231 | 
            +
                    return [startnode, endnode]
         | 
| 223 232 | 
             
                  end
         | 
| 224 | 
            -
                else
         | 
| 225 | 
            -
                  startnode = Node.new
         | 
| 226 | 
            -
                  startnode.pars = @pars.dup
         | 
| 227 | 
            -
                  endnode = Node.new
         | 
| 228 | 
            -
                  endnode.pars = @pars.dup
         | 
| 229 | 
            -
                  startnode.addTrans(t,endnode)
         | 
| 230 | 
            -
                  return [startnode, endnode]
         | 
| 231 233 | 
             
                end
         | 
| 232 234 | 
             
              end
         | 
| 235 | 
            +
              
         | 
| 233 236 | 
             
            end
         | 
| 237 | 
            +
             | 
    
        data/lib/Node.rb
    CHANGED
    
    | @@ -8,56 +8,58 @@ | |
| 8 8 | 
             
            #       ----------> □
         | 
| 9 9 | 
             
            #
         | 
| 10 10 |  | 
| 11 | 
            -
             | 
| 12 | 
            -
               | 
| 13 | 
            -
                 | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
                 | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
                 | 
| 26 | 
            -
                   | 
| 27 | 
            -
             | 
| 28 | 
            -
                   | 
| 11 | 
            +
            module ReExpand
         | 
| 12 | 
            +
              class Trans
         | 
| 13 | 
            +
                def initialize(pat,dest)
         | 
| 14 | 
            +
                  # pat にマッチしたら dest に遷移
         | 
| 15 | 
            +
                  @pat = pat
         | 
| 16 | 
            +
                  @dest = dest
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
                
         | 
| 19 | 
            +
                attr_reader :pat, :dest
         | 
| 20 | 
            +
                
         | 
| 21 | 
            +
                def str
         | 
| 22 | 
            +
                  @pat.split(/\t/)[0].to_s
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
                
         | 
| 25 | 
            +
                def arg
         | 
| 26 | 
            +
                  if @pat =~ /^(.*)\t(.*)$/ then
         | 
| 27 | 
            +
                    return $2
         | 
| 28 | 
            +
                  else
         | 
| 29 | 
            +
                    return @pat
         | 
| 30 | 
            +
                  end
         | 
| 29 31 | 
             
                end
         | 
| 30 32 | 
             
              end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
                 | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
                 | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
                 | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
                 | 
| 33 | 
            +
              
         | 
| 34 | 
            +
              class Node
         | 
| 35 | 
            +
                @@id = 1
         | 
| 36 | 
            +
                @@nodes = {}
         | 
| 37 | 
            +
                
         | 
| 38 | 
            +
                def initialize
         | 
| 39 | 
            +
                  @accept = nil
         | 
| 40 | 
            +
                  @trans = []
         | 
| 41 | 
            +
                  @id = @@id
         | 
| 42 | 
            +
                  @@nodes[@id] = self
         | 
| 43 | 
            +
                  @@id += 1
         | 
| 44 | 
            +
                  @pars = []
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
                
         | 
| 47 | 
            +
                attr_reader :id
         | 
| 48 | 
            +
                attr_reader :trans
         | 
| 49 | 
            +
                attr :accept, true
         | 
| 50 | 
            +
                attr :pars, true
         | 
| 51 | 
            +
                
         | 
| 52 | 
            +
                def addTrans(pat,dest)
         | 
| 53 | 
            +
                  t = Trans.new(pat,dest)
         | 
| 54 | 
            +
                  @trans << t
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
                
         | 
| 57 | 
            +
                def Node.node(id) # ノードidからノードを取得
         | 
| 58 | 
            +
                  @@nodes[id.to_i]
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
                
         | 
| 61 | 
            +
                def Node.nodes
         | 
| 62 | 
            +
                  @@nodes.values
         | 
| 63 | 
            +
                end
         | 
| 62 64 | 
             
              end
         | 
| 63 65 | 
             
            end
         | 
    
        data/lib/Scanner.rb
    CHANGED
    
    | @@ -5,55 +5,57 @@ | |
| 5 5 |  | 
| 6 6 | 
             
            $KCODE = 'utf8'
         | 
| 7 7 |  | 
| 8 | 
            -
             | 
| 9 | 
            -
               | 
| 10 | 
            -
                 | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
                @u = ''
         | 
| 15 | 
            -
              end
         | 
| 16 | 
            -
             | 
| 17 | 
            -
              def gettoken
         | 
| 18 | 
            -
                if @u != '' then
         | 
| 19 | 
            -
                  @t = @u
         | 
| 20 | 
            -
                  @u = ''
         | 
| 21 | 
            -
                  return @t
         | 
| 22 | 
            -
                end
         | 
| 23 | 
            -
                if @p >= @a.length then
         | 
| 8 | 
            +
            module ReExpand
         | 
| 9 | 
            +
              class Scanner
         | 
| 10 | 
            +
                def initialize(s)
         | 
| 11 | 
            +
                  @s = s
         | 
| 12 | 
            +
                  @a = s.split(//)
         | 
| 13 | 
            +
                  @p = 0
         | 
| 24 14 | 
             
                  @t = ''
         | 
| 25 | 
            -
                   | 
| 15 | 
            +
                  @u = ''
         | 
| 26 16 | 
             
                end
         | 
| 27 | 
            -
                 | 
| 28 | 
            -
                 | 
| 29 | 
            -
                  @ | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 17 | 
            +
                
         | 
| 18 | 
            +
                def gettoken
         | 
| 19 | 
            +
                  if @u != '' then
         | 
| 20 | 
            +
                    @t = @u
         | 
| 21 | 
            +
                    @u = ''
         | 
| 22 | 
            +
                    return @t
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
                  if @p >= @a.length then
         | 
| 25 | 
            +
                    @t = ''
         | 
| 26 | 
            +
                    return ''
         | 
| 27 | 
            +
                  end
         | 
| 33 28 | 
             
                  @t = @a[@p]
         | 
| 34 | 
            -
                  @t  | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
                   | 
| 38 | 
            -
                else
         | 
| 39 | 
            -
                  @p += 1
         | 
| 40 | 
            -
                  while @p < @a.length && @a[@p] !~ /^[\(\|\)\*\+\?\[\]\\]$/ do
         | 
| 41 | 
            -
                    @t += @a[@p]
         | 
| 29 | 
            +
                  if @t =~ /^[\(\|\)\*\?\[\]]$/ then
         | 
| 30 | 
            +
                    @p += 1
         | 
| 31 | 
            +
                    return @t
         | 
| 32 | 
            +
                  elsif @t == '\\' then
         | 
| 42 33 | 
             
                    @p += 1
         | 
| 34 | 
            +
                    @t = @a[@p]
         | 
| 35 | 
            +
                    @t = "\n" if @t == 'n'
         | 
| 36 | 
            +
                    @t = "\t" if @t == 't'
         | 
| 37 | 
            +
                    @p += 1
         | 
| 38 | 
            +
                    return @t
         | 
| 39 | 
            +
                  else
         | 
| 40 | 
            +
                    @p += 1
         | 
| 41 | 
            +
                    while @p < @a.length && @a[@p] !~ /^[\(\|\)\*\+\?\[\]\\]$/ do
         | 
| 42 | 
            +
                      @t += @a[@p]
         | 
| 43 | 
            +
                      @p += 1
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
                    return @t
         | 
| 43 46 | 
             
                  end
         | 
| 44 | 
            -
                  return @t
         | 
| 45 47 | 
             
                end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
                   | 
| 51 | 
            -
             | 
| 52 | 
            -
                   | 
| 48 | 
            +
                
         | 
| 49 | 
            +
                def ungettoken
         | 
| 50 | 
            +
                  if @u == '' then
         | 
| 51 | 
            +
                    @u = @t
         | 
| 52 | 
            +
                  else
         | 
| 53 | 
            +
                    puts "Can't ungettoken(#{token})"
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
                
         | 
| 57 | 
            +
                def nexttoken
         | 
| 58 | 
            +
                  return @t
         | 
| 53 59 | 
             
                end
         | 
| 54 | 
            -
              end
         | 
| 55 | 
            -
             | 
| 56 | 
            -
              def nexttoken
         | 
| 57 | 
            -
                return @t
         | 
| 58 60 | 
             
              end
         | 
| 59 61 | 
             
            end
         | 
    
        data/lib/re_expand.rb
    CHANGED
    
    | @@ -3,7 +3,7 @@ $:.unshift(File.dirname(__FILE__)) unless | |
| 3 3 | 
             
              $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
         | 
| 4 4 |  | 
| 5 5 | 
             
            module ReExpand
         | 
| 6 | 
            -
              VERSION = '0.0. | 
| 6 | 
            +
              VERSION = '0.0.2'
         | 
| 7 7 | 
             
            end
         | 
| 8 8 |  | 
| 9 9 | 
             
            require 'Generator'
         | 
| @@ -14,7 +14,7 @@ require 'Scanner' | |
| 14 14 | 
             
            class String
         | 
| 15 15 | 
             
              # ExpandHelp用のライブラリを利用
         | 
| 16 16 | 
             
              def expand(filterpat=' ')
         | 
| 17 | 
            -
                g = Generator.new
         | 
| 17 | 
            +
                g = ReExpand::Generator.new
         | 
| 18 18 | 
             
                g.add(self,'')
         | 
| 19 19 | 
             
                strings = []
         | 
| 20 20 | 
             
                if filterpat.class == String then
         | 
    
        data/test/test_generator.rb
    CHANGED
    
    | @@ -1,36 +1,32 @@ | |
| 1 1 | 
             
            # -*- coding: utf-8 -*-
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
                 | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
                 | 
| 3 | 
            +
            module ReExpand
         | 
| 4 | 
            +
              class GeneratorTest < Test::Unit::TestCase
         | 
| 5 | 
            +
                def setup
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
                
         | 
| 8 | 
            +
                def teardown
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
                
         | 
| 11 | 
            +
                def test_clock
         | 
| 12 | 
            +
                  g = Generator.new
         | 
| 13 | 
            +
                  g.add '(時計|時間|時刻)を(0|1|2|3|4|5|6|7|8|9|10|11|12)時に(セットする|設定する|あわせる)', 'set time #{$2}:00'
         | 
| 14 | 
            +
                  res = g.generate(' 10 ')
         | 
| 15 | 
            +
                  assert res[0].member?(['時刻を10時に設定する','set time 10:00'])
         | 
| 16 | 
            +
                  assert res[0].member?(['時計を10時にセットする','set time 10:00'])
         | 
| 17 | 
            +
                  assert !res[0].member?(['時計を8時にセットする','set time 8:00'])
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
                
         | 
| 20 | 
            +
                def test_substring
         | 
| 21 | 
            +
                  g = Generator.new
         | 
| 22 | 
            +
                  g.add '(a)bcd(e(fg)h)i(jk)', '#{$1}/#{$2}/#{$3}/#{$4}'
         | 
| 23 | 
            +
                  res = g.generate(' b ')
         | 
| 24 | 
            +
                  assert res[0].member?(['abcdefghijk', 'a/efgh/fg/jk'])
         | 
| 25 | 
            +
                  assert !res[0].member?(['abcdefghijk', 'a/fgh/fg/jk'])
         | 
| 26 | 
            +
                  g.add '(ab|cd)efg(hij|klm)n', '#{$1}/#{$2}'
         | 
| 27 | 
            +
                  res = g.generate(' ef ')
         | 
| 28 | 
            +
                  assert res[0].member?(['abefghijn', 'ab/hij'])
         | 
| 29 | 
            +
                  assert res[0].member?(['cdefgklmn', 'cd/klm'])
         | 
| 30 | 
            +
                end
         | 
| 31 31 | 
             
              end
         | 
| 32 32 | 
             
            end
         | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
    
        data/test/test_scanner.rb
    CHANGED
    
    | @@ -1,27 +1,28 @@ | |
| 1 1 | 
             
            # -*- coding: utf-8 -*-
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
                 | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
                 | 
| 3 | 
            +
            module ReExpand
         | 
| 4 | 
            +
              class ScannerTest < Test::Unit::TestCase
         | 
| 5 | 
            +
                def setup
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
                
         | 
| 8 | 
            +
                def teardown
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
                
         | 
| 11 | 
            +
                def test_1
         | 
| 12 | 
            +
                  s = Scanner.new('abc*def')
         | 
| 13 | 
            +
                  assert_equal s.gettoken, 'abc'
         | 
| 14 | 
            +
                  assert_equal s.gettoken, '*'
         | 
| 15 | 
            +
                  assert_equal s.gettoken, 'def'
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
                
         | 
| 18 | 
            +
                def test_2
         | 
| 19 | 
            +
                  s = Scanner.new("(a\tb|c\td)")
         | 
| 20 | 
            +
                  assert_equal s.gettoken, "("
         | 
| 21 | 
            +
                  assert_equal s.gettoken, "a\tb"
         | 
| 22 | 
            +
                  assert_equal s.gettoken, '|'
         | 
| 23 | 
            +
                  assert_equal s.gettoken, "c\td"
         | 
| 24 | 
            +
                  assert_equal s.gettoken, ')'
         | 
| 25 | 
            +
                end
         | 
| 26 26 | 
             
              end
         | 
| 27 27 | 
             
            end
         | 
| 28 | 
            +
             | 
    
        metadata
    CHANGED
    
    | @@ -1,13 +1,13 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: re_expand
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              hash:  | 
| 4 | 
            +
              hash: 27
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
              segments: 
         | 
| 7 7 | 
             
              - 0
         | 
| 8 8 | 
             
              - 0
         | 
| 9 | 
            -
              -  | 
| 10 | 
            -
              version: 0.0. | 
| 9 | 
            +
              - 2
         | 
| 10 | 
            +
              version: 0.0.2
         | 
| 11 11 | 
             
            platform: ruby
         | 
| 12 12 | 
             
            authors: 
         | 
| 13 13 | 
             
            - Toshiyuki Masui
         |