rlsm 1.1.0 → 1.8.1
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/Manifest +26 -0
- data/README +10 -10
- data/Rakefile +9 -55
- data/data/monoids.db +0 -0
- data/examples/benchmark.rb +14 -0
- data/examples/creating_db.rb +52 -0
- data/examples/creating_lists.rb +185 -0
- data/examples/numbers.rb +41 -0
- data/examples/order8.rb +13 -0
- data/examples/presenting_monoids_in_tex.rb +373 -0
- data/examples/regular_monoids.rb +144 -0
- data/ext/array/array_c_ext.c +21 -12
- data/ext/monoid/monoid_c_ext.c +76 -85
- data/lib/rlsm.rb +1 -1
- data/lib/rlsm/dfa.rb +9 -8
- data/lib/rlsm/helper.rb +12 -6
- data/lib/rlsm/monoid.rb +627 -217
- data/lib/rlsm/regexp.rb +2 -1
- data/lib/rlsm/regexp_parser.rb +2 -1
- data/rlsm.gemspec +26 -0
- data/test/test_dfa.rb +16 -14
- data/test/test_monoid.rb +43 -43
- data/test/test_regexp.rb +2 -2
- metadata +51 -83
- data/ext/binop/binop_c_ext.c +0 -57
- data/ext/binop/extconf.rb +0 -2
- data/lib/rlsm/binary_operation.rb +0 -151
- data/test/test_binop.rb +0 -119
data/ext/array/array_c_ext.c
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
|
3
|
+
#ifndef RARRAY_PTR
|
4
|
+
#define RARRAY_PTR(ary) RARRAY(ary)->ptr
|
5
|
+
#endif
|
6
|
+
|
7
|
+
#ifndef RARRAY_LEN
|
8
|
+
#define RARRAY_LEN(ary) RARRAY(ary)->len
|
9
|
+
#endif
|
10
|
+
|
3
11
|
static int
|
4
12
|
c_subset_next(int* sub, int n, int k) {
|
5
13
|
int i = k - 1;
|
@@ -49,16 +57,16 @@ ary2ruby(int* subset, int k, VALUE ary) {
|
|
49
57
|
int i;
|
50
58
|
|
51
59
|
for (i=0; i < k; ++i) {
|
52
|
-
rb_ary_store(result, i,
|
60
|
+
rb_ary_store(result, i, RARRAY_PTR(ary)[subset[i]]);
|
53
61
|
}
|
54
62
|
|
55
63
|
return result;
|
56
64
|
}
|
57
65
|
|
58
66
|
static VALUE
|
59
|
-
powerset(VALUE self) {
|
67
|
+
powerset(VALUE self, VALUE ary) {
|
60
68
|
int k;
|
61
|
-
int n =
|
69
|
+
int n = RARRAY_LEN(ary);
|
62
70
|
if (!rb_block_given_p()) {
|
63
71
|
VALUE result = rb_ary_new();
|
64
72
|
for (k=0; k <= n; ++k) {
|
@@ -67,7 +75,7 @@ powerset(VALUE self) {
|
|
67
75
|
for (i=0; i < k; ++i) { subset[i] = i; }
|
68
76
|
|
69
77
|
while(1) {
|
70
|
-
rb_ary_push(result, ary2ruby(subset,k,
|
78
|
+
rb_ary_push(result, ary2ruby(subset,k,ary));
|
71
79
|
res = c_subset_next(subset, n, k);
|
72
80
|
if (res == -1)
|
73
81
|
break;
|
@@ -82,7 +90,7 @@ powerset(VALUE self) {
|
|
82
90
|
for (i=0; i < k; ++i) { subset[i] = i; }
|
83
91
|
|
84
92
|
while(1) {
|
85
|
-
rb_yield(ary2ruby(subset,k,
|
93
|
+
rb_yield(ary2ruby(subset,k,ary));
|
86
94
|
res = c_subset_next(subset, n, k);
|
87
95
|
if (res == -1)
|
88
96
|
break;
|
@@ -94,16 +102,16 @@ powerset(VALUE self) {
|
|
94
102
|
}
|
95
103
|
|
96
104
|
static VALUE
|
97
|
-
permutations(VALUE self) {
|
105
|
+
permutations(VALUE self, VALUE ary) {
|
98
106
|
int res;
|
99
|
-
int n =
|
107
|
+
int n = RARRAY_LEN(ary);
|
100
108
|
int* perm = (int*) ALLOCA_N(int, n);
|
101
109
|
int t;
|
102
110
|
for (t=0; t < n; ++t) { perm[t] = t; }
|
103
111
|
|
104
112
|
if (rb_block_given_p()) {
|
105
113
|
while(1) {
|
106
|
-
rb_yield(ary2ruby(perm, n,
|
114
|
+
rb_yield(ary2ruby(perm, n, ary));
|
107
115
|
res = c_next_perm(perm, n);
|
108
116
|
if (res == -1)
|
109
117
|
break;
|
@@ -112,7 +120,7 @@ permutations(VALUE self) {
|
|
112
120
|
else {
|
113
121
|
VALUE result = rb_ary_new();
|
114
122
|
while(1) {
|
115
|
-
rb_ary_push(result,ary2ruby(perm, n,
|
123
|
+
rb_ary_push(result,ary2ruby(perm, n, ary));
|
116
124
|
res = c_next_perm(perm, n);
|
117
125
|
if (res == -1)
|
118
126
|
break;
|
@@ -128,9 +136,10 @@ permutations(VALUE self) {
|
|
128
136
|
extern "C" {
|
129
137
|
#endif
|
130
138
|
void Init_array_cext() {
|
131
|
-
VALUE
|
132
|
-
|
133
|
-
|
139
|
+
VALUE rlsm = rb_define_module("RLSM");
|
140
|
+
VALUE ary_ext = rb_define_module_under(rlsm, "ArrayExt");
|
141
|
+
rb_define_singleton_method(ary_ext, "powerset", (VALUE(*)(ANYARGS))powerset, 1);
|
142
|
+
rb_define_singleton_method(ary_ext, "permutations", (VALUE(*)(ANYARGS))permutations, 1);
|
134
143
|
}
|
135
144
|
#ifdef __cplusplus
|
136
145
|
}
|
data/ext/monoid/monoid_c_ext.c
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
|
3
|
+
#ifndef RARRAY_PTR
|
4
|
+
#define RARRAY_PTR(ary) RARRAY(ary)->ptr
|
5
|
+
#endif
|
6
|
+
|
7
|
+
#ifndef RARRAY_LEN
|
8
|
+
#define RARRAY_LEN(ary) RARRAY(ary)->len
|
9
|
+
#endif
|
10
|
+
|
3
11
|
typedef int bool;
|
4
12
|
|
5
13
|
static int
|
6
14
|
mi_index(VALUE ary, int index) {
|
7
15
|
int i;
|
8
|
-
for (i=0; i <
|
9
|
-
if (NUM2INT(
|
16
|
+
for (i=0; i < RARRAY_LEN(ary); ++i) {
|
17
|
+
if (NUM2INT(RARRAY_PTR(ary)[i]) == index) { return i; }
|
10
18
|
}
|
11
19
|
|
12
20
|
return -1;
|
@@ -40,7 +48,7 @@ mi_helper_init_table(VALUE diagonal, int order) {
|
|
40
48
|
else if (i % order == 0)
|
41
49
|
result[i] = i / order;
|
42
50
|
else if (i % order == i / order)
|
43
|
-
result[i] = NUM2INT(
|
51
|
+
result[i] = NUM2INT(RARRAY_PTR(diagonal)[i / order]);
|
44
52
|
else
|
45
53
|
result[i] = 0;
|
46
54
|
}
|
@@ -51,9 +59,9 @@ mi_helper_init_table(VALUE diagonal, int order) {
|
|
51
59
|
static bool
|
52
60
|
mi_is_perm_stable(VALUE diagonal, VALUE perm) {
|
53
61
|
int i;
|
54
|
-
for (i=0; i <
|
55
|
-
int a = NUM2INT(
|
56
|
-
int b = NUM2INT(
|
62
|
+
for (i=0; i < RARRAY_LEN(diagonal); ++i) {
|
63
|
+
int a = NUM2INT(RARRAY_PTR(diagonal)[i]);
|
64
|
+
int b = NUM2INT(RARRAY_PTR(perm)[NUM2INT(RARRAY_PTR(diagonal)[mi_index(perm, i)])]);
|
57
65
|
|
58
66
|
if ( a != b)
|
59
67
|
return 0;
|
@@ -62,25 +70,13 @@ mi_is_perm_stable(VALUE diagonal, VALUE perm) {
|
|
62
70
|
return 1;
|
63
71
|
}
|
64
72
|
|
65
|
-
static bool
|
66
|
-
mi_is_invertable(VALUE diag, int index) {
|
67
|
-
int i, pot = NUM2INT(RARRAY(diag)->ptr[index]);
|
68
|
-
|
69
|
-
for (i=0; i < RARRAY(diag)->len; ++i) {
|
70
|
-
if (pot == 0) { return 1; }
|
71
|
-
pot = NUM2INT(RARRAY(diag)->ptr[pot]);
|
72
|
-
}
|
73
|
-
|
74
|
-
return 0;
|
75
|
-
}
|
76
|
-
|
77
73
|
static VALUE
|
78
74
|
mi_helper_select_perms(VALUE diagonal, VALUE perms, int order) {
|
79
75
|
VALUE result = rb_ary_new();
|
80
76
|
VALUE perm;
|
81
77
|
int i;
|
82
|
-
for (i=0; i <
|
83
|
-
perm =
|
78
|
+
for (i=0; i < RARRAY_LEN(perms); ++i) {
|
79
|
+
perm = RARRAY_PTR(perms)[i];
|
84
80
|
if (mi_is_perm_stable(diagonal, perm))
|
85
81
|
rb_ary_push(result, perm);
|
86
82
|
}
|
@@ -88,36 +84,19 @@ mi_helper_select_perms(VALUE diagonal, VALUE perms, int order) {
|
|
88
84
|
return result;
|
89
85
|
}
|
90
86
|
|
91
|
-
static int*
|
92
|
-
mi_helper_rc_restrictions(VALUE diagonal, int order) {
|
93
|
-
int* result = (int*) calloc(order, sizeof(int));
|
94
|
-
result[0] = 1;
|
95
|
-
|
96
|
-
int i;
|
97
|
-
for (i=1; i < order; ++i) {
|
98
|
-
result[i] = 1;
|
99
|
-
if (NUM2INT(RARRAY(diagonal)->ptr[i]) == i)
|
100
|
-
result[i] *= 2; /* idempotent */
|
101
|
-
if (mi_is_invertable(diagonal, i))
|
102
|
-
result[i] *= 3; /* invertible */
|
103
|
-
}
|
104
|
-
|
105
|
-
return result;
|
106
|
-
}
|
107
|
-
|
108
87
|
static bool
|
109
88
|
mi_is_diagonal_valid(int* diagonal, int ord, VALUE perms) {
|
110
89
|
int i,j;
|
111
90
|
VALUE perm;
|
112
|
-
for (i=0; i <
|
113
|
-
perm =
|
91
|
+
for (i=0; i < RARRAY_LEN(perms); ++i) {
|
92
|
+
perm = RARRAY_PTR(perms)[i];
|
114
93
|
|
115
94
|
for (j=0; j < ord; ++j) {
|
116
95
|
int ii, pdii;
|
117
96
|
ii = mi_index(perm, j);
|
118
97
|
if (diagonal[ii] == -1) { break; }
|
119
98
|
|
120
|
-
pdii = NUM2INT(
|
99
|
+
pdii = NUM2INT(RARRAY_PTR(perm)[diagonal[ii]]);
|
121
100
|
if (diagonal[j] < pdii) { break; }
|
122
101
|
if (diagonal[j] > pdii) { return 0; }
|
123
102
|
}
|
@@ -162,9 +141,9 @@ mi_is_iso_antiiso(const int* table, int order, VALUE perms) {
|
|
162
141
|
int max_index = order*order;
|
163
142
|
VALUE perm;
|
164
143
|
|
165
|
-
for (p = 0; p <
|
144
|
+
for (p = 0; p < RARRAY_LEN(perms); ++p) {
|
166
145
|
int smaller_iso = 0, smaller_aiso = 0;
|
167
|
-
perm =
|
146
|
+
perm = RARRAY_PTR(perms)[p];
|
168
147
|
for (i = order+1; i < max_index; ++i) {
|
169
148
|
int ix1, ix2, ti, tii, taii, ptii, ptaii;
|
170
149
|
ix1 = mi_index(perm, i / order);
|
@@ -177,8 +156,8 @@ mi_is_iso_antiiso(const int* table, int order, VALUE perms) {
|
|
177
156
|
if (ti == -1 || tii == -1 || taii == -1 )
|
178
157
|
break;
|
179
158
|
|
180
|
-
ptii = NUM2INT(
|
181
|
-
ptaii = NUM2INT(
|
159
|
+
ptii = NUM2INT(RARRAY_PTR(perm)[tii]);
|
160
|
+
ptaii = NUM2INT(RARRAY_PTR(perm)[taii]);
|
182
161
|
|
183
162
|
if (ti < ptii)
|
184
163
|
smaller_iso = 1;
|
@@ -197,40 +176,9 @@ mi_is_iso_antiiso(const int* table, int order, VALUE perms) {
|
|
197
176
|
return 1;
|
198
177
|
}
|
199
178
|
|
200
|
-
static bool
|
201
|
-
mi_is_rc_rest_satisfied(const int* table, int order, const int* rc_rest) {
|
202
|
-
int i,j,k;
|
203
|
-
for (i=1; i < order; ++i) {
|
204
|
-
if (rc_rest[i] != 1) {
|
205
|
-
if (rc_rest[i] % 2 == 0) {
|
206
|
-
for (j=1; j < order; ++j) {
|
207
|
-
if (table[order*i + j] == 0 || table[order*j + i] == 0)
|
208
|
-
return 0;
|
209
|
-
}
|
210
|
-
}
|
211
|
-
|
212
|
-
if (rc_rest[i] % 3 == 0) {
|
213
|
-
for (j=0; j < order; ++j) {
|
214
|
-
for (k=j+1; k < order; ++k) {
|
215
|
-
if (table[order*i + j] != -1 && table[order*i + j] == table[order*i + k] )
|
216
|
-
return 0;
|
217
|
-
if (table[order*j + i] != -1 && table[order*j + i] == table[order*k + i])
|
218
|
-
return 0;
|
219
|
-
|
220
|
-
}
|
221
|
-
}
|
222
|
-
}
|
223
|
-
}
|
224
|
-
}
|
225
|
-
|
226
|
-
return 1;
|
227
|
-
}
|
228
179
|
|
229
180
|
static bool
|
230
|
-
mi_table_valid(const int* table, int order,
|
231
|
-
if (!mi_is_rc_rest_satisfied(table, order, rc_rest))
|
232
|
-
return 0;
|
233
|
-
|
181
|
+
mi_table_valid(const int* table, int order, VALUE perms) {
|
234
182
|
if (!mi_is_associative(table, order))
|
235
183
|
return 0;
|
236
184
|
|
@@ -253,7 +201,7 @@ each_diagonal(VALUE self, VALUE rorder, VALUE perms) {
|
|
253
201
|
while(1) {
|
254
202
|
diagonal[index]++;
|
255
203
|
if (diagonal[index] >= order) {
|
256
|
-
if (index == 1) { return; } /* finished */
|
204
|
+
if (index == 1) { return Qnil; } /* finished */
|
257
205
|
diagonal[index] = -1;
|
258
206
|
index--;
|
259
207
|
}
|
@@ -270,25 +218,24 @@ each_diagonal(VALUE self, VALUE rorder, VALUE perms) {
|
|
270
218
|
|
271
219
|
static VALUE
|
272
220
|
e_w_diagonal(VALUE self, VALUE diagonal, VALUE perms) {
|
273
|
-
int order =
|
221
|
+
int order = RARRAY_LEN(diagonal), t_order = order*order;
|
274
222
|
int* table = mi_helper_init_table(diagonal, order);
|
275
223
|
VALUE rperms = mi_helper_select_perms(diagonal, perms, order);
|
276
|
-
int* rc_rest = mi_helper_rc_restrictions(diagonal, order);
|
277
224
|
|
278
|
-
if (mi_table_valid(table, order,
|
225
|
+
if (mi_table_valid(table, order, rperms)) { rb_yield(mi_ary2rb(table, t_order)); }
|
279
226
|
|
280
227
|
int index = t_order - 2;
|
281
228
|
while (1) {
|
282
229
|
table[index]++;
|
283
230
|
if (table[index] >= order) {
|
284
|
-
if (index <= order + 2) { return; } /* finished */
|
231
|
+
if (index <= order + 2) { return Qnil; } /* finished */
|
285
232
|
table[index] = -1;
|
286
233
|
index--;
|
287
234
|
/* skip diagonal and first column */
|
288
235
|
if ((index % order == index / order) || (index % order == 0))
|
289
236
|
index--;
|
290
237
|
}
|
291
|
-
else if (mi_table_valid(table, order,
|
238
|
+
else if (mi_table_valid(table, order, rperms)) {
|
292
239
|
if (index == t_order - 2)
|
293
240
|
rb_yield(mi_ary2rb(table, t_order));
|
294
241
|
else {
|
@@ -307,14 +254,56 @@ static VALUE
|
|
307
254
|
e_pos(VALUE self, VALUE table, VALUE rorder) {
|
308
255
|
int i, order = NUM2INT(rorder);
|
309
256
|
for(i=0; i < order; ++i) {
|
310
|
-
if (NUM2INT(
|
311
|
-
rb_raise(rb_const_get(
|
257
|
+
if (NUM2INT(RARRAY_PTR(table)[i]) != i || NUM2INT(RARRAY_PTR(table)[order*i]) != i) {
|
258
|
+
rb_raise(rb_const_get(rb_define_module("RLSM"), rb_intern("Error")), "Neutral element isn't in first row.");
|
312
259
|
}
|
313
260
|
}
|
314
261
|
|
315
262
|
return Qnil;
|
316
263
|
}
|
317
264
|
|
265
|
+
static VALUE
|
266
|
+
non_associative_triple(VALUE self) {
|
267
|
+
VALUE table = rb_iv_get(self, "@table");
|
268
|
+
VALUE max = NUM2INT(rb_iv_get(self, "@order"));
|
269
|
+
VALUE base = rb_iv_get(self, "@elements");
|
270
|
+
|
271
|
+
int i,j,k;
|
272
|
+
for (i=0; i < max; ++i) {
|
273
|
+
for (j=0; j < max; ++j) {
|
274
|
+
for (k=0; k < max; ++k) {
|
275
|
+
int ij,jk, i_jk, ij_k;
|
276
|
+
ij = NUM2INT(RARRAY_PTR(table)[max*i + j]);
|
277
|
+
jk = NUM2INT(RARRAY_PTR(table)[max*j + k]);
|
278
|
+
i_jk = NUM2INT(RARRAY_PTR(table)[max*i + jk]);
|
279
|
+
ij_k = NUM2INT(RARRAY_PTR(table)[max*ij + k]);
|
280
|
+
if (ij_k != i_jk) {
|
281
|
+
return (rb_ary_new3(3,RARRAY_PTR(base)[i],RARRAY_PTR(base)[j],RARRAY_PTR(base)[k]));
|
282
|
+
}
|
283
|
+
}
|
284
|
+
}
|
285
|
+
}
|
286
|
+
|
287
|
+
return (Qnil);
|
288
|
+
}
|
289
|
+
|
290
|
+
static VALUE
|
291
|
+
is_commutative(VALUE self) {
|
292
|
+
VALUE table = rb_iv_get(self, "@table");
|
293
|
+
VALUE max = NUM2INT(rb_iv_get(self, "@order"));
|
294
|
+
|
295
|
+
int i,j;
|
296
|
+
for (i=0; i < max; ++i) {
|
297
|
+
for (j=0; j < max; ++j) {
|
298
|
+
if (NUM2INT(RARRAY_PTR(table)[max*i + j]) != NUM2INT(RARRAY_PTR(table)[max*j + i]))
|
299
|
+
return (Qfalse);
|
300
|
+
}
|
301
|
+
}
|
302
|
+
|
303
|
+
return (Qtrue);
|
304
|
+
}
|
305
|
+
|
306
|
+
|
318
307
|
#ifdef __cplusplus
|
319
308
|
extern "C" {
|
320
309
|
#endif
|
@@ -323,7 +312,9 @@ extern "C" {
|
|
323
312
|
VALUE monoid = rb_define_class_under(rlsm, "Monoid", rb_cObject);
|
324
313
|
rb_define_singleton_method(monoid, "each_diagonal", (VALUE(*)(ANYARGS))each_diagonal, 2);
|
325
314
|
rb_define_singleton_method(monoid, "each_with_diagonal", (VALUE(*)(ANYARGS))e_w_diagonal, 2);
|
326
|
-
|
315
|
+
rb_define_method(monoid, "enforce_identity_position", (VALUE(*)(ANYARGS))e_pos, 2);
|
316
|
+
rb_define_method(monoid, "is_commutative", (VALUE(*)(ANYARGS))is_commutative, 0);
|
317
|
+
rb_define_method(monoid, "non_associative_triple", (VALUE(*)(ANYARGS))non_associative_triple, 0);
|
327
318
|
}
|
328
319
|
#ifdef __cplusplus
|
329
320
|
}
|
data/lib/rlsm.rb
CHANGED
data/lib/rlsm/dfa.rb
CHANGED
@@ -6,6 +6,7 @@ RLSM::require_extension('array')
|
|
6
6
|
require "strscan"
|
7
7
|
|
8
8
|
module RLSM
|
9
|
+
# @private
|
9
10
|
class DFA
|
10
11
|
#Synonym for new.
|
11
12
|
def self.[](description)
|
@@ -65,7 +66,7 @@ module RLSM
|
|
65
66
|
#Processes given +string+ starting in state +state+.
|
66
67
|
def [](state, string)
|
67
68
|
unless @states.include?(state)
|
68
|
-
raise
|
69
|
+
raise RLSM::Error, "Unknown state: #{state}"
|
69
70
|
end
|
70
71
|
|
71
72
|
present_state = state
|
@@ -92,7 +93,7 @@ module RLSM
|
|
92
93
|
|
93
94
|
#Checks if given +state+ is dead, i.e. its not a final state and it hs no outgoing transitions.
|
94
95
|
def dead?(state)
|
95
|
-
raise
|
96
|
+
raise RLSM::Error, "Unknown state: #{state}" unless @states.include?(state)
|
96
97
|
|
97
98
|
state != @initial_state and
|
98
99
|
! @final_states.include?(state) and
|
@@ -101,7 +102,7 @@ module RLSM
|
|
101
102
|
|
102
103
|
#Checks if given +state+ is reachable, i.e. it exists a +string+, such that <tt>self << string == state</tt> is true.
|
103
104
|
def reachable?(state)
|
104
|
-
raise
|
105
|
+
raise RLSM::Error, "Unknown state: #{state}" unless @states.include?(state)
|
105
106
|
|
106
107
|
reachable_states.include? state
|
107
108
|
end
|
@@ -312,7 +313,7 @@ module RLSM
|
|
312
313
|
end
|
313
314
|
|
314
315
|
def bijective_maps_to(other)
|
315
|
-
bijective_maps = other.states.
|
316
|
+
bijective_maps = RLSM::ArrayExt::permutations(other.states).map do |perm|
|
316
317
|
Hash[*@states.zip(perm).flatten]
|
317
318
|
end
|
318
319
|
|
@@ -391,7 +392,7 @@ module RLSM
|
|
391
392
|
|
392
393
|
def parse_initial_state(description)
|
393
394
|
unless description.count('}') == 1
|
394
|
-
raise
|
395
|
+
raise RLSM::Error, "None or at least two initial states."
|
395
396
|
end
|
396
397
|
|
397
398
|
@initial_state = description[/\}\s*\*?(\w+)/,1]
|
@@ -436,14 +437,14 @@ module RLSM
|
|
436
437
|
elsif parser.scan(/\w+/)
|
437
438
|
#do nothing (states already parsed)
|
438
439
|
else
|
439
|
-
raise
|
440
|
+
raise RLSM::Error, "Parse Error, could not parse #{description}"
|
440
441
|
end
|
441
442
|
|
442
443
|
break unless parser.scan(/ /)
|
443
444
|
end
|
444
445
|
|
445
446
|
unless parser.eos?
|
446
|
-
raise
|
447
|
+
raise RLSM::Error, "Parse Error, could not parse #{description}"
|
447
448
|
end
|
448
449
|
|
449
450
|
@alphabet = @alphabet.sort
|
@@ -466,7 +467,7 @@ module RLSM
|
|
466
467
|
if trans[label].nil?
|
467
468
|
trans[label] = destination
|
468
469
|
elsif trans[label] != destination
|
469
|
-
raise
|
470
|
+
raise RLSM::Error, "Parse Error: Transition labels must be uniq."
|
470
471
|
end
|
471
472
|
end
|
472
473
|
end
|