实现
结合 上一篇文章 的代码,实现了正则表达式转 NFA,主要做了三件小事
- 转义字符
- 将隐式 concatenation 转为显式运算符&
- 表达式转 NFA
re.go
| 12
 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
 
 | package main
 func re_to_nfa(exp string) *nfa {
 priority := map[byte]int{
 '(': 1,
 '|': 2,
 '&': 3,
 }
 var (
 opstack  []byte
 nfastack []*nfa
 )
 apply_op := func(op byte) {
 switch op {
 case '*':
 nfastack[len(nfastack)-1] = nfa_star(nfastack[len(nfastack)-1])
 case '&':
 nfastack[len(nfastack)-2] = nfa_cat(nfastack[len(nfastack)-2], nfastack[len(nfastack)-1])
 nfastack = nfastack[:len(nfastack)-1]
 case '|':
 nfastack[len(nfastack)-2] = nfa_or(nfastack[len(nfastack)-2], nfastack[len(nfastack)-1])
 nfastack = nfastack[:len(nfastack)-1]
 }
 }
 add_op := func(op byte) {
 switch op {
 case '*':
 apply_op('*')
 case ')':
 for len(opstack) > 0 {
 top := opstack[len(opstack)-1]
 opstack = opstack[:len(opstack)-1]
 if top == '(' {
 break
 }
 apply_op(top)
 }
 case '&', '|':
 if len(opstack) > 0 {
 prio := priority[op]
 for len(opstack) > 0 {
 top := opstack[len(opstack)-1]
 if priority[top] < prio {
 break
 }
 opstack = opstack[:len(opstack)-1]
 apply_op(op)
 }
 }
 opstack = append(opstack, op)
 case '(':
 opstack = append(opstack, op)
 }
 }
 cat := false
 escape := false
 for i := 0; i < len(exp); i++ {
 c := exp[i]
 if escape {
 switch c {
 case 'n':
 c = '\n'
 case 't':
 c = '\t'
 case 'r':
 c = '\r'
 }
 escape = false
 } else {
 switch c {
 case '\\':
 escape = true
 continue
 case '(':
 if cat {
 add_op('&')
 }
 fallthrough
 case '*', '|', ')':
 cat = c != '|' && c != '('
 add_op(c)
 continue
 }
 }
 if cat {
 add_op('&')
 }
 nfastack = append(nfastack, nfa_char(c))
 cat = true
 }
 for i := len(opstack) - 1; i >= 0; i-- {
 apply_op(opstack[i])
 }
 return nfastack[0]
 }
 
 | 
写了一个玩具 re0