diff --git a/etc/go.snippets b/etc/go.snippets index abc7eec5..346a084b 100644 --- a/etc/go.snippets +++ b/etc/go.snippets @@ -42,17 +42,19 @@ snippet c if `Filename()`.Context == Index { Pulse = m } + `Filename()`.Message = m return `Filename()` } func (`Filename()` *`toupper(substitute(expand("%:t"), ".go", "", ""))`) Start(m *ctx.Message, arg ...string) bool { + `Filename()`.Message = m return false } func (`Filename()` *`toupper(substitute(expand("%:t"), ".go", "", ""))`) Close(m *ctx.Message, arg ...string) bool { switch `Filename()`.Context { - case m.Target: - case m.Source: + case m.Target(): + case m.Source(): } return true } diff --git a/etc/init.shy b/etc/init.shy index aa1cca26..c83b64c8 100644 --- a/etc/init.shy +++ b/etc/init.shy @@ -1,2 +1,35 @@ -~cli - ~aaa login root root +~aaa login root root + +function plus + var a = 1 + for $a < 10 + ~stdio print $a + let a = $a + 1 + end +end +~yac check +~lex check +~log config bench.log hi.log + + +return + if 2 < 1 + let a = 1 +2 + if 3 = 3 + let a = 2 +4 + end + elif 3 > 4 + let a = 1 +6 + else + let a = 2 +2 + end + + for $a < 10 + var b = 1 + for $b < 4 + let b = $b+1 + end + let a = $a + 1 + end +return $a + "hello\n context & message word\ + nice" diff --git a/src/context/aaa/aaa.go b/src/context/aaa/aaa.go index 9aa9b684..9a553e88 100644 --- a/src/context/aaa/aaa.go +++ b/src/context/aaa/aaa.go @@ -33,6 +33,7 @@ func (aaa *AAA) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server } func (aaa *AAA) Begin(m *ctx.Message, arg ...string) ctx.Server { + aaa.Context.Master(nil) aaa.Caches["group"] = &ctx.Cache{Name: "用户组", Value: "", Help: "用户组"} aaa.Caches["username"] = &ctx.Cache{Name: "用户名", Value: "", Help: "用户名"} aaa.Caches["password"] = &ctx.Cache{Name: "用户密码", Value: "", Help: "用户密码,加密存储", Hand: func(m *ctx.Message, x *ctx.Cache, arg ...string) string { diff --git a/src/context/cli/cli.go b/src/context/cli/cli.go index a6a0ddea..144690e5 100644 --- a/src/context/cli/cli.go +++ b/src/context/cli/cli.go @@ -3,9 +3,6 @@ package cli // {{{ import ( // {{{ "context" - "bufio" - "io" - "fmt" "strconv" "strings" @@ -19,27 +16,19 @@ import ( // {{{ // }}} -type CLI struct { // {{{ - out io.WriteCloser - bio *bufio.Reader - lines []string +type CLI struct { + nfs *ctx.Message + lex *ctx.Message + yac *ctx.Message - yac *ctx.Message - lex *ctx.Message target *ctx.Context alias map[string][]string *ctx.Context } -// }}} - -func (cli *CLI) check(arg []string) bool { // {{{ - if len(arg) < 0 { - return false - } - - switch arg[0] { +func (cli *CLI) check(arg string) bool { // {{{ + switch arg { case "", "0", "false": return false } @@ -48,36 +37,33 @@ func (cli *CLI) check(arg []string) bool { // {{{ } // }}} -func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{ + +func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { c.Caches = map[string]*ctx.Cache{} c.Configs = map[string]*ctx.Config{} - c.Caches["skip"] = &ctx.Cache{Name: "跳过执行", Value: cli.Pulse.Cap("skip"), Help: "命令只解析不执行"} s := new(CLI) s.Context = c s.lex = cli.lex s.yac = cli.yac - if m.Has("for") { - s.lines = append(s.lines, cli.lines[cli.Pulse.Capi("pos")-1:]...) - } else { - s.lines = append(s.lines, cli.lines[cli.Pulse.Capi("pos"):]...) - } + s.nfs = cli.nfs + s.target = cli.target return s } -// }}} -func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ +func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { + cli.Caches["level"] = &ctx.Cache{Name: "嵌套层级", Value: "0", Help: "嵌套层级"} + cli.Caches["skip"] = &ctx.Cache{Name: "跳过执行", Value: "0", Help: "命令只解析不执行"} + cli.Caches["else"] = &ctx.Cache{Name: "解析选择语句", Value: "false", Help: "解析选择语句"} + cli.Caches["loop"] = &ctx.Cache{Name: "解析循环语句", Value: "-2", Help: "解析选择语句"} + cli.Caches["fork"] = &ctx.Cache{Name: "解析结束", Value: "-2", Help: "解析结束模块销毁"} + cli.Caches["exit"] = &ctx.Cache{Name: "解析结束", Value: "false", Help: "解析结束模块销毁"} + cli.Caches["target"] = &ctx.Cache{Name: "操作目标", Value: cli.Name, Help: "命令操作的目标"} cli.Caches["result"] = &ctx.Cache{Name: "执行结果", Value: "", Help: "前一条命令的执行结果"} cli.Caches["back"] = &ctx.Cache{Name: "前一条指令", Value: "", Help: "前一条指令"} cli.Caches["next"] = &ctx.Cache{Name: "下一条指令", Value: "", Help: "下一条指令"} - cli.Caches["nline"] = &ctx.Cache{Name: "缓存命令行数", Value: "0", Help: "缓存命令行数"} - cli.Caches["pos"] = &ctx.Cache{Name: "当前缓存命令", Value: "0", Help: "当前缓存命令"} - - cli.Caches["else"] = &ctx.Cache{Name: "解析选择语句", Value: "false", Help: "解析选择语句"} - cli.Caches["exit"] = &ctx.Cache{Name: "解析结束", Value: "false", Help: "解析结束模块销毁"} - cli.Configs["lex"] = &ctx.Config{Name: "词法解析器", Value: "", Help: "命令行词法解析器", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string { if len(arg) > 0 && len(arg[0]) > 0 { // {{{ cli, ok := m.Target().Server.(*CLI) @@ -100,7 +86,7 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ // }}} }} cli.Configs["yac"] = &ctx.Config{Name: "词法解析器", Value: "", Help: "命令行词法解析器", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string { - if len(arg) > 0 && len(arg[0]) > 0 { // {{{ + if len(arg) > 0 && len(arg[0]) > 0 { cli, ok := m.Target().Server.(*CLI) m.Assert(ok, "模块类型错误") @@ -108,31 +94,45 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ m.Assert(yac != nil, "词法解析模块不存在") if yac.Cap("status") != "start" { yac.Target().Start(yac) - m.Spawn(yac.Target()).Cmd("train", "void", "void", "[\t ]+") + yac.Cmd("train", "void", "void", "[\t ]+") - m.Spawn(yac.Target()).Cmd("train", "key", "key", "[A-Za-z_][A-Za-z_0-9]*") - m.Spawn(yac.Target()).Cmd("train", "num", "num", "mul{", "[1-9][0-9]*", "0[0-9]+", "0x[0-9]+", "}") - m.Spawn(yac.Target()).Cmd("train", "str", "str", "mul{", "\"[^\"]*\"", "'[^']*'", "}") + yac.Cmd("train", "key", "key", "[A-Za-z_][A-Za-z_0-9]*") + yac.Cmd("train", "num", "num", "mul{", "[1-9][0-9]*", "0[0-9]+", "0x[0-9]+", "}") + yac.Cmd("train", "str", "str", "mul{", "\"[^\"]*\"", "'[^']*'", "}") - m.Spawn(yac.Target()).Cmd("train", "tran", "tran", "mul{", "@", "$", "}", "opt{", "[a-zA-Z0-9]+", "}") - m.Spawn(yac.Target()).Cmd("train", "word", "word", "mul{", "~", "!", "tran", "\"[^\"]*\"", "'[^']*'", "[a-zA-Z0-9_/.]+", "}") + yac.Cmd("train", "tran", "tran", "mul{", "@", "$", "}", "opt{", "[a-zA-Z0-9]+", "}") + yac.Cmd("train", "word", "word", "mul{", "~", "!", "tran", "str", "[a-zA-Z0-9_/.]+", "}") - // m.Spawn(yac.Target()).Cmd("train", "op1", "op1", "opt{", "mul{", "-z", "-n", "}", "}", "word") - // m.Spawn(yac.Target()).Cmd("train", "op2", "op2", "op1", "rep{", "mul{", "+", "-", "*", "/", "}", "op1", "}") - // m.Spawn(yac.Target()).Cmd("train", "op1", "op1", "(", "op2", ")") - // - m.Spawn(yac.Target()).Cmd("train", "stm", "var", "var", "key", "opt{", "=", "op2", "}") + yac.Cmd("train", "op1", "op1", "mul{", "$", "@", "}") + yac.Cmd("train", "op1", "op1", "mul{", "-z", "-n", "}") + yac.Cmd("train", "op1", "op1", "mul{", "-", "+", "}") + yac.Cmd("train", "op2", "op2", "mul{", "+", "-", "*", "/", "}") + yac.Cmd("train", "op2", "op2", "mul{", ">", ">=", "<", "<=", "=", "!=", "}") - m.Spawn(yac.Target()).Cmd("train", "cmd", "cmd", "rep{", "word", "}") - m.Spawn(yac.Target()).Cmd("train", "tran", "tran", "$", "(", "cmd", ")") + yac.Cmd("train", "val", "val", "opt{", "op1", "}", "mul{", "num", "key", "str", "}") + yac.Cmd("train", "exp", "exp", "val", "rep{", "op2", "val", "}") + yac.Cmd("train", "val", "val", "(", "exp", ")") - m.Spawn(yac.Target()).Cmd("train", "line", "line", "opt{", "mul{", "stm", "cmd", "}", "}", "mul{", ";", "\n", "#[^\n]*\n", "}") + yac.Cmd("train", "stm", "var", "var", "key", "opt{", "=", "exp", "}") + yac.Cmd("train", "stm", "let", "let", "key", "=", "exp") + yac.Cmd("train", "stm", "if", "if", "exp") + yac.Cmd("train", "stm", "elif", "elif", "exp") + yac.Cmd("train", "stm", "for", "for", "exp") + yac.Cmd("train", "stm", "else", "else") + yac.Cmd("train", "stm", "end", "end") + yac.Cmd("train", "stm", "function", "function", "rep{", "key", "}") + yac.Cmd("train", "stm", "return", "return", "rep{", "exp", "}") + + yac.Cmd("train", "cmd", "cmd", "rep{", "word", "}") + yac.Cmd("train", "tran", "tran", "$", "(", "cmd", ")") + + yac.Cmd("train", "line", "line", "opt{", "mul{", "stm", "cmd", "}", "}", "mul{", ";", "\n", "#[^\n]*\n", "}") } cli.yac = yac return arg[0] } return x.Value - // }}} + }} cli.Configs["PS1"] = &ctx.Config{Name: "命令行提示符(target/detail)", Value: "target", Help: "命令行提示符,target:显示当前模块,detail:显示详细信息", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string { if len(arg) > 0 { // {{{ @@ -176,7 +176,6 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ // }}} }} - cli.target = cli.Context cli.alias = map[string][]string{ "~": []string{"context"}, "!": []string{"message"}, @@ -191,125 +190,55 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ return cli } -// }}} -func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{ +func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { cli.Caches["#"] = &ctx.Cache{Name: "参数个数", Value: fmt.Sprintf("%d", len(arg)), Help: "参数个数"} for i, v := range arg { cli.Caches[fmt.Sprintf("%d", i)] = &ctx.Cache{Name: "执行参数", Value: v, Help: "执行参数"} } - cli.Context.Exit = make(chan bool) - if m.Caps("else", false); !m.Has("skip") { - m.Caps("skip", false) - } else if m.Capi("skip", 1) == 1 { - m.Caps("else", true) + if m.Has("level") { + m.Cap("level", m.Option("level")) } + if m.Has("skip") { + m.Cap("skip", m.Option("skip")) + if m.Caps("else", false); m.Capi("skip") == 1 { + m.Caps("else", true) + } + } + if m.Has("loop") { + m.Cap("loop", m.Option("loop")) + } + if m.Has("fork") { + m.Cap("fork", m.Option("fork")) + } + m.Caps("exit", false) - if true { - if m.Has("stdio") { + cli.Context.Exit = make(chan bool) + cli.Context.Master(cli.Context) + + if m.Has("stdio") || len(arg) > 0 { + go func() { cli.Caches["init.shy"] = &ctx.Cache{Name: "启动脚本", Value: "etc/init.shy", Help: "模块启动时自动运行的脚本"} - if len(arg) > 0 { + if m.Conf("yac", "yac"); len(arg) > 0 { m.Cap("init.shy", arg[0]) } - go func() { - m.Find("nfs").Cmd("scan", m.Cap("init.shy")) - m.Find("nfs").Cmd("scan", "stdio") - }() - } - } else { - if m.Has("stdio") { - cli.Caches["init.shy"] = &ctx.Cache{Name: "启动脚本", Value: "etc/init.shy", Help: "模块启动时自动运行的脚本"} - cli.Caches["level"] = &ctx.Cache{Name: "模块嵌套层数", Value: "0", Help: "模块嵌套层数"} - if len(arg) > 0 { - m.Cap("init.shy", arg[0]) - } - m.Cap("next", fmt.Sprintf("source %s\n", m.Cap("init.shy"))) - cli.bio = bufio.NewReader(os.Stdin) - cli.out = os.Stdout - m.Conf("yac", "yac") - m.Cap("stream", "stdout") - } else if stream, ok := m.Data["file"]; ok { - if bio, ok := stream.(*bufio.Reader); ok { - cli.bio = bio - m.Cap("stream", "bufio") + + if cli.nfs = m.Find("nfs"); m.Has("stdio") { + cli.nfs.Cmd("scan", m.Cap("stream", "stdio"), m.Cmd("source", m.Cap("init.shy")).Get("result")) } else { - cli.bio = bufio.NewReader(stream.(io.ReadWriteCloser)) - m.Cap("stream", "file") + cli.nfs.Cmd("scan", m.Cap("stream", m.Cap("init.shy"))) } - } - - m.Capi("nline", 0, len(cli.lines)) - m.Caps("pos", m.Has("for")) - - m.Log("info", nil, "%p %s pos:%s nline:%s %d", cli.bio, m.Cap("stream"), m.Cap("pos"), m.Cap("nline"), len(cli.lines)) - - go m.AssertOne(m, true, func(m *ctx.Message) { - for !m.Caps("exit") { - line := m.Cap("next") - if m.Cap("next", ""); line == "" { - if cli.bio == nil { - line = cli.lines[m.Capi("pos", 1)-1] - } else { - // cli.print(m.Conf("PS1")) - if l, e := cli.bio.ReadString('\n'); m.Assert(e) { - line = l - } - } - } - - if line == "\n" && cli.out != nil { - line = m.Cap("back") + "\n" - m.Cap("back", "") - } - - yac := m.Spawn(cli.yac.Target()) - yac.Cmd("parse", "line", "void", line) - } - }, func(m *ctx.Message) { - m.Caps("exit", true) - m.Spawn(cli.Context).Set("detail", "end").Post(cli.Context) - }) + }() } m.Deal(func(msg *ctx.Message, arg ...string) bool { - return !cli.Has("skip") || !m.Caps("skip") || Index.Has(msg.Get("detail"), "command") + return !m.Caps("skip") || Index.Has(msg.Get("detail"), "command") }, func(msg *ctx.Message, arg ...string) bool { - if cli.Has("skip") && m.Caps("skip") { + if m.Caps("skip") { return !m.Caps("exit") } - if !msg.Hand && cli.Owner == ctx.Index.Owner { - msg.Hand = true - msg.Log("system", nil, "%v", msg.Meta["detail"]) - - msg.Set("result").Set("append") - c := exec.Command(msg.Meta["detail"][0], msg.Meta["detail"][1:]...) - - if cli.out == os.Stdout { - c.Stdin, c.Stdout, c.Stderr = os.Stdin, os.Stdout, os.Stderr - if e := c.Start(); e != nil { - msg.Echo("error: ") - msg.Echo("%s\n", e) - } else if e := c.Wait(); e != nil { - msg.Echo("error: ") - msg.Echo("%s\n", e) - } - } else { - if out, e := c.CombinedOutput(); e != nil { - msg.Echo("error: ") - msg.Echo("%s\n", e) - } else { - msg.Echo(string(out)) - } - } - } - - if msg.Target().Context() != nil || msg.Target() == ctx.Index { - cli.target = msg.Target() - } - m.Cap("target", cli.target.Name) - return !m.Caps("exit") }) @@ -321,26 +250,10 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{ return !cli.Pulse.Has("save") } -// }}} -func (cli *CLI) Close(m *ctx.Message, arg ...string) bool { // {{{ +func (cli *CLI) Close(m *ctx.Message, arg ...string) bool { switch cli.Context { case m.Target(): - if p, ok := cli.Context.Context().Server.(*CLI); ok { - if p.bio != nil && cli.Context != Index { - if m.Has("for") { - cli.lines = cli.lines[1:] - } - p.lines = append(p.lines, cli.lines...) - p.Pulse.Capi("nline", 0, len(p.lines)) - } - if p.Pulse.Capi("pos", cli.Pulse.Capi("pos")); m.Has("for") { - p.Pulse.Capi("pos", -1) - } - - m.Log("info", nil, "%p %s pos:%s nline:%s %d", cli.bio, m.Cap("stream"), m.Cap("pos"), m.Cap("nline"), len(cli.lines)) - m.Log("info", nil, "%p %s pos:%s nline:%s %d", p.bio, p.Pulse.Cap("stream"), p.Pulse.Cap("pos"), p.Pulse.Cap("nline"), len(p.lines)) - } - + m.Echo(cli.nfs.Cap("return")) case m.Source(): if m.Name == "aaa" { if !cli.Context.Close(m.Spawn(cli.Context), arg...) { @@ -352,15 +265,40 @@ func (cli *CLI) Close(m *ctx.Message, arg ...string) bool { // {{{ return true } -// }}} - var Pulse *ctx.Message var Index = &ctx.Context{Name: "cli", Help: "管理中心", - Caches: map[string]*ctx.Cache{ - "skip": &ctx.Cache{Name: "跳过执行", Value: "0", Help: "命令只解析不执行"}, - }, + Caches: map[string]*ctx.Cache{}, Configs: map[string]*ctx.Config{}, Commands: map[string]*ctx.Command{ + "alias": &ctx.Command{Name: "alias [short [long]]|[delete short]", Help: "查看、定义或删除命令别名, short: 命令别名, long: 命令原名, delete: 删除别名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) && !m.Caps("skip") { // {{{ + switch len(arg) { + case 0: + for k, v := range cli.alias { + m.Echo("%s: %v\n", k, v) + } + case 1: + m.Echo("%s: %v\n", arg[0], cli.alias[arg[0]]) + default: + if arg[0] == "delete" { + m.Echo("delete: %s %v\n", arg[1], cli.alias[arg[1]]) + delete(cli.alias, arg[1]) + } else { + cli.alias[arg[0]] = arg[1:] + m.Echo("%s: %v\n", arg[0], cli.alias[arg[0]]) + } + } + } // }}} + }}, + "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) { + if _, ok := m.Source().Server.(*CLI); m.Assert(ok) && !m.Caps("skip") { // {{{ + if d, e := time.ParseDuration(arg[0]); m.Assert(e) { + m.Log("info", nil, "sleep %v", d) + time.Sleep(d) + m.Log("info", nil, "sleep %v done", d) + } + } // }}} + }}, "express": &ctx.Command{Name: "express exp", Help: "表达式运算", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { result := "false" // {{{ switch len(arg) { @@ -448,7 +386,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } else { result = fmt.Sprintf("%t", arg[0] >= arg[2]) } - case "==": + case "=": if e1 == nil && e2 == nil { result = fmt.Sprintf("%t", v1 == v2) } else { @@ -474,8 +412,24 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Echo(result) // }}} }}, - "op1": &ctx.Command{Name: "op1 word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if _, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ + "str": &ctx.Command{Name: "str word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if _, ok := m.Target().Server.(*CLI); m.Assert(ok) && !m.Caps("skip") { // {{{ + str := arg[0][1 : len(arg[0])-1] + str = strings.Replace(str, "\\n", "\n", -1) + str = strings.Replace(str, "\\t", "\t", -1) + m.Echo(str) + } else { + m.Set("result", arg...) + } + // }}} + }}, + "val": &ctx.Command{Name: "val word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if _, ok := m.Target().Server.(*CLI); m.Assert(ok) && !m.Caps("skip") { // {{{ + if arg[0] == "(" { + m.Echo(arg[1]) + return + } + if len(arg) == 1 { m.Echo(arg[0]) return @@ -494,19 +448,25 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } else { m.Echo("true") } + case "$": + m.Echo(m.Cap(arg[1])) + case "@": + m.Echo(m.Conf(arg[1])) } + } else { + m.Set("result", arg...) } // }}} }}, - "op2": &ctx.Command{Name: "op2 word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ + "exp": &ctx.Command{Name: "exp word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if _, ok := m.Target().Server.(*CLI); m.Assert(ok) && !m.Caps("skip") { // {{{ pre := map[string]int{"+": 1, "-": 1, "*": 2, "/": 2} 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(cli.Context).Cmd("express", num[len(op)-1], op[len(op)-1], num[len(op)]) + num[len(op)-1] = m.Cmd("express", num[len(op)-1], op[len(op)-1], num[len(op)]).Get("result") num = num[:len(num)-1] op = op[:len(op)-1] } @@ -516,15 +476,18 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } for i := len(op) - 1; i >= 0; i-- { - num[i] = m.Spawn(cli.Context).Cmd("express", num[i], op[i], num[i+1]) + num[i] = m.Cmd("express", num[i], op[i], num[i+1]).Get("result") } m.Echo("%s", num[0]) + } else { + m.Set("result", arg...) } // }}} }}, "tran": &ctx.Command{Name: "tran word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if _, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) && !m.Caps("skip") { // {{{ + msg := m.Spawn(cli.target) switch len(arg) { case 1: switch arg[0] { @@ -536,16 +499,17 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", case 2: switch arg[0] { case "$": - m.Echo(m.Cap(arg[1])) + m.Echo(msg.Cap(arg[1])) case "@": - m.Echo(m.Conf(arg[1])) + m.Echo(msg.Conf(arg[1])) } } + } else { + m.Set("result", arg...) } // }}} }}, "cmd": &ctx.Command{Name: "cmd word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ - + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) && !m.Caps("skip") { msg := m.Spawn(cli.target) if a, ok := cli.alias[arg[0]]; ok { msg.Set("detail", a...) @@ -553,182 +517,139 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } else { msg.Set("detail", arg...) } + msg.Cmd() - msg.Post(cli.Context) - if m.Hand = false; msg.Hand { - m.Hand = true - m.Meta["result"] = msg.Meta["result"] - } - } // }}} - }}, - "parse": &ctx.Command{Name: "parse word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ + if !msg.Hand && cli.Owner == ctx.Index.Owner { + msg.Hand = true + msg.Log("system", nil, "%v", msg.Meta["detail"]) - msg := m.Spawn(cli.target) - if a, ok := cli.alias[arg[0]]; ok { - msg.Set("detail", a...) - msg.Meta["detail"] = append(msg.Meta["detail"], arg[1:]...) - } else { - msg.Set("detail", arg...) - } + msg.Set("result").Set("append") + c := exec.Command(msg.Meta["detail"][0], msg.Meta["detail"][1:]...) - msg.Post(cli.Context) - if m.Hand = false; msg.Hand { - m.Hand = true - m.Meta["result"] = msg.Meta["result"] - } - } // }}} - }}, - "lines": &ctx.Command{Name: "line word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ - arg = arg[:len(arg)-1] - - m.Hand = false - result := strings.TrimRight(strings.Join(arg, ""), "\n") - if m.Cap("result", result); len(result) > 0 { - m.Echo(result + "\n") - // cli.print(result + "\n") - } - - if m.Cap("back", ""); cli.bio != nil { - cli.lines = append(cli.lines, strings.Join(arg, " ")) - m.Capi("nline", 1) - m.Capi("pos", 1) - } - } // }}} - }}, - "alias": &ctx.Command{Name: "alias [short [long]]|[delete short]", Help: "查看、定义或删除命令别名, short: 命令别名, long: 命令原名, delete: 删除别名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{ - switch len(arg) { - case 0: - for k, v := range cli.alias { - m.Echo("%s: %v\n", k, v) - } - case 1: - m.Echo("%s: %v\n", arg[0], cli.alias[arg[0]]) - default: - if arg[0] == "delete" { - m.Echo("delete: %s %v\n", arg[1], cli.alias[arg[1]]) - delete(cli.alias, arg[1]) + if false { + c.Stdin, c.Stdout, c.Stderr = os.Stdin, os.Stdout, os.Stderr + if e := c.Start(); e != nil { + msg.Echo("error: ") + msg.Echo("%s\n", e) + } else if e := c.Wait(); e != nil { + msg.Echo("error: ") + m.Echo("%s\n", e) + } } else { - cli.alias[arg[0]] = arg[1:] - m.Echo("%s: %v\n", arg[0], cli.alias[arg[0]]) + if out, e := c.CombinedOutput(); e != nil { + msg.Echo("error: ") + msg.Echo("%s\n", e) + } else { + msg.Echo(string(out)) + } } } - } // }}} - }}, - "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) { - if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{ - if d, e := time.ParseDuration(arg[0]); m.Assert(e) { - m.Log("info", nil, "sleep %v", d) - time.Sleep(d) - m.Log("info", nil, "sleep %v done", d) + + if msg.Target().Context() != nil || msg.Target() == ctx.Index { + cli.target = msg.Target() } - } // }}} + + m.Cap("target", cli.target.Name) + m.Set("result", msg.Meta["result"]...) + + } else { + m.Set("result", arg...) + } }}, "var": &ctx.Command{Name: "var a [= exp]", Help: "定义变量, a: 变量名, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{ - val := "" - if len(arg) > 3 { - val = m.Spawn(cli.Context).Cmd(append([]string{"express"}, arg[3:]...)...) + if _, ok := m.Target().Server.(*CLI); m.Assert(ok) && !m.Caps("skip") { // {{{ + if m.Cap(arg[1], arg[1], "", "临时变量"); len(arg) > 3 { + m.Cap(arg[1], arg[3]) } - m.Cap(arg[1], arg[1], val, "临时变量") + } else { + m.Set("result", arg...) } // }}} }}, "let": &ctx.Command{Name: "let a = exp", Help: "设置变量, a: 变量名, exp: 表达式(a {+|-|*|/|%} b)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{ - m.Echo(cli.Pulse.Cap(arg[0], m.Spawn(cli.Context).Cmd(append([]string{"express"}, arg[2:]...)...))) + if _, ok := m.Target().Server.(*CLI); m.Assert(ok) && !m.Caps("skip") { // {{{ + m.Cap(arg[1], arg[3]) + } else { + m.Set("result", arg...) } // }}} }}, "source": &ctx.Command{Name: "source file", Help: "运行脚本, file: 脚本文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{ - if f, e := os.Open(arg[0]); m.Assert(e) { - m.Put("option", "file", f).Start(fmt.Sprintf("%s%d", key, Pulse.Capi("level", 1)), "脚本文件") - <-m.Target().Exit - Pulse.Capi("level", -1) - } - } // }}} + if _, ok := m.Target().Server.(*CLI); m.Assert(ok) && !m.Caps("skip") { + m.Start(fmt.Sprintf("%s%d", key, m.Optioni("level", m.Capi("level")+1)), "脚本文件", arg[0]) + } }}, "return": &ctx.Command{Name: "return result...", Help: "结束脚本, rusult: 返回值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{ - call := cli.Requests[len(cli.Requests)-1] - call.Set("result", arg...) - cli.Pulse.Caps("exit", true) - } // }}} + if _, ok := m.Target().Server.(*CLI); m.Assert(ok) && !m.Caps("skip") { + m.Add("append", "return", arg[1:]...) + } }}, "if": &ctx.Command{Name: "if exp", Help: "条件语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{ - if m.Target(m.Source()); (cli.Has("skip") && cli.Pulse.Caps("skip")) || !cli.check(arg) { - m.Add("option", "skip") + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { + if m.Optioni("skip", 0); m.Caps("skip") || !cli.check(arg[1]) { + m.Optioni("skip", m.Capi("skip")+1) } - m.Put("option", "file", cli.bio).Start(fmt.Sprintf("%s%d", key, Pulse.Capi("level", 1)), "条件语句") - <-m.Target().Exit - Pulse.Capi("level", -1) - } // }}} + m.Start(fmt.Sprintf("%s%d", key, m.Optioni("level", m.Capi("level")+1)), "条件语句") + } }}, "elif": &ctx.Command{Name: "elif exp", Help: "条件语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{ - if cli.Pulse.Caps("skip", !cli.Pulse.Caps("else")) { + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { + if !m.Caps("else") { + m.Caps("skip", true) return } - cli.Pulse.Caps("else", cli.Pulse.Caps("skip", !cli.check(arg))) - } // }}} + + if m.Caps("skip") { + cli.nfs.Capi("pos", -1) + m.Caps("skip", false) + return + } + + m.Caps("else", m.Caps("skip", !cli.check(arg[1]))) + } }}, "else": &ctx.Command{Name: "else", Help: "条件语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{ - cli.Pulse.Caps("skip", !cli.Pulse.Caps("else")) - } // }}} + if _, ok := m.Target().Server.(*CLI); m.Assert(ok) { + m.Caps("skip", !m.Caps("else")) + } }}, "end": &ctx.Command{Name: "end", Help: "结束语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{ - if cli.Pulse.Caps("exit", true); cli.Pulse.Has("for") && !cli.Pulse.Caps("skip") { - cli.Pulse.Caps("exit", false) - cli.Pulse.Cap("pos", "0") - + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { + if m.Capi("fork") != -2 { + m.Spawn(cli.nfs.Target()).Cmd("copy", cli.Name, m.Cap("fork"), m.Option("pos")) } - cli.bio = nil - } // }}} + + if m.Caps("exit", true); !m.Caps("skip") && m.Capi("loop") >= 0 { + m.Append("back", m.Cap("loop")) + m.Caps("exit", false) + } else { + m.Put("append", "cli", cli.Context.Context()) + } + } }}, "for": &ctx.Command{Name: "for exp", Help: "循环语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{ - if cli.Pulse.Has("for") && cli.Pulse.Capi("pos") == 1 { - cli.Pulse.Caps("skip", !cli.check(arg)) + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { + if m.Capi("loop") != -2 && m.Capi("loop") == m.Optioni("pos")-1 { + m.Caps("skip", !cli.check(arg[1])) return } - if m.Target(m.Source()); (cli.Has("skip") && cli.Pulse.Caps("skip")) || !cli.check(arg) { - m.Add("option", "skip") + + if m.Optioni("skip", 0); m.Caps("skip") || !cli.check(arg[1]) { + m.Optioni("skip", m.Capi("skip")+1) } - m.Add("option", "for", cli.Pulse.Cap("back")) - m.Put("option", "file", cli.bio).Start(fmt.Sprintf("%s%d", key, Pulse.Capi("level", 1)), "循环语句") - <-m.Target().Exit - Pulse.Capi("level", -1) - } // }}} + m.Optioni("loop", m.Optioni("pos")-1) + m.Start(fmt.Sprintf("%s%d", key, m.Optioni("level", m.Capi("level")+1)), "循环语句") + } }}, "function": &ctx.Command{Name: "function name", Help: "函数定义, name: 函数名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{ - if _, ok := cli.Context.Context().Server.(*CLI); ok { - m.Target(m.Source().Context()) - } else { - m.Target(m.Source()) - } - - m.Add("option", "skip").Add("option", "save") - m.Put("option", "file", cli.bio).Start(arg[0], "函数定义") - <-m.Target().Exit - } // }}} + if _, ok := m.Target().Server.(*CLI); m.Assert(ok) { + m.Optioni("fork", m.Optioni("pos")+1) + m.Optioni("skip", m.Capi("skip")+1) + m.Start(arg[1], "循环语句") + } }}, "call": &ctx.Command{Name: "call name arg...", Help: "函数调用, name: 函数名, arg: 参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - m.Target(m.Source()) // {{{ - m.BackTrace(func(msg *ctx.Message) bool { - if fun := msg.Find(arg[0], false); fun != nil { - fun.Add("detail", arg[0], arg[1:]...).Target().Start(fun) - <-fun.Target().Exit - m.Set("result", fun.Meta["result"]...) - return false - } - return true - }) // }}} + fun := m.Find("nfs.file1." + arg[0]) + fun.Target().Start(fun) }}, }, } @@ -737,4 +658,6 @@ func init() { cli := &CLI{} cli.Context = Index ctx.Index.Register(Index, cli) + + cli.target = Index } diff --git a/src/context/ctx.go b/src/context/ctx.go index 5b2d170f..be505ad2 100644 --- a/src/context/ctx.go +++ b/src/context/ctx.go @@ -127,6 +127,8 @@ func (c *Context) Spawn(m *Message, name string, help string) *Context { // {{{ func (c *Context) Begin(m *Message) *Context { // {{{ c.Caches["status"] = &Cache{Name: "服务状态(begin/start/close)", Value: "begin", Help: "服务状态,begin:初始完成,start:正在运行,close:未在运行"} c.Caches["stream"] = &Cache{Name: "服务数据", Value: "", Help: "服务数据"} + c.Caches["debug"] = &Cache{Name: "命令日志", Value: "true", Help: "嵌套层级"} + c.Configs["debug"] = &Config{Name: "过程日志", Value: "true", Help: "嵌套层级"} m.Index = 1 c.Pulse = m @@ -153,6 +155,7 @@ func (c *Context) Begin(m *Message) *Context { // {{{ // }}} func (c *Context) Start(m *Message) bool { // {{{ + m.Hand = true if m != c.Requests[0] { c.Requests, m.Index = append(c.Requests, m), len(c.Requests)+1 @@ -238,8 +241,11 @@ func (c *Context) Context() *Context { // {{{ // }}} func (c *Context) Master(s ...*Context) *Context { // {{{ - if len(s) > 0 && s[0] == c { - c.master = c + if len(s) > 0 { + switch s[0] { + case nil, c: + c.master = s[0] + } } return c.master } @@ -445,8 +451,8 @@ func (c *Context) Del(arg ...string) { // {{{ // }}} type Message struct { - code int time time.Time + code int Hand bool Recv chan bool @@ -467,7 +473,15 @@ type Message struct { Template *Message } -func (m *Message) Source() *Context { // {{{ +func (m *Message) Code() int { // {{{ + return m.code +} + +// }}} +func (m *Message) Source(s ...*Context) *Context { // {{{ + if len(s) > 0 { + m.source = s[0] + } return m.source } @@ -931,18 +945,123 @@ func (m *Message) Echo(str string, arg ...interface{}) *Message { // {{{ return m.Add("result", fmt.Sprintf(str, arg...)) } +// }}} +func (m *Message) Copy(msg *Message, meta string, arg ...string) *Message { // {{{ + switch meta { + case "detail", "result": + m.Meta[meta] = append(m.Meta[meta][:0], msg.Meta[meta]...) + case "option", "append": + if len(arg) == 0 { + arg = msg.Meta[meta] + } + + for _, k := range arg { + if v, ok := msg.Meta[k]; ok { + m.Set(meta, k).Add(meta, k, v...) + } + if v, ok := msg.Data[k]; ok { + m.Put(meta, k, v) + } + } + } + + return m +} + +// }}} + +func (m *Message) Insert(meta string, index int, arg ...interface{}) string { // {{{ + if m.Meta == nil { + m.Meta = make(map[string][]string) + } + + str := []string{} + for _, v := range arg { + switch s := v.(type) { + case string: + str = append(str, s) + case []string: + str = append(str, s...) + case []int: + for _, v := range s { + str = append(str, fmt.Sprintf("%d", v)) + } + case []bool: + for _, v := range s { + str = append(str, fmt.Sprintf("%t", v)) + } + default: + str = append(str, fmt.Sprintf("%v", s)) + } + } + + if index == -1 { + index, m.Meta[meta] = 0, append(str, m.Meta[meta]...) + } else if index == -2 { + index, m.Meta[meta] = len(m.Meta[meta]), append(m.Meta[meta], str...) + } else { + if index < -2 { + index += len(m.Meta[meta]) + 2 + } + if index < 0 { + index = 0 + } + + for i := len(m.Meta[meta]); i < index+len(str); i++ { + m.Meta[meta] = append(m.Meta[meta], "") + } + for i := 0; i < len(str); i++ { + m.Meta[meta][index+i] = str[i] + } + } + + return m.Meta[meta][index] +} + +// }}} +func (m *Message) Detail(index int, arg ...interface{}) string { // {{{ + return m.Insert("detail", index, arg...) +} + +// }}} +func (m *Message) Detaili(index int, arg ...int) int { // {{{ + i, e := strconv.Atoi(m.Insert("detail", index, arg)) + m.Assert(e) + return i +} + +// }}} +func (m *Message) Details(index int, arg ...bool) bool { // {{{ + return right(m.Insert("detail", index, arg)) +} + +// }}} +func (m *Message) Result(index int, arg ...interface{}) string { // {{{ + return m.Insert("result", index, arg...) +} + +// }}} +func (m *Message) Resulti(index int, arg ...int) int { // {{{ + i, e := strconv.Atoi(m.Insert("result", index, arg)) + m.Assert(e) + return i +} + +// }}} +func (m *Message) Results(index int, arg ...bool) bool { // {{{ + return right(m.Insert("result", index, arg)) +} + // }}} func (m *Message) Option(key string, arg ...string) string { // {{{ if len(arg) > 0 { - m.Log("fuck", nil, "option set %s %v", key, arg) m.Set("option", append([]string{key}, arg...)...) } for msg := m; msg != nil; msg = msg.message { - msg.Log("fuck", nil, "option") - if m.Has(key) { - return m.Get(key) + if msg.Has(key) { + return msg.Get(key) } } return "" @@ -977,15 +1096,12 @@ func (m *Message) Options(key string, arg ...bool) bool { // {{{ } // }}} - func (m *Message) Append(key string, arg ...string) string { // {{{ if len(arg) > 0 { - m.Log("fuck", nil, "append set %s %v", key, arg) m.Set("append", append([]string{key}, arg...)...) } for msg := m; msg != nil; msg = msg.message { - msg.Log("fuck", nil, "append") if m.Has(key) { return m.Get(key) } @@ -1144,16 +1260,25 @@ func (m *Message) Post(s *Context, async ...bool) string { // {{{ } // }}} -func (m *Message) Cmd(arg ...string) string { // {{{ +func (m *Message) Cmd(arg ...interface{}) *Message { // {{{ + if m.Hand { + msg := m.Spawn(m.target) + msg.source = m.source + m = msg + } + if len(arg) > 0 { - m.Set("detail", arg...) + m.Set("detail") + m.Detail(0, arg...) } if s := m.target.master; s != nil && s != m.source.master { - return m.Post(s) + m.Post(s) + } else { + m.Exec(m.Meta["detail"][0], m.Meta["detail"][1:]...) } - return m.Exec(m.Meta["detail"][0], m.Meta["detail"][1:]...) + return m } // }}} @@ -1316,11 +1441,14 @@ func (m *Message) Cap(key string, arg ...string) string { // {{{ var Pulse = &Message{code: 0, time: time.Now(), Wait: make(chan bool), source: Index, master: Index, target: Index} var Index = &Context{Name: "ctx", Help: "模块中心", Caches: map[string]*Cache{ + "debug": &Cache{Name: "服务数量", Value: "true", Help: "显示已经启动运行模块的数量"}, "nserver": &Cache{Name: "服务数量", Value: "0", Help: "显示已经启动运行模块的数量"}, "ncontext": &Cache{Name: "模块数量", Value: "0", Help: "显示功能树已经注册模块的数量"}, "nmessage": &Cache{Name: "消息数量", Value: "0", Help: "显示模块启动时所创建消息的数量"}, }, Configs: map[string]*Config{ + "debug": &Config{Name: "调试模式(true/false)", Value: "true", Help: "是否打印错误信息,off:不打印,on:打印)"}, + "default": &Config{Name: "默认的搜索起点(root/back/home)", Value: "root", Help: "模块搜索的默认起点,root:从根模块,back:从父模块,home:从当前模块"}, "start": &Config{Name: "启动模块", Value: "cli", Help: "启动时自动运行的模块"}, @@ -1364,9 +1492,8 @@ var Index = &Context{Name: "ctx", Help: "模块中心", "ContextSessionSize": &Config{Name: "会话队列长度", Value: "10", Help: "每个模块可以启动其它模块的数量"}, "MessageQueueSize": &Config{Name: "消息队列长度", Value: "10", Help: "每个模块接收消息的队列长度"}, - "debug": &Config{Name: "调试模式(true/false)", Value: "false", Help: "是否打印错误信息,off:不打印,on:打印)"}, - "cert": &Config{Name: "证书文件", Value: "etc/cert.pem", Help: "证书文件"}, - "key": &Config{Name: "私钥文件", Value: "etc/key.pem", Help: "私钥文件"}, + "cert": &Config{Name: "证书文件", Value: "etc/cert.pem", Help: "证书文件"}, + "key": &Config{Name: "私钥文件", Value: "etc/key.pem", Help: "私钥文件"}, }, Commands: map[string]*Command{ "userinfo": &Command{Name: "userinfo [add|del [context key name help]|[command|config|cache group name]]", Help: "查看模块的用户信息", @@ -1494,6 +1621,16 @@ var Index = &Context{Name: "ctx", Help: "模块中心", // }}} }}, + "detail": &Command{Name: "detail index val...", Help: "查看消息", Hand: func(m *Message, c *Context, key string, arg ...string) { + msg := m.Spawn(m.Target()) + + msg.Detail(1, "nie", 1, []string{"123", "123"}, true, []bool{false, true}, []int{1, 2, 2}) + + m.Echo("%v", msg.Meta) + msg.Detail(2, "nie") + m.Echo("%v", msg.Meta) + + }}, "option": &Command{Name: "option key val...", Help: "查看消息", Hand: func(m *Message, c *Context, key string, arg ...string) { if len(arg) > 0 { // {{{ m.Option(arg[0], arg[1:]...) @@ -1623,7 +1760,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", }) case len(arg) > 0 && v != m: v.Meta = m.Meta - v.Cmd(arg...) + v.Cmd(arg) m.Meta = v.Meta default: m.target = v.target @@ -1881,7 +2018,7 @@ func Start(args ...string) { log.Println() for _, m := range Pulse.Search(Pulse.Conf("start")) { - m.Set("option", "stdio").target.Start(m) + m.Set("detail", Pulse.Conf("init.shy")).Set("option", "stdio").target.Start(m) } <-Index.master.Exit diff --git a/src/context/lex/lex.go b/src/context/lex/lex.go index 54725bfc..e06c7e96 100644 --- a/src/context/lex/lex.go +++ b/src/context/lex/lex.go @@ -1,31 +1,32 @@ -package lex // {{{ -// }}} -import ( // {{{ +package lex + +import ( "context" "fmt" "strconv" ) -// }}} - -type Seed struct { // {{{ +type Seed struct { page int hash int word string } - -// }}} -type State struct { // {{{ +type State struct { star bool next int hash int } +type Point struct { + s int + c byte +} -// }}} -type LEX struct { // {{{ +type LEX struct { seed []*Seed + page map[string]int hash map[string]int + char map[byte][]byte state map[State]*State mat []map[byte]*State @@ -34,9 +35,7 @@ type LEX struct { // {{{ *ctx.Context } -// }}} - -func (lex *LEX) index(hash string, h string) int { // {{{ +func (lex *LEX) index(hash string, h string) int { if x, e := strconv.Atoi(h); e == nil { return x } @@ -53,42 +52,31 @@ func (lex *LEX) index(hash string, h string) int { // {{{ return x } - x := lex.Capi(hash, 1) - which[h] = x - return x + which[h] = lex.Capi(hash, 1) + return which[h] } -// }}} -func (lex *LEX) charset(c byte) []byte { // {{{ - switch c { - case 't': - return []byte{'\t'} - case 'n': - return []byte{'\n'} - case 's': - return []byte{'\t', ' ', '\n'} - case 'd': - return []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'} - case 'x': - return []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F'} +func (lex *LEX) charset(c byte) []byte { + if cs, ok := lex.char[c]; ok { + return cs } return []byte{c} } -// }}} -func (lex *LEX) train(page int, hash int, seed []byte) int { // {{{ +func (lex *LEX) train(page int, hash int, seed []byte) int { cn := make([]bool, lex.Capi("ncell")) c := make([]byte, 0, lex.Capi("ncell")) sn := make([]bool, lex.Capi("nline")) s := []int{page} - ends := []*State{} + points := []*Point{} - for p, set := 0, true; p < len(seed); p++ { + for p := 0; p < len(seed); p++ { switch seed[p] { case '[': + set := true if p++; seed[p] == '^' { set, p = false, p+1 } @@ -152,56 +140,38 @@ func (lex *LEX) train(page int, hash int, seed []byte) int { // {{{ for i := 0; i < len(s); i++ { for line, j := 0, byte(0); int(j) < len(c); j++ { - state := lex.mat[s[i]][c[j]] - lex.Log("debug", nil, "GET(%d,%d): %v", s[i], c[j], state) - if state == nil { - state = &State{} + + state := &State{} + if lex.mat[s[i]][c[j]] != nil { + *state = *lex.mat[s[i]][c[j]] + } else { lex.Capi("nnode", 1) } + lex.Log("debug", nil, "GET(%d,%d): %v", s[i], c[j], state) switch flag { case '+': state.star = true case '*': state.star = true - fallthrough + sn[s[i]] = true case '?': - if sn[s[i]] = true; p == len(seed)-1 { - for _, n := range ends { - if n.next == s[i] { - lex.Log("debug", nil, "GET() state:%v", n) - n.hash = hash - lex.Log("debug", nil, "END() state:%v", n) - } - } - } + sn[s[i]] = true } - if p == len(seed)-1 { - state.hash = hash - } else { - if state.next == 0 { - if line == 0 || !lex.Caps("compact") { - lex.mat = append(lex.mat, make(map[byte]*State)) - line = lex.Capi("nline", 1) - 1 - sn = append(sn, false) - } - state.next = line + if state.next == 0 { + if line == 0 || !lex.Caps("compact") { + lex.mat = append(lex.mat, make(map[byte]*State)) + line = lex.Capi("nline", 1) - 1 + sn = append(sn, false) } - sn[state.next] = true - } - - if s, ok := lex.state[*state]; !ok { - lex.state[*state] = state - lex.Capi("nreal", 1) - } else { - state = s + state.next = line } + sn[state.next] = true lex.mat[s[i]][c[j]] = state - + points = append(points, &Point{s[i], c[j]}) lex.Log("debug", nil, "SET(%d,%d): %v(%s,%s)", s[i], c[j], state, lex.Cap("nnode"), lex.Cap("nreal")) - ends = append(ends, state) } } @@ -213,14 +183,50 @@ func (lex *LEX) train(page int, hash int, seed []byte) int { // {{{ sn[i] = false } } + + for _, n := range s { + if n < lex.Capi("nlang") || n >= len(lex.mat) { + continue + } + + if len(lex.mat[n]) == 0 { + lex.Log("debug", nil, "DEL: %d %d", lex.Capi("nline")-1, lex.Capi("nline", 0, n)) + lex.mat = lex.mat[:n] + } + } + + for _, n := range s { + for _, p := range points { + state := &State{} + *state = *lex.mat[p.s][p.c] + + if state.next == n { + lex.Log("debug", nil, "GET(%d, %d): %v", p.s, p.c, state) + if state.next >= len(lex.mat) { + state.next = 0 + } + if hash > 0 { + state.hash = hash + } + lex.Log("debug", nil, "SET(%d, %d): %v", p.s, p.c, state) + } + + if x, ok := lex.state[*state]; ok { + lex.mat[p.s][p.c] = x + } else { + lex.state[*state] = state + lex.mat[p.s][p.c] = state + lex.Capi("nreal", 1) + } + } + } + return hash } -// }}} -func (lex *LEX) parse(page int, line []byte) (hash int, word []byte, rest []byte) { // {{{ +func (lex *LEX) parse(page int, line []byte) (hash int, word []byte, rest []byte) { pos := 0 - for star, s := 0, page; s != 0 && pos < len(line); pos++ { c := line[pos] @@ -262,9 +268,7 @@ func (lex *LEX) parse(page int, line []byte) (hash int, word []byte, rest []byte return } -// }}} - -func (lex *LEX) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{ +func (lex *LEX) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { c.Caches = map[string]*ctx.Cache{} c.Configs = map[string]*ctx.Config{} @@ -273,30 +277,33 @@ func (lex *LEX) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server return s } -// }}} -func (lex *LEX) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ +func (lex *LEX) Begin(m *ctx.Message, arg ...string) ctx.Server { if lex.Context == Index { Pulse = m } + lex.Context.Master(nil) + lex.Message = m lex.Caches["ncell"] = &ctx.Cache{Name: "字符上限", Value: "128", Help: "字符上限"} - lex.Caches["nlang"] = &ctx.Cache{Name: "集合上限", Value: "16", Help: "集合上限"} + lex.Caches["nlang"] = &ctx.Cache{Name: "集合上限", Value: "32", Help: "集合上限"} lex.Caches["nseed"] = &ctx.Cache{Name: "种子数量", Value: "0", Help: "种子数量"} lex.Caches["npage"] = &ctx.Cache{Name: "集合数量", Value: "0", Help: "集合数量"} lex.Caches["nhash"] = &ctx.Cache{Name: "类型数量", Value: "0", Help: "类型数量"} - lex.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: "16", Help: "状态数量"} + lex.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: "32", Help: "状态数量"} lex.Caches["nnode"] = &ctx.Cache{Name: "节点数量", Value: "0", Help: "节点数量"} lex.Caches["nreal"] = &ctx.Cache{Name: "实点数量", Value: "0", Help: "实点数量"} lex.Caches["compact"] = &ctx.Cache{Name: "紧凑模式", Value: "true", Help: "实点数量"} - lex.Caches["debug"] = &ctx.Cache{Name: "调试模式", Value: "false", Help: "调试模式"} + + lex.Caps("debug", false) + lex.Confs("debug", false) return lex } -// }}} -func (lex *LEX) Start(m *ctx.Message, arg ...string) bool { // {{{ +func (lex *LEX) Start(m *ctx.Message, arg ...string) bool { + lex.Context.Master(nil) lex.Message = m lex.seed = make([]*Seed, 0, 9) @@ -308,8 +315,7 @@ func (lex *LEX) Start(m *ctx.Message, arg ...string) bool { // {{{ return false } -// }}} -func (lex *LEX) Close(m *ctx.Message, arg ...string) bool { // {{{ +func (lex *LEX) Close(m *ctx.Message, arg ...string) bool { switch lex.Context { case m.Target(): case m.Source(): @@ -317,18 +323,17 @@ func (lex *LEX) Close(m *ctx.Message, arg ...string) bool { // {{{ return true } -// }}} - var Pulse *ctx.Message var Index = &ctx.Context{Name: "lex", Help: "词法中心", Caches: map[string]*ctx.Cache{}, Configs: map[string]*ctx.Config{}, Commands: map[string]*ctx.Command{ "train": &ctx.Command{Name: "train seed [hash [page]", Help: "添加词法规则", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { // {{{ + if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { page, hash := 1, 1 if len(arg) > 2 { page = lex.index("npage", arg[2]) + m.Assert(page < m.Capi("nlang"), "词法集合过多") } if len(arg) > 1 { hash = lex.index("nhash", arg[1]) @@ -338,26 +343,24 @@ var Index = &ctx.Context{Name: "lex", Help: "词法中心", lex.mat[page] = map[byte]*State{} } - lex.seed = append(lex.seed, &Seed{page, hash, string(arg[0])}) - lex.Log("debug", nil, "%d %d %d %v", page, hash, lex.Capi("nseed", 1), arg[0]) - lex.Cap("stream", fmt.Sprintf("%s,%s,%s", lex.Cap("nseed"), lex.Cap("npage"), lex.Cap("nhash"))) - - m.Echo("%d", lex.train(page, hash, []byte(arg[0]))) - } // }}} + m.Result(0, lex.train(page, hash, []byte(arg[0]))) + lex.seed = append(lex.seed, &Seed{page, hash, arg[0]}) + lex.Cap("stream", fmt.Sprintf("%d,%s,%s", lex.Capi("nseed", 1), lex.Cap("npage"), lex.Cap("nhash"))) + } }}, "parse": &ctx.Command{Name: "parse line [page]", Help: "解析单词", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { // {{{ + if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { page := 1 if len(arg) > 1 { page = lex.index("npage", arg[1]) } hash, word, rest := lex.parse(page, []byte(arg[0])) - m.Add("result", fmt.Sprintf("%d", hash), string(word), string(rest)) - } // }}} + m.Result(0, hash, string(word), string(rest)) + } }}, "split": &ctx.Command{Name: "split line page void help", Help: "分割语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { // {{{ + if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { page := 1 if len(arg) > 1 { page = lex.index("npage", arg[1]) @@ -378,10 +381,10 @@ var Index = &ctx.Context{Name: "lex", Help: "词法中心", _, _, rest = lex.parse(void, []byte(rest)) hash, word, rest := lex.parse(page, []byte(rest)) m.Add("result", fmt.Sprintf("%d", hash), string(word), string(rest)) - } // }}} + } }}, "info": &ctx.Command{Name: "info", Help: "显示缓存", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { // {{{ + if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { for i, v := range lex.seed { m.Echo("seed: %d %v\n", i, v) } @@ -399,7 +402,32 @@ var Index = &ctx.Context{Name: "lex", Help: "词法中心", m.Echo("node: %v %v %v\n", i, k, v) } } - } // }}} + } + }}, + "check": &ctx.Command{Name: "check page void word...", Help: "解析语句, page: 语法集合, void: 空白语法集合, word: 语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { + set := map[*State]bool{} + nreal := 0 + for _, v := range lex.state { + nreal++ + set[v] = true + } + + nnode := 0 + for i, v := range lex.mat { + for j, x := range v { + if x == nil && int(j) < m.Capi("nlang") { + continue + } + nnode++ + + if _, ok := set[x]; !ok { + m.Log("fuck", nil, "not in %d %d %v %p", i, j, x, x) + } + } + } + m.Log("fuck", nil, "node: %d real: %d", nnode, nreal) + } }}, }, } @@ -408,4 +436,13 @@ func init() { lex := &LEX{} lex.Context = Index ctx.Index.Register(Index, lex) + + lex.char = map[byte][]byte{ + 't': []byte{'\t'}, + 'n': []byte{'\n'}, + 'b': []byte{'\t', ' '}, + 's': []byte{'\t', ' ', '\n'}, + 'd': []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}, + 'x': []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F'}, + } } diff --git a/src/context/nfs/nfs.go b/src/context/nfs/nfs.go index a52c9c42..4ac48cd7 100644 --- a/src/context/nfs/nfs.go +++ b/src/context/nfs/nfs.go @@ -1,6 +1,6 @@ -package nfs - -import ( +package nfs // {{{ +// }}} +import ( // {{{ "context" "bufio" @@ -12,13 +12,16 @@ import ( "strings" ) +// }}} + type NFS struct { in *os.File out *os.File + buf []string *ctx.Context } -func (nfs *NFS) print(str string, arg ...interface{}) bool { +func (nfs *NFS) print(str string, arg ...interface{}) bool { // {{{ if nfs.out == nil { return false } @@ -27,17 +30,23 @@ func (nfs *NFS) print(str string, arg ...interface{}) bool { return true } +// }}} + func (nfs *NFS) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { c.Caches = map[string]*ctx.Cache{ - "pos": &ctx.Cache{Name: "读写位置", Value: "0", Help: "读写位置"}, + "pos": &ctx.Cache{Name: "读写位置", Value: "0", Help: "读写位置"}, + "nline": &ctx.Cache{Name: "缓存命令行数", Value: "0", Help: "缓存命令行数"}, + "return": &ctx.Cache{Name: "缓存命令行数", Value: "0", Help: "缓存命令行数"}, } c.Configs = map[string]*ctx.Config{} - if info, e := os.Stat(arg[1]); e == nil { - c.Caches["name"] = &ctx.Cache{Name: "name", Value: info.Name(), Help: "文件名"} - c.Caches["mode"] = &ctx.Cache{Name: "mode", Value: info.Mode().String(), Help: "文件权限"} - c.Caches["size"] = &ctx.Cache{Name: "size", Value: fmt.Sprintf("%d", info.Size()), Help: "文件大小"} - c.Caches["time"] = &ctx.Cache{Name: "time", Value: info.ModTime().Format("15:03:04"), Help: "创建时间"} + if len(arg) > 1 { + if info, e := os.Stat(arg[1]); e == nil { + c.Caches["name"] = &ctx.Cache{Name: "name", Value: info.Name(), Help: "文件名"} + c.Caches["mode"] = &ctx.Cache{Name: "mode", Value: info.Mode().String(), Help: "文件权限"} + c.Caches["size"] = &ctx.Cache{Name: "size", Value: fmt.Sprintf("%d", info.Size()), Help: "文件大小"} + c.Caches["time"] = &ctx.Cache{Name: "time", Value: info.ModTime().Format("15:03:04"), Help: "创建时间"} + } } s := new(NFS) @@ -46,13 +55,15 @@ func (nfs *NFS) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server } -func (nfs *NFS) Begin(m *ctx.Message, arg ...string) ctx.Server { +func (nfs *NFS) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ + nfs.Context.Master(nil) if nfs.Context == Index { Pulse = m } return nfs } +// }}} func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { if out, ok := m.Data["out"]; ok { nfs.out = out.(*os.File) @@ -60,34 +71,75 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { if in, ok := m.Data["in"]; ok { nfs.in = in.(*os.File) } - - m.Log("info", nil, "%d %v", Pulse.Capi("nfile"), arg) - if m.Cap("stream", arg[1]); arg[0] == "open" { - return false + if len(arg) > 1 { + if m.Cap("stream", arg[1]); arg[0] == "open" { + return false + } } cli := m.Reply() - cli.Conf("yac", "yac") yac := m.Find(cli.Conf("yac")) bio := bufio.NewScanner(nfs.in) + nfs.Context.Master(nil) + pos := 0 + + if buf, ok := m.Data["buf"]; ok { + nfs.buf = buf.([]string) + m.Capi("nline", len(nfs.buf)) + goto out + } + + if len(arg) > 2 { + nfs.print("%v\n", arg[2]) + } nfs.print("%s", cli.Conf("PS1")) - for bio.Scan() { - line := m - if yac != nil { - // line = cli.Spawn(yac.Target()) - line = m.Spawn(yac.Target()) - } else { - line = m.Reply() - } - line.Cmd(append([]string{"parse", "line", "void"}, strings.Split(bio.Text()+" \n", " ")...)...) + for rest, text := "", ""; pos < m.Capi("nline") || bio.Scan(); { + if pos == m.Capi("nline") { + if text = bio.Text(); len(text) > 0 && text[len(text)-1] == '\\' { + rest += text[:len(text)-1] + continue + } - if result := strings.TrimRight(strings.Join(line.Meta["result"], ""), "\n"); len(result) > 0 { - nfs.print("%s", result+"\n") + if text, rest = rest+text, ""; len(text) == 0 && len(nfs.buf) > 0 && nfs.in == os.Stdin { + pos-- + } else { + nfs.buf = append(nfs.buf, text) + m.Capi("nline", 1) + } } + + for ; pos < m.Capi("nline"); pos++ { + + for text = nfs.buf[pos] + "\n"; text != ""; { + line := m.Spawn(yac.Target()) + line.Optioni("pos", pos) + line.Put("option", "cli", cli.Target()) + text = line.Cmd("parse", "line", "void", text).Get("result") + cli.Target(line.Data["cli"].(*ctx.Context)) + if line.Has("return") { + goto out + } + if line.Has("back") { + pos = line.Appendi("back") + } + + if result := strings.TrimRight(strings.Join(line.Meta["result"][1:len(line.Meta["result"])-1], ""), "\n"); len(result) > 0 { + nfs.print("%s", result+"\n") + } + } + } + nfs.print("%s", cli.Conf("PS1")) } - return true + +out: + if len(arg) > 1 { + cli.Cmd("end") + } else { + m.Cap("status", "stop") + } + return false } func (nfs *NFS) Close(m *ctx.Message, arg ...string) bool { @@ -112,105 +164,135 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", "size": &ctx.Config{Name: "size", Value: "1024", Help: "读取文件的默认大小值"}, }, Commands: map[string]*ctx.Command{ - "scan": &ctx.Command{Name: "scan file", Help: "扫描文件, file: 文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if arg[0] == "stdio" { - m.Put("option", "in", os.Stdin).Put("option", "out", os.Stdout) - m.Start("stdio", "扫描文件", m.Meta["detail"]...) - } else if f, e := os.Open(arg[0]); m.Assert(e) { - m.Put("option", "in", f) - m.Start(fmt.Sprintf("file%d", Pulse.Capi("nfile", 1)), "扫描文件", m.Meta["detail"]...) + "buffer": &ctx.Command{Name: "buffer [index string]", Help: "扫描文件, file: 文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.buf != nil { // {{{ + for i, v := range nfs.buf { + m.Echo("%d: %s\n", i, v) + } + } // }}} + }}, + "copy": &ctx.Command{Name: "copy name [begin [end]]", Help: "复制文件, file: 文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && len(nfs.buf) > 0 { + begin, end := 0, len(nfs.buf) + if len(arg) > 1 { + i, e := strconv.Atoi(arg[1]) + m.Assert(e) + begin = i + } + if len(arg) > 2 { + i, e := strconv.Atoi(arg[2]) + m.Assert(e) + end = i + } + m.Put("option", "buf", nfs.buf[begin:end]) + m.Start(arg[0], "扫描文件", key) } - m.Echo(m.Target().Name) + }}, + "scan": &ctx.Command{Name: "scan file", Help: "扫描文件, file: 文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if arg[0] == "stdio" { // {{{ + m.Put("option", "in", os.Stdin).Put("option", "out", os.Stdout).Start("stdio", "扫描文件", m.Meta["detail"]...) + } else if f, e := os.Open(arg[0]); m.Assert(e) { + m.Put("option", "in", f).Start(fmt.Sprintf("file%d", Pulse.Capi("nfile", 1)), "扫描文件", m.Meta["detail"]...) + } + // }}} + }}, + "print": &ctx.Command{Name: "print str", Help: "扫描文件, file: 文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil { // {{{ + fmt.Fprintf(nfs.out, "%s\n", arg[0]) + } + // }}} }}, "open": &ctx.Command{Name: "open file", Help: "打开文件, file: 文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if f, e := os.OpenFile(arg[0], os.O_RDWR|os.O_CREATE, os.ModePerm); m.Assert(e) { + if f, e := os.OpenFile(arg[0], os.O_RDWR|os.O_CREATE, os.ModePerm); m.Assert(e) { // {{{ m.Put("option", "in", f).Put("option", "out", f) m.Start(fmt.Sprintf("file%d", Pulse.Capi("nfile", 1)), "打开文件", m.Meta["detail"]...) - } - m.Echo(m.Target().Name) + m.Echo(m.Target().Name) + } // }}} }}, "read": &ctx.Command{Name: "read [size [pos]]", Help: "读取文件, size: 读取大小, pos: 读取位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - nfs, ok := m.Target().Server.(*NFS) - m.Assert(ok) + if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.in != nil { // {{{ + var e error + n := m.Confi("size") + if len(arg) > 0 { + n, e = strconv.Atoi(arg[0]) + m.Assert(e) + } + if len(arg) > 1 { + m.Cap("pos", arg[1]) + } - var e error - n := m.Confi("size") - if len(arg) > 0 { - n, e = strconv.Atoi(arg[0]) - m.Assert(e) - } - if len(arg) > 1 { - m.Cap("pos", arg[1]) - } + buf := make([]byte, n) + if n, e = nfs.in.ReadAt(buf, int64(m.Capi("pos"))); e != io.EOF { + m.Assert(e) + } + m.Echo(string(buf)) - buf := make([]byte, n) - if n, e = nfs.in.ReadAt(buf, int64(m.Capi("pos"))); e != io.EOF { - m.Assert(e) - } - m.Echo(string(buf)) - - if m.Capi("pos", n); m.Capi("pos") == m.Capi("size") { - m.Cap("pos", "0") - } + if m.Capi("pos", n); m.Capi("pos") == m.Capi("size") { + m.Cap("pos", "0") + } + } // }}} }}, "write": &ctx.Command{Name: "write string [pos]", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - nfs, ok := m.Target().Server.(*NFS) - if m.Assert(ok); len(arg) > 1 { - m.Cap("pos", arg[1]) - } - - if len(arg[0]) == 0 { - m.Assert(nfs.in.Truncate(int64(m.Capi("pos")))) - m.Cap("size", m.Cap("pos")) - m.Cap("pos", "0") - } else { - n, e := nfs.in.WriteAt([]byte(arg[0]), int64(m.Capi("pos"))) - if m.Assert(e) && m.Capi("pos", n) > m.Capi("size") { - m.Cap("size", m.Cap("pos")) + if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil { // {{{ + if len(arg) > 1 { + m.Cap("pos", arg[1]) } - } - m.Echo(m.Cap("pos")) + if len(arg[0]) == 0 { + m.Assert(nfs.out.Truncate(int64(m.Capi("pos")))) + m.Cap("size", m.Cap("pos")) + m.Cap("pos", "0") + } else { + n, e := nfs.out.WriteAt([]byte(arg[0]), int64(m.Capi("pos"))) + if m.Assert(e) && m.Capi("pos", n) > m.Capi("size") { + m.Cap("size", m.Cap("pos")) + } + } + + m.Echo(m.Cap("pos")) + } // }}} }}, "load": &ctx.Command{Name: "load file [size]", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - f, e := os.Open(arg[0]) - if e != nil { - return - } - defer f.Close() + if f, e := os.Open(arg[0]); m.Assert(e) { // {{{ + defer f.Close() - m.Meta = nil - size := 1024 - if len(arg) > 1 { - if s, e := strconv.Atoi(arg[1]); e == nil { - size = s + m.Meta = nil + size := 1024 + if len(arg) > 1 { + if s, e := strconv.Atoi(arg[1]); m.Assert(e) { + size = s + } } - } - buf := make([]byte, size) - l, e := f.Read(buf) - m.Echo(string(buf[:l])) - m.Log("info", nil, "read %d", l) + buf := make([]byte, size) + + if l, e := f.Read(buf); m.Assert(e) { + m.Log("info", nil, "read %d", l) + m.Echo(string(buf[:l])) + } + } // }}} }}, "save": &ctx.Command{Name: "save file string...", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - f, e := os.Create(arg[0]) - m.Assert(e) - defer f.Close() - fmt.Fprint(f, strings.Join(arg[1:], "")) + if f, e := os.Create(arg[0]); m.Assert(e) { // {{{ + defer f.Close() + + fmt.Fprint(f, strings.Join(arg[1:], "")) + } // }}} }}, "genqr": &ctx.Command{Name: "genqr [size] file string...", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - size := 256 + size := 256 // {{{ if len(arg) > 2 { if s, e := strconv.Atoi(arg[0]); e == nil { arg = arg[1:] size = s } } - qrcode.WriteFile(strings.Join(arg[1:], ""), qrcode.Medium, size, arg[0]) + qrcode.WriteFile(strings.Join(arg[1:], ""), qrcode.Medium, size, arg[0]) // }}} }}, }, Index: map[string]*ctx.Context{ "void": &ctx.Context{Name: "void", Commands: map[string]*ctx.Command{ + "scan": &ctx.Command{}, "open": &ctx.Command{}, "save": &ctx.Command{}, "load": &ctx.Command{}, diff --git a/src/context/ssh/ssh.go b/src/context/ssh/ssh.go index d2690d35..8a3ad173 100644 --- a/src/context/ssh/ssh.go +++ b/src/context/ssh/ssh.go @@ -59,7 +59,7 @@ func (ssh *SSH) Start(m *ctx.Message, arg ...string) bool { if msg.Log("info", nil, "remote: %v", msg.Meta["option"]); msg.Has("detail") { msg.Log("info", nil, "%d exec: %v", m.Capi("nrecv", 1), msg.Meta["detail"]) - msg.Cmd(msg.Meta["detail"]...) + msg.Cmd(msg.Meta["detail"]) target = msg.Target() m.Cap("target", target.Name) @@ -113,10 +113,10 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", Configs: map[string]*ctx.Config{}, Commands: map[string]*ctx.Command{ "listen": &ctx.Command{Name: "listen address protocol", Help: "监听连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - m.Find("tcp").Cmd(m.Meta["detail"]...) + m.Find("tcp").Cmd(m.Meta["detail"]) }}, "dial": &ctx.Command{Name: "dial address protocol", Help: "建立连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - m.Find("tcp").Cmd(m.Meta["detail"]...) + m.Find("tcp").Cmd(m.Meta["detail"]) }}, "open": &ctx.Command{Name: "open", Help: "打开连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { m.Start(fmt.Sprintf("host%d", Pulse.Capi("nhost", 1)), "主机连接") diff --git a/src/context/web/web.go b/src/context/web/web.go index 1029061c..3beb9bfd 100644 --- a/src/context/web/web.go +++ b/src/context/web/web.go @@ -240,7 +240,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", if line = strings.TrimSpace(line); line != "" { lex.Cmd("split", line, "void") cli.Wait = make(chan bool) - cli.Cmd(lex.Meta["result"]...) + cli.Cmd(lex.Meta["result"]) m.Meta["result"] = cli.Meta["result"] } diff --git a/src/context/yac/yac.go b/src/context/yac/yac.go index 54e4b698..829df12f 100644 --- a/src/context/yac/yac.go +++ b/src/context/yac/yac.go @@ -1,29 +1,29 @@ -package yac // {{{ -// }}} -import ( // {{{ +package yac + +import ( "context" "fmt" "strings" ) -// }}} - -type Seed struct { // {{{ +type Seed struct { page int hash int word []string } - -// }}} -type State struct { // {{{ - star int +type State struct { next int + star int hash int } +type Point struct { + s int + c byte +} -// }}} -type YAC struct { // {{{ +type YAC struct { seed []*Seed + page map[string]int word map[int]string hash map[string]int @@ -37,122 +37,100 @@ type YAC struct { // {{{ *ctx.Context } -// }}} - -func (yac *YAC) train(page, hash int, word []string) ([]*State, int) { // {{{ - - if yac.mat[page] == nil { - yac.mat[page] = map[byte]*State{} - for i := 0; i < yac.Capi("nlang"); i++ { - yac.mat[page][byte(i)] = nil - } +func (yac *YAC) name(page int) string { + name, ok := yac.word[page] + if !ok { + name = fmt.Sprintf("yac%d", page) } + return name +} + +func (yac *YAC) train(page, hash int, word []string) (int, []*Point, []*Point) { sn := make([]bool, yac.Capi("nline")) ss := []int{page} - begin := page - point := []*State{} - ends := []*State{} - state := []*State{} - mul := false - skip := len(word) + points := []*Point{} + ends := []*Point{} - for i, n := 0, 1; i < len(word); i += n { - if !mul { + for i, n, m := 0, 1, false; i < len(word); i += n { + if !m { if hash <= 0 && word[i] == "}" { - if skip = i + 2; hash == -1 { - hash = 0 - break - } - return ends, skip - } else { - ends = ends[:0] + return i + 2, points, ends } + ends = ends[:0] } for _, s := range ss { switch word[i] { - case "opt{": + case "opt{", "rep{": sn[s] = true - state, n = yac.train(s, 0, word[i+1:]) - for _, x := range state { - for i := len(sn); i <= x.next; i++ { + num, point, end := yac.train(s, 0, word[i+1:]) + n, points = num, append(points, point...) + for _, x := range end { + state := &State{} + *state = *yac.mat[x.s][x.c] + for i := len(sn); i <= state.next; i++ { sn = append(sn, false) } - sn[x.next] = true - point = append(point, x) - } - case "rep{": - sn[s] = true - state, n = yac.train(s, -1, word[i+1:]) - for _, x := range state { - x.star = s - sn[x.next] = true - point = append(point, x) - yac.Pulse.Log("debug", nil, "END: %v", x) + sn[state.next] = true + points = append(points, x) + + if word[i] == "rep{" { + state.star = s + yac.mat[x.s][x.c] = state + yac.Log("debug", nil, "REP(%d, %d): %v", x.s, x.c, state) + } } case "mul{": - mul, n = true, 1 + m, n = true, 1 goto next case "}": - if mul { - mul = false + if m { + m = false goto next } + fallthrough default: - c := byte(0) - if x, ok := yac.page[word[i]]; !ok { - lex := yac.lex.Spawn(yac.lex.Target()) - lex.Cmd("parse", word[i], fmt.Sprintf("yac%d", s)) + x, ok := yac.page[word[i]] + + if !ok { + lex := yac.lex.Cmd("parse", word[i], yac.name(s)) if lex.Gets("result") { x = lex.Geti("result") } else { x = len(yac.mat[s]) - lex = yac.lex.Spawn(yac.lex.Target()) - lex.Cmd("train", word[i], fmt.Sprintf("%d", x), fmt.Sprintf("yac%d", s)) + yac.lex.Cmd("train", word[i], x, yac.name(s)) } - c = byte(x) - } else { - c = byte(x) } - state := yac.mat[s][c] - yac.Pulse.Log("debug", nil, "GET(%d, %d): %v", s, c, state) - if state == nil { - state = &State{} - yac.Pulse.Capi("nnode", 1) + c := byte(x) + state := &State{} + if yac.mat[s][c] != nil { + *state = *yac.mat[s][c] + } else { + yac.Capi("nnode", 1) } + yac.Log("debug", nil, "GET(%d, %d): %v \033[31m(%s)\033[0m", s, c, state, word[i]) if state.next == 0 { + state.next = yac.Capi("nline", 1) - 1 yac.mat = append(yac.mat, map[byte]*State{}) - state.next = yac.Pulse.Capi("nline", 1) - 1 for i := 0; i < yac.Capi("nlang"); i++ { yac.mat[state.next][byte(i)] = nil } sn = append(sn, false) } sn[state.next] = true - - if x, ok := yac.state[*state]; !ok { - yac.Pulse.Capi("nreal", 1) - yac.state[*state] = state - } else { - yac.mat[s][c] = x - } yac.mat[s][c] = state - yac.Pulse.Log("debug", nil, "SET(%d, %d): %v", s, c, state) - ends = append(ends, state) - point = append(point, state) - if s > begin { - begin = s - } - + ends = append(ends, &Point{s, c}) + points = append(points, &Point{s, c}) + yac.Log("debug", nil, "SET(%d, %d): %v", s, c, state) } } next: - if !mul { + if !m { ss = ss[:0] for s, b := range sn { if sn[s] = false; b { @@ -163,7 +141,7 @@ func (yac *YAC) train(page, hash int, word []string) ([]*State, int) { // {{{ } for _, n := range ss { - if n < yac.Pulse.Capi("nlang") || n >= len(yac.mat) { + if n < yac.Capi("nlang") || n >= len(yac.mat) { continue } @@ -175,33 +153,41 @@ func (yac *YAC) train(page, hash int, word []string) ([]*State, int) { // {{{ } } if void { - yac.Pulse.Log("debug", nil, "DEL: %d %d", yac.Pulse.Capi("nline"), n) - yac.Pulse.Capi("nline", 0, n) + yac.Log("debug", nil, "DEL: %d %d", yac.Capi("nline")-1, yac.Capi("nline", 0, n)) yac.mat = yac.mat[:n] } } for _, n := range ss { - for _, s := range point { - if s.next == n { - yac.Pulse.Log("debug", nil, "GET: %v", s) - if s.next >= len(yac.mat) { - s.next = 0 + for _, p := range points { + state := &State{} + *state = *yac.mat[p.s][p.c] + + if state.next == n { + yac.Log("debug", nil, "GET(%d, %d): %v", p.s, p.c, state) + if state.next >= len(yac.mat) { + state.next = 0 } if hash > 0 { - s.hash = hash + state.hash = hash } - yac.Pulse.Log("debug", nil, "SET: %v", s) + yac.Log("debug", nil, "SET(%d, %d): %v", p.s, p.c, state) + } + + if x, ok := yac.state[*state]; ok { + yac.mat[p.s][p.c] = x + } else { + yac.state[*state] = state + yac.mat[p.s][p.c] = state + yac.Capi("nreal", 1) } } - } - return ends, skip + return len(word), points, ends } -// }}} -func (yac *YAC) parse(m *ctx.Message, page, void int, line string) ([]string, string) { // {{{ +func (yac *YAC) parse(m *ctx.Message, cli *ctx.Context, page, void int, line string) (*ctx.Context, string, []string) { level := m.Capi("level", 1) m.Log("debug", nil, "%s\\%d %s(%d):", m.Cap("label")[0:level], level, yac.word[page], page) @@ -209,35 +195,34 @@ func (yac *YAC) parse(m *ctx.Message, page, void int, line string) ([]string, st hash, word := 0, []string{} for star, s := 0, page; s != 0 && len(line) > 0; { - lex := yac.lex.Spawn(yac.lex.Target()) - lex.Cmd("parse", line, fmt.Sprintf("yac%d", void)) - line = lex.Meta["result"][2] + line = yac.lex.Cmd("parse", line, yac.name(void)).Result(2) + lex := yac.lex.Cmd("parse", line, yac.name(s)) - lex = yac.lex.Spawn(yac.lex.Target()) - lex.Cmd("parse", line, fmt.Sprintf("yac%d", s)) - - c := byte(lex.Geti("result")) + c := byte(lex.Resulti(0)) state := yac.mat[s][c] - if state == nil { + if state != nil { + if key := yac.lex.Cmd("parse", line, "key"); key.Resulti(0) == 0 || len(key.Result(1)) <= len(lex.Result(1)) { + m.Log("debug", nil, "%s|%d get(%d,%d): %v \033[31m(%s)\033[0m", m.Cap("label")[0:level], level, s, c, state, lex.Result(1)) + line, word = lex.Result(2), append(word, lex.Result(1)) + } else { + state = nil + } + } + if state == nil { for i := 0; i < yac.Capi("ncell"); i++ { x := yac.mat[s][byte(i)] if i >= m.Capi("nlang") || x == nil { continue } m.Log("debug", nil, "%s|%d try(%d,%d): %v", m.Cap("label")[0:level], level, s, i, x) - if w, l := yac.parse(m, i, void, line); l != line { + if c, l, w := yac.parse(m, cli, i, void, line); l != line { m.Log("debug", nil, "%s|%d end(%d,%d): %v", m.Cap("label")[0:level], level, s, i, x) + cli, line, state = c, l, x word = append(word, w...) - state = x - line = l break } } - } else { - m.Log("debug", nil, "%s|%d get(%d,%d): %v \033[31m(%s)\033[0m", m.Cap("label")[0:level], level, s, c, state, lex.Meta["result"][1]) - word = append(word, lex.Meta["result"][1]) - line = lex.Meta["result"][2] } if state == nil { @@ -245,8 +230,7 @@ func (yac *YAC) parse(m *ctx.Message, page, void int, line string) ([]string, st continue } - star, s, hash = state.star, state.next, state.hash - if s == 0 { + if s, star, hash = state.next, state.star, state.hash; s == 0 { s, star = star, 0 } } @@ -254,21 +238,24 @@ func (yac *YAC) parse(m *ctx.Message, page, void int, line string) ([]string, st if hash == 0 { word = word[:0] } else { - msg := m.Spawn(yac.Message.Source()).Add("detail", yac.hand[hash], word...) - if msg.Cmd(); msg.Hand { - m.Log("debug", nil, "%s>%d set(%d): \033[31m%v\033[0m->\033[32m%v\033[0m", m.Cap("label")[0:level], level, hash, word, msg.Meta["result"]) + if msg := m.Spawn(cli).Cmd(yac.hand[hash], word); msg.Hand { + m.Log("debug", nil, "%s>%d set(%d): \033[31m%v\033[0m->\033[32m%v\033[0m", + m.Cap("label")[0:level], level, hash, word, msg.Meta["result"]) word = msg.Meta["result"] + + m.Copy(msg, "append", "back", "return") + if cli = msg.Target(); msg.Has("cli") { + cli = msg.Data["cli"].(*ctx.Context) + } } } m.Log("debug", nil, "%s/%d %s(%d):", m.Cap("label")[0:level], level, yac.hand[hash], hash) - level = m.Capi("level", -1) - return word, line + m.Capi("level", -1) + return cli, line, word } -// }}} - -func (yac *YAC) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{ +func (yac *YAC) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { c.Caches = map[string]*ctx.Cache{} c.Configs = map[string]*ctx.Config{} @@ -277,45 +264,47 @@ func (yac *YAC) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server return s } -// }}} -func (yac *YAC) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ - yac.Message = m +func (yac *YAC) Begin(m *ctx.Message, arg ...string) ctx.Server { if yac.Context == Index { Pulse = m } + yac.Context.Master(nil) + yac.Message = m - yac.Caches["ncell"] = &ctx.Cache{Name: "单词上限", Value: "128", Help: "单词上限"} - yac.Caches["nlang"] = &ctx.Cache{Name: "集合上限", Value: "16", Help: "集合上限"} + yac.Caches["ncell"] = &ctx.Cache{Name: "词法上限", Value: "128", Help: "词法集合的最大数量"} + yac.Caches["nlang"] = &ctx.Cache{Name: "语法上限", Value: "16", 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.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: "16", Help: "状态数量"} - yac.Caches["nnode"] = &ctx.Cache{Name: "节点数量", Value: "0", Help: "节点数量"} - yac.Caches["nreal"] = &ctx.Cache{Name: "实点数量", Value: "0", Help: "实点数量"} + yac.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: "16", 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: "嵌套层级", Value: "0", Help: "嵌套层级"} - yac.Caches["label"] = &ctx.Cache{Name: "嵌套标记", Value: "####################", Help: "嵌套层级"} + yac.Caches["level"] = &ctx.Cache{Name: "嵌套层级", Value: "0", Help: "语法解析嵌套层级"} + yac.Caches["label"] = &ctx.Cache{Name: "嵌套标记", Value: "####################", Help: "嵌套层级日志的标记"} + + yac.Caps("debug", true) + yac.Confs("debug", false) 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.Capi("nlang")) yac.state = map[State]*State{} + yac.mat = make([]map[byte]*State, m.Capi("nlang")) return yac } -// }}} -func (yac *YAC) Start(m *ctx.Message, arg ...string) bool { // {{{ +func (yac *YAC) Start(m *ctx.Message, arg ...string) bool { + yac.Context.Master(nil) yac.Message = m return false } -// }}} -func (yac *YAC) Close(m *ctx.Message, arg ...string) bool { // {{{ +func (yac *YAC) Close(m *ctx.Message, arg ...string) bool { switch yac.Context { case m.Target(): case m.Source(): @@ -323,20 +312,24 @@ func (yac *YAC) Close(m *ctx.Message, arg ...string) bool { // {{{ return true } -// }}} - var Pulse *ctx.Message var Index = &ctx.Context{Name: "yac", Help: "语法中心", Caches: map[string]*ctx.Cache{}, Configs: map[string]*ctx.Config{}, Commands: map[string]*ctx.Command{ "train": &ctx.Command{Name: "train page hash word...", Help: "添加语法规则, page: 语法集合, hash: 语句类型, word: 语法模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { // {{{ + 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.Capi("nlang"), "语法集合过多") + yac.mat[page] = map[byte]*State{} + for i := 0; i < yac.Capi("nlang"); i++ { + yac.mat[page][byte(i)] = nil + } } hash, ok := yac.hash[arg[1]] @@ -348,23 +341,80 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", if yac.lex == nil { lex := m.Find("lex", true) - lex.Start("lyacc", "语法词法") + if lex.Cap("status") == "start" { + lex.Start(yac.Context.Name+"lex", "语法词法") + } else { + lex.Target().Start(lex) + } yac.lex = lex } - yac.seed = append(yac.seed, &Seed{page, hash, arg[2:]}) - yac.Capi("nseed", 1) + yac.train(page, hash, arg[2:]) - } // }}} + yac.seed = append(yac.seed, &Seed{page, hash, arg[2:]}) + yac.Cap("stream", fmt.Sprintf("%d,%s,%s", yac.Capi("nseed", 1), yac.Cap("npage"), yac.Cap("nhash"))) + } }}, "parse": &ctx.Command{Name: "parse page void word...", Help: "解析语句, page: 语法集合, void: 空白语法集合, word: 语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { // {{{ + if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { page, ok := yac.page[arg[0]] m.Assert(ok) void, ok := yac.page[arg[1]] m.Assert(ok) - word, rest := yac.parse(m, page, void, strings.Join(arg[2:], " ")) - m.Add("result", rest, word...) - } // }}} + + if cli, ok := m.Data["cli"].(*ctx.Context); m.Assert(ok) { + cli, rest, word := yac.parse(m, cli, page, void, strings.Join(arg[2:], " ")) + m.Data["cli"] = cli + m.Result(0, rest, word) + } + } + }}, + "info": &ctx.Command{Name: "info", Help: "显示缓存", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { + for i, v := range yac.seed { + m.Echo("seed: %d %v\n", i, v) + } + for i, v := range yac.page { + m.Echo("page: %s %d\n", i, v) + } + for i, v := range yac.hash { + m.Echo("hash: %s %d\n", i, v) + } + for i, v := range yac.state { + m.Echo("node: %v %v\n", i, v) + } + for i, v := range yac.mat { + for k, v := range v { + if v != nil { + m.Echo("node: %s(%d,%d): %v\n", yac.name(i), i, k, v) + } + } + } + } + }}, + "check": &ctx.Command{Name: "check page void word...", Help: "解析语句, page: 语法集合, void: 空白语法集合, word: 语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { + set := map[*State]bool{} + nreal := 0 + for _, v := range yac.state { + nreal++ + set[v] = true + } + + nnode := 0 + for i, v := range yac.mat { + for j, x := range v { + if x == nil && int(j) < m.Capi("nlang") { + continue + } + nnode++ + + if _, ok := set[x]; !ok { + m.Log("fuck", nil, "not in %d %d %v %p", i, j, x, x) + } + } + } + m.Log("fuck", nil, "node: %d real: %d", nnode, nreal) + } }}, }, } diff --git a/src/example/bench.go b/src/example/bench.go index 533f7327..9137ac0b 100644 --- a/src/example/bench.go +++ b/src/example/bench.go @@ -12,6 +12,7 @@ import ( _ "context/web" _ "context/lex" + _ "context/log" _ "context/yac" "os"