-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild.go
More file actions
98 lines (91 loc) · 1.94 KB
/
Copy pathbuild.go
File metadata and controls
98 lines (91 loc) · 1.94 KB
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package nfa
type NFANewState = func() State
func NFAAnd(fa1, fa2 *NFA) *NFA {
n := &NFA{
Init: fa1.Init,
Accept: fa2.Accept,
Marks: fa1.Marks,
Trans: fa1.Trans,
}
for s, c := range fa2.Trans {
n.Trans[s] = c
}
for s, c := range fa2.Marks {
n.Marks[s] = c
}
n.AddConn(fa1.Accept, fa2.Init, Epsilon)
return n
}
func NFAOr(fa1, fa2 *NFA, newState NFANewState) *NFA {
i := newState()
ac := newState()
n := &NFA{
Init: i,
Accept: ac,
Marks: fa1.Marks,
Trans: fa1.Trans,
}
for s, c := range fa2.Trans {
n.Trans[s] = c
}
for s, c := range fa2.Marks {
n.Marks[s] = c
}
n.AddConn(i, fa1.Init, Epsilon)
n.AddConn(i, fa2.Init, Epsilon)
n.AddConn(fa1.Accept, ac, Epsilon)
n.AddConn(fa2.Accept, ac, Epsilon)
return n
}
func NFARepeat(fa0 *NFA) *NFA {
fa0.AddConn(fa0.Accept, fa0.Init, Epsilon)
fa0.AddConn(fa0.Init, fa0.Accept, Epsilon)
return fa0
}
func NFAMark(fa0 *NFA, mark int) *NFA {
if _, ok := fa0.Marks[fa0.Accept]; !ok {
fa0.Marks[fa0.Accept] = NewSet[int]()
}
fa0.Marks[fa0.Accept].Add(mark)
return fa0
}
func NFAChar(c Char, newState NFANewState) *NFA {
i := newState()
ac := newState()
n := &NFA{
Init: i,
Accept: ac,
Marks: make(map[State]Set[int]),
Trans: map[State]*ClosureAndtrans{},
}
n.AddConn(i, ac, c)
return n
}
func PostfixToNFA(seq TokenSeq) *NFA {
s0 := 0
newState := func() State {
s0 += 1
return State(s0)
}
stack := &Stack[*NFA]{s: make([]*NFA, 0)}
for _, t := range seq {
if t.IsChar() {
stack.Push(NFAChar(t.Char(), newState))
} else if t.Type() == REPEAT {
stack.Push(NFARepeat(stack.Pop()))
} else if t.Type() == MARK {
stack.Push(NFAMark(stack.Pop(), t.Mark()))
} else if t.Type() == AND {
fa2 := stack.Pop()
fa1 := stack.Pop()
stack.Push(NFAAnd(fa1, fa2))
} else if t.Type() == OR {
stack.Push(NFAOr(stack.Pop(), stack.Pop(), newState))
}
}
out := stack.Pop()
if !stack.Empty() {
panic("operate val num error")
}
return out
}