lexmachine/inst/inst.go
2022-08-24 15:59:27 +08:00

93 lines
1.9 KiB
Go

package inst
import (
"fmt"
"strings"
)
const (
CHAR = iota // CHAR instruction op code: match a byte in the range [X, Y] (inclusive)
SPLIT // SPLIT instruction op code: split jump to both X and Y
JMP // JMP instruction op code: jmp to X
MATCH // MATCH instruction op code: match the string
)
// Inst represents an NFA byte code instruction
type Inst struct {
Op uint8
X uint32
Y uint32
}
// Slice is a list of NFA instructions
type Slice []*Inst
// New creates a new instruction
func New(op uint8, x, y uint32) *Inst {
return &Inst{
Op: op,
X: x,
Y: y,
}
}
// String humanizes the byte code
func (i Inst) String() (s string) {
switch i.Op {
case CHAR:
if i.X == i.Y {
s = fmt.Sprintf("CHAR %d (%q)", i.X, string([]byte{byte(i.X)}))
} else {
s = fmt.Sprintf("CHAR %d (%q), %d (%q)", i.X, string([]byte{byte(i.X)}), i.Y, string([]byte{byte(i.Y)}))
}
case SPLIT:
s = fmt.Sprintf("SPLIT %v, %v", i.X, i.Y)
case JMP:
s = fmt.Sprintf("JMP %v", i.X)
case MATCH:
s = "MATCH"
}
return
}
// Serialize outputs machine readable assembly
func (i Inst) Serialize() (s string) {
switch i.Op {
case CHAR:
s = fmt.Sprintf("CHAR %d %d", i.X, i.Y)
case SPLIT:
s = fmt.Sprintf("SPLIT %v %v", i.X, i.Y)
case JMP:
s = fmt.Sprintf("JMP %v", i.X)
case MATCH:
s = "MATCH"
}
return
}
// String humanizes the byte code
func (is Slice) String() (s string) {
s = "{\n"
for i, inst := range is {
if inst == nil {
continue
}
if i < 10 {
s += fmt.Sprintf(" 0%v %v\n", i, inst)
} else {
s += fmt.Sprintf(" %v %v\n", i, inst)
}
}
s += "}"
return
}
// Serialize outputs machine readable assembly
func (is Slice) Serialize() (s string) {
lines := make([]string, 0, len(is))
for i, inst := range is {
lines = append(lines, fmt.Sprintf("%d %s", i, inst.Serialize()))
}
return strings.Join(lines, "\n")
}