compiler/ lib/ examples/ std/ arch/ rv64/ tests/ abi.sizes.rad 3.4 KiB aggregate.return.rad 4.0 KiB arith.assignment.rad 580 B arith.basic.rad 176 B arith.modulo.rad 96 B arith.subword.rad 3.8 KiB arith.sum.rad 177 B arith.w64.rad 4.1 KiB array.assign.rad 221 B array.bounds.check.rad 321 B array.index.assign.rad 367 B array.index.rad 249 B array.length.rad 262 B array.math.rad 1.2 KiB array.nested.assign.rad 319 B array.nested.rad 325 B array.record.elements.rad 1.7 KiB array.repeat.edge.rad 548 B array.repeat.rad 828 B array.return.rad 330 B array.slice.empty.rad 108 B array.slice.gen.end.rad 126 B array.slice.gen.index.rad 139 B array.slice.gen.open.rad 125 B array.slice.gen.start.end.rad 127 B array.slice.gen.start.rad 126 B array.slice.rad 759 B as.precedence.rad 212 B assert.basic.rad 387 B assert.fail.rad 138 B assert.false.rad 140 B assert.true.rad 100 B assign.mutable.rad 6.1 KiB assign.rad 129 B assign.shadow.mutable.rad 461 B binop.bitwise.rad 1.2 KiB binop.cmp.rad 426 B bool.comparison.array.rad 688 B bool.comparison.nested.gen.rad 1.0 KiB bool.comparison.opt.rad 905 B bool.comparison.record.gen.rad 1.0 KiB bool.comparison.record.rad 1.1 KiB bool.comparison.slice.gen.rad 157 B bool.comparison.slice.rad 4.1 KiB bool.comparison.slice.record.gen.rad 2.0 KiB bool.comparison.slice.union.gen.rad 2.5 KiB bool.comparison.union.ctor.rad 690 B bool.comparison.union.gen.rad 1.2 KiB bool.comparison.union.record.gen.rad 1.5 KiB bool.comparison.union.simple.gen.rad 281 B bool.operators.complex.rad 384 B bool.operators.rad 831 B bool.short.circuit.rad 2.3 KiB bool.simple.rad 194 B bool.values.rad 772 B builtin.size.align.rad 1.3 KiB builtin.sliceof.mut.rad 606 B builtin.sliceof.rad 505 B call.arg.clobber.rad 717 B call.basic.rad 241 B call.clobber.rad 462 B cast.same.size.rad 1.0 KiB casting.numbers.rad 1.5 KiB char.literal.rad 165 B compound.assign.field.rad 285 B compound.assign.rad 1.1 KiB cond.assign.rad 723 B cond.expr.aggregate.rad 1.1 KiB cond.expr.rad 1.8 KiB cond.for.else.break.rad 326 B cond.for.indexed.rad 238 B cond.for.rad 165 B cond.for.range.indexed.rad 526 B cond.for.range.rad 171 B cond.for.unsigned.range.rad 644 B cond.forever.break.continue.rad 182 B cond.forever.break.rad 232 B cond.fused.rad 926 B cond.if.case.rad 2.2 KiB cond.if.else.min.rad 143 B cond.if.else.rad 225 B cond.if.elseif.rad 420 B cond.if.noelse.rad 120 B cond.if.rad 865 B cond.match.fallthrough.rad 369 B cond.match.guard.rad 1.4 KiB cond.match.guard.regalloc.rad 1.3 KiB cond.while.else.break.rad 282 B cond.while.rad 119 B const.array.copy.mutate.rad 386 B const.array.rad 195 B const.basic.rad 325 B const.char.rad 159 B const.fn.array.rad 664 B const.record.array.rad 1.2 KiB const.record.array.simple.rad 523 B const.record.ctor.rad 170 B const.record.fn.rad 353 B const.record.rad 182 B const.slice.param.rad 333 B const.union.payload.ctor.rad 349 B const.union.record.literal.rad 359 B data.array.rad 767 B data.bool.rad 216 B data.i16.rad 261 B data.i32.rad 281 B data.i8.rad 248 B data.record.rad 561 B data.simple.rad 436 B data.u16.rad 220 B data.u32.rad 240 B data.u8.rad 208 B data.union.rad 886 B debug.tag.rad 557 B edge.cases.2.rad 337 B edge.cases.3.rad 594 B edge.cases.4.rad 1.2 KiB edge.cases.5.rad 1.0 KiB edge.cases.6.rad 2.6 KiB edge.cases.7.addr.bug.rad 224 B edge.cases.8.bug.rad 508 B edge.cases.rad 223 B error.basic.rad 159 B error.catch.rad 1.6 KiB error.division.zero.rad 164 B error.modulo.zero.rad 162 B error.multi.basic.rad 672 B error.multi.catch.rad 772 B error.multi.catch.typed.binding.rad 791 B error.multi.catch.typed.catchall.rad 1.0 KiB error.multi.catch.typed.rad 1.1 KiB error.multi.propagate.multi.rad 953 B error.multi.propagate.rad 825 B error.multi.try.optional.rad 507 B error.slice.bounds.rad 219 B error.try.bang.success.rad 370 B error.try.catch.binding.rad 2.0 KiB error.try.optional.rad 1.8 KiB error.try.rad 4.0 KiB fn.block.scope.rad 508 B fn.callback.nested.rad 1.2 KiB fn.default.rad 131 B fn.local.rad 140 B fn.recursion.2.rad 239 B fn.void.rad 150 B for.else.continue.rad 1.1 KiB frame.large.rad 567 B if-let-mut.rad 1.1 KiB iflet.shadow.leak.rad 317 B integer.bitwise.basic.rad 693 B integer.overflow.rad 1.8 KiB large.blit.store.rad 2.1 KiB let.guard.rad 1.9 KiB literal.w64.rad 1.7 KiB loc.addr.offset.bug.rad 410 B loc.addr.opt.to.opt.rad 433 B loc.addr.optional.assign.rad 408 B loc.addr.record.assign.rad 443 B loop.complex.flow.rad 1007 B loop.sealblock.rad 911 B match.array.rad 3.4 KiB match.char.rad 1.6 KiB match.multi.seal.rad 987 B match.multi.survive.rad 1.6 KiB match.mutref.push.rad 1.0 KiB match.mutref.union.rad 662 B match.nested.call.rad 1.7 KiB match.nested.deep.rad 2.2 KiB match.nested.deref.rad 3.7 KiB match.nested.guard.rad 1.6 KiB match.nested.iflet.guard.rad 1.6 KiB match.nested.iflet.rad 1.4 KiB match.nested.letelse.rad 813 B match.nested.letelse.union.rad 1.3 KiB match.nested.literal.rad 3.1 KiB match.nested.multi.rad 2.4 KiB match.nested.pattern.rad 5.2 KiB match.nested.record.rad 2.0 KiB match.nested.union.rad 2.3 KiB match.nested.whilelet.rad 2.4 KiB match.string.rad 1.8 KiB match.value.copy.rad 2.0 KiB match.void.then.or.rad 1.6 KiB memzero.result.bug.rad 806 B memzero.union.bug.rad 576 B mutref.loop.bug.rad 1.8 KiB opt.assignment.bug.rad 1.3 KiB opt.bug.test.rad 1.4 KiB opt.if.let.complex.rad 6.2 KiB opt.if.let.guard.rad 809 B opt.if.let.rad 956 B opt.nil.check.rad 1.5 KiB opt.record.eq.rad 842 B opt.record.rad 655 B opt.return.array.rad 289 B opt.return.nested.rad 797 B opt.return.record.rad 344 B opt.slice.npo.rad 2.8 KiB opt.type.rad 200 B opt.while.let.complex.rad 404 B panic.rad 111 B placeholder.basic.rad 133 B placeholder.comprehensive.rad 562 B pointer.copy.edge.case.rad 1.3 KiB pointer.slice.index.rad 269 B pointer.slice.store.rad 881 B prog.ackermann.rad 5.0 KiB prog.bignum.rad 9.4 KiB prog.binsearch.rad 2.4 KiB prog.bubblesort.rad 2.0 KiB prog.cordic.rad 6.9 KiB prog.crc32.rad 2.7 KiB prog.dijkstra.rad 7.7 KiB prog.eval.rad 6.2 KiB prog.hanoi.rad 3.8 KiB prog.huffman.rad 9.3 KiB prog.hybridsort.rad 3.0 KiB prog.linkedlist.rad 5.8 KiB prog.lzw.rad 6.7 KiB prog.matmul.rad 2.9 KiB prog.mersenne.rad 5.2 KiB prog.nqueens.rad 3.4 KiB prog.rbtree.rad 8.2 KiB prog.regex.rad 10.2 KiB prog.sha256.rad 7.0 KiB prog.sieve.rad 2.8 KiB prog.symtab.rad 10.1 KiB prog.tokenizer.rad 13.8 KiB prog.vm.rad 17.4 KiB ptr.assign.rad 137 B ptr.deref.rad 622 B ptr.eq.rad 966 B ptr.mutate.rad 244 B ptr.opaque.rad 1.4 KiB record.access.rad 285 B record.alignment.rad 179 B record.array.elements.rad 1.7 KiB record.copy.rad 2.0 KiB record.field.assign.rad 184 B record.nested.calls.2.rad 612 B record.nested.calls.3.rad 734 B record.param.lit.rad 353 B record.ptr.access.rad 227 B record.ptr.mutate.rad 243 B record.shorthand.rad 1.5 KiB record.unlabeled.rad 407 B ref.if.bug.rad 519 B ref.immut.loop.bug.rad 670 B ref.mut.ptr.rad 261 B regalloc.callee.save.rad 1.5 KiB regalloc.spill.reuse.rad 473 B reserve.loop.rad 392 B result.void.success.rad 716 B slice.alloc.loop.rad 788 B slice.append.rad 3.3 KiB slice.cap.rad 941 B slice.delete.rad 971 B slice.of.rad 460 B slice.subslice.rad 1.4 KiB spill.blockarg.clobber.rad 3.5 KiB spill.loop.rad 1.6 KiB stack.local.corrupt.rad 320 B static.array.mutate.rad 387 B static.basic.rad 327 B static.fn.array.rad 628 B static.record.array.rad 503 B static.slice.index.assign.rad 408 B static.slice.offset.rad 668 B string.basic.rad 149 B string.escape.rad 349 B string.index.rad 116 B switch.blockargs.clobber.rad 1.3 KiB trait.aggregate.ret.rad 1.5 KiB trait.array.optional.rad 1.7 KiB trait.basic.rad 565 B trait.control.flow.rad 1.1 KiB trait.fn.param.rad 1.6 KiB trait.multiple.methods.rad 1.2 KiB trait.multiple.traits.rad 1.2 KiB trait.multiple.types.rad 1.3 KiB trait.supertrait.rad 2.5 KiB trait.throws.rad 1.0 KiB trait.writer.rad 2.6 KiB type.unify.rad 4.5 KiB undefined.rad 417 B union-tag.rad 911 B union.bitfield.rad 1.2 KiB union.discriminant.cast.rad 389 B union.edge.case.2.rad 679 B union.edge.case.3.rad 608 B union.mixed.assign.rad 977 B union.payload.mutref.rad 1.4 KiB union.payload.rad 580 B union.record.forward.rad 1.3 KiB union.void.match.rad 403 B union.void.rad 824 B unsigned.compare.rad 1.9 KiB var.align.rad 1013 B var.infer.rad 549 B decode.rad 14.6 KiB emit.rad 24.4 KiB encode.rad 19.9 KiB isel.rad 41.1 KiB printer.rad 13.0 KiB tests.rad 15.7 KiB rv64.rad 13.0 KiB collections/ lang/ sys/ arch.rad 65 B collections.rad 36 B fmt.rad 3.8 KiB intrinsics.rad 206 B io.rad 1.2 KiB lang.rad 222 B mem.rad 2.2 KiB sys.rad 167 B testing.rad 2.4 KiB tests.rad 11.6 KiB vec.rad 3.1 KiB std.rad 231 B scripts/ seed/ test/ vim/ .gitignore 353 B .gitsigners 112 B LICENSE 1.1 KiB Makefile 3.1 KiB README 2.5 KiB std.lib 987 B std.lib.test 252 B
lib/std/arch/rv64/tests/prog.regex.rad 10.2 KiB raw
1
//! NFA-based regex matcher.
2
//! Implement a simple regular expression engine using Thompson's NFA
3
//! construction. Supports: literal characters, '.', '*', '+', '?',
4
//! and concatenation.
5
6
const MAX_STATES: u32 = 128;
7
const MAX_TRANSITIONS: u32 = 256;
8
const NIL: u32 = 0xFFFFFFFF;
9
10
const TRANS_CHAR: u32 = 0;
11
const TRANS_EPSILON: u32 = 1;
12
const TRANS_DOT: u32 = 2;
13
14
record Trans {
15
    kind: u32,
16
    ch: u8,
17
    to: u32,
18
}
19
20
record Frag {
21
    start: u32,
22
    endState: u32,
23
}
24
25
record NfaState {
26
    trans: *mut [Trans],
27
    transCount: u32,
28
    stateFirst: *mut [u32],
29
    transNext: *mut [u32],
30
    stateCount: u32,
31
    acceptState: u32,
32
    current: *mut [u32],
33
    nextSet: *mut [u32],
34
    closure: *mut [u32],
35
    fragStack: *mut [Frag],
36
    fragTop: u32,
37
}
38
39
fn newState(nfa: *mut NfaState) -> u32 {
40
    let s: u32 = nfa.stateCount;
41
    nfa.stateFirst[s] = NIL;
42
    nfa.stateCount += 1;
43
    return s;
44
}
45
46
fn addTrans(nfa: *mut NfaState, from: u32, kind: u32, ch: u8, to: u32) {
47
    let idx: u32 = nfa.transCount;
48
    nfa.trans[idx] = Trans { kind, ch, to };
49
    nfa.transNext[idx] = nfa.stateFirst[from];
50
    nfa.stateFirst[from] = idx;
51
    nfa.transCount += 1;
52
}
53
54
fn pushFrag(nfa: *mut NfaState, f: Frag) {
55
    nfa.fragStack[nfa.fragTop] = f;
56
    nfa.fragTop += 1;
57
}
58
59
fn popFrag(nfa: *mut NfaState) -> Frag {
60
    nfa.fragTop -= 1;
61
    return nfa.fragStack[nfa.fragTop];
62
}
63
64
fn setEmpty(s: *mut [u32]) {
65
    s[0] = 0;
66
    s[1] = 0;
67
    s[2] = 0;
68
    s[3] = 0;
69
}
70
71
fn setAdd(s: *mut [u32], bit: u32) {
72
    let word: u32 = bit / 32;
73
    let pos: u32 = bit % 32;
74
    s[word] |= (1 << pos);
75
}
76
77
fn setHas(s: *[u32], bit: u32) -> bool {
78
    let word: u32 = bit / 32;
79
    let pos: u32 = bit % 32;
80
    return (s[word] >> pos) & 1 == 1;
81
}
82
83
fn setIsEmpty(s: *[u32]) -> bool {
84
    return s[0] == 0 and s[1] == 0 and s[2] == 0 and s[3] == 0;
85
}
86
87
fn setCopy(dst: *mut [u32], src: *[u32]) {
88
    dst[0] = src[0];
89
    dst[1] = src[1];
90
    dst[2] = src[2];
91
    dst[3] = src[3];
92
}
93
94
fn epsilonClosure(nfa: *mut NfaState, states: *mut [u32]) {
95
    setCopy(nfa.closure, states);
96
97
    let mut changed: bool = true;
98
    while changed {
99
        changed = false;
100
        let mut s: u32 = 0;
101
        while s < nfa.stateCount {
102
            if setHas(nfa.closure, s) {
103
                let mut t: u32 = nfa.stateFirst[s];
104
                while t != NIL {
105
                    if nfa.trans[t].kind == TRANS_EPSILON {
106
                        if not setHas(nfa.closure, nfa.trans[t].to) {
107
                            setAdd(nfa.closure, nfa.trans[t].to);
108
                            changed = true;
109
                        }
110
                    }
111
                    t = nfa.transNext[t];
112
                }
113
            }
114
            s += 1;
115
        }
116
    }
117
118
    setCopy(states, nfa.closure);
119
}
120
121
fn resetNFA(nfa: *mut NfaState) {
122
    nfa.stateCount = 0;
123
    nfa.transCount = 0;
124
    nfa.fragTop = 0;
125
    let mut i: u32 = 0;
126
    while i < MAX_STATES {
127
        nfa.stateFirst[i] = NIL;
128
        i += 1;
129
    }
130
    i = 0;
131
    while i < MAX_TRANSITIONS {
132
        nfa.transNext[i] = NIL;
133
        i += 1;
134
    }
135
}
136
137
fn compile(nfa: *mut NfaState, pattern: *[u8]) -> u32 {
138
    resetNFA(nfa);
139
140
    let mut i: u32 = 0;
141
    while i < pattern.len {
142
        let ch: u8 = pattern[i];
143
144
        if i + 1 < pattern.len {
145
            let nextCh: u8 = pattern[i + 1];
146
147
            if nextCh == 42 {
148
                let s: u32 = newState(nfa);
149
                let e: u32 = newState(nfa);
150
                let body: u32 = newState(nfa);
151
152
                if ch == 46 {
153
                    addTrans(nfa, body, TRANS_DOT, 0, body);
154
                } else {
155
                    addTrans(nfa, body, TRANS_CHAR, ch, body);
156
                }
157
                addTrans(nfa, s, TRANS_EPSILON, 0, body);
158
                addTrans(nfa, s, TRANS_EPSILON, 0, e);
159
                addTrans(nfa, body, TRANS_EPSILON, 0, e);
160
161
                pushFrag(nfa, Frag { start: s, endState: e });
162
                i += 2;
163
                continue;
164
            }
165
            if nextCh == 43 {
166
                let s: u32 = newState(nfa);
167
                let m: u32 = newState(nfa);
168
                let e: u32 = newState(nfa);
169
170
                if ch == 46 {
171
                    addTrans(nfa, s, TRANS_DOT, 0, m);
172
                    addTrans(nfa, m, TRANS_DOT, 0, m);
173
                } else {
174
                    addTrans(nfa, s, TRANS_CHAR, ch, m);
175
                    addTrans(nfa, m, TRANS_CHAR, ch, m);
176
                }
177
                addTrans(nfa, m, TRANS_EPSILON, 0, e);
178
179
                pushFrag(nfa, Frag { start: s, endState: e });
180
                i += 2;
181
                continue;
182
            }
183
            if nextCh == 63 {
184
                let s: u32 = newState(nfa);
185
                let m: u32 = newState(nfa);
186
                let e: u32 = newState(nfa);
187
188
                if ch == 46 {
189
                    addTrans(nfa, s, TRANS_DOT, 0, m);
190
                } else {
191
                    addTrans(nfa, s, TRANS_CHAR, ch, m);
192
                }
193
                addTrans(nfa, s, TRANS_EPSILON, 0, e);
194
                addTrans(nfa, m, TRANS_EPSILON, 0, e);
195
196
                pushFrag(nfa, Frag { start: s, endState: e });
197
                i += 2;
198
                continue;
199
            }
200
        }
201
202
        let s: u32 = newState(nfa);
203
        let e: u32 = newState(nfa);
204
        if ch == 46 {
205
            addTrans(nfa, s, TRANS_DOT, 0, e);
206
        } else {
207
            addTrans(nfa, s, TRANS_CHAR, ch, e);
208
        }
209
        pushFrag(nfa, Frag { start: s, endState: e });
210
        i += 1;
211
    }
212
213
    if nfa.fragTop == 0 {
214
        let s: u32 = newState(nfa);
215
        nfa.acceptState = s;
216
        return s;
217
    }
218
219
    let numFrags: u32 = nfa.fragTop;
220
    let mut frags: [Frag; 64] = [Frag { start: 0, endState: 0 }; 64];
221
    let mut k: u32 = 0;
222
    while k < numFrags {
223
        frags[numFrags - 1 - k] = popFrag(nfa);
224
        k += 1;
225
    }
226
227
    let mut j: u32 = 0;
228
    while j < numFrags - 1 {
229
        addTrans(nfa, frags[j].endState, TRANS_EPSILON, 0, frags[j + 1].start);
230
        j += 1;
231
    }
232
233
    nfa.acceptState = frags[numFrags - 1].endState;
234
    return frags[0].start;
235
}
236
237
fn nfaMatches(nfa: *mut NfaState, start: u32, input: *[u8]) -> bool {
238
    setEmpty(nfa.current);
239
    setAdd(nfa.current, start);
240
    epsilonClosure(nfa, nfa.current);
241
242
    let mut i: u32 = 0;
243
    while i < input.len {
244
        let ch: u8 = input[i];
245
        setEmpty(nfa.nextSet);
246
247
        let mut s: u32 = 0;
248
        while s < nfa.stateCount {
249
            if setHas(nfa.current, s) {
250
                let mut t: u32 = nfa.stateFirst[s];
251
                while t != NIL {
252
                    if nfa.trans[t].kind == TRANS_CHAR and nfa.trans[t].ch == ch {
253
                        setAdd(nfa.nextSet, nfa.trans[t].to);
254
                    } else if nfa.trans[t].kind == TRANS_DOT {
255
                        setAdd(nfa.nextSet, nfa.trans[t].to);
256
                    }
257
                    t = nfa.transNext[t];
258
                }
259
            }
260
            s += 1;
261
        }
262
263
        epsilonClosure(nfa, nfa.nextSet);
264
        setCopy(nfa.current, nfa.nextSet);
265
266
        if setIsEmpty(nfa.current) {
267
            return false;
268
        }
269
        i += 1;
270
    }
271
272
    return setHas(nfa.current, nfa.acceptState);
273
}
274
275
fn testLiteral(nfa: *mut NfaState) -> i32 {
276
    let start: u32 = compile(nfa, "abc");
277
278
    assert nfaMatches(nfa, start, "abc");
279
    if nfaMatches(nfa, start, "ab") { return 2; }
280
    if nfaMatches(nfa, start, "abcd") { return 3; }
281
    if nfaMatches(nfa, start, "abd") { return 4; }
282
283
    return 0;
284
}
285
286
fn testStar(nfa: *mut NfaState) -> i32 {
287
    let start: u32 = compile(nfa, "a*");
288
289
    assert nfaMatches(nfa, start, "");
290
    assert nfaMatches(nfa, start, "a");
291
    assert nfaMatches(nfa, start, "aaa");
292
    if nfaMatches(nfa, start, "b") { return 4; }
293
294
    return 0;
295
}
296
297
fn testPlus(nfa: *mut NfaState) -> i32 {
298
    let start: u32 = compile(nfa, "a+");
299
300
    if nfaMatches(nfa, start, "") { return 1; }
301
    assert nfaMatches(nfa, start, "a");
302
    assert nfaMatches(nfa, start, "aaaaa");
303
304
    return 0;
305
}
306
307
fn testQuestion(nfa: *mut NfaState) -> i32 {
308
    let start: u32 = compile(nfa, "a?");
309
310
    assert nfaMatches(nfa, start, "");
311
    assert nfaMatches(nfa, start, "a");
312
    if nfaMatches(nfa, start, "aa") { return 3; }
313
314
    return 0;
315
}
316
317
fn testDot(nfa: *mut NfaState) -> i32 {
318
    let start: u32 = compile(nfa, "..");
319
320
    assert nfaMatches(nfa, start, "ab");
321
    assert nfaMatches(nfa, start, "zz");
322
    if nfaMatches(nfa, start, "a") { return 3; }
323
    if nfaMatches(nfa, start, "abc") { return 4; }
324
325
    return 0;
326
}
327
328
fn testComplex(nfa: *mut NfaState) -> i32 {
329
    let start: u32 = compile(nfa, "ab*c");
330
331
    assert nfaMatches(nfa, start, "ac");
332
    assert nfaMatches(nfa, start, "abc");
333
    assert nfaMatches(nfa, start, "abbc");
334
    assert nfaMatches(nfa, start, "abbbc");
335
    if nfaMatches(nfa, start, "a") { return 5; }
336
    if nfaMatches(nfa, start, "adc") { return 6; }
337
338
    return 0;
339
}
340
341
fn testDotStar(nfa: *mut NfaState) -> i32 {
342
    let start: u32 = compile(nfa, ".*");
343
344
    assert nfaMatches(nfa, start, "");
345
    assert nfaMatches(nfa, start, "hello");
346
    assert nfaMatches(nfa, start, "x");
347
348
    return 0;
349
}
350
351
@default fn main() -> i32 {
352
    let mut trans: [Trans; 256] = [Trans { kind: 0, ch: 0, to: 0 }; 256];
353
    let mut stateFirst: [u32; 128] = [0xFFFFFFFF; 128];
354
    let mut transNext: [u32; 256] = [0xFFFFFFFF; 256];
355
    let mut current: [u32; 4] = [0; 4];
356
    let mut nextSet: [u32; 4] = [0; 4];
357
    let mut closureBuf: [u32; 4] = [0; 4];
358
    let mut fragStack: [Frag; 64] = [Frag { start: 0, endState: 0 }; 64];
359
360
    let mut nfa: NfaState = NfaState {
361
        trans: &mut trans[..],
362
        transCount: 0,
363
        stateFirst: &mut stateFirst[..],
364
        transNext: &mut transNext[..],
365
        stateCount: 0,
366
        acceptState: 0,
367
        current: &mut current[..],
368
        nextSet: &mut nextSet[..],
369
        closure: &mut closureBuf[..],
370
        fragStack: &mut fragStack[..],
371
        fragTop: 0,
372
    };
373
374
    let r1: i32 = testLiteral(&mut nfa);
375
    if r1 != 0 { return 10 + r1; }
376
377
    let r2: i32 = testStar(&mut nfa);
378
    if r2 != 0 { return 20 + r2; }
379
380
    let r3: i32 = testPlus(&mut nfa);
381
    if r3 != 0 { return 30 + r3; }
382
383
    let r4: i32 = testQuestion(&mut nfa);
384
    if r4 != 0 { return 40 + r4; }
385
386
    let r5: i32 = testDot(&mut nfa);
387
    if r5 != 0 { return 50 + r5; }
388
389
    let r6: i32 = testComplex(&mut nfa);
390
    if r6 != 0 { return 60 + r6; }
391
392
    let r7: i32 = testDotStar(&mut nfa);
393
    if r7 != 0 { return 70 + r7; }
394
395
    return 0;
396
}