asmodis-rlsm 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENCE +674 -0
- data/README +35 -0
- data/lib/dfa.rb +686 -0
- data/lib/mgen.rb +130 -0
- data/lib/monkey_patching.rb +109 -0
- data/lib/monoid.rb +533 -0
- data/lib/rlsm.rb +22 -0
- data/lib/rlsm_regexp.rb +584 -0
- data/spec/dfa_spec.rb +99 -0
- data/spec/monoid_spec.rb +270 -0
- data/spec/regexp_spec.rb +25 -0
- metadata +64 -0
data/spec/dfa_spec.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'dfa')
|
2
|
+
|
3
|
+
describe RLSM::DFA do
|
4
|
+
before :each do
|
5
|
+
@dfa = RLSM::DFA.new ['a'],[0],0,[0],[['a',0,0]]
|
6
|
+
@dfa2 = RLSM::DFA.new( ['a', 'b'], [0,1,2], 0, [2],
|
7
|
+
[['a',0,0], ['a',1,2], ['a',2,2],
|
8
|
+
['b',0,1], ['b',1,1], ['b',2,2]])
|
9
|
+
@dfa3 = RLSM::DFA.new( ['a', 'b'], [0,1,2], 0, [2],
|
10
|
+
[['a',0,0], ['a',1,2], ['a',2,2],
|
11
|
+
['b',0,1], ['b',1,1]])
|
12
|
+
|
13
|
+
@dfa4 = RLSM::DFA.new( ['a', 'b'], [0,1,2,3,4], 0, [2,3],
|
14
|
+
[['a',0,0], ['a',1,2], ['a',2,2],
|
15
|
+
['b',0,1], ['b',1,1],
|
16
|
+
['a',3,4], ['a',4,3], ['b',3,2]])
|
17
|
+
|
18
|
+
@dfa5 = RLSM::DFA.new( ['a', 'b'], [0,1,2], 0, [1],
|
19
|
+
[['a',0,0], ['a',1,2], ['a',2,2],
|
20
|
+
['b',0,1], ['b',1,1]])
|
21
|
+
|
22
|
+
@dfa5b = RLSM::DFA.new( ['a', 'b'], [0,1,'c'], 0, [1],
|
23
|
+
[['a',0,0], ['a',1,'c'], ['a','c','c'],
|
24
|
+
['b',0,1], ['b',1,1]])
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should have an initial state" do
|
28
|
+
@dfa.initial_state.should_not be_nil
|
29
|
+
@dfa.initial_state.label.should == '0'
|
30
|
+
@dfa2.initial_state.should_not be_nil
|
31
|
+
@dfa2.initial_state.label.should == '0'
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should know the number of states" do
|
35
|
+
@dfa.num_states.should == 1
|
36
|
+
@dfa2.num_states.should == 3
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should know the number of final states" do
|
40
|
+
@dfa.num_finals.should == 1
|
41
|
+
@dfa2.num_finals.should == 1
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should know if it is complete" do
|
45
|
+
@dfa.complete?.should == true
|
46
|
+
@dfa2.complete?.should == true
|
47
|
+
@dfa3.complete?.should == false
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should complete a non complete DFA if requested" do
|
51
|
+
@dfa3.complete.should be_complete
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should find dead states" do
|
55
|
+
[@dfa,@dfa2,@dfa3].each { |d| d.dead_states?.should == false }
|
56
|
+
|
57
|
+
@dfa5.dead_states?.should == true
|
58
|
+
@dfa5.dead_states.map { |s| s.label }.should == ['2']
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should find unreachable states" do
|
62
|
+
[@dfa,@dfa2,@dfa3].each { |d| d.unreachable_states?.should == false }
|
63
|
+
|
64
|
+
@dfa4.unreachable_states?.should == true
|
65
|
+
@dfa4.unreachable_states.size.should == 2
|
66
|
+
@dfa4.unreachable_states.map { |s| s.label }.sort.should == ['3','4']
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should remove dead states" do
|
70
|
+
@dfa5.remove_dead_states.states.map { |s| s.label }.should == ['0','1']
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should remove unreachable states" do
|
74
|
+
d = @dfa4.remove_unreachable_states
|
75
|
+
d.states.map { |s| s.label }.sort.should == ['0','1','2']
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should minimize a DFA" do
|
79
|
+
d = RLSM::DFA.new(['a','b','c'], [0,1,2,3,4], 0, [4],
|
80
|
+
[['a',0,1], ['b',0,2], ['c',1,3], ['c',2,3], ['c',3,4]])
|
81
|
+
|
82
|
+
d.minimize!
|
83
|
+
d.states.map { |s| s.label }.sort.should == ['0','12', '3','4']
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should check for isomorphisms" do
|
87
|
+
@dfa2.should be_isomorph_to(@dfa2)
|
88
|
+
@dfa5.should be_isomorph_to(@dfa5b)
|
89
|
+
@dfa3.should_not be_isomorph_to(@dfa2)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should calculate the transition monoid" do
|
93
|
+
@dfa.transition_monoid.should == RLSM::Monoid.new('0')
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should caclulate a RegExp representation" do
|
97
|
+
@dfa.to_regexp.to_s.should == 'a*'
|
98
|
+
end
|
99
|
+
end
|
data/spec/monoid_spec.rb
ADDED
@@ -0,0 +1,270 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'monoid')
|
2
|
+
|
3
|
+
describe RLSM::Monoid, "basic stuff" do
|
4
|
+
before :each do
|
5
|
+
@m1 = RLSM::Monoid.new '0'
|
6
|
+
@m2 = RLSM::Monoid.new '00 01' #-> 01 11
|
7
|
+
@m3 = RLSM::Monoid.new '012 112 212'
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should have '0' as the neutral element" do
|
11
|
+
@m1[0,0].should == 0
|
12
|
+
|
13
|
+
[0,1].each { |x| @m2[0,x].should == x; @m2[x,0].should == x }
|
14
|
+
[0,1,2].each { |x| @m3[0,x].should == x; @m3[x,0].should == x }
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should decide if an other monoid is isomorphic" do
|
18
|
+
@m2.should == RLSM::Monoid.new('01 11')
|
19
|
+
@m3.should == RLSM::Monoid.new('002 012 022')
|
20
|
+
|
21
|
+
@m2.should_not == @m3
|
22
|
+
|
23
|
+
@m2.should_not == RLSM::Monoid.new('01 10')
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
describe RLSM::Monoid do
|
29
|
+
before :each do
|
30
|
+
@m0 = RLSM::Monoid.new '0'
|
31
|
+
@m1 = RLSM::Monoid.new '01 11'
|
32
|
+
@m2 = RLSM::Monoid.new '0123 1032 2323 3232'
|
33
|
+
end
|
34
|
+
|
35
|
+
[[],[0],[1], [2], [1,2], [1,3], [2,3], [1,2,3]].each do |set|
|
36
|
+
@m0 = RLSM::Monoid.new '0'
|
37
|
+
@m1 = RLSM::Monoid.new '01 11'
|
38
|
+
@m2 = RLSM::Monoid.new '0123 1032 2323 3232'
|
39
|
+
|
40
|
+
case set
|
41
|
+
when [], [0]
|
42
|
+
[@m0, @m1, @m2].each do |m|
|
43
|
+
it "should calculate the submonoid of #{m} generated by #{set}" do
|
44
|
+
sm = m.get_submonoid(set)
|
45
|
+
sm.should_not be_nil
|
46
|
+
sm.should == RLSM::Monoid.new('0')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
when [1]
|
50
|
+
it "should calculate the submonoid of #{@m1} generated by #{set}" do
|
51
|
+
@m1.get_submonoid(set).should == @m1
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should calculate the submonoid of #{@m2} generated by #{set}" do
|
55
|
+
@m2.get_submonoid(set).should == RLSM::Monoid.new('01 10')
|
56
|
+
end
|
57
|
+
when [2]
|
58
|
+
it "should calculate the submonoid of #{@m2} generated by #{set}" do
|
59
|
+
@m2.get_submonoid(set).should == @m1
|
60
|
+
end
|
61
|
+
when [1,2]
|
62
|
+
it "should calculate the submonoid of #{@m2} generated by #{set}" do
|
63
|
+
@m2.get_submonoid(set).should == @m2
|
64
|
+
end
|
65
|
+
when [1,3]
|
66
|
+
it "should calculate the submonoid of #{@m2} generated by #{set}" do
|
67
|
+
@m2.get_submonoid(set).should == @m2
|
68
|
+
end
|
69
|
+
when [2,3]
|
70
|
+
it "should calculate the submonoid of #{@m2} generated by #{set}" do
|
71
|
+
@m2.get_submonoid(set).should == RLSM::Monoid.new('012 112 221')
|
72
|
+
end
|
73
|
+
when [1,2,3]
|
74
|
+
it "should calculate the submonoid of #{@m2} generated by #{set}" do
|
75
|
+
@m2.get_submonoid(set).should == @m2
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should calculate the generator subset of #{RLSM::Monoid.new('0')}" do
|
81
|
+
RLSM::Monoid.new('0').generating_subset.should == []
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should calculate the generator subset of #{RLSM::Monoid.new('01 11')}" do
|
85
|
+
RLSM::Monoid.new('01 11').generating_subset.should == [1]
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should calculate the generator subset of #{RLSM::Monoid.new('0123 1032 2323 3232')}" do
|
89
|
+
RLSM::Monoid.new('0123 1032 2323 3232').generating_subset.should == [1,2]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
describe RLSM::Monoid do
|
95
|
+
before :each do
|
96
|
+
@m1 = RLSM::Monoid.new '012345 113315 245255 315355 442245 555555'
|
97
|
+
@m2 = RLSM::Monoid.new '012345 103254 235454 324545 455454 544545'
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should calculate left ideals of elements" do
|
101
|
+
@m1.left_ideal_of(0).should == [0,1,2,3,4,5]
|
102
|
+
@m1.left_ideal_of(1).should == [1,4,5]
|
103
|
+
@m1.left_ideal_of(2).should == [2,3,5]
|
104
|
+
@m1.left_ideal_of(3).should == [2,3,5]
|
105
|
+
@m1.left_ideal_of(4).should == [1,4,5]
|
106
|
+
@m1.left_ideal_of(5).should == [5]
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should calculate right ideals of elements" do
|
110
|
+
@m1.right_ideal_of(0).should == [0,1,2,3,4,5]
|
111
|
+
@m1.right_ideal_of(1).should == [1,3,5]
|
112
|
+
@m1.right_ideal_of(2).should == [2,4,5]
|
113
|
+
@m1.right_ideal_of(3).should == [1,3,5]
|
114
|
+
@m1.right_ideal_of(4).should == [2,4,5]
|
115
|
+
@m1.right_ideal_of(5).should == [5]
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should calculate ideals of elements" do
|
119
|
+
@m1.ideal_of(0).should == [0,1,2,3,4,5]
|
120
|
+
@m1.ideal_of(1).should == [1,2,3,4,5]
|
121
|
+
@m1.ideal_of(2).should == [1,2,3,4,5]
|
122
|
+
@m1.ideal_of(3).should == [1,2,3,4,5]
|
123
|
+
@m1.ideal_of(4).should == [1,2,3,4,5]
|
124
|
+
@m1.ideal_of(5).should == [5]
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should calculate L-classes of elements" do
|
128
|
+
@m1.l_class_of(0).should == [0]
|
129
|
+
@m1.l_class_of(1).should == [1,4]
|
130
|
+
@m1.l_class_of(2).should == [2,3]
|
131
|
+
@m1.l_class_of(3).should == [2,3]
|
132
|
+
@m1.l_class_of(4).should == [1,4]
|
133
|
+
@m1.l_class_of(5).should == [5]
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should calculate R-classes of elements" do
|
137
|
+
@m1.r_class_of(0).should == [0]
|
138
|
+
@m1.r_class_of(1).should == [1,3]
|
139
|
+
@m1.r_class_of(2).should == [2,4]
|
140
|
+
@m1.r_class_of(3).should == [1,3]
|
141
|
+
@m1.r_class_of(4).should == [2,4]
|
142
|
+
@m1.r_class_of(5).should == [5]
|
143
|
+
end
|
144
|
+
|
145
|
+
# it "should calculate J-classes of elements" do
|
146
|
+
# @m1.j_class_of(0).should == [0]
|
147
|
+
# @m1.j_class_of(1).should == [1,2,3,4]
|
148
|
+
# @m1.j_class_of(2).should == [1,2,3,4]
|
149
|
+
# @m1.j_class_of(3).should == [1,2,3,4]
|
150
|
+
# @m1.j_class_of(4).should == [1,2,3,4]
|
151
|
+
# @m1.j_class_of(5).should == [5]
|
152
|
+
# end
|
153
|
+
|
154
|
+
it "should calculate H-classes of elements" do
|
155
|
+
@m1.h_class_of(0).should == [0]
|
156
|
+
@m1.h_class_of(1).should == [1]
|
157
|
+
@m1.h_class_of(2).should == [2]
|
158
|
+
@m1.h_class_of(3).should == [3]
|
159
|
+
@m1.h_class_of(4).should == [4]
|
160
|
+
@m1.h_class_of(5).should == [5]
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should calculate D-classes of elements" do
|
164
|
+
@m1.d_class_of(0).should == [0]
|
165
|
+
@m1.d_class_of(1).should == [1,2,3,4]
|
166
|
+
@m1.d_class_of(2).should == [1,2,3,4]
|
167
|
+
@m1.d_class_of(3).should == [1,2,3,4]
|
168
|
+
@m1.d_class_of(4).should == [1,2,3,4]
|
169
|
+
@m1.d_class_of(5).should == [5]
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should detect aperiodicity" do
|
173
|
+
@m1.aperiodic?.should == true
|
174
|
+
@m2.aperiodic?.should == false
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe RLSM::Monoid do
|
179
|
+
before :each do
|
180
|
+
@m1 = RLSM::Monoid.new '0'
|
181
|
+
@m2 = RLSM::Monoid.new '01 10'
|
182
|
+
@m3 = RLSM::Monoid.new '01 11'
|
183
|
+
@m4 = RLSM::Monoid.new '012 102 222'
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should detect a null element" do
|
187
|
+
@m1.null_element.should == false
|
188
|
+
@m2.null_element.should == false
|
189
|
+
@m3.null_element.should == 1
|
190
|
+
@m4.null_element.should == 2
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should detect idempotent elements" do
|
194
|
+
[@m1, @m2, @m3].each { |m| m.idempotent?(0).should == true }
|
195
|
+
@m2.idempotent?(1).should == false
|
196
|
+
@m3.idempotent?(1).should == true
|
197
|
+
@m4.idempotent?(2).should == true
|
198
|
+
@m4.idempotent?(1).should == false
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should find all idempotents" do
|
202
|
+
@m1.idempotents.should == [0]
|
203
|
+
@m2.idempotents.should == [0]
|
204
|
+
@m3.idempotents.should == [0,1]
|
205
|
+
@m4.idempotents.should == [0,2]
|
206
|
+
end
|
207
|
+
|
208
|
+
it "should decide if all elements are idempotent" do
|
209
|
+
@m1.idempotent?.should == true
|
210
|
+
@m2.idempotent?.should == false
|
211
|
+
@m3.idempotent?.should == true
|
212
|
+
@m4.idempotent?.should == false
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
describe RLSM::Monoid do
|
217
|
+
before :each do
|
218
|
+
@m1 = RLSM::Monoid.new('0123 1032 2323 3232')
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should calculate all submonoids of a given order upto to isomorphie" do
|
222
|
+
@m1.submonoids_of_order(1).should == [RLSM::Monoid.new('0')]
|
223
|
+
@m1.submonoids_of_order(2).should == [RLSM::Monoid.new('01 10'), RLSM::Monoid.new('01 11')]
|
224
|
+
@m1.submonoids_of_order(3).should == [RLSM::Monoid.new('012 112 221')]
|
225
|
+
@m1.submonoids_of_order(4).should == [@m1]
|
226
|
+
end
|
227
|
+
|
228
|
+
it "should calculate all submonoids upto to isomorphie" do
|
229
|
+
@m1.submonoids.should == [RLSM::Monoid.new('0'), RLSM::Monoid.new('01 10'), RLSM::Monoid.new('01 11'),RLSM::Monoid.new('012 112 221'), @m1]
|
230
|
+
|
231
|
+
RLSM::Monoid.new('0').submonoids.should == [RLSM::Monoid.new('0')]
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should calculate all proper submonoids upto to isomorphie" do
|
235
|
+
@m1.proper_submonoids.should == [RLSM::Monoid.new('01 10'), RLSM::Monoid.new('01 11'),RLSM::Monoid.new('012 112 221')]
|
236
|
+
|
237
|
+
RLSM::Monoid.new('0').proper_submonoids.should == []
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
describe RLSM::Monoid do
|
242
|
+
['0', '01 11', '012 112 212', '01234 11111 21212 31133 41234'].each do |tab|
|
243
|
+
it "should detect syntacticity of #{tab}" do
|
244
|
+
RLSM::Monoid.new(tab).syntactic?.should == true
|
245
|
+
end
|
246
|
+
|
247
|
+
it "should find a disjunctive subset of #{tab}" do
|
248
|
+
case tab
|
249
|
+
when '0'
|
250
|
+
RLSM::Monoid.new(tab).disjunctive_subset.should == []
|
251
|
+
when '01 11'
|
252
|
+
RLSM::Monoid.new(tab).disjunctive_subset.should == [0]
|
253
|
+
when '012 112 212'
|
254
|
+
RLSM::Monoid.new(tab).disjunctive_subset.should == [1]
|
255
|
+
when '01234 11111 21212 31133 41234'
|
256
|
+
RLSM::Monoid.new(tab).disjunctive_subset.should == [0,4]
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
['0123 1111 2222 3333', '01234 10234 22222 33222 44222'].each do |tab|
|
262
|
+
it "should detect nonsyntacticity of #{tab}" do
|
263
|
+
RLSM::Monoid.new(tab).syntactic?.should == false
|
264
|
+
end
|
265
|
+
|
266
|
+
it "should not find a disjunctive subset of #{tab}" do
|
267
|
+
RLSM::Monoid.new(tab).disjunctive_subset.should be_nil
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
data/spec/regexp_spec.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'dfa')
|
2
|
+
|
3
|
+
describe RLSM::RegExp do
|
4
|
+
['(ab', '(|ab)', '(ab|)', 'ab(*)', '(*a|b)', 'ab()cd'].each do |str|
|
5
|
+
it "should raise error for input #{str}" do
|
6
|
+
lambda { RLSM::RegExp.new str }.should raise_error(Exception)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
['', '&', 'a', 'a|b', 'ab', '(a|b)c', '(a*|bc&&&d)|abc|(a|b|c)*'].each do |s|
|
11
|
+
it "should accept the input #{s}" do
|
12
|
+
lambda { RLSM::RegExp.new s }.should_not raise_error(Exception)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should simplify a input" do
|
17
|
+
RLSM::RegExp.new('a&&**&&c***(bbbcccaa)**').to_s.should == 'ac*(bbbcccaa)*'
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should convert a regexp to an dfa" do
|
21
|
+
dfa1 = RLSM::RegExp.new('(a|b)aa*(&|b)a*').to_dfa
|
22
|
+
dfa1.states.size.should == 4
|
23
|
+
dfa1.final_states.map {|f| f.label}.sort.should == ['1', '2'].sort
|
24
|
+
end
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: asmodis-rlsm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- asmodis
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-10-19 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: RLSM contains the three classes DFA, Monoid and REgExp for work with regular languages.
|
17
|
+
email: g.diemant@gmx.net
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
- LICENCE
|
25
|
+
files:
|
26
|
+
- LICENCE
|
27
|
+
- README
|
28
|
+
- lib/monkey_patching.rb
|
29
|
+
- lib/monoid.rb
|
30
|
+
- lib/mgen.rb
|
31
|
+
- lib/rlsm_regexp.rb
|
32
|
+
- lib/dfa.rb
|
33
|
+
- lib/rlsm.rb
|
34
|
+
has_rdoc: true
|
35
|
+
homepage: http://github.org/asmodis/rlsm
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options:
|
38
|
+
- --main
|
39
|
+
- README
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
version:
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
version:
|
54
|
+
requirements: []
|
55
|
+
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 1.2.0
|
58
|
+
signing_key:
|
59
|
+
specification_version: 2
|
60
|
+
summary: Classes for work with formal languages
|
61
|
+
test_files:
|
62
|
+
- spec/monoid_spec.rb
|
63
|
+
- spec/dfa_spec.rb
|
64
|
+
- spec/regexp_spec.rb
|