package syntax
import (
"bytes"
"fmt"
"math"
)
type InstOp int
const (
Onerep InstOp = 0
Notonerep = 1
Setrep = 2
Oneloop = 3
Notoneloop = 4
Setloop = 5
Onelazy = 6
Notonelazy = 7
Setlazy = 8
One = 9
Notone = 10
Set = 11
Multi = 12
Ref = 13
Bol = 14
Eol = 15
Boundary = 16
Nonboundary = 17
Beginning = 18
Start = 19
EndZ = 20
End = 21
Nothing = 22
Lazybranch = 23
Branchmark = 24
Lazybranchmark = 25
Nullcount = 26
Setcount = 27
Branchcount = 28
Lazybranchcount = 29
Nullmark = 30
Setmark = 31
Capturemark = 32
Getmark = 33
Setjump = 34
Backjump = 35
Forejump = 36
Testref = 37
Goto = 38
Prune = 39
Stop = 40
ECMABoundary = 41
NonECMABoundary = 42
Mask = 63
Rtl = 64
Back = 128
Back2 = 256
Ci = 512
)
type Code struct {
Codes []int
Strings [][]rune
Sets []*CharSet
TrackCount int
Caps map [int ]int
Capsize int
FcPrefix *Prefix
BmPrefix *BmPrefix
Anchors AnchorLoc
RightToLeft bool
}
func opcodeBacktracks(op InstOp ) bool {
op &= Mask
switch op {
case Oneloop , Notoneloop , Setloop , Onelazy , Notonelazy , Setlazy , Lazybranch , Branchmark , Lazybranchmark ,
Nullcount , Setcount , Branchcount , Lazybranchcount , Setmark , Capturemark , Getmark , Setjump , Backjump ,
Forejump , Goto :
return true
default :
return false
}
}
func opcodeSize(op InstOp ) int {
op &= Mask
switch op {
case Nothing , Bol , Eol , Boundary , Nonboundary , ECMABoundary , NonECMABoundary , Beginning , Start , EndZ ,
End , Nullmark , Setmark , Getmark , Setjump , Backjump , Forejump , Stop :
return 1
case One , Notone , Multi , Ref , Testref , Goto , Nullcount , Setcount , Lazybranch , Branchmark , Lazybranchmark ,
Prune , Set :
return 2
case Capturemark , Branchcount , Lazybranchcount , Onerep , Notonerep , Oneloop , Notoneloop , Onelazy , Notonelazy ,
Setlazy , Setrep , Setloop :
return 3
default :
panic (fmt .Errorf ("Unexpected op code: %v" , op ))
}
}
var codeStr = []string {
"Onerep" , "Notonerep" , "Setrep" ,
"Oneloop" , "Notoneloop" , "Setloop" ,
"Onelazy" , "Notonelazy" , "Setlazy" ,
"One" , "Notone" , "Set" ,
"Multi" , "Ref" ,
"Bol" , "Eol" , "Boundary" , "Nonboundary" , "Beginning" , "Start" , "EndZ" , "End" ,
"Nothing" ,
"Lazybranch" , "Branchmark" , "Lazybranchmark" ,
"Nullcount" , "Setcount" , "Branchcount" , "Lazybranchcount" ,
"Nullmark" , "Setmark" , "Capturemark" , "Getmark" ,
"Setjump" , "Backjump" , "Forejump" , "Testref" , "Goto" ,
"Prune" , "Stop" ,
"ECMABoundary" , "NonECMABoundary" ,
}
func operatorDescription(op InstOp ) string {
desc := codeStr [op &Mask ]
if (op & Ci ) != 0 {
desc += "-Ci"
}
if (op & Rtl ) != 0 {
desc += "-Rtl"
}
if (op & Back ) != 0 {
desc += "-Back"
}
if (op & Back2 ) != 0 {
desc += "-Back2"
}
return desc
}
func (c *Code ) OpcodeDescription (offset int ) string {
buf := &bytes .Buffer {}
op := InstOp (c .Codes [offset ])
fmt .Fprintf (buf , "%06d " , offset )
if opcodeBacktracks (op & Mask ) {
buf .WriteString ("*" )
} else {
buf .WriteString (" " )
}
buf .WriteString (operatorDescription (op ))
buf .WriteString ("(" )
op &= Mask
switch op {
case One , Notone , Onerep , Notonerep , Oneloop , Notoneloop , Onelazy , Notonelazy :
buf .WriteString ("Ch = " )
buf .WriteString (CharDescription (rune (c .Codes [offset +1 ])))
case Set , Setrep , Setloop , Setlazy :
buf .WriteString ("Set = " )
buf .WriteString (c .Sets [c .Codes [offset +1 ]].String ())
case Multi :
fmt .Fprintf (buf , "String = %s" , string (c .Strings [c .Codes [offset +1 ]]))
case Ref , Testref :
fmt .Fprintf (buf , "Index = %d" , c .Codes [offset +1 ])
case Capturemark :
fmt .Fprintf (buf , "Index = %d" , c .Codes [offset +1 ])
if c .Codes [offset +2 ] != -1 {
fmt .Fprintf (buf , ", Unindex = %d" , c .Codes [offset +2 ])
}
case Nullcount , Setcount :
fmt .Fprintf (buf , "Value = %d" , c .Codes [offset +1 ])
case Goto , Lazybranch , Branchmark , Lazybranchmark , Branchcount , Lazybranchcount :
fmt .Fprintf (buf , "Addr = %d" , c .Codes [offset +1 ])
}
switch op {
case Onerep , Notonerep , Oneloop , Notoneloop , Onelazy , Notonelazy , Setrep , Setloop , Setlazy :
buf .WriteString (", Rep = " )
if c .Codes [offset +2 ] == math .MaxInt32 {
buf .WriteString ("inf" )
} else {
fmt .Fprintf (buf , "%d" , c .Codes [offset +2 ])
}
case Branchcount , Lazybranchcount :
buf .WriteString (", Limit = " )
if c .Codes [offset +2 ] == math .MaxInt32 {
buf .WriteString ("inf" )
} else {
fmt .Fprintf (buf , "%d" , c .Codes [offset +2 ])
}
}
buf .WriteString (")" )
return buf .String ()
}
func (c *Code ) Dump () string {
buf := &bytes .Buffer {}
if c .RightToLeft {
fmt .Fprintln (buf , "Direction: right-to-left" )
} else {
fmt .Fprintln (buf , "Direction: left-to-right" )
}
if c .FcPrefix == nil {
fmt .Fprintln (buf , "Firstchars: n/a" )
} else {
fmt .Fprintf (buf , "Firstchars: %v\n" , c .FcPrefix .PrefixSet .String ())
}
if c .BmPrefix == nil {
fmt .Fprintln (buf , "Prefix: n/a" )
} else {
fmt .Fprintf (buf , "Prefix: %v\n" , Escape (c .BmPrefix .String ()))
}
fmt .Fprintf (buf , "Anchors: %v\n" , c .Anchors )
fmt .Fprintln (buf )
if c .BmPrefix != nil {
fmt .Fprintln (buf , "BoyerMoore:" )
fmt .Fprintln (buf , c .BmPrefix .Dump (" " ))
}
for i := 0 ; i < len (c .Codes ); i += opcodeSize (InstOp (c .Codes [i ])) {
fmt .Fprintln (buf , c .OpcodeDescription (i ))
}
return buf .String ()
}
The pages are generated with Golds v0.8.2 . (GOOS=linux 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 @zigo_101 (reachable from the left QR code) to get the latest news of Golds .