Source File
onepass.go
Belonging Package
regexp
package regexp
import (
)
type onePassProg struct {
Inst []onePassInst
Start int // index of start instruction
NumCap int // number of InstCapture insts in re
}
type onePassInst struct {
syntax.Inst
Next []uint32
}
var strings.Builder
for iop() == syntax.InstRune && len(.Rune) == 1 && syntax.Flags(.Arg)&syntax.FoldCase == 0 {
.WriteRune(.Rune[0])
, = .Out, &.Inst[.Out]
}
if .Op == syntax.InstEmptyWidth &&
syntax.EmptyOp(.Arg)&syntax.EmptyEndText != 0 &&
.Inst[.Out].Op == syntax.InstMatch {
= true
}
return .String(), ,
}
func ( *onePassInst, rune) uint32 {
:= .MatchRunePos()
if >= 0 {
return .Next[]
}
if .Op == syntax.InstAltMatch {
return .Out
}
return 0
}
func ( *syntax.Inst) syntax.InstOp {
:= .Op
switch {
case syntax.InstRune1, syntax.InstRuneAny, syntax.InstRuneAnyNotNL:
= syntax.InstRune
}
return
}
type queueOnePass struct {
sparse []uint32
dense []uint32
size, nextIndex uint32
}
func ( *queueOnePass) () bool {
return .nextIndex >= .size
}
func ( *queueOnePass) () ( uint32) {
= .dense[.nextIndex]
.nextIndex++
return
}
func ( *queueOnePass) () {
.size = 0
.nextIndex = 0
}
func ( *queueOnePass) ( uint32) bool {
if >= uint32(len(.sparse)) {
return false
}
return .sparse[] < .size && .dense[.sparse[]] ==
}
func ( *queueOnePass) ( uint32) {
if !.contains() {
.insertNew()
}
}
func ( *queueOnePass) ( uint32) {
if >= uint32(len(.sparse)) {
return
}
.sparse[] = .size
.dense[.size] =
.size++
}
func ( int) ( *queueOnePass) {
return &queueOnePass{
sparse: make([]uint32, ),
dense: make([]uint32, ),
}
}
const mergeFailed = uint32(0xffffffff)
var (
noRune = []rune{}
noNext = []uint32{mergeFailed}
)
func (, *[]rune, , uint32) ([]rune, []uint32) {
:= len(*)
:= len(*)
if &0x1 != 0 || &0x1 != 0 {
panic("mergeRuneSets odd length []rune")
}
var (
, int
)
:= make([]rune, 0)
:= make([]uint32, 0)
:= true
defer func() {
if ! {
= nil
= nil
}
}()
:= -1
:= func( *int, *[]rune, uint32) bool {
if > 0 && (*)[*] <= [] {
return false
}
= append(, (*)[*], (*)[*+1])
* += 2
+= 2
= append(, )
return true
}
for < || < {
switch {
case >= :
= (&, , )
case >= :
= (&, , )
case (*)[] < (*)[]:
= (&, , )
default:
= (&, , )
}
if ! {
return noRune, noNext
}
}
return ,
}
func ( *onePassProg, *syntax.Prog) {
for , := range .Inst {
switch .Op {
case syntax.InstAlt, syntax.InstAltMatch, syntax.InstRune:
case syntax.InstCapture, syntax.InstEmptyWidth, syntax.InstNop, syntax.InstMatch, syntax.InstFail:
.Inst[].Next = nil
case syntax.InstRune1, syntax.InstRuneAny, syntax.InstRuneAnyNotNL:
.Inst[].Next = nil
.Inst[] = onePassInst{Inst: }
}
}
}
func ( *syntax.Prog) *onePassProg {
:= &onePassProg{
Start: .Start,
NumCap: .NumCap,
Inst: make([]onePassInst, len(.Inst)),
}
for , := range .Inst {
.Inst[] = onePassInst{Inst: }
}
continue
if * == * {
* = *
}
}
}
return
}
[] = append([]rune{}, [.Out]...)
.Next = make([]uint32, len([])/2+1)
for := range .Next {
.Next[] = .Out
}
case syntax.InstEmptyWidth:
= (.Out, )
[] = [.Out]
[] = append([]rune{}, [.Out]...)
.Next = make([]uint32, len([])/2+1)
for := range .Next {
.Next[] = .Out
}
case syntax.InstMatch, syntax.InstFail:
[] = .Op == syntax.InstMatch
case syntax.InstRune:
[] = false
if len(.Next) > 0 {
break
}
.insert(.Out)
if len(.Rune) == 0 {
[] = []rune{}
.Next = []uint32{.Out}
break
}
:= make([]rune, 0)
if len(.Rune) == 1 && syntax.Flags(.Arg)&syntax.FoldCase != 0 {
:= .Rune[0]
= append(, , )
for := unicode.SimpleFold(); != ; = unicode.SimpleFold() {
= append(, , )
}
sort.Sort(runeSlice())
} else {
= append(, .Rune...)
}
[] =
.Next = make([]uint32, len([])/2+1)
for := range .Next {
.Next[] = .Out
}
.Op = syntax.InstRune
case syntax.InstRune1:
[] = false
if len(.Next) > 0 {
break
}
.insert(.Out)
if syntax.Flags(.Arg)&syntax.FoldCase != 0 {
:= .Rune[0]
= append(, , )
for := unicode.SimpleFold(); != ; = unicode.SimpleFold() {
= append(, , )
}
sort.Sort(runeSlice())
} else {
= append(, .Rune[0], .Rune[0])
}
[] =
.Next = make([]uint32, len([])/2+1)
for := range .Next {
.Next[] = .Out
}
.Op = syntax.InstRune
case syntax.InstRuneAny:
[] = false
if len(.Next) > 0 {
break
}
.insert(.Out)
[] = append([]rune{}, anyRune...)
.Next = []uint32{.Out}
case syntax.InstRuneAnyNotNL:
[] = false
if len(.Next) > 0 {
break
}
.insert(.Out)
[] = append([]rune{}, anyRuneNotNL...)
.Next = make([]uint32, len([])/2+1)
for := range .Next {
.Next[] = .Out
}
}
return
}
.clear()
.insert(uint32(.Start))
:= make([]bool, len(.Inst))
for !.empty() {
.clear()
:= .next()
if !(, ) {
= nil
break
}
}
if != nil {
for := range .Inst {
.Inst[].Rune = []
}
}
return
}
func ( *syntax.Prog) ( *onePassProg) {
if .Start == 0 {
return nil
if .Inst[.Start].Op != syntax.InstEmptyWidth ||
syntax.EmptyOp(.Inst[.Start].Arg)&syntax.EmptyBeginText != syntax.EmptyBeginText {
return nil
for , := range .Inst {
:= .Inst[.Out].Op
switch .Op {
default:
if == syntax.InstMatch {
return nil
}
case syntax.InstAlt, syntax.InstAltMatch:
if == syntax.InstMatch || .Inst[.Arg].Op == syntax.InstMatch {
return nil
}
case syntax.InstEmptyWidth:
if == syntax.InstMatch {
if syntax.EmptyOp(.Arg)&syntax.EmptyEndText == syntax.EmptyEndText {
continue
}
return nil
}
}
= onePassCopy()
= makeOnePass()
if != nil {
cleanupOnePass(, )
}
return
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |