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 CHANGED
@@ -17,217 +17,221 @@ require 'Scanner'
17
17
  require 'Node'
18
18
  require 'Asearch'
19
19
 
20
- class GenNode
21
- def initialize(id, state=[], s="", substrings=[], accept=false)
22
- @id = id
23
- @s = s
24
- @substrings = substrings
25
- @accept = accept
26
- @state = state
27
- end
28
-
29
- attr :id, true
30
- attr :s, true
31
- attr :substrings, true
32
- attr :accept, true
33
- attr :state, true
34
- end
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
- # ルールを解析して状態遷移機械を作成し、patにマッチするもののリストを返す
56
- #
57
- def generate(pat, app = nil)
58
- res = [[],[],[]] # 曖昧度0,1,2のマッチ結果
59
- patterns = pat.split.map { |p| p.downcase }
60
-
61
- @asearch = Asearch.new(pat)
62
- scanner = Scanner.new(@s.join('|'))
63
-
64
- # HelpDataで指定した状態遷移機械全体を生成
65
- # (少し時間がかかる)
66
- (startnode, endnode) = regexp(scanner,true) # top level
67
-
68
- #
69
- # 状態遷移機械からDepth-Firstで文字列を生成する
70
- # n個のノードを経由して生成される状態の集合をlists[n]に入れる
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
- list = []
79
- list[0] = GenNode.new(startnode.id, @asearch.initstate)
80
- lists[0] = list
56
+ # ルールを解析して状態遷移機械を作成し、patにマッチするもののリストを返す
81
57
  #
82
- (0..1000).each { |length|
83
- break if app && app.inputPending
84
- list = lists[length]
85
- newlist = []
86
- # puts "#{length} - #{list.length}"
87
- list.each { |entry|
88
- srcnode = Node.node(entry.id)
89
- if list.length * srcnode.trans.length < 10000 then
90
- srcnode.trans.each { |trans|
91
- ss = entry.substrings.dup
92
- srcnode.pars.each { |i|
93
- ss[i-1] = ss[i-1].to_s + trans.arg
94
- }
95
- newstate = @asearch.state(entry.state, trans.str) # 新しいマッチング状態を計算してノードに保存
96
- s = entry.s + trans.str
97
- acceptno = trans.dest.accept
98
- newlist << GenNode.new(trans.dest.id, newstate, s, ss, acceptno)
99
- #
100
- # この時点で、マッチしているかどうかをstateとacceptpatで判断できる
101
- # マッチしてたら出力リストに加える
102
- #
103
- if acceptno then
104
- maxambig = 2
105
- (0..maxambig).each { |ambig|
106
- if !listed[ambig][s] then
107
- if (newstate[ambig] & @asearch.acceptpat) != 0 then # マッチ
108
- maxambig = ambig if ambig < maxambig # 曖昧度0でマッチすれば曖昧度1の検索は不要
109
- listed[ambig][s] = true
110
- sslen = ss.length
111
- if sslen > 0 then
112
- # patstr = "(.*)\t" * (sslen-1) + "(.*)"
113
- patstr = (["(.*)"] * sslen).join("\t")
114
- /#{patstr}/ =~ ss.join("\t")
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
- end
124
- }
125
- end
126
- }
127
- end
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
- break if newlist.length == 0
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
- startnode.pars = @pars
156
- endnode.pars = @pars
157
- (n1, n2) = regcat(s)
158
- startnode.addTrans('',n1)
159
- if toplevel then
160
- n2.accept = @ruleid
161
- end
162
- n2.addTrans('',endnode)
163
- while s.gettoken == '|' && s.nexttoken != '' do
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 += 1
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
- end
176
- s.ungettoken
177
- return [startnode, endnode]
178
- end
179
-
180
- def regcat(s) # regfactor { regfactor }
181
- (startnode, endnode) = regfactor(s)
182
- while s.gettoken !~ /^[\)\]\|]$/ && s.nexttoken != '' do
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
- (n1, n2) = regfactor(s)
185
- endnode.addTrans('',n1)
186
- endnode = n2
178
+ return [startnode, endnode]
187
179
  end
188
- s.ungettoken
189
- return [startnode, endnode]
190
- end
191
-
192
- def regfactor(s) # regterm [ '?' | '+' | '*' ]
193
- (startnode, endnode) = regterm(s)
194
- t = s.gettoken
195
- if t =~ /^[\?]$/ then
196
- startnode.addTrans('',endnode)
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
- return [startnode,endnode]
206
- end
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 == ')' then
217
- @pars.pop
218
- n2.pars = @pars.dup
219
- return [n1, n2]
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
- puts 'missing )'
222
- exit
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
- class Trans
12
- def initialize(pat,dest)
13
- # pat にマッチしたら dest に遷移
14
- @pat = pat
15
- @dest = dest
16
- end
17
-
18
- attr_reader :pat, :dest
19
-
20
- def str
21
- @pat.split(/\t/)[0].to_s
22
- end
23
-
24
- def arg
25
- if @pat =~ /^(.*)\t(.*)$/ then
26
- return $2
27
- else
28
- return @pat
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
- end
32
-
33
- class Node
34
- @@id = 1
35
- @@nodes = {}
36
-
37
- def initialize
38
- @accept = nil
39
- @trans = []
40
- @id = @@id
41
- @@nodes[@id] = self
42
- @@id += 1
43
- @pars = []
44
- end
45
-
46
- attr_reader :id
47
- attr_reader :trans
48
- attr :accept, true
49
- attr :pars, true
50
-
51
- def addTrans(pat,dest)
52
- t = Trans.new(pat,dest)
53
- @trans << t
54
- end
55
-
56
- def Node.node(id) # ノードidからノードを取得
57
- @@nodes[id.to_i]
58
- end
59
-
60
- def Node.nodes
61
- @@nodes.values
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
- class Scanner
9
- def initialize(s)
10
- @s = s
11
- @a = s.split(//)
12
- @p = 0
13
- @t = ''
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
- return ''
15
+ @u = ''
26
16
  end
27
- @t = @a[@p]
28
- if @t =~ /^[\(\|\)\*\?\[\]]$/ then
29
- @p += 1
30
- return @t
31
- elsif @t == '\\' then
32
- @p += 1
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 = "\n" if @t == 'n'
35
- @t = "\t" if @t == 't'
36
- @p += 1
37
- return @t
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
- end
47
-
48
- def ungettoken
49
- if @u == '' then
50
- @u = @t
51
- else
52
- puts "Can't ungettoken(#{token})"
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.1'
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
@@ -1,36 +1,32 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- require 'Generator'
4
-
5
- class GeneratorTest < Test::Unit::TestCase
6
- def setup
7
- end
8
-
9
- def teardown
10
- end
11
-
12
- def test_clock
13
- g = Generator.new
14
- g.add '(時計|時間|時刻)を(0|1|2|3|4|5|6|7|8|9|10|11|12)時に(セットする|設定する|あわせる)', 'set time #{$2}:00'
15
- res = g.generate(' 10 ')
16
- assert res[0].member?(['時刻を10時に設定する','set time 10:00'])
17
- assert res[0].member?(['時計を10時にセットする','set time 10:00'])
18
- assert !res[0].member?(['時計を8時にセットする','set time 8:00'])
19
- end
20
-
21
- def test_substring
22
- g = Generator.new
23
- g.add '(a)bcd(e(fg)h)i(jk)', '#{$1}/#{$2}/#{$3}/#{$4}'
24
- res = g.generate(' b ')
25
- assert res[0].member?(['abcdefghijk', 'a/efgh/fg/jk'])
26
- assert !res[0].member?(['abcdefghijk', 'a/fgh/fg/jk'])
27
- g.add '(ab|cd)efg(hij|klm)n', '#{$1}/#{$2}'
28
- res = g.generate(' ef ')
29
- assert res[0].member?(['abefghijn', 'ab/hij'])
30
- assert res[0].member?(['cdefgklmn', 'cd/klm'])
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
- require 'Scanner'
4
-
5
- class ScannerTest < Test::Unit::TestCase
6
- def setup
7
- end
8
-
9
- def teardown
10
- end
11
-
12
- def test_1
13
- s = Scanner.new('abc*def')
14
- assert_equal s.gettoken, 'abc'
15
- assert_equal s.gettoken, '*'
16
- assert_equal s.gettoken, 'def'
17
- end
18
-
19
- def test_2
20
- s = Scanner.new("(a\tb|c\td)")
21
- assert_equal s.gettoken, "("
22
- assert_equal s.gettoken, "a\tb"
23
- assert_equal s.gettoken, '|'
24
- assert_equal s.gettoken, "c\td"
25
- assert_equal s.gettoken, ')'
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: 29
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Toshiyuki Masui