Command parse compound

This commit is contained in:
Tnze
2022-01-03 15:57:54 +08:00
parent 9433dd98de
commit be3a834696
13 changed files with 250 additions and 114 deletions

View File

@ -6,22 +6,22 @@ func (g *Graph) AppendLiteral(child *Literal) *Graph {
}
func (g *Graph) Literal(str string) LiteralBuilder {
index := len(g.nodes)
index := int32(len(g.nodes))
g.nodes = append(g.nodes, Node{
g: g,
index: index,
flags: LiteralNode,
kind: LiteralNode,
Name: str,
})
return LiteralBuilder{g: g, current: index}
}
func (g *Graph) Argument(name string, parser Parser) ArgumentBuilder {
index := len(g.nodes)
index := int32(len(g.nodes))
g.nodes = append(g.nodes, Node{
g: g,
index: index,
flags: ArgumentNode,
kind: ArgumentNode,
Name: name,
Parser: parser,
})
@ -30,7 +30,7 @@ func (g *Graph) Argument(name string, parser Parser) ArgumentBuilder {
type LiteralBuilder struct {
g *Graph
current int
current int32
}
func (n LiteralBuilder) AppendLiteral(node *Literal) LiteralBuilderWithLiteral {
@ -57,7 +57,7 @@ func (n LiteralBuilder) Unhandle() *Literal {
type ArgumentBuilder struct {
g *Graph
current int
current int32
}
func (n ArgumentBuilder) AppendLiteral(node *Literal) ArgumentBuilderWithLiteral {

View File

@ -18,8 +18,8 @@ type Graph struct {
func NewGraph() *Graph {
g := new(Graph)
root := Node{
g: g,
flags: RootNode,
g: g,
kind: RootNode,
}
g.nodes = append(g.nodes, root)
return g
@ -43,7 +43,7 @@ func (g *Graph) Run(cmd string) error {
return nil
}
if next == 0 {
panic("root node can't be child")
return errors.New("command contains extra text: " + left)
}
cmd = left
@ -56,19 +56,20 @@ type ParsedData interface{}
type HandlerFunc func(args []ParsedData) error
type Node struct {
g *Graph
index int
flags byte
Name string
Children []int
Parser Parser
Run HandlerFunc
g *Graph
index int32
kind byte
Name string
Children []int32
SuggestionsType string
Parser Parser
Run HandlerFunc
}
type Literal Node
type Argument Node
func (n *Node) parse(cmd string) (left string, value ParsedData, next int, err error) {
switch n.flags & 0x03 {
func (n *Node) parse(cmd string) (left string, value ParsedData, next int32, err error) {
switch n.kind & 0x03 {
case RootNode:
left = cmd
value = nil
@ -90,7 +91,7 @@ func (n *Node) parse(cmd string) (left string, value ParsedData, next int, err e
// find next
if len(n.Children) > 0 {
// look up the first child's type
switch n.g.nodes[n.Children[0]].flags & 0x03 {
switch n.g.nodes[n.Children[0]].kind & 0x03 {
case RootNode:
panic("root node can't be child")
default:

View File

@ -1,63 +1,32 @@
package command
import "testing"
import (
"log"
"testing"
)
func TestRoot_Run(t *testing.T) {
handleFunc := func(args []ParsedData) error {
log.Printf("Command: args: %v", args)
return nil
}
g := NewGraph()
g.AppendLiteral(g.Literal("whitelist").
AppendLiteral(g.Literal("add").
AppendArgument(g.Argument("targets", StringParser(0)).
HandleFunc(func(args []ParsedData) error {
t.Logf("whitelist add: %v", args)
return nil
})).Unhandle()).
AppendLiteral(g.Literal("remove").
AppendArgument(g.Argument("targets", StringParser(0)).
HandleFunc(func(args []ParsedData) error {
t.Logf("whitelist remove: %v", args)
return nil
})).Unhandle()).
AppendLiteral(g.Literal("on").
HandleFunc(func(args []ParsedData) error {
t.Logf("whitelist on: %v", args)
return nil
})).
AppendLiteral(g.Literal("off").
HandleFunc(func(args []ParsedData) error {
t.Logf("whitelist off: %v", args)
return nil
})).
g.AppendLiteral(g.Literal("me").
AppendArgument(g.Argument("action", StringParser(2)).
HandleFunc(handleFunc)).
Unhandle(),
).AppendLiteral(g.Literal("help").
AppendArgument(g.Argument("command", StringParser(0)).
HandleFunc(handleFunc)).
HandleFunc(handleFunc),
).AppendLiteral(g.Literal("list").
AppendLiteral(g.Literal("uuids").
HandleFunc(handleFunc)).
HandleFunc(handleFunc),
)
targetB := g.Argument("targetB", StringParser(0)).
HandleFunc(func(args []ParsedData) error {
t.Logf("tp A <from/to> B parsed: %v", args)
return nil
})
g.AppendLiteral(g.Literal("tp").AppendArgument(
g.Argument("targetA", StringParser(0)).
AppendLiteral(g.Literal("from").
AppendArgument(targetB).
Unhandle()).
AppendLiteral(g.Literal("to").
AppendArgument(targetB).
Unhandle()).
Unhandle(),
).Unhandle())
err := g.Run("tp Tnze to Xi_Xi_Mi")
err := g.Run("me Tnze Xi_Xi_Mi")
if err != nil {
t.Fatal(err)
}
//g2 := NewGraph()
//g2.Then(
// g.Lite("whitelist").Then(
// // using reflect to generate all arguments nodes
// g.Lite("add").Then(g.Func(func(player GameProfile) {
//
// })),
// ),
//)
}

View File

@ -0,0 +1,49 @@
package command
import (
"io"
"unsafe"
pk "github.com/Tnze/go-mc/net/packet"
)
const (
isExecutable = 1 << (iota + 2)
hasRedirect
hasSuggestionsType
)
func (g *Graph) WriteTo(w io.Writer) (int64, error) {
return pk.Tuple{
pk.Array(g.nodes),
pk.VarInt(0),
}.WriteTo(w)
}
func (n Node) WriteTo(w io.Writer) (int64, error) {
var flag byte
flag |= n.kind & 0x03
if n.Run != nil {
flag |= isExecutable
}
return pk.Tuple{
pk.Byte(flag),
pk.Array((*[]pk.VarInt)(unsafe.Pointer(&n.Children))),
pk.Opt{
Has: func() bool { return n.kind&hasRedirect != 0 },
Field: nil, // TODO: send redirect node
},
pk.Opt{
Has: func() bool { return n.kind == ArgumentNode || n.kind == LiteralNode },
Field: pk.String(n.Name),
},
pk.Opt{
Has: func() bool { return n.kind == ArgumentNode },
Field: n.Parser, // Parser identifier and Properties
},
pk.Opt{
Has: func() bool { return flag&hasSuggestionsType != 0 },
Field: nil, // TODO: send Suggestions type
},
}.WriteTo(w)
}