1
 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
use crate::*;

pub const NON: Re = Re::Set(Bset(0, 0));
pub const ALP: Re = Re::Set(Bset(!0, !0));

pub type Binop = fn(Pre, Pre) -> Re;
pub const ALT: Binop = Re::Alt;
pub const CAT: Binop = Re::Cat;

pub type Unop = fn(Pre) -> Re;
pub const NOT: Unop = Re::Not;
pub const KLE: Unop = Re::Kle;
pub const PLS: Unop = Re::Pls;

pub fn unop(f: Unop, x: Re) -> Re {
    use Re::*;
    match (f, x) {
        (NOT, Kle(box ALP)) => NON,
        (NOT, NON) => Kle(box ALP),
        (NOT, Not(x)) => *x,
        // (KLE, Kle(x)) => Kle(x),
        // (KLE, Pls(x)) => Kle(x),
        // (PLS, Kle(x)) => Kle(x),
        (f, x) => f(box x),
    }
}

pub fn binop(f: Binop, l: Re, r: Re) -> Re {
    use Re::*;
    match (f, l, r) {
        (ALT, _, x @ Kle(box ALP)) => x,
        (ALT, x @ Kle(box ALP), _) => x,
        (ALT, x, NON) => x,
        (ALT, NON, x) => x,

        (CAT, _, NON) => NON,
        (CAT, NON, _) => NON,

        (CAT, Cat(x, y), z) => binop(CAT, *x, binop(CAT, *y, z)),
        (ALT, Alt(x, y), z) => binop(ALT, *x, binop(ALT, *y, z)),
        (ALT, Set(x), Set(y)) => Set(x | y),

        (ALT, x, y) if x == y => x,

        (f, l, r) => f(box l, box r),
    }
}