1
0
mirror of https://shylinux.com/x/ContextOS synced 2025-04-25 16:58:06 +08:00
This commit is contained in:
shaoying 2019-07-21 12:44:48 +08:00
parent 9f81fa985d
commit 5461b95f36
15 changed files with 936 additions and 866 deletions

View File

@ -1,11 +1,11 @@
~aaa
role root user shy shaoying
~mdb
note model favor spirit spirit relate relate
note model money expend expend amount amount
note model state active active elapse elapse
note model event action action target target
note model proxy ctx text cmd text
note model share stuff stuff right right
# ~mdb
# note model favor spirit spirit relate relate
# note model money expend expend amount amount
# note model state active active elapse elapse
# note model event action action target target
# note model proxy ctx text cmd text
# note model share stuff stuff right right
#

View File

@ -1,7 +1,6 @@
package aaa
import (
"gopkg.in/gomail.v2"
"contexts/ctx"
"crypto"
"crypto/aes"
@ -16,6 +15,7 @@ import (
"encoding/json"
"encoding/pem"
"fmt"
"gopkg.in/gomail.v2"
"io/ioutil"
"math/big"
"math/rand"
@ -36,7 +36,7 @@ type AAA struct {
}
func Auto(m *ctx.Message, arg ...string) {
msg := m.Spawn().Add("option", "auto_cmd", "").Cmd("auth", arg)
msg := m.Spawn().Add("option", "bio.cmd", "").Cmd("auth", arg)
msg.Table(func(line int, maps map[string]string) {
m.Add("append", "value", maps["key"])
m.Add("append", "name", fmt.Sprintf("%s: %s", maps["type"], maps["meta"]))
@ -130,10 +130,10 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
"expire": &ctx.Config{Name: "expire(s)", Value: "72000", Help: "会话超时"},
"email": &ctx.Config{Name: "email", Value: map[string]interface{}{
"self": "shylinux@163.com",
"smtp": "smtp.163.com",
"port": "25",
}, Help: "会话超时"},
"self": "shylinux@163.com",
"smtp": "smtp.163.com",
"port": "25",
}, Help: "会话超时"},
},
Commands: map[string]*ctx.Command{
"_init": &ctx.Command{Name: "_init", Help: "数字摘要", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
@ -723,7 +723,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
msg.SetHeader("From", m.Conf("email", "self"))
msg.SetHeader("To", arg[0])
msg.SetHeader("Subject", arg[1])
msg.SetBody("text/html", strings.Join(arg[2:], ""))
msg.SetBody("text/html", strings.Join(arg[2:], ""))
d := gomail.NewDialer(m.Conf("email", "smtp"), kit.Int(m.Conf("email", "port")), m.Conf("email", "self"), m.Conf("email", "code"))
if e := d.DialAndSend(msg); e != nil {
m.Echo("%v", e)
@ -832,8 +832,8 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
// 生成证书
template := x509.Certificate{
SerialNumber: big.NewInt(1),
IsCA: true,
SerialNumber: big.NewInt(1),
IsCA: true,
BasicConstraintsValid: true,
KeyUsage: x509.KeyUsageCertSign,
Subject: pkix.Name{CommonName: kit.Format(common)},

View File

@ -16,24 +16,13 @@ import (
"fmt"
"os"
"plugin"
"regexp"
"runtime"
"strconv"
"strings"
"time"
)
type Frame struct {
key string
run bool
pos int
index int
list []string
}
type CLI struct {
label map[string]string
stack []*Frame
*time.Timer
Context *ctx.Context
}
@ -51,51 +40,16 @@ func (cli *CLI) schedule(m *ctx.Message) string {
}
func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
c.Caches = map[string]*ctx.Cache{
"level": &ctx.Cache{Name: "level", Value: "0", Help: "嵌套层级"},
"parse": &ctx.Cache{Name: "parse(true/false)", Value: "true", Help: "命令解析"},
}
return &CLI{Context: c}
}
func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server {
return cli
}
func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
m.Cap("stream", m.Sess("yac").Call(func(cmd *ctx.Message) *ctx.Message {
if !m.Caps("parse") {
switch cmd.Detail(0) {
case "if":
cmd.Set("detail", "if", "false")
case "else":
case "end":
case "for":
default:
cmd.Hand = true
return nil
}
}
if cmd.Cmd(); cmd.Has("return") {
m.Options("scan_end", true)
m.Target().Close(m)
}
v := cmd.Optionv("ps_target")
if v != nil {
m.Optionv("ps_target", v)
}
return nil
}, "scan", arg).Target().Name)
return false
return true
}
func (cli *CLI) Close(m *ctx.Message, arg ...string) bool {
switch cli.Context {
case m.Target():
case m.Source():
}
return true
return false
}
var Index = &ctx.Context{Name: "cli", Help: "管理中心",
@ -605,52 +559,6 @@ func main() {
}
return
}},
"source": &ctx.Command{Name: "source [script|stdio|snippet]", Help: "解析脚本, script: 脚本文件, stdio: 命令终端, snippet: 代码片段", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Cmdy("dir", "", "dir_deep", "dir_reg", ".*\\.(sh|shy|py)$")
return
}
// 解析脚本文件
if p := m.Cmdx("nfs.path", arg[0]); p != "" && strings.Contains(p, ".") {
arg[0] = p
switch path.Ext(p) {
case "":
case ".shy":
m.Option("scan_end", "false")
m.Start(fmt.Sprintf("shell%d", m.Capi("nshell", 1)), "shell", arg...)
m.Wait()
default:
m.Cmdy("system", m.Conf("system", []string{"script", strings.TrimPrefix(path.Ext(p), ".")}), arg)
}
m.Append("directory", "")
return
}
// 解析终端命令
if arg[0] == "stdio" {
m.Option("scan_end", "false")
m.Start("shy", "shell", "stdio", "engine")
m.Wait()
return
}
text := strings.Join(arg, " ")
if !strings.HasPrefix(text, "sess") && m.Options("remote") {
text = m.Current(text)
}
// 解析代码片段
m.Sess("yac").Call(func(msg *ctx.Message) *ctx.Message {
switch msg.Cmd().Detail(0) {
case "cmd":
m.Set("append").Copy(msg, "append")
m.Set("result").Copy(msg, "result")
}
return nil
}, "parse", "line", "void", text)
return
}},
"sleep": &ctx.Command{Name: "sleep time", Help: "睡眠, time(ns/us/ms/s/m/h): 时间值(纳秒/微秒/毫秒/秒/分钟/小时)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if d, e := time.ParseDuration(arg[0]); m.Assert(e) {
m.Log("info", "sleep %v", d)
@ -866,7 +774,7 @@ func main() {
m.Echo("quit")
case "1":
if m.Option("cli.modal") != "action" {
if m.Option("bio.modal") != "action" {
m.Cmd("cli.source", m.Conf("system", "script.exit"))
m.Echo("restart")
}
@ -1289,16 +1197,16 @@ var version = struct {
detail = append(detail, arg...)
// 目标切换
target := m.Optionv("ps_target")
target := m.Optionv("bio.ctx")
if detail[0] != "context" {
defer func() { m.Optionv("ps_target", target) }()
defer func() { m.Optionv("bio.ctx", target) }()
}
// 解析脚本
msg := m
for k, v := range m.Confv("system", "script").(map[string]interface{}) {
if strings.HasSuffix(detail[0], "."+k) {
msg = m.Spawn(m.Optionv("ps_target"))
msg = m.Spawn(m.Optionv("bio.ctx"))
detail[0] = m.Cmdx("nfs.path", detail[0])
detail = append([]string{v.(string)}, detail...)
break
@ -1319,7 +1227,7 @@ var version = struct {
}
detail[0] = routes[len(routes)-1]
} else {
msg = m.Spawn(m.Optionv("ps_target"))
msg = m.Spawn(m.Optionv("bio.ctx"))
}
}
msg.Copy(m, "option").Copy(m, "append")
@ -1378,7 +1286,7 @@ var version = struct {
if msg.Set("detail", args).Cmd(); !msg.Hand {
msg.Cmd("system", args)
}
if msg.Appends("ps_target1") {
if msg.Appends("bio.ctx1") {
target = msg.Target()
}
@ -1413,251 +1321,11 @@ var version = struct {
}
// 返回结果
m.Optionv("ps_target", msg.Target())
m.Optionv("bio.ctx", msg.Target())
m.Set("append").Copy(msg, "append")
m.Set("result").Copy(msg, "result")
return
}},
"str": &ctx.Command{Name: "str word", Help: "解析字符串", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Echo(arg[0][1 : len(arg[0])-1])
return
}},
"exe": &ctx.Command{Name: "exe $ ( cmd )", Help: "解析嵌套命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
switch len(arg) {
case 1:
m.Echo(arg[0])
case 2:
msg := m.Spawn(m.Optionv("ps_target"))
switch arg[0] {
case "$":
m.Echo(msg.Cap(arg[1]))
case "@":
value := msg.Option(arg[1])
if value == "" {
value = msg.Conf(arg[1])
}
m.Echo(value)
default:
m.Echo(arg[0]).Echo(arg[1])
}
default:
switch arg[0] {
case "$", "@":
m.Result(0, arg[2:len(arg)-1])
}
}
return
}},
"val": &ctx.Command{Name: "val exp", Help: "表达式运算", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
result := "false"
switch len(arg) {
case 0:
result = ""
case 1:
result = arg[0]
case 2:
switch arg[0] {
case "-z":
if arg[1] == "" {
result = "true"
}
case "-n":
if arg[1] != "" {
result = "true"
}
case "-e":
if _, e := os.Stat(arg[1]); e == nil {
result = "true"
}
case "-f":
if info, e := os.Stat(arg[1]); e == nil && !info.IsDir() {
result = "true"
}
case "-d":
if info, e := os.Stat(arg[1]); e == nil && info.IsDir() {
result = "true"
}
case "+":
result = arg[1]
case "-":
result = arg[1]
if i, e := strconv.Atoi(arg[1]); e == nil {
result = fmt.Sprintf("%d", -i)
}
}
case 3:
v1, e1 := strconv.Atoi(arg[0])
v2, e2 := strconv.Atoi(arg[2])
switch arg[1] {
case ":=":
if !m.Target().Has(arg[0]) {
result = m.Cap(arg[0], arg[0], arg[2], "临时变量")
}
case "=":
result = m.Cap(arg[0], arg[2])
case "+=":
if i, e := strconv.Atoi(m.Cap(arg[0])); e == nil && e2 == nil {
result = m.Cap(arg[0], fmt.Sprintf("%d", v2+i))
} else {
result = m.Cap(arg[0], m.Cap(arg[0])+arg[2])
}
case "+":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%d", v1+v2)
} else {
result = arg[0] + arg[2]
}
case "-":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%d", v1-v2)
} else {
result = strings.Replace(arg[0], arg[1], "", -1)
}
case "*":
result = arg[0]
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%d", v1*v2)
}
case "/":
result = arg[0]
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%d", v1/v2)
}
case "%":
result = arg[0]
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%d", v1%v2)
}
case "<":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 < v2)
} else {
result = fmt.Sprintf("%t", arg[0] < arg[2])
}
case "<=":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 <= v2)
} else {
result = fmt.Sprintf("%t", arg[0] <= arg[2])
}
case ">":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 > v2)
} else {
result = fmt.Sprintf("%t", arg[0] > arg[2])
}
case ">=":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 >= v2)
} else {
result = fmt.Sprintf("%t", arg[0] >= arg[2])
}
case "==":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 == v2)
} else {
result = fmt.Sprintf("%t", arg[0] == arg[2])
}
case "!=":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 != v2)
} else {
result = fmt.Sprintf("%t", arg[0] != arg[2])
}
case "~":
if m, e := regexp.MatchString(arg[2], arg[0]); m && e == nil {
result = "true"
}
case "!~":
if m, e := regexp.MatchString(arg[2], arg[0]); !m || e != nil {
result = "true"
}
}
}
m.Echo(result)
return
}},
"exp": &ctx.Command{Name: "exp word", Help: "表达式运算", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) > 0 && arg[0] == "{" {
msg := m.Spawn()
for i := 1; i < len(arg); i++ {
key := arg[i]
for i += 3; i < len(arg); i++ {
if arg[i] == "]" {
break
}
msg.Add("append", key, arg[i])
}
}
m.Echo("%d", msg.Code())
return
}
pre := map[string]int{
"=": 1,
"+": 2, "-": 2,
"*": 3, "/": 3, "%": 3,
}
num := []string{arg[0]}
op := []string{}
for i := 1; i < len(arg); i += 2 {
if len(op) > 0 && pre[op[len(op)-1]] >= pre[arg[i]] {
num[len(op)-1] = m.Spawn().Cmd("val", num[len(op)-1], op[len(op)-1], num[len(op)]).Get("result")
num = num[:len(num)-1]
op = op[:len(op)-1]
}
num = append(num, arg[i+1])
op = append(op, arg[i])
}
for i := len(op) - 1; i >= 0; i-- {
num[i] = m.Spawn().Cmd("val", num[i], op[i], num[i+1]).Get("result")
}
m.Echo("%s", num[0])
return
}},
"let": &ctx.Command{Name: "let a = exp", Help: "设置变量, a: 变量名, exp: 表达式(a {+|-|*|/|%} b)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
switch arg[2] {
case "=":
m.Cap(arg[1], arg[3])
case "<-":
m.Cap(arg[1], m.Cap("last_msg"))
}
m.Echo(m.Cap(arg[1]))
return
}},
"var": &ctx.Command{Name: "var a [= exp]", Help: "定义变量, a: 变量名, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if m.Cap(arg[1], arg[1], "", "临时变量"); len(arg) > 1 {
switch arg[2] {
case "=":
m.Cap(arg[1], arg[3])
case "<-":
m.Cap(arg[1], m.Cap("last_msg"))
}
}
m.Echo(m.Cap(arg[1]))
return
}},
"expr": &ctx.Command{Name: "expr arg...", Help: "输出表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Echo("%s", strings.Join(arg[1:], ""))
return
}},
"return": &ctx.Command{Name: "return result...", Help: "结束脚本, result: 返回值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Add("append", "return", arg[1:])
return
}},
"arguments": &ctx.Command{Name: "arguments", Help: "脚本参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Set("result", m.Optionv("arguments"))
return
}},
"tmux": &ctx.Command{Name: "tmux buffer", Help: "终端管理, buffer: 查看复制", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
switch arg[0] {
@ -1702,125 +1370,6 @@ var version = struct {
m.Table()
return
}},
"label": &ctx.Command{Name: "label name", Help: "记录当前脚本的位置, name: 位置名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
if cli.label == nil {
cli.label = map[string]string{}
}
cli.label[arg[1]] = m.Option("file_pos")
}
return
}},
"goto": &ctx.Command{Name: "goto label [exp] condition", Help: "向上跳转到指定位置, label: 跳转位置, condition: 跳转条件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
if pos, ok := cli.label[arg[1]]; ok {
if !kit.Right(arg[len(arg)-1]) {
return
}
m.Append("file_pos0", pos)
}
}
return
}},
"if": &ctx.Command{Name: "if exp", Help: "条件语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
run := m.Caps("parse") && kit.Right(arg[1])
cli.stack = append(cli.stack, &Frame{pos: m.Optioni("file_pos"), key: key, run: run})
m.Capi("level", 1)
m.Caps("parse", run)
}
return
}},
"else": &ctx.Command{Name: "else", Help: "条件语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
if !m.Caps("parse") {
m.Caps("parse", true)
} else {
if len(cli.stack) == 1 {
m.Caps("parse", false)
} else {
frame := cli.stack[len(cli.stack)-2]
m.Caps("parse", !frame.run)
}
}
}
return
}},
"end": &ctx.Command{Name: "end", Help: "结束语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
if frame := cli.stack[len(cli.stack)-1]; frame.key == "for" && frame.run {
m.Append("file_pos0", frame.pos)
return
}
if cli.stack = cli.stack[:len(cli.stack)-1]; m.Capi("level", -1) > 0 {
m.Caps("parse", cli.stack[len(cli.stack)-1].run)
} else {
m.Caps("parse", true)
}
}
return
}},
"for": &ctx.Command{Name: "for [[express ;] condition]|[index message meta value]",
Help: "循环语句, express: 每次循环运行的表达式, condition: 循环条件, index: 索引消息, message: 消息编号, meta: value: ",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
run := m.Caps("parse")
defer func() { m.Caps("parse", run) }()
msg := m
if run {
if arg[1] == "index" {
if code, e := strconv.Atoi(arg[2]); m.Assert(e) {
msg = m.Target().Message().Tree(code)
run = run && msg != nil && msg.Meta != nil
switch len(arg) {
case 4:
run = run && len(msg.Meta) > 0
case 5:
run = run && len(msg.Meta[arg[3]]) > 0
}
}
} else {
run = run && kit.Right(arg[len(arg)-1])
}
if len(cli.stack) > 0 {
if frame := cli.stack[len(cli.stack)-1]; frame.key == "for" && frame.pos == m.Optioni("file_pos") {
if arg[1] == "index" {
frame.index++
if run = run && len(frame.list) > frame.index; run {
if len(arg) == 5 {
arg[3] = arg[4]
}
m.Cap(arg[3], frame.list[frame.index])
}
}
frame.run = run
return
}
}
}
cli.stack = append(cli.stack, &Frame{pos: m.Optioni("file_pos"), key: key, run: run, index: 0})
if m.Capi("level", 1); run && arg[1] == "index" {
frame := cli.stack[len(cli.stack)-1]
switch len(arg) {
case 4:
frame.list = []string{}
for k, _ := range msg.Meta {
frame.list = append(frame.list, k)
}
case 5:
frame.list = msg.Meta[arg[3]]
arg[3] = arg[4]
}
m.Cap(arg[3], arg[3], frame.list[0], "临时变量")
}
}
return
}},
},
}

View File

@ -4,5 +4,5 @@ var version = struct {
host string
self int
}{
"2019-07-20 15:41:22", "mac", 229,
"2019-07-20 17:10:58", "mac", 232,
}

View File

@ -36,7 +36,7 @@ func (c *Context) Plugin(s *Context, args []string) string {
m := &Message{code: 0, time: time.Now(), source: s, target: s, Meta: map[string][]string{}}
kit.DisableLog = true
m.Option("log.disable", true)
m.Option("cli.modal", "action")
m.Option("bio.modal", "action")
if len(args) == 0 {
m.Echo("%s: %s\n\n", s.Name, s.Help)
@ -57,9 +57,9 @@ func (c *Context) Plugin(s *Context, args []string) string {
}
m.Cmd(args)
}
for _, v := range m.Meta["result"] {
m.Show(v)
}
for _, v := range m.Meta["result"] {
m.Show(v)
}
return ""
}
func (c *Context) Spawn(m *Message, name string, help string) *Context {
@ -235,7 +235,7 @@ func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message))
}
func (m *Message) Gos(msg *Message, hand ...func(msg *Message)) *Message {
go func() {
msg.Option("routine", m.Capi("ngo", 1))
msg.Option("ctx.routine", m.Capi("ngo", 1))
m.TryCatch(msg, true, hand...)
}()
return m

View File

@ -22,10 +22,15 @@ func (ctx *CTX) Spawn(m *Message, c *Context, arg ...string) Server {
return s
}
func (ctx *CTX) Begin(m *Message, arg ...string) Server {
m.Option("ctx.routine", 0)
m.Option("log.disable", true)
m.Option("ctx.chain", "aaa", "ssh", "cli", "nfs")
m.Option("page.limit", 10)
m.Option("page.offset", 0)
m.Option("routine", 0)
m.Optionv("ctx.form", map[string]int{
"page.limit": 1, "page.offset": 1,
})
m.root = m
m.Sess(m.target.Name, m)
@ -39,19 +44,20 @@ func (ctx *CTX) Begin(m *Message, arg ...string) Server {
return ctx
}
func (ctx *CTX) Start(m *Message, arg ...string) bool {
m.Cmd("ctx._init")
if m.Optionv("ps_target", Index); len(arg) == 0 {
m.Option("cli.modal", "active")
if m.Optionv("bio.ctx", Index); len(arg) == 0 {
m.Option("bio.modal", "active")
m.Option("log.disable", false)
m.Cap("stream", "shy")
m.Cap("stream", "stdio")
m.Cmd("log._init")
m.Cmd("yac._init")
m.Cmd("gdb._init")
m.Cmd("cli.source", m.Conf("system", "script.init")).Cmd("cli.source", "stdio").Cmd("cli.source", m.Conf("system", "script.exit"))
m.Cmd("ctx._init")
m.Cmd("nfs.source", m.Conf("system", "script.init")).Cmd("nfs.source", "stdio").Cmd("nfs.source", m.Conf("system", "script.exit"))
} else {
m.Option("cli.modal", "action")
// m.Cmd("yac._init")
for _, v := range m.Spawn().Cmd(arg).Meta["result"] {
m.Option("bio.modal", "action")
m.Cmd("ctx._init")
for _, v := range m.Sess("cli").Cmd(arg).Meta["result"] {
fmt.Printf("%s", v)
}
}
@ -103,7 +109,8 @@ var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{},
},
Commands: map[string]*Command{
"_init": &Command{Name: "_init", Help: "启动", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
for _, x := range []string{"lex", "cli", "nfs", "aaa", "ssh", "web"} {
for _, x := range []string{"lex", "cli", "yac", "nfs", "aaa", "ssh", "web"} {
kit.Log("error", "%v", x)
m.Cmd(x + "._init")
}
return
@ -735,7 +742,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{},
"message": &Command{Name: "message [code] [cmd...]", Help: "查看消息", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
msg := m
if ms := m.Find(m.Cap("ps_target")); ms != nil {
if ms := m.Find(m.Cap("bio.ctx")); ms != nil {
msg = ms
}
@ -816,7 +823,11 @@ var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{},
keys[k] = true
m.Add("append", "key", k)
m.Add("append", "len", len(msg.Meta[k]))
m.Add("append", "value", fmt.Sprintf("%v", msg.Meta[k]))
if _, ok := msg.Data[k]; ok {
m.Add("append", "value", kit.Format(msg.Data[k]))
} else {
m.Add("append", "value", kit.Format(msg.Meta[k]))
}
continue
}
@ -1420,7 +1431,7 @@ func Start(args ...string) bool {
args = args[1:]
}
if len(args) > 0 && args[0] == "daemon" {
Pulse.Options("cli.modal", "daemon")
Pulse.Options("bio.modal", "daemon")
Pulse.Options("daemon", true)
args = args[1:]
}

View File

@ -129,7 +129,7 @@ func (m *Message) Format(arg ...interface{}) string {
case "code":
meta = append(meta, kit.Format(m.code))
case "ship":
meta = append(meta, fmt.Sprintf("%s:%d(%s->%s)", m.Option("routine"), m.code, m.source.Name, m.target.Name))
meta = append(meta, fmt.Sprintf("%s:%d(%s->%s)", m.Option("ctx.routine"), m.code, m.source.Name, m.target.Name))
case "source":
target := m.target
m.target = m.source
@ -535,7 +535,7 @@ func (m *Message) Log(action string, str string, arg ...interface{}) *Message {
func (m *Message) Show(str string, args ...interface{}) *Message {
res := fmt.Sprintf(str, args...)
if m.Option("cli.modal") == "action" {
if m.Option("bio.modal") == "action" {
fmt.Printf(res)
} else if kit.STDIO != nil {
kit.STDIO.Show(res)
@ -631,7 +631,7 @@ func (m *Message) Match(key string, spawn bool, hand func(m *Message, s *Context
}
context := []*Context{m.target}
for _, v := range []string{"aaa", "ssh", "cli", "nfs"} {
for _, v := range kit.Trans(m.Optionv("ctx.chain")) {
if msg := m.Sess(v, false); msg != nil && msg.target != nil {
context = append(context, msg.target)
}

View File

@ -281,6 +281,97 @@ func (m *Message) Results(arg ...interface{}) bool {
return kit.Right(m.Result(arg...))
}
func (m *Message) Form(x *Command, arg []string) []string {
for _, form := range []map[string]int{m.Optionv("ctx.form").(map[string]int), x.Form} {
if args := []string{}; form != nil {
for i := 0; i < len(arg); i++ {
if n, ok := form[arg[i]]; ok {
if n < 0 {
n += len(arg) - i
}
for j := i + 1; j <= i+n && j < len(arg); j++ {
if _, ok := form[arg[j]]; ok {
n = j - i - 1
}
}
if i+1+n > len(arg) {
m.Add("option", arg[i], arg[i+1:])
} else {
m.Add("option", arg[i], arg[i+1:i+1+n])
}
i += n
} else {
args = append(args, arg[i])
}
}
arg = args
}
}
return arg
}
func (m *Message) Push(str string, arg ...interface{}) *Message {
return m.Add("append", str, arg...)
}
func (m *Message) Sort(key string, arg ...string) *Message {
cmp := "str"
if len(arg) > 0 {
cmp = arg[0]
}
number := map[int]int{}
table := []map[string]string{}
m.Table(func(index int, line map[string]string) {
table = append(table, line)
switch cmp {
case "int":
number[index] = kit.Int(line[key])
case "int_r":
number[index] = -kit.Int(line[key])
case "time":
number[index] = kit.Time(line[key])
case "time_r":
number[index] = -kit.Time(line[key])
}
})
for i := 0; i < len(table)-1; i++ {
for j := i + 1; j < len(table); j++ {
result := false
switch cmp {
case "str":
if table[i][key] > table[j][key] {
result = true
}
case "str_r":
if table[i][key] < table[j][key] {
result = true
}
default:
if number[i] > number[j] {
result = true
}
}
if result {
table[i], table[j] = table[j], table[i]
number[i], number[j] = number[j], number[i]
}
}
}
for _, k := range m.Meta["append"] {
delete(m.Meta, k)
}
for _, v := range table {
for _, k := range m.Meta["append"] {
m.Add("append", k, v[k])
}
}
return m
}
func (m *Message) Table(cbs ...interface{}) *Message {
if len(m.Meta["append"]) == 0 {
return m
@ -376,63 +467,11 @@ func (m *Message) Table(cbs ...interface{}) *Message {
return m
}
func (m *Message) Sort(key string, arg ...string) *Message {
cmp := "str"
func (m *Message) Echo(str string, arg ...interface{}) *Message {
if len(arg) > 0 {
cmp = arg[0]
return m.Add("result", fmt.Sprintf(str, arg...))
}
number := map[int]int{}
table := []map[string]string{}
m.Table(func(index int, line map[string]string) {
table = append(table, line)
switch cmp {
case "int":
number[index] = kit.Int(line[key])
case "int_r":
number[index] = -kit.Int(line[key])
case "time":
number[index] = kit.Time(line[key])
case "time_r":
number[index] = -kit.Time(line[key])
}
})
for i := 0; i < len(table)-1; i++ {
for j := i + 1; j < len(table); j++ {
result := false
switch cmp {
case "str":
if table[i][key] > table[j][key] {
result = true
}
case "str_r":
if table[i][key] < table[j][key] {
result = true
}
default:
if number[i] > number[j] {
result = true
}
}
if result {
table[i], table[j] = table[j], table[i]
number[i], number[j] = number[j], number[i]
}
}
}
for _, k := range m.Meta["append"] {
delete(m.Meta, k)
}
for _, v := range table {
for _, k := range m.Meta["append"] {
m.Add("append", k, v[k])
}
}
return m
return m.Add("result", str)
}
func (m *Message) Copy(msg *Message, arg ...string) *Message {
if msg == nil || m == msg {
@ -487,15 +526,6 @@ func (m *Message) Copy(msg *Message, arg ...string) *Message {
return m
}
func (m *Message) Push(str string, arg ...interface{}) *Message {
return m.Add("append", str, arg...)
}
func (m *Message) Echo(str string, arg ...interface{}) *Message {
if len(arg) > 0 {
return m.Add("result", fmt.Sprintf(str, arg...))
}
return m.Add("result", str)
}
func (m *Message) Cmdp(t time.Duration, head []string, prefix []string, suffix [][]string) *Message {
if head != nil && len(head) > 0 {
@ -571,43 +601,19 @@ func (m *Message) Cmd(args ...interface{}) *Message {
if x, ok := c.Commands[key]; ok && x.Hand != nil {
msg.TryCatch(msg, true, func(msg *Message) {
msg.Log("cmd", "%s %s %v %v", c.Name, key, arg, msg.Meta["option"])
for _, form := range []map[string]int{map[string]int{"page.limit": 1, "page.offset": 1}, x.Form} {
if args := []string{}; form != nil {
for i := 0; i < len(arg); i++ {
if n, ok := form[arg[i]]; ok {
if n < 0 {
n += len(arg) - i
}
for j := i + 1; j <= i+n && j < len(arg); j++ {
if _, ok := form[arg[j]]; ok {
n = j - i - 1
}
}
if i+1+n > len(arg) {
msg.Add("option", arg[i], arg[i+1:])
} else {
msg.Add("option", arg[i], arg[i+1:i+1+n])
}
i += n
} else {
args = append(args, arg[i])
}
}
arg = args
}
}
msg.Hand = true
x.Hand(msg, c, key, msg.Form(x, arg)...)
msg.Log("cmd", "%s %s %v %v", c.Name, key, len(msg.Meta["result"]), msg.Meta["append"])
return
target := msg.target
msg.target = s
msg.Hand = true
switch v := msg.Gdb("command", key, arg).(type) {
case string:
msg.Echo(v)
case nil:
if msg.Options("auto_cmd") {
if msg.Options("bio.cmd") {
if x.Auto != nil {
x.Auto(msg, c, key, arg...)
}

View File

@ -22,12 +22,13 @@ type State struct {
next int
hash int
}
type LEX struct {
seed []*Seed
hash map[string]int
hashs map[int]string
pages map[int]string
page map[string]int
seed []*Seed
hash map[string]int
word map[int]string
hand map[int]string
page map[string]int
char map[byte][]byte
state map[State]*State
@ -36,10 +37,16 @@ type LEX struct {
*ctx.Context
}
func (lex *LEX) charset(c byte) []byte {
if cs, ok := lex.char[c]; ok {
return cs
}
return []byte{c}
}
func (lex *LEX) index(m *ctx.Message, hash string, h string) int {
which, names := lex.hash, lex.hashs
which, names := lex.hash, lex.word
if hash == "npage" {
which, names = lex.page, lex.pages
which, names = lex.page, lex.hand
}
if x, e := strconv.Atoi(h); e == nil {
@ -60,12 +67,6 @@ func (lex *LEX) index(m *ctx.Message, hash string, h string) int {
m.Assert(hash != "npage" || m.Capi("npage") < m.Confi("meta", "nlang"), "语法集合超过上限")
return which[h]
}
func (lex *LEX) charset(c byte) []byte {
if cs, ok := lex.char[c]; ok {
return cs
}
return []byte{c}
}
func (lex *LEX) train(m *ctx.Message, page int, hash int, seed []byte) int {
m.Log("debug", "%s %s page: %v hash: %v seed: %v", "train", "lex", page, hash, string(seed))
@ -288,8 +289,8 @@ func (lex *LEX) Begin(m *ctx.Message, arg ...string) ctx.Server {
lex.page = map[string]int{"nil": 0}
lex.hash = map[string]int{"nil": 0}
lex.hashs = map[int]string{0: "nil"}
lex.pages = map[int]string{0: "nil"}
lex.word = map[int]string{0: "nil"}
lex.hand = map[int]string{0: "nil"}
lex.char = map[byte][]byte{
't': []byte{'\t'},
@ -376,7 +377,7 @@ var Index = &ctx.Context{Name: "lex", Help: "词法中心",
}
m.Push("word", string(word))
m.Push("hash", lex.hashs[hash])
m.Push("hash", lex.word[hash])
m.Push("rest", string(rest))
input = rest
}
@ -387,40 +388,34 @@ var Index = &ctx.Context{Name: "lex", Help: "词法中心",
"show": &ctx.Command{Name: "show seed|page|hash|mat|node", Help: "查看信息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) {
if len(arg) == 0 {
m.Append("seed", len(lex.seed))
m.Append("page", len(lex.page))
m.Append("hash", len(lex.hash))
m.Append("nmat", len(lex.mat))
m.Append("node", len(lex.state))
m.Push("seed", len(lex.seed))
m.Push("page", len(lex.page))
m.Push("hash", len(lex.hash))
m.Push("nmat", len(lex.mat))
m.Push("node", len(lex.state))
m.Table()
return
}
switch arg[0] {
case "seed":
for _, v := range lex.seed {
m.Push("page", fmt.Sprintf("%s", lex.pages[v.page]))
m.Push("word", fmt.Sprintf("%s", strings.Replace(strings.Replace(v.word, "\n", "\\n", -1), "\t", "\\t", -1)))
m.Push("hash", fmt.Sprintf("%s", lex.hashs[v.hash]))
m.Push("page", lex.hand[v.page])
m.Push("word", strings.Replace(strings.Replace(v.word, "\n", "\\n", -1), "\t", "\\t", -1))
m.Push("hash", lex.word[v.hash])
}
m.Sort("page", "int").Table()
case "page":
for k, v := range lex.page {
if k == "nil" {
continue
}
m.Push("page", k)
m.Push("code", fmt.Sprintf("%d", v))
m.Push("code", v)
}
m.Sort("code", "int").Table()
case "hash":
for k, v := range lex.hash {
if k == "nil" {
continue
}
m.Push("hash", k)
m.Push("code", fmt.Sprintf("%d", v))
m.Push("code", v)
}
m.Sort("code", "int").Table()
@ -435,7 +430,7 @@ var Index = &ctx.Context{Name: "lex", Help: "词法中心",
case "mat":
for i, v := range lex.mat {
if i <= m.Capi("npage") {
m.Push("index", lex.pages[i])
m.Push("index", lex.hand[i])
} else if i < m.Confi("meta", "nlang") {
continue
} else {

View File

@ -57,7 +57,7 @@ func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool {
var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
Caches: map[string]*ctx.Cache{
"nsource": &ctx.Cache{Name: "nsource", Value: "0", Help: "已打开数据库的数量"},
"redis": &ctx.Cache{Name: "redis", Value: "", Help: "服务地址"},
"redis": &ctx.Cache{Name: "redis", Value: "", Help: "服务地址"},
},
Configs: map[string]*ctx.Config{
"database": &ctx.Config{Name: "database", Value: "demo", Help: "默认数据库"},
@ -138,7 +138,7 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
break
}
if mdb.conn.Err() != nil {
mdb.conn, e = redis.Dial("tcp", m.Cap("redis"), redis.DialKeepAlive(time.Second*10))
mdb.conn, e = redis.Dial("tcp", m.Cap("redis"), redis.DialKeepAlive(time.Second*10))
}
args := []interface{}{}
for _, v := range arg[1:] {
@ -156,13 +156,13 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
}
m.Table()
default:
str := kit.Format(res)
var data interface{}
if json.Unmarshal([]byte(str), &data) == nil {
m.Echo(kit.Formats(data))
} else {
m.Echo(str)
}
str := kit.Format(res)
var data interface{}
if json.Unmarshal([]byte(str), &data) == nil {
m.Echo(kit.Formats(data))
} else {
m.Echo(str)
}
}
}
}
@ -265,7 +265,7 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
"db": &ctx.Command{Name: "db [which]", Help: "查看或选择数据库",
Auto: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) bool {
if len(arg) == 0 {
m.Put("option", "auto_cmd", "").Spawn().Cmd("query", "show databases").Table(func(line map[string]string) {
m.Put("option", "bio.cmd", "").Spawn().Cmd("query", "show databases").Table(func(line map[string]string) {
for _, v := range line {
m.Auto(v, "", "")
}
@ -287,13 +287,13 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
Auto: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) bool {
switch len(arg) {
case 0:
m.Put("option", "auto_cmd", "").Spawn().Cmd("query", "show tables").Table(func(line map[string]string) {
m.Put("option", "bio.cmd", "").Spawn().Cmd("query", "show tables").Table(func(line map[string]string) {
for _, v := range line {
m.Auto(v, "", "")
}
})
case 1:
m.Put("option", "auto_cmd", "").Spawn().Cmd("query", fmt.Sprintf("desc %s", arg[0])).Table(func(line map[string]string) {
m.Put("option", "bio.cmd", "").Spawn().Cmd("query", fmt.Sprintf("desc %s", arg[0])).Table(func(line map[string]string) {
m.Auto(line["Field"], line["Type"], line["Default"])
})
}
@ -314,7 +314,7 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
Form: map[string]int{"where": 1, "eq": 2, "like": 2, "in": 2, "begin": 2, "group": 1, "order": 1, "desc": 0, "limit": 1, "offset": 1, "other": -1},
Auto: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) bool {
if len(arg) == 0 {
m.Put("option", "auto_cmd", "").Spawn().Cmd("query", "show tables").Table(func(line map[string]string) {
m.Put("option", "bio.cmd", "").Spawn().Cmd("query", "show tables").Table(func(line map[string]string) {
for _, v := range line {
m.Auto(v, "", "")
}

View File

@ -191,11 +191,10 @@ func (nfs *NFS) Read(p []byte) (n int, err error) {
rest := make([]rune, 0, 1024)
back := make([]rune, 0, 1024)
m.Optionv("auto_target", m.Optionv("ps_target"))
m.Option("auto_cmd", "")
m.Options("show_shadow", m.Confs("show_shadow"))
m.Option("bio.cmd", "")
m.Options("bio.shadow", m.Confs("show_shadow"))
defer func() { m.Option("auto_cmd", "") }()
defer func() { m.Option("bio.cmd", "") }()
frame, table, index, pick := map[string]interface{}{}, []map[string]string{}, 0, 0
if change, f, t, i := nfs.Auto(what, ":", 0); change {
@ -358,13 +357,13 @@ func (nfs *NFS) Read(p []byte) (n int, err error) {
case termbox.KeyCtrlG:
case termbox.KeyCtrlX:
m.Options("show_shadow", !m.Options("show_shadow"))
m.Options("bio.shadow", !m.Options("bio.shadow"))
case termbox.KeyCtrlS:
case termbox.KeyCtrlZ:
case termbox.KeyTab:
m.Options("show_shadow", true)
m.Options("bio.shadow", true)
// if index > len(what) {
// nfs.shadow("", table, frame)
// } else {
@ -380,7 +379,7 @@ func (nfs *NFS) Read(p []byte) (n int, err error) {
case termbox.KeySpace:
what = append(what, ' ')
nfs.prompt(what).shadow(rest)
if !m.Options("show_shadow") {
if !m.Options("bio.shadow") {
break
}
@ -402,7 +401,7 @@ func (nfs *NFS) Read(p []byte) (n int, err error) {
default:
what = append(what, ev.Ch)
nfs.prompt(what).shadow(rest)
if !m.Options("show_shadow") {
if !m.Options("bio.shadow") {
break
}
@ -428,9 +427,10 @@ func (nfs *NFS) Read(p []byte) (n int, err error) {
return
}
func (nfs *NFS) Auto(what []rune, trigger string, index int) (change bool, frame map[string]interface{}, table []map[string]string, nindex int) {
return
m := nfs.Context.Message()
auto_target := m.Optionv("auto_target").(*ctx.Context)
auto_target := m.Optionv("bio.ctx").(*ctx.Context)
auto_cmd := ""
auto_arg := []string{}
@ -439,14 +439,14 @@ func (nfs *NFS) Auto(what []rune, trigger string, index int) (change bool, frame
switch m.Conf("term", "help_state") {
case "context":
auto_target = auto_target.Sub(m.Option("auto_key"))
m.Optionv("auto_target", auto_target)
m.Optionv("bio.ctx", auto_target)
trigger = ":"
case "command":
m.Option("arg_index", index)
auto_cmd = m.Option("auto_cmd", m.Option("auto_key"))
auto_cmd = m.Option("bio.cmd", m.Option("auto_key"))
trigger = "="
case "argument":
auto_cmd = m.Option("auto_cmd")
auto_cmd = m.Option("bio.cmd")
auto_arg = strings.Split(strings.TrimSpace(string(what[m.Optioni("arg_index"):])), " ")
trigger = "="
}
@ -720,7 +720,7 @@ func (nfs *NFS) Term(msg *ctx.Message, action string, args ...interface{}) *NFS
}
func (nfs *NFS) prompt(arg ...interface{}) *NFS {
m := nfs.Context.Message()
target, _ := m.Optionv("ps_target").(*ctx.Context)
target, _ := m.Optionv("bio.ctx").(*ctx.Context)
if target == nil {
target = nfs.Context
}
@ -783,10 +783,10 @@ func (nfs *NFS) shadow(args ...interface{}) *NFS {
return nfs
}
func (nfs *NFS) printf(arg ...interface{}) *NFS {
func (nfs *NFS) print(arg ...string) *NFS {
m := nfs.Context.Message()
line := strings.TrimRight(kit.Format(arg...), "\n")
line := strings.TrimRight(strings.Join(arg, ""), "\n")
m.Log("debug", "noutput %s", m.Cap("noutput", m.Capi("noutput")+1))
m.Confv("output", -2, map[string]interface{}{"time": time.Now().Unix(), "line": line})
@ -900,16 +900,6 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
}
if len(arg) > 0 && arg[0] == "scan" {
// 终端用户
m.Cmd("aaa.role", "root", "user", m.Option("username", m.Conf("runtime", "boot.username")))
// 创建会话
m.Option("sessid", m.Cmdx("aaa.user", "session", "select"))
// 创建空间
m.Option("bench", m.Cmdx("aaa.sess", "bench", "select"))
// 默认配置
m.Cap("stream", arg[1])
nfs.Caches["ninput"] = &ctx.Cache{Value: "0"}
nfs.Caches["noutput"] = &ctx.Cache{Value: "0"}
@ -919,20 +909,28 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
nfs.Configs["prompt"] = &ctx.Config{Value: ""}
// 终端控制
if nfs.in = m.Optionv("in").(*os.File); m.Has("out") {
if nfs.out = m.Optionv("out").(*os.File); m.Conf("runtime", "host.GOOS") != "windows" && !m.Options("daemon") {
kit.STDIO = nfs
nfs.Term(m, "init")
m.Conf("term", "use", true)
if nfs.in = m.Optionv("bio.in").(*os.File); m.Has("bio.out") {
if nfs.out = m.Optionv("bio.out").(*os.File); m.Conf("runtime", "host.GOOS") != "windows" && !m.Options("daemon") {
m.Conf("term", "use", nfs.Term(m, "init") != nil)
defer nfs.Term(m, "exit")
}
if what := make(chan bool); m.Options("daemon") {
<-what
kit.STDIO = nfs
} else if m.Options("daemon") {
return true
}
}
// 终端用户
m.Cmd("aaa.role", "root", "user", m.Option("username", m.Conf("runtime", "boot.username")))
m.Option("sessid", m.Cmdx("aaa.user", "session", "select"))
m.Optionv("bio.ctx", m.Target())
stack := kit.Stack{}
stack.Push(m.Option("stack.key", "source"), m.Options("stack.run", true), m.Optioni("stack.pos", 0))
line, bio := "", bufio.NewScanner(nfs)
for nfs.prompt(); !m.Options("scan_end"); nfs.prompt() {
for nfs.prompt(); ; nfs.prompt() {
// 读取数据
for bio.Scan() {
if text := bio.Text(); text == "" {
continue
@ -944,31 +942,66 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
}
}
if line == "" {
line = "return"
break
}
m.Log("debug", "%s %d %d [%s]", "input", m.Capi("ninput", 1), len(line), line)
m.Confv("input", -2, map[string]interface{}{"time": time.Now().Unix(), "line": line})
// 解析数据
for i := m.Capi("ninput") - 1; i < m.Capi("ninput"); i++ {
line = m.Conf("input", []interface{}{i, "line"})
msg := m.Backs(m.Spawn(m.Source()).Set(
"detail", line).Set(
"option", "file_pos", i).Set(
"option", "username", m.Conf("runtime", "boot.username")))
// 结束语句
if strings.TrimSpace(line) == "end" {
m.Log("stack", " pop %v", stack.Peek().String("/"))
if stack.Pop(); m.Options("stack.run") && m.Option("stack.key") == "for" {
i = m.Optioni("stack.pos") - 1
}
frame := stack.Peek()
m.Options("stack.run", frame.Run)
m.Option("stack.key", frame.Key)
continue
}
nfs.printf(m.Conf("prompt"), line)
nfs.printf(msg.Meta["result"])
// 跳过语句
if !stack.Peek().Run {
m.Log("stack", "skip %v", line)
continue
}
if msg.Appends("file_pos0") {
i = int(msg.Appendi("file_pos0")) - 1
msg.Append("file_pos0", "")
// 执行语句
msg := m.Cmd("yac.parse", line+"\n").Set("option", "bio.pos", i)
nfs.print(m.Conf("prompt"), line)
nfs.print(msg.Meta["result"]...)
// 切换模块
if v := msg.Optionv("bio.ctx"); v != nil {
m.Optionv("bio.ctx", v)
}
// 压栈语句
if msg.Appends("stack.key") {
stack.Push(m.Option("stack.key", msg.Append("stack.key")), m.Options("stack.run", msg.Appends("stack.run")), m.Optioni("stack.pos", i))
m.Log("stack", "push %v", stack.Peek().String("\\"))
msg.Append("stack.key", "")
}
// 跳转语句
if msg.Appends("bio.pos0") {
i = int(msg.Appendi("bio.pos0")) - 1
msg.Append("bio.pos0", "")
}
// 结束脚本
if msg.Appends("bio.end") {
m.Copy(msg, "append")
m.Copy(msg, "result")
break
}
}
line = ""
}
return false
return true
}
m.Cap("stream", m.Option("ms_source"))
@ -1775,7 +1808,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
}
m.Start(fmt.Sprintf("file%d", m.Capi("nfile")), fmt.Sprintf("file %s", arg[0]), "open", arg[0])
m.Append("ps_target1", m.Cap("module"))
m.Append("bio.ctx1", m.Cap("module"))
m.Echo(m.Cap("module"))
return
}},
@ -1819,19 +1852,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
return
}},
"scan": &ctx.Command{Name: "scan file name", Help: "扫描文件, file: 文件名, name: 模块名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if _, ok := m.Target().Server.(*NFS); m.Assert(ok) {
if help := fmt.Sprintf("scan %s", arg[0]); arg[0] == "stdio" {
m.Put("option", "in", os.Stdin).Put("option", "out", os.Stdout).Start(arg[0], help, key, arg[0])
} else if p, f, e := open(m, arg[0]); m.Assert(e) {
m.Put("option", "in", f).Start(fmt.Sprintf("file%d", m.Capi("nfile", 1)), help, key, p)
}
}
return
}},
"printf": &ctx.Command{Name: "printf arg", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) {
nfs.printf(arg)
nfs.print(arg...)
}
return
}},
@ -1850,8 +1873,8 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
"action": &ctx.Command{Name: "action cmd", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) {
msg := m.Cmd("cli.source", arg)
nfs.printf(msg.Conf("prompt"), arg, "\n")
nfs.printf(msg.Meta["result"])
// nfs.print(msg.Conf("prompt"), arg, "\n")
nfs.print(msg.Meta["result"]...)
}
return
}},
@ -1876,6 +1899,103 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
}
return
}},
"source": &ctx.Command{Name: "source [script|stdio|snippet]", Help: "解析脚本, script: 脚本文件, stdio: 命令终端, snippet: 代码片段", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if _, ok := m.Target().Server.(*NFS); m.Assert(ok) {
m.Optionv("bio.args", arg)
if help := fmt.Sprintf("scan %s", arg[0]); arg[0] == "stdio" {
m.Put("option", "bio.in", os.Stdin).Put("option", "bio.out", os.Stdout).Start(arg[0], help, "scan", arg[0])
m.Wait()
} else if p, f, e := open(m, arg[0]); e == nil {
m.Put("option", "bio.in", f).Start(fmt.Sprintf("file%d", m.Capi("nfile", 1)), help, "scan", p)
m.Wait()
} else {
}
}
return
if len(arg) == 0 {
m.Cmdy("dir", "", "dir_deep", "dir_reg", ".*\\.(sh|shy|py)$")
return
}
m.Cap("stream", m.Sess("yac").Call(func(cmd *ctx.Message) *ctx.Message {
if !m.Caps("parse") {
switch cmd.Detail(0) {
case "if":
cmd.Set("detail", "if", "false")
case "else":
case "end":
case "for":
default:
cmd.Hand = true
return nil
}
}
if cmd.Cmd(); cmd.Has("return") {
m.Options("scan_end", true)
m.Target().Close(m)
}
v := cmd.Optionv("bio.ctx")
if v != nil {
m.Optionv("bio.ctx", v)
}
return nil
}, "scan", arg).Target().Name)
// 解析脚本文件
if p := m.Cmdx("nfs.path", arg[0]); p != "" && strings.Contains(p, ".") {
arg[0] = p
switch path.Ext(p) {
case "":
case ".shy":
m.Option("scan_end", "false")
m.Start(fmt.Sprintf("shell%d", m.Capi("nshell", 1)), "shell", arg...)
m.Wait()
default:
m.Cmdy("system", m.Conf("system", []string{"script", strings.TrimPrefix(path.Ext(p), ".")}), arg)
}
m.Append("directory", "")
return
}
// 解析终端命令
if arg[0] == "stdio" {
m.Option("scan_end", "false")
m.Start("shy", "shell", "stdio", "engine")
m.Wait()
return
}
text := strings.Join(arg, " ")
if !strings.HasPrefix(text, "sess") && m.Options("remote") {
text = m.Current(text)
}
// 解析代码片段
m.Sess("yac").Call(func(msg *ctx.Message) *ctx.Message {
switch msg.Cmd().Detail(0) {
case "cmd":
m.Set("append").Copy(msg, "append")
m.Set("result").Copy(msg, "result")
}
return nil
}, "parse", "line", "void", text)
return
}},
"arguments": &ctx.Command{Name: "arguments", Help: "脚本参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
args := kit.Trans(m.Optionv("bio.args"))
if len(arg) == 0 {
m.Set("result", args)
} else {
m.Echo(kit.Select("", args, kit.Int(arg[0])))
}
return
}},
},
}

View File

@ -3,8 +3,11 @@ package yac
import (
"contexts/ctx"
"fmt"
"os"
"regexp"
"strconv"
"strings"
"toolkit"
)
type Seed struct {
@ -12,26 +15,28 @@ type Seed struct {
hash int
word []string
}
type State struct {
next int
star int
hash int
}
type Point struct {
s int
c byte
}
type State struct {
star int
next int
hash int
}
type YAC struct {
seed []*Seed
page map[string]int
word map[int]string
hash map[string]int
hand map[int]string
hash map[string]int
mat []map[byte]*State
state map[State]*State
mat []map[byte]*State
lex *ctx.Message
label map[string]string
*ctx.Context
}
@ -41,6 +46,21 @@ func (yac *YAC) name(page int) string {
}
return fmt.Sprintf("yac%d", page)
}
func (yac *YAC) index(m *ctx.Message, hash string, h string) int {
which, names := yac.page, yac.word
if hash == "nhash" {
which, names = yac.hash, yac.hand
}
if x, ok := which[h]; ok {
return x
}
which[h] = m.Capi(hash, 1)
names[which[h]] = h
m.Assert(hash != "npage" || m.Capi("npage") < m.Confi("meta", "nlang"), "语法集合超过上限")
return which[h]
}
func (yac *YAC) train(m *ctx.Message, page, hash int, word []string, level int) (int, []*Point, []*Point) {
m.Log("debug", "%s %s\\%d page: %v hash: %v word: %v", "train", strings.Repeat("#", level), level, page, hash, word)
@ -127,7 +147,7 @@ func (yac *YAC) train(m *ctx.Message, page, hash int, word []string, level int)
}
}
for _, s := range ss {
if s < m.Confi("info", "nlang") || s >= len(yac.mat) {
if s < m.Confi("meta", "nlang") || s >= len(yac.mat) {
continue
}
void := true
@ -171,168 +191,179 @@ func (yac *YAC) train(m *ctx.Message, page, hash int, word []string, level int)
m.Log("debug", "%s %s/%d word: %d point: %d end: %d", "train", strings.Repeat("#", level), level, len(word), len(points), len(ends))
return len(word), points, ends
}
func (yac *YAC) parse(m *ctx.Message, out *ctx.Message, page int, void int, line string, level int) (string, []string, int) {
func (yac *YAC) parse(m *ctx.Message, msg *ctx.Message, page int, void int, line string, level int) (string, []string, int) {
m.Log("debug", "%s %s\\%d %s(%d): %s", "parse", strings.Repeat("#", level), level, yac.name(page), page, line)
hash, word := 0, []string{}
lex, hash, word := yac.lex, 0, []string{}
for star, s := 0, page; s != 0 && len(line) > 0; {
//解析空白
lex := yac.lex.Spawn()
if lex.Cmd("parse", line, yac.name(void)); lex.Result(0) == "-1" {
if lex = yac.lex.Spawn().Cmd("parse", line, yac.name(void)); lex.Result(0) == "-1" {
break
}
//解析单词
line = lex.Result(1)
lex = yac.lex.Spawn()
if lex.Cmd("parse", line, yac.name(s)); lex.Result(0) == "-1" {
//解析单词
if lex = yac.lex.Spawn().Cmd("parse", line, yac.name(s)); lex.Result(0) == "-1" {
break
}
//解析状态
result := append([]string{}, lex.Meta["result"]...)
i, _ := strconv.Atoi(result[0])
c := byte(i)
state := yac.mat[s][c]
if state != nil { //全局语法检查
//解析状态
state := yac.mat[s][byte(kit.Int(result[0]))]
//全局语法检查
if state != nil {
if key := yac.lex.Spawn().Cmd("parse", line, "key"); key.Resulti(0) == 0 || len(key.Result(2)) <= len(result[2]) {
line, word = result[1], append(word, result[2])
} else {
state = nil
}
}
if state == nil { //嵌套语法递归解析
for i := 0; i < m.Confi("info", "ncell"); i++ {
if x := yac.mat[s][byte(i)]; i < m.Confi("info", "nlang") && x != nil {
if l, w, _ := yac.parse(m, out, i, void, line, level+1); l != line {
line, word = l, append(word, w...)
state = x
//嵌套语法递归解析
if state == nil {
for i := 0; i < m.Confi("meta", "ncell"); i++ {
if x := yac.mat[s][byte(i)]; i < m.Confi("meta", "nlang") && x != nil {
if l, w, _ := yac.parse(m, msg, i, void, line, level+1); l != line {
line, word, state = l, append(word, w...), x
break
}
}
}
}
if state == nil { //语法切换
//语法切换
if state == nil {
s, star = star, 0
continue
}
if s, star, hash = state.next, state.star, state.hash; s == 0 { //状态切换
} else if s, star, hash = state.next, state.star, state.hash; s == 0 {
s, star = star, 0
}
}
if hash == 0 {
word = word[:0]
} else if !m.Confs("exec", []string{yac.hand[hash], "disable"}) { //执行命令
msg := out.Spawn(m.Source()).Add("detail", yac.hand[hash], word)
if m.Back(msg); msg.Hand { //命令替换
word = msg.Meta["result"]
cmd := msg.Spawn(m.Optionv("bio.ctx"))
if cmd.Cmd(yac.hand[hash], word); cmd.Hand {
word = cmd.Meta["result"]
}
if v := cmd.Optionv("bio.ctx"); v != nil {
m.Optionv("bio.ctx", v)
}
}
m.Log("debug", "%s %s/%d %s(%d): %v", "parse", strings.Repeat("#", level), level, yac.name(page), page, word)
m.Log("debug", "%s %s/%d %s(%d): %v", "parse", strings.Repeat("#", level), level, yac.hand[hash], hash, word)
return line, word, hash
}
func (yac *YAC) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
if len(arg) > 0 && arg[0] == "scan" {
return yac
}
return &YAC{Context: c}
}
func (yac *YAC) Begin(m *ctx.Message, arg ...string) ctx.Server {
yac.Caches["nseed"] = &ctx.Cache{Name: "种子数量", Value: "0", Help: "语法模板的数量"}
yac.Caches["npage"] = &ctx.Cache{Name: "集合数量", Value: "0", Help: "语法集合的数量"}
yac.Caches["nhash"] = &ctx.Cache{Name: "类型数量", Value: "0", Help: "语句类型的数量"}
yac.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: m.Conf("meta", "nlang"), Help: "状态机状态的数量"}
yac.Caches["nnode"] = &ctx.Cache{Name: "节点数量", Value: "0", Help: "状态机连接的逻辑数量"}
yac.Caches["nreal"] = &ctx.Cache{Name: "实点数量", Value: "0", Help: "状态机连接的存储数量"}
yac.Caches["level"] = &ctx.Cache{Name: "level", Value: "0", Help: "嵌套层级"}
yac.Caches["parse"] = &ctx.Cache{Name: "parse(true/false)", Value: "true", Help: "命令解析"}
yac.page = map[string]int{"nil": 0}
yac.word = map[int]string{0: "nil"}
yac.hash = map[string]int{"nil": 0}
yac.hand = map[int]string{0: "nil"}
yac.state = map[State]*State{}
yac.mat = make([]map[byte]*State, m.Capi("nline"))
return yac
}
func (yac *YAC) Start(m *ctx.Message, arg ...string) (close bool) {
if len(arg) > 0 && arg[0] == "scan" {
m.Cap("stream", arg[1])
m.Sess("nfs").Call(func(input *ctx.Message) *ctx.Message {
_, word, _ := yac.parse(m, input, m.Optioni("page"), m.Optioni("void"), input.Detail(0)+"\n", 1)
input.Result(0, word)
return nil
}, "scan", arg[1:])
return false
}
return true
}
func (yac *YAC) Close(m *ctx.Message, arg ...string) bool {
return true
return false
}
var Index = &ctx.Context{Name: "yac", Help: "语法中心",
Caches: map[string]*ctx.Cache{
"nparse": &ctx.Cache{Name: "nparse", Value: "0", Help: "解析器数量"},
"nshy": &ctx.Cache{Name: "nshy", Value: "0", Help: "引擎数量"},
},
Configs: map[string]*ctx.Config{
"nline": &ctx.Config{Name: "nline", Value: "line", Help: "默认页"},
"nvoid": &ctx.Config{Name: "nvoid", Value: "void", Help: "默认值"},
"meta": &ctx.Config{Name: "meta", Value: map[string]interface{}{
"ncell": 128, "nlang": 64, "compact": true,
"name": "shy%d", "help": "engine",
}, Help: "初始参数"},
"seed": &ctx.Config{Name: "seed", Value: []interface{}{
map[string]interface{}{"page": "void", "hash": "void", "word": []interface{}{"[\t ]+"}},
map[string]interface{}{"page": "key", "hash": "key", "word": []interface{}{"[A-Za-z_][A-Za-z_0-9]*"}},
map[string]interface{}{"page": "num", "hash": "num", "word": []interface{}{"mul{", "0", "-?[1-9][0-9]*", "0[0-9]+", "0x[0-9]+", "}"}},
map[string]interface{}{"page": "key", "hash": "key", "word": []interface{}{"[A-Za-z_][A-Za-z_0-9]*"}},
map[string]interface{}{"page": "str", "hash": "str", "word": []interface{}{"mul{", "\"[^\"]*\"", "'[^']*'", "}"}},
map[string]interface{}{"page": "exe", "hash": "exe", "word": []interface{}{"mul{", "$", "@", "}", "key"}},
map[string]interface{}{"page": "exe", "hash": "exe", "word": []interface{}{"mul{", "$", "@", "}", "opt{", "key", "}"}},
map[string]interface{}{"page": "op1", "hash": "op1", "word": []interface{}{"mul{", "-z", "-n", "}"}},
map[string]interface{}{"page": "op1", "hash": "op1", "word": []interface{}{"mul{", "-e", "-f", "-d", "}"}},
map[string]interface{}{"page": "op1", "hash": "op1", "word": []interface{}{"mul{", "-", "+", "}"}},
map[string]interface{}{"page": "op2", "hash": "op2", "word": []interface{}{"mul{", ":=", "=", "+=", "}"}},
map[string]interface{}{"page": "op2", "hash": "op2", "word": []interface{}{"mul{", "+", "-", "*", "/", "%", "}"}},
map[string]interface{}{"page": "op2", "hash": "op2", "word": []interface{}{"mul{", "<", "<=", ">", ">=", "==", "!=", "}"}},
map[string]interface{}{"page": "op2", "hash": "op2", "word": []interface{}{"mul{", "~", "!~", "}"}},
map[string]interface{}{"page": "val", "hash": "val", "word": []interface{}{"opt{", "op1", "}", "mul{", "num", "key", "str", "exe", "}"}},
map[string]interface{}{"page": "exp", "hash": "exp", "word": []interface{}{"val", "rep{", "op2", "val", "}"}},
map[string]interface{}{"page": "map", "hash": "map", "word": []interface{}{"key", ":", "\\[", "rep{", "key", "}", "\\]"}},
map[string]interface{}{"page": "exp", "hash": "exp", "word": []interface{}{"\\{", "rep{", "map", "}", "\\}"}},
map[string]interface{}{"page": "val", "hash": "val", "word": []interface{}{"opt{", "op1", "}", "(", "exp", ")"}},
map[string]interface{}{"page": "stm", "hash": "var", "word": []interface{}{"var", "key", "opt{", "=", "exp", "}"}},
map[string]interface{}{"page": "stm", "hash": "let", "word": []interface{}{"let", "key", "opt{", "=", "exp", "}"}},
map[string]interface{}{"page": "stm", "hash": "var", "word": []interface{}{"var", "key", "<-"}},
map[string]interface{}{"page": "stm", "hash": "var", "word": []interface{}{"var", "key", "<-", "opt{", "exe", "}"}},
map[string]interface{}{"page": "stm", "hash": "let", "word": []interface{}{"let", "key", "<-", "opt{", "exe", "}"}},
map[string]interface{}{"page": "stm", "hash": "if", "word": []interface{}{"if", "exp"}},
map[string]interface{}{"page": "stm", "hash": "else", "word": []interface{}{"else"}},
map[string]interface{}{"page": "stm", "hash": "end", "word": []interface{}{"end"}},
map[string]interface{}{"page": "stm", "hash": "for", "word": []interface{}{"for", "opt{", "exp", ";", "}", "exp"}},
map[string]interface{}{"page": "stm", "hash": "for", "word": []interface{}{"for", "index", "exp", "opt{", "exp", "}", "exp"}},
map[string]interface{}{"page": "stm", "hash": "label", "word": []interface{}{"label", "exp"}},
map[string]interface{}{"page": "stm", "hash": "goto", "word": []interface{}{"goto", "exp", "opt{", "exp", "}", "exp"}},
map[string]interface{}{"page": "stm", "hash": "expr", "word": []interface{}{"expr", "rep{", "exp", "}"}},
map[string]interface{}{"page": "stm", "hash": "var", "word": []interface{}{"var", "key", "opt{", "=", "exp", "}"}},
map[string]interface{}{"page": "stm", "hash": "return", "word": []interface{}{"return", "rep{", "exp", "}"}},
map[string]interface{}{"page": "word", "hash": "word", "word": []interface{}{"mul{", "~", "!", "=", "\\?\\?", "\\?", "<", ">$", ">@", ">", "\\|", "%", "exe", "str", "[a-zA-Z0-9_/\\-.:*%]+", "}"}},
map[string]interface{}{"page": "word", "hash": "word", "word": []interface{}{"mul{", "~", "!", "\\?", "\\?\\?", "exe", "str", "[\\-a-zA-Z0-9_:/.]+", "=", "<", ">$", ">@", ">", "\\|", "%", "}"}},
map[string]interface{}{"page": "cmd", "hash": "cmd", "word": []interface{}{"rep{", "word", "}"}},
map[string]interface{}{"page": "exe", "hash": "exe", "word": []interface{}{"$", "(", "cmd", ")"}},
map[string]interface{}{"page": "com", "hash": "com", "word": []interface{}{"mul{", ";", "#[^\n]*\n?", "\n", "}"}},
map[string]interface{}{"page": "line", "hash": "line", "word": []interface{}{"opt{", "mul{", "stm", "cmd", "}", "}", "com"}},
map[string]interface{}{"page": "exe", "hash": "exe", "word": []interface{}{"$", "(", "cmd", ")"}},
map[string]interface{}{"page": "stm", "hash": "if", "word": []interface{}{"if", "exp"}},
map[string]interface{}{"page": "stm", "hash": "for", "word": []interface{}{"for", "rep{", "exp", "}"}},
/*
map[string]interface{}{"page": "op1", "hash": "op1", "word": []interface{}{"mul{", "-z", "-n", "}"}},
map[string]interface{}{"page": "op1", "hash": "op1", "word": []interface{}{"mul{", "-e", "-f", "-d", "}"}},
map[string]interface{}{"page": "op2", "hash": "op2", "word": []interface{}{"mul{", ":=", "=", "+=", "}"}},
map[string]interface{}{"page": "op2", "hash": "op2", "word": []interface{}{"mul{", "~", "!~", "}"}},
map[string]interface{}{"page": "exp", "hash": "exp", "word": []interface{}{"\\{", "rep{", "map", "}", "\\}"}},
map[string]interface{}{"page": "val", "hash": "val", "word": []interface{}{"opt{", "op1", "}", "(", "exp", ")"}},
map[string]interface{}{"page": "stm", "hash": "var", "word": []interface{}{"var", "key", "<-"}},
map[string]interface{}{"page": "stm", "hash": "var", "word": []interface{}{"var", "key", "<-", "opt{", "exe", "}"}},
map[string]interface{}{"page": "stm", "hash": "let", "word": []interface{}{"let", "key", "<-", "opt{", "exe", "}"}},
map[string]interface{}{"page": "stm", "hash": "else", "word": []interface{}{"else"}},
map[string]interface{}{"page": "stm", "hash": "end", "word": []interface{}{"end"}},
map[string]interface{}{"page": "stm", "hash": "for", "word": []interface{}{"for", "opt{", "exp", ";", "}", "exp"}},
map[string]interface{}{"page": "stm", "hash": "for", "word": []interface{}{"for", "index", "exp", "opt{", "exp", "}", "exp"}},
map[string]interface{}{"page": "stm", "hash": "label", "word": []interface{}{"label", "exp"}},
map[string]interface{}{"page": "stm", "hash": "goto", "word": []interface{}{"goto", "exp", "opt{", "exp", "}", "exp"}},
map[string]interface{}{"page": "stm", "hash": "expr", "word": []interface{}{"expr", "rep{", "exp", "}"}},
map[string]interface{}{"page": "stm", "hash": "return", "word": []interface{}{"return", "rep{", "exp", "}"}},
*/
map[string]interface{}{"page": "line", "hash": "line", "word": []interface{}{"opt{", "mul{", "stm", "cmd", "}", "}", "mul{", ";", "\n", "#[^\n]*\n", "}"}},
}, Help: "语法集合的最大数量"},
"info": &ctx.Config{Name: "info", Value: map[string]interface{}{"ncell": 128, "nlang": 64}, Help: "嵌套层级日志的标记"},
"exec": &ctx.Config{Name: "info", Value: map[string]interface{}{
"line": map[string]interface{}{"disable": true},
"void": map[string]interface{}{"disable": true},
"num": map[string]interface{}{"disable": true},
"key": map[string]interface{}{"disable": true},
"op1": map[string]interface{}{"disable": true},
"op2": map[string]interface{}{"disable": true},
"word": map[string]interface{}{"disable": true},
"line": map[string]interface{}{"disable": true},
}, Help: "嵌套层级日志的标记"},
},
Commands: map[string]*ctx.Command{
"_init": &ctx.Command{Name: "_init", Help: "添加语法规则, page: 语法集合, hash: 语句类型, word: 语法模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) {
yac.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: "64", Help: "状态机状态的数量"}
yac.Caches["nnode"] = &ctx.Cache{Name: "节点数量", Value: "0", Help: "状态机连接的逻辑数量"}
yac.Caches["nreal"] = &ctx.Cache{Name: "实点数量", Value: "0", Help: "状态机连接的存储数量"}
yac.Caches["nseed"] = &ctx.Cache{Name: "种子数量", Value: "0", Help: "语法模板的数量"}
yac.Caches["npage"] = &ctx.Cache{Name: "集合数量", Value: "0", Help: "语法集合的数量"}
yac.Caches["nhash"] = &ctx.Cache{Name: "类型数量", Value: "0", Help: "语句类型的数量"}
yac.page = map[string]int{"nil": 0}
yac.word = map[int]string{0: "nil"}
yac.hash = map[string]int{"nil": 0}
yac.hand = map[int]string{0: "nil"}
yac.mat = make([]map[byte]*State, m.Confi("info", "nlang"))
yac.state = map[State]*State{}
yac.lex = m.Cmd("lex.spawn")
m.Confm("seed", func(line int, seed map[string]interface{}) {
m.Spawn().Cmd("train", seed["page"], seed["hash"], seed["word"])
})
@ -341,70 +372,40 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
}},
"train": &ctx.Command{Name: "train page hash word...", Help: "添加语法规则, page: 语法集合, hash: 语句类型, word: 语法模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) {
page, ok := yac.page[arg[0]]
if !ok {
page = m.Capi("npage", 1)
yac.page[arg[0]] = page
yac.word[page] = arg[0]
m.Assert(page < m.Confi("info", "nlang"), "语法集合过多")
page := yac.index(m, "npage", arg[0])
hash := yac.index(m, "nhash", arg[1])
if yac.mat[page] == nil {
yac.mat[page] = map[byte]*State{}
for i := 0; i < m.Confi("info", "nlang"); i++ {
for i := 0; i < m.Confi("meta", "nlang"); i++ {
yac.mat[page][byte(i)] = nil
}
}
hash, ok := yac.hash[arg[1]]
if !ok {
hash = m.Capi("nhash", 1)
yac.hash[arg[1]] = hash
yac.hand[hash] = arg[1]
}
if yac.lex == nil {
yac.lex = m.Cmd("lex.spawn")
}
yac.train(m, page, hash, arg[2:], 1)
yac.seed = append(yac.seed, &Seed{page, hash, arg[2:]})
m.Cap("stream", fmt.Sprintf("%d,%s,%s", m.Capi("nseed", 1), m.Cap("npage"), m.Cap("nhash")))
m.Cap("stream", fmt.Sprintf("%d,%s,%s", m.Cap("nseed", len(yac.seed)),
m.Cap("npage"), m.Cap("nhash", len(yac.hash)-1)))
}
return
}},
"parse": &ctx.Command{Name: "parse page void word...", Help: "解析语句, page: 初始语法, void: 空白语法, word: 解析语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
"parse": &ctx.Command{Name: "parse line", Help: "解析语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) {
str, word, hash := yac.parse(m, m, m.Optioni("page", yac.page[arg[0]]), m.Optioni("void", yac.page[arg[1]]), arg[2], 1)
m.Result(str, yac.hand[hash], word)
}
return
}},
"scan": &ctx.Command{Name: "scan filename modulename", Help: "解析文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) {
m.Optioni("page", yac.page["line"])
m.Optioni("void", yac.page["void"])
m.Optioni("yac.page", yac.page[m.Conf("nline")])
m.Optioni("yac.void", yac.page[m.Conf("nvoid")])
name := ""
if len(arg) > 1 {
name = arg[1]
} else {
name = fmt.Sprintf("parse%d", m.Capi("nparse", 1))
}
if len(arg) > 0 {
m.Start(name, "parse", key, arg[0])
} else {
m.Start(name, "parse")
}
_, word, _ := yac.parse(m, m, m.Optioni("yac.page"), m.Optioni("yac.void"), arg[0], 1)
m.Result(word)
}
return
}},
"show": &ctx.Command{Name: "show seed|page|hash|mat", Help: "查看信息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) {
if len(arg) == 0 {
m.Append("seed", len(yac.seed))
m.Append("page", len(yac.page))
m.Append("hash", len(yac.hash))
m.Append("node", len(yac.state))
m.Push("seed", len(yac.seed))
m.Push("page", len(yac.page))
m.Push("hash", len(yac.hash))
m.Push("nmat", len(yac.mat))
m.Push("node", len(yac.state))
m.Table()
return
}
@ -412,32 +413,51 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
switch arg[0] {
case "seed":
for _, v := range yac.seed {
m.Add("append", "page", fmt.Sprintf("%d", v.page))
m.Add("append", "hash", fmt.Sprintf("%d", v.hash))
m.Add("append", "word", fmt.Sprintf("%s", strings.Replace(strings.Replace(strings.Join(v.word, " "), "\n", "\\n", -1), "\t", "\\t", -1)))
m.Push("page", yac.hand[v.page])
m.Push("word", strings.Replace(strings.Replace(fmt.Sprint(v.word), "\n", "\\n", -1), "\t", "\\t", -1))
m.Push("hash", yac.word[v.hash])
}
m.Table()
m.Sort("page", "int").Table()
case "page":
for k, v := range yac.page {
m.Add("append", "page", k)
m.Add("append", "code", fmt.Sprintf("%d", v))
m.Add("append", "code", v)
}
m.Sort("code", "int").Table()
case "hash":
for k, v := range yac.hash {
m.Add("append", "hash", k)
m.Add("append", "code", fmt.Sprintf("%d", v))
m.Add("append", "code", v)
m.Add("append", "hand", yac.hand[v])
}
m.Sort("code", "int").Table()
case "node":
for _, v := range yac.state {
m.Push("star", v.star)
m.Push("next", v.next)
m.Push("hash", v.hash)
}
m.Table()
case "mat":
for _, v := range yac.mat {
for j := byte(0); j < byte(m.Confi("info", "ncell")); j++ {
s := v[j]
if s == nil {
m.Add("append", fmt.Sprintf("%d", j), "")
for i, v := range yac.mat {
if i <= m.Capi("npage") {
m.Push("index", yac.hand[i])
} else if i < m.Confi("meta", "nlang") {
continue
} else {
m.Push("index", i)
}
for j := byte(0); j < byte(m.Confi("meta", "ncell")); j++ {
c := fmt.Sprintf("%d", j)
if s := v[j]; s == nil {
m.Push(c, "")
} else {
m.Add("append", fmt.Sprintf("%d", j), fmt.Sprintf("%d,%d,%d", s.star, s.next, s.hash))
m.Push(c, fmt.Sprintf("%d,%d,%d", s.star, s.next, s.hash))
}
}
}
@ -480,6 +500,352 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
}
return
}},
"str": &ctx.Command{Name: "str word", Help: "解析字符串", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Echo(arg[0][1 : len(arg[0])-1])
return
}},
"exe": &ctx.Command{Name: "exe $ ( cmd )", Help: "解析嵌套命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
switch len(arg) {
case 1:
m.Echo(arg[0])
case 2:
msg := m.Spawn(m.Optionv("bio.ctx"))
switch arg[0] {
case "$":
m.Echo(msg.Cap(arg[1]))
case "@":
value := msg.Option(arg[1])
if value == "" {
value = msg.Conf(arg[1])
}
m.Echo(value)
default:
m.Echo(arg[0]).Echo(arg[1])
}
default:
switch arg[0] {
case "$", "@":
m.Result(0, arg[2:len(arg)-1])
}
}
return
}},
"val": &ctx.Command{Name: "val exp", Help: "表达式运算", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
result := "false"
switch len(arg) {
case 0:
result = ""
case 1:
result = arg[0]
case 2:
switch arg[0] {
case "-z":
if arg[1] == "" {
result = "true"
}
case "-n":
if arg[1] != "" {
result = "true"
}
case "-e":
if _, e := os.Stat(arg[1]); e == nil {
result = "true"
}
case "-f":
if info, e := os.Stat(arg[1]); e == nil && !info.IsDir() {
result = "true"
}
case "-d":
if info, e := os.Stat(arg[1]); e == nil && info.IsDir() {
result = "true"
}
case "+":
result = arg[1]
case "-":
result = arg[1]
if i, e := strconv.Atoi(arg[1]); e == nil {
result = fmt.Sprintf("%d", -i)
}
}
case 3:
v1, e1 := strconv.Atoi(arg[0])
v2, e2 := strconv.Atoi(arg[2])
switch arg[1] {
case ":=":
if !m.Target().Has(arg[0]) {
result = m.Cap(arg[0], arg[0], arg[2], "临时变量")
}
case "=":
result = m.Cap(arg[0], arg[2])
case "+=":
if i, e := strconv.Atoi(m.Cap(arg[0])); e == nil && e2 == nil {
result = m.Cap(arg[0], fmt.Sprintf("%d", v2+i))
} else {
result = m.Cap(arg[0], m.Cap(arg[0])+arg[2])
}
case "+":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%d", v1+v2)
} else {
result = arg[0] + arg[2]
}
case "-":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%d", v1-v2)
} else {
result = strings.Replace(arg[0], arg[1], "", -1)
}
case "*":
result = arg[0]
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%d", v1*v2)
}
case "/":
result = arg[0]
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%d", v1/v2)
}
case "%":
result = arg[0]
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%d", v1%v2)
}
case "<":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 < v2)
} else {
result = fmt.Sprintf("%t", arg[0] < arg[2])
}
case "<=":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 <= v2)
} else {
result = fmt.Sprintf("%t", arg[0] <= arg[2])
}
case ">":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 > v2)
} else {
result = fmt.Sprintf("%t", arg[0] > arg[2])
}
case ">=":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 >= v2)
} else {
result = fmt.Sprintf("%t", arg[0] >= arg[2])
}
case "==":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 == v2)
} else {
result = fmt.Sprintf("%t", arg[0] == arg[2])
}
case "!=":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 != v2)
} else {
result = fmt.Sprintf("%t", arg[0] != arg[2])
}
case "~":
if m, e := regexp.MatchString(arg[2], arg[0]); m && e == nil {
result = "true"
}
case "!~":
if m, e := regexp.MatchString(arg[2], arg[0]); !m || e != nil {
result = "true"
}
}
}
m.Echo(result)
return
}},
"exp": &ctx.Command{Name: "exp word", Help: "表达式运算", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) > 0 && arg[0] == "{" {
msg := m.Spawn()
for i := 1; i < len(arg); i++ {
key := arg[i]
for i += 3; i < len(arg); i++ {
if arg[i] == "]" {
break
}
msg.Add("append", key, arg[i])
}
}
m.Echo("%d", msg.Code())
return
}
pre := map[string]int{
"=": -1,
"+": 2, "-": 2,
"*": 3, "/": 3, "%": 3,
}
num, op := []string{arg[0]}, []string{}
for i := 1; i < len(arg); i += 2 {
if len(op) > 0 && pre[op[len(op)-1]] >= pre[arg[i]] {
num[len(op)-1] = m.Cmdx("yac.val", num[len(op)-1], op[len(op)-1], num[len(op)])
num, op = num[:len(num)-1], op[:len(op)-1]
}
num, op = append(num, arg[i+1]), append(op, arg[i])
}
for i := len(op) - 1; i >= 0; i-- {
num[i] = m.Cmdx("yac.val", num[i], op[i], num[i+1])
}
m.Echo("%s", num[0])
return
}},
"let": &ctx.Command{Name: "let a = exp", Help: "设置变量, a: 变量名, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
switch arg[2] {
case "=":
m.Cap(arg[1], arg[3])
m.Log("stack", " set %v = %v", arg[1], arg[3])
case "<-":
m.Cap(arg[1], m.Cap("last_msg"))
}
m.Echo(m.Cap(arg[1]))
return
}},
"var": &ctx.Command{Name: "var a [= exp]", Help: "定义变量, a: 变量名, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if m.Cap(arg[1], arg[1], "", "临时变量"); len(arg) > 1 {
switch arg[2] {
case "=":
m.Cap(arg[1], arg[3])
case "<-":
m.Cap(arg[1], m.Cap("last_msg"))
}
}
m.Echo(m.Cap(arg[1]))
return
}},
"return": &ctx.Command{Name: "return result...", Help: "结束脚本, result: 返回值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Appends("bio.end", true)
m.Result(arg[1:])
return
}},
"com": &ctx.Command{Name: "com", Help: "解析注释", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
return
}},
"if": &ctx.Command{Name: "if exp", Help: "条件语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Push("stack.key", arg[0])
m.Push("stack.run", m.Options("stack.run") && kit.Right(arg[1]))
return
}},
"for": &ctx.Command{Name: "for [[express ;] condition]|[index message meta value]",
Help: "循环语句, express: 每次循环运行的表达式, condition: 循环条件, index: 索引消息, message: 消息编号, meta: value: ",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Push("stack.key", arg[0])
m.Push("stack.run", m.Options("stack.run") && kit.Right(arg[1]))
/*
if cli, ok := m.Target().Server.(*YAC); m.Assert(ok) {
run := m.Caps("parse")
defer func() { m.Caps("parse", run) }()
msg := m
if run {
if arg[1] == "index" {
if code, e := strconv.Atoi(arg[2]); m.Assert(e) {
msg = m.Target().Message().Tree(code)
run = run && msg != nil && msg.Meta != nil
switch len(arg) {
case 4:
run = run && len(msg.Meta) > 0
case 5:
run = run && len(msg.Meta[arg[3]]) > 0
}
}
} else {
run = run && kit.Right(arg[len(arg)-1])
}
if len(cli.stack) > 0 {
if frame := cli.stack[len(cli.stack)-1]; frame.key == "for" && frame.pos == m.Optioni("file_pos") {
if arg[1] == "index" {
frame.index++
if run = run && len(frame.list) > frame.index; run {
if len(arg) == 5 {
arg[3] = arg[4]
}
m.Cap(arg[3], frame.list[frame.index])
}
}
frame.run = run
return
}
}
}
cli.stack = append(cli.stack, &Frame{pos: m.Optioni("file_pos"), key: key, run: run, index: 0})
if m.Capi("level", 1); run && arg[1] == "index" {
frame := cli.stack[len(cli.stack)-1]
switch len(arg) {
case 4:
frame.list = []string{}
for k, _ := range msg.Meta {
frame.list = append(frame.list, k)
}
case 5:
frame.list = msg.Meta[arg[3]]
arg[3] = arg[4]
}
m.Cap(arg[3], arg[3], frame.list[0], "临时变量")
}
}
*/
return
}},
"expr": &ctx.Command{Name: "expr arg...", Help: "输出表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Echo("%s", strings.Join(arg[1:], ""))
return
}},
"label": &ctx.Command{Name: "label name", Help: "记录当前脚本的位置, name: 位置名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if cli, ok := m.Target().Server.(*YAC); m.Assert(ok) {
if cli.label == nil {
cli.label = map[string]string{}
}
cli.label[arg[1]] = m.Option("file_pos")
}
return
}},
"goto": &ctx.Command{Name: "goto label [exp] condition", Help: "向上跳转到指定位置, label: 跳转位置, condition: 跳转条件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if cli, ok := m.Target().Server.(*YAC); m.Assert(ok) {
if pos, ok := cli.label[arg[1]]; ok {
if !kit.Right(arg[len(arg)-1]) {
return
}
m.Append("file_pos0", pos)
}
}
return
}},
"else": &ctx.Command{Name: "else", Help: "条件语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
/*
if cli, ok := m.Target().Server.(*YAC); m.Assert(ok) {
if !m.Caps("parse") {
m.Caps("parse", true)
} else {
if len(cli.stack) == 1 {
m.Caps("parse", false)
} else {
frame := cli.stack[len(cli.stack)-2]
m.Caps("parse", !frame.run)
}
}
}
*/
return
}},
},
}

35
src/toolkit/stmt.go Normal file
View File

@ -0,0 +1,35 @@
package kit
import (
"fmt"
"strings"
)
type Frame struct {
Key string
Run bool
Pos int
deep int
// list []string
}
func (f *Frame) String(meta string) string {
return fmt.Sprintf("%s%s%d %s %t", strings.Repeat("#", f.deep), meta, f.deep, f.Key, f.Run)
}
type Stack struct {
fs []*Frame
}
func (s *Stack) Pop() *Frame {
f := s.fs[len(s.fs)-1]
s.fs = s.fs[:len(s.fs)-1]
return f
}
func (s *Stack) Push(key string, run bool, pos int) *Frame {
s.fs = append(s.fs, &Frame{key, run, pos, len(s.fs)})
return s.fs[len(s.fs)-1]
}
func (s *Stack) Peek() *Frame {
return s.fs[len(s.fs)-1]
}

View File

@ -116,18 +116,6 @@ func Format(arg ...interface{}) string {
result = append(result, string(val))
case []rune:
result = append(result, string(val))
case []string:
result = append(result, val...)
// case []interface{}:
//
// result = append(result, "[")
// for i, value := range val {
// result = append(result, Format(value))
// if i < len(val)-1 {
// result = append(result, ",")
// }
// }
// result = append(result, "]")
case time.Time:
result = append(result, fmt.Sprintf("%s", val.Format("2006-01-02 15:03:04")))
case *os.File:
@ -210,7 +198,7 @@ func Trans(arg ...interface{}) []string {
}
case []interface{}:
for _, v := range val {
ls = append(ls, Format(v))
ls = append(ls, Trans(v)...)
}
default:
ls = append(ls, Format(val))