mirror of
https://shylinux.com/x/icebergs
synced 2025-04-26 01:24:05 +08:00
198 lines
5.3 KiB
Go
198 lines
5.3 KiB
Go
package yac
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
|
|
ice "github.com/shylinux/icebergs"
|
|
"github.com/shylinux/icebergs/base/cli"
|
|
"github.com/shylinux/icebergs/base/mdb"
|
|
kit "github.com/shylinux/toolkits"
|
|
)
|
|
|
|
type frame struct {
|
|
key string
|
|
skip bool
|
|
data map[string]string
|
|
}
|
|
|
|
type stack struct {
|
|
fs []*frame
|
|
res []string
|
|
}
|
|
|
|
func (s *stack) push(f *frame) *stack {
|
|
f.data = map[string]string{}
|
|
s.fs = append(s.fs, f)
|
|
return s
|
|
}
|
|
func (s *stack) define(key, value string) {
|
|
if len(s.fs) > 0 {
|
|
s.fs[len(s.fs)-1].data[key] = value
|
|
}
|
|
}
|
|
func (s *stack) value(key string) string {
|
|
for i := len(s.fs) - 1; i >= 0; i-- {
|
|
if value, ok := s.fs[i].data[key]; ok {
|
|
return value
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func _script_push_stack(m *ice.Message, f *frame) {
|
|
stack := m.Optionv("stack").(*stack)
|
|
stack.push(f)
|
|
}
|
|
func _script_define(m *ice.Message, key, value string) {
|
|
stack := m.Optionv("stack").(*stack)
|
|
stack.define(key, value)
|
|
}
|
|
func _script_runing(m *ice.Message, nhash string) bool {
|
|
switch nhash {
|
|
case "if", "for", "end":
|
|
return true
|
|
}
|
|
|
|
stack := m.Optionv("stack").(*stack)
|
|
return !stack.fs[len(stack.fs)-1].skip
|
|
}
|
|
func _script_pop_stack(m *ice.Message) {
|
|
stack := m.Optionv("stack").(*stack)
|
|
stack.fs = stack.fs[:len(stack.fs)-1]
|
|
}
|
|
func _script_res(m *ice.Message, arg ...interface{}) {
|
|
stack := m.Optionv("stack").(*stack)
|
|
stack.res = append(stack.res, kit.Simple(arg...)...)
|
|
}
|
|
|
|
const SCRIPT = "script"
|
|
|
|
func init() {
|
|
Index.Merge(&ice.Context{Commands: map[string]*ice.Command{
|
|
SCRIPT: {Name: "script name npage text:textarea auto create", Help: "脚本解析", Action: map[string]*ice.Action{
|
|
mdb.CREATE: {Name: "create name=shy", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
|
m.Cmd(MATRIX, mdb.CREATE, m.Option(kit.MDB_NAME))
|
|
for _, p := range [][]string{
|
|
[]string{"num", "num", "[0-9]+"},
|
|
[]string{"key", "key", "[abc]+"},
|
|
[]string{"op2", "op2", "[+\\\\-*/%]"},
|
|
[]string{"op2", "op2", "[>=<]"},
|
|
[]string{"val", "val", "mul{ num key }"},
|
|
[]string{"exp", "exp", "val"},
|
|
[]string{"exp", "exp", "val op2 val"},
|
|
[]string{"stm", "var", "var key = exp"},
|
|
[]string{"stm", "for", "for exp"},
|
|
[]string{"stm", "if", "if exp"},
|
|
[]string{"stm", "cmd", "pwd"},
|
|
[]string{"stm", "end", "end"},
|
|
[]string{"script", "script", "rep{ stm }"},
|
|
} {
|
|
m.Cmdx(MATRIX, mdb.INSERT, m.Option(kit.MDB_NAME), p)
|
|
}
|
|
}},
|
|
"exp": {Name: "exp num op2 num", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
|
stack := m.Optionv("stack").(*stack)
|
|
|
|
arg[0] = kit.Select(arg[0], stack.value(arg[0]))
|
|
if len(arg) == 1 {
|
|
m.Echo(arg[0])
|
|
return
|
|
}
|
|
arg[2] = kit.Select(arg[2], stack.value(arg[2]))
|
|
|
|
m.Debug(" %v %v %v", arg[0], arg[1], arg[2])
|
|
n1, e1 := strconv.ParseInt(arg[0], 10, 64)
|
|
n2, e2 := strconv.ParseInt(arg[2], 10, 64)
|
|
m.Debug(" %v %v %v", n1, arg[1], n2)
|
|
switch arg[1] {
|
|
case ">":
|
|
if e1 == nil && e2 == nil {
|
|
m.Echo("%t", n1 > n2)
|
|
} else {
|
|
m.Echo("%t", arg[0] > arg[2])
|
|
}
|
|
case "+":
|
|
if e1 == nil && e2 == nil {
|
|
m.Echo("%d", n1+n2)
|
|
} else {
|
|
m.Echo("%s", arg[0]+arg[2])
|
|
}
|
|
case "-":
|
|
if e1 == nil && e2 == nil {
|
|
m.Echo("%d", n1-n2)
|
|
} else {
|
|
m.Echo("%s", strings.ReplaceAll(arg[0], arg[2], ""))
|
|
}
|
|
case "*":
|
|
if e1 == nil && e2 == nil {
|
|
m.Echo("%d", n1*n2)
|
|
} else {
|
|
m.Echo(arg[0])
|
|
}
|
|
case "/":
|
|
if e1 == nil && e2 == nil {
|
|
m.Echo("%d", n1/n2)
|
|
} else {
|
|
m.Echo("%s", strings.ReplaceAll(arg[0], arg[2], ""))
|
|
}
|
|
case "%":
|
|
if e1 == nil && e2 == nil {
|
|
m.Echo("%d", n1%n2)
|
|
} else {
|
|
m.Echo(arg[0])
|
|
}
|
|
default:
|
|
m.Echo(arg[0], arg[1], arg[2])
|
|
}
|
|
}},
|
|
"if": {Name: "if exp", Help: "判断", Hand: func(m *ice.Message, arg ...string) {
|
|
if arg[1] == "true" {
|
|
_script_push_stack(m, &frame{key: arg[0], skip: false})
|
|
return
|
|
}
|
|
if arg[1] == "false" {
|
|
_script_push_stack(m, &frame{key: arg[0], skip: true})
|
|
return
|
|
}
|
|
if n1, e1 := strconv.ParseInt(arg[1], 10, 64); e1 == nil {
|
|
_script_push_stack(m, &frame{key: arg[0], skip: n1 == 0})
|
|
m.Echo("%t", n1 != 0)
|
|
} else {
|
|
_script_push_stack(m, &frame{skip: len(arg[1]) == 0})
|
|
m.Echo("%t", len(arg[1]) > 0)
|
|
}
|
|
}},
|
|
"var": {Name: "var key = exp", Help: "变量", Hand: func(m *ice.Message, arg ...string) {
|
|
_script_define(m, arg[1], arg[3])
|
|
}},
|
|
"for": {Name: "for exp", Help: "循环", Hand: func(m *ice.Message, arg ...string) {
|
|
}},
|
|
"cmd": {Name: "cmd", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
|
|
_script_res(m, m.Cmdx(cli.SYSTEM, arg))
|
|
}},
|
|
"end": {Name: "end", Help: "结束", Hand: func(m *ice.Message, arg ...string) {
|
|
_script_pop_stack(m)
|
|
}},
|
|
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
if len(arg) < 2 {
|
|
m.Cmdy(MATRIX, arg)
|
|
return
|
|
}
|
|
|
|
stack := &stack{}
|
|
stack.push(&frame{})
|
|
m.Option("stack", stack)
|
|
m.Cmdy(MATRIX, PARSE, arg[0], arg[1], arg[2], func(nhash string, hash int, word []string, rest []byte) (int, []string, []byte) {
|
|
m.Debug("script %v %v", nhash, word)
|
|
if _, ok := c.Commands[SCRIPT].Action[nhash]; ok && _script_runing(m, nhash) {
|
|
msg := m.Cmd(SCRIPT, nhash, word)
|
|
return hash, msg.Resultv(), rest
|
|
}
|
|
return hash, word, rest
|
|
})
|
|
m.Resultv(stack.res)
|
|
}},
|
|
}})
|
|
}
|