From 55fefaf130138c20246b2d485ec927e6d7ae6360 Mon Sep 17 00:00:00 2001 From: shaoying Date: Mon, 7 Jan 2019 09:30:29 +0800 Subject: [PATCH] opt lex&yac --- src/contexts/cli/cli.go | 36 ++++--- src/contexts/ctx/ctx.go | 86 +++++++++++------ src/contexts/gdb/gdb.go | 112 ++++++++++++---------- src/contexts/lex/lex.go | 45 ++++----- src/contexts/log/log.go | 130 +++++++++++-------------- src/contexts/nfs/nfs.go | 99 +++++++++++++++---- src/contexts/yac/yac.go | 207 +++++++++++++++++----------------------- src/toolkit/kit.go | 51 +++++++--- 8 files changed, 422 insertions(+), 344 deletions(-) diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index c87fb8fc..86cf6172 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -133,6 +133,7 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { } if m.Option("prompt", cmd.Cmd().Conf("prompt")); cmd.Has("return") { + kit.Log("error", "waht ?????") m.Options("scan_end", true) m.Target().Close(m) } @@ -157,8 +158,8 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", "nshell": &ctx.Cache{Name: "nshell", Value: "0", Help: "终端数量"}, }, Configs: map[string]*ctx.Config{ - "init.shy": &ctx.Config{Name: "init.shy", Value: "etc/init.shy", Help: "启动脚本"}, - "exit.shy": &ctx.Config{Name: "exit.shy", Value: "etc/exit.shy", Help: "启动脚本"}, + "init_shy": &ctx.Config{Name: "init_shy", Value: "etc/init.shy", Help: "启动脚本"}, + "exit_shy": &ctx.Config{Name: "exit_shy", Value: "etc/exit.shy", Help: "启动脚本"}, "time_unit": &ctx.Config{Name: "time_unit", Value: "1000", Help: "时间倍数"}, "time_close": &ctx.Config{Name: "time_close(open/close)", Value: "open", Help: "时间区间"}, @@ -620,31 +621,30 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Add("append", "return", arg[1:]) return }}, - "source": &ctx.Command{Name: "source [stdio [init.shy [exit.shy]]]|[filename [async]]|string", Help: "解析脚本, filename: 文件名, async: 异步执行", + "source": &ctx.Command{Name: "source [stdio [init_shy [exit_shy]]]|[filename [async]]|string", Help: "解析脚本, filename: 文件名, async: 异步执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if _, ok := m.Source().Server.(*CLI); ok { - msg := m.Spawn(c) - m.Copy(msg, "target") + m.Copy(m.Spawn(c), "target") } - m.Cmd("yac.init") - m.Cmd("aaa.init") - if len(arg) == 0 || arg[0] == "stdio" { - m.Sess("log", false).Cmd("init") + if (len(arg) == 0 || arg[0] == "stdio") && m.Target().Name == "cli" { + // 启动终端 + m.Cmd("yac.init") + if m.Start("shy", "shell", "stdio"); m.Cmds("nfs.path", m.Confx("init_shy", arg, 1)) { + // msg := m.Spawn().Add("option", "scan_end", "false").Cmd("source", m.Conf("init_shy")) - if m.Start("shy", "shell", "stdio"); m.Sess("nfs").Cmd("path", m.Confx("init.shy", arg, 1)).Results(0) { - msg := m.Spawn().Add("option", "scan_end", "false").Cmd("source", m.Conf("init.shy")) - m.Cap("ps_target", msg.Append("last_target")) - m.Option("prompt", m.Conf("prompt")) - m.Find("nfs.stdio").Cmd("prompt") + // m.Cap("ps_target", msg.Append("last_target")) + // m.Option("prompt", m.Conf("prompt")) + // m.Find("nfs.stdio").Cmd("prompt") } - if m.Wait(); m.Sess("nfs").Cmd("path", m.Confx("exit.shy", arg, 2)).Results(0) { - m.Spawn().Add("option", "scan_end", "false").Cmd("source", m.Conf("exit.shy")) + if m.Wait(); m.Cmds("nfs.path", m.Confx("exit_shy", arg, 2)) { + m.Spawn().Add("option", "scan_end", "false").Cmd("source", m.Conf("exit_shy")) } return } - if m.Sess("nfs").Cmd("path", arg[0]).Results(0) && arg[0] != "bench" { + // 运行脚本 + if m.Cmds("nfs.path", arg[0]) && strings.HasSuffix(arg[0], ".shy") { m.Start(fmt.Sprintf("shell%d", m.Capi("nshell", 1)), "shell", arg...) if len(arg) < 2 || arg[1] != "async" { m.Wait() @@ -1138,8 +1138,6 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", return } - m.Log("what", "wath %v", m.Spawn().Cmd("time")) - now := int64(m.Sess("cli").Cmd("time").Appendi("timestamp")) begin := now if len(arg) > 0 && arg[0] == "begin" { diff --git a/src/contexts/ctx/ctx.go b/src/contexts/ctx/ctx.go index eaf93114..ffba1e69 100644 --- a/src/contexts/ctx/ctx.go +++ b/src/contexts/ctx/ctx.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "html/template" + "io/ioutil" "regexp" "strconv" "strings" @@ -106,6 +107,12 @@ func (c *Context) Begin(m *Message, arg ...string) *Context { c.requests = append(c.requests, m) m.source.sessions = append(m.source.sessions, m) + switch v := m.Gdb("context", "begin", c.Name).(type) { + case string: + kit.Log("error", "fuck %v", v) + case nil: + } + m.Log("begin", "%d context %v %v", m.Capi("ncontext", 1), m.Meta["detail"], m.Meta["option"]) for k, x := range c.Configs { if x.Hand != nil { @@ -124,17 +131,26 @@ func (c *Context) Start(m *Message, arg ...string) bool { if len(arg) > 0 && arg[0] == "sync" { sync, arg = true, arg[1:] } - m.Set("detail", arg) + if len(arg) > 0 { + m.Set("detail", arg) + } c.requests = append(c.requests, m) m.source.sessions = append(m.source.sessions, m) + + switch v := m.Gdb("context", "start", c.Name).(type) { + case string: + kit.Log("error", "fuck %v", v) + case nil: + } + if m.Hand = true; m.Cap("status") == "start" { return true } c.exit = make(chan bool, 2) go m.TryCatch(m, true, func(m *Message) { - m.Log(m.Cap("status", "start"), "%d server %v %v", m.root.Capi("nserver", 1), m.Meta["detail"], m.Meta["option"]) + m.Log(m.Cap("status", "start"), "%d server %v %v", m.Capi("nserver", 1), m.Meta["detail"], m.Meta["option"]) c.message = m if c.exit <- false; c.Server == nil || c.Server.Start(m, m.Meta["detail"]...) { @@ -260,7 +276,7 @@ func (c *Context) BackTrace(m *Message, hand func(m *Message) (stop bool)) *Cont } type LOGGER interface { - LOG(*Message, string, string) + Log(*Message, string, string, ...interface{}) } type DEBUG interface { Wait(*Message, ...interface{}) interface{} @@ -288,18 +304,17 @@ type Message struct { } func (m *Message) Log(action string, str string, arg ...interface{}) *Message { - kit.Errorf(fmt.Sprintf("%s %s %s", m.Format(), action, fmt.Sprintf(str, arg...))) - return m - if action == "error" { - kit.Errorf(str, arg...) - } - if l := m.Sess("log", false); l != nil { if log, ok := l.target.Server.(LOGGER); ok { - log.LOG(m, action, fmt.Sprintf(str, arg...)) + log.Log(m, action, str, arg...) + return m } } + if action == "error" { + kit.Log("error", fmt.Sprintf("%s %s %s", m.Format(), action, fmt.Sprintf(str, arg...))) + } + return m } func (m *Message) Gdb(arg ...interface{}) interface{} { @@ -323,7 +338,7 @@ func (m *Message) Spawn(arg ...interface{}) *Message { msg := &Message{ time: time.Now(), - code: m.root.Capi("nmessage", 1), + code: m.Capi("nmessage", 1), source: m.target, target: c, message: m, @@ -385,6 +400,15 @@ func (m *Message) Format(arg ...string) string { meta = append(meta, fmt.Sprintf("%v", m.Meta["append"])) case "result": meta = append(meta, fmt.Sprintf("%v", m.Meta["result"])) + case "full": + meta = append(meta, fmt.Sprintf("%s\n", m.Format("time", "ship"))) + meta = append(meta, fmt.Sprintf("detail: %s\n", m.Format("detail"))) + meta = append(meta, fmt.Sprintf("option: %s\n", m.Format("option"))) + for k, v := range m.Meta { + meta = append(meta, fmt.Sprintf(" %s: %v\n", k, v)) + } + meta = append(meta, fmt.Sprintf("append: %s\n", m.Format("append"))) + meta = append(meta, fmt.Sprintf("result: %s\n", m.Format("result"))) } } return strings.Join(meta, " ") @@ -478,7 +502,7 @@ func (m *Message) Get(key string, arg ...interface{}) string { } index = (index+2)%(len(meta)+2) - 2 - if index > 0 && index < len(meta) { + if index >= 0 && index < len(meta) { return meta[index] } } @@ -1018,7 +1042,10 @@ func (m *Message) Match(key string, spawn bool, hand func(m *Message, s *Context context = append(context, m.source) for _, s := range context { - for c := s; c != nil && !hand(m, s, c, key) && c != c.context; c = c.context { + for c := s; c != nil; c = c.context { + if hand(m, s, c, key) { + return m + } } } return m @@ -1142,7 +1169,7 @@ func (m *Message) Cmd(args ...interface{}) *Message { m = m.Match(key, true, func(m *Message, s *Context, c *Context, key string) bool { if x, ok := c.Commands[key]; ok && x.Hand != nil { m.TryCatch(m, true, func(m *Message) { - m.Log("cmd", "%s:%s %s %v %v", c.Name, s.Name, key, arg, m.Meta["option"]) + m.Log("cmd", "%s %s %v %v", c.Name, key, arg, m.Meta["option"]) if args := []string{}; x.Form != nil { for i := 0; i < len(arg); i++ { @@ -1166,7 +1193,12 @@ func (m *Message) Cmd(args ...interface{}) *Message { } m.Hand = true - x.Hand(m, c, key, arg...) + switch v := m.Gdb("command", key, arg).(type) { + case string: + m.Echo(v) + case nil: + x.Hand(m, c, key, arg...) + } }) } return m.Hand @@ -1245,11 +1277,11 @@ func (m *Message) Confx(key string, args ...interface{}) string { if args = args[1:]; len(args) > 0 { format, args = kit.Format(args[0]), args[1:] } - arg := []interface{}{format, value} for _, v := range args { - args = append(args, v) + arg = append(arg, v) } + return kit.Format(arg...) } func (m *Message) Confs(key string, arg ...interface{}) bool { @@ -1318,16 +1350,6 @@ func (m *Message) Capi(key string, arg ...interface{}) int { return n } func (m *Message) Cap(key string, arg ...interface{}) string { - if len(arg) == 0 { - if val, ok := m.Gdb("cache", "read", key).(string); ok { - return val - } - } else { - if val, ok := m.Gdb("cache", "write", key, arg[0]).(string); ok { - return val - } - } - var cache *Cache m.Match(key, false, func(m *Message, s *Context, c *Context, key string) bool { if x, ok := c.Caches[key]; ok { @@ -3157,6 +3179,9 @@ func (ctx *CTX) Begin(m *Message, arg ...string) Server { return ctx } func (ctx *CTX) Start(m *Message, arg ...string) bool { + gdb := m.Sess("gdb") + gdb.Target().Start(gdb) + m.Cmd("cli.source", arg) return false } @@ -3169,7 +3194,10 @@ func Start(args ...string) bool { args = append(args, os.Args[1:]...) } - if Index.Begin(Pulse, args...); Index.Start(Pulse, args...) { - } + ioutil.WriteFile(fmt.Sprintf("bench.pid"), []byte(kit.Format(os.Getpid())), 0666) + + Index.Begin(Pulse, args...) + Index.Start(Pulse, args...) + Index.Close(Pulse, args...) return false } diff --git a/src/contexts/gdb/gdb.go b/src/contexts/gdb/gdb.go index 3b512622..8a8a8488 100644 --- a/src/contexts/gdb/gdb.go +++ b/src/contexts/gdb/gdb.go @@ -2,6 +2,8 @@ package gdb import ( "contexts/ctx" + "fmt" + "io/ioutil" "os" "os/signal" "syscall" @@ -16,7 +18,7 @@ type GDB struct { } func (gdb *GDB) Value(m *ctx.Message, arg ...interface{}) bool { - if value, ok := kit.Chain(gdb.Configs["debug"].Value, append(arg, "value")).(map[string]interface{}); ok { + if value, ok := kit.Chain(gdb.Configs["debug"].Value, kit.Trans(arg, "value")).(map[string]interface{}); ok { if !kit.Right(value["enable"]) { return false } @@ -34,25 +36,35 @@ func (gdb *GDB) Value(m *ctx.Message, arg ...interface{}) bool { } return false } -func (gdb *GDB) Wait(m *ctx.Message, arg ...interface{}) interface{} { +func (gdb *GDB) Wait(msg *ctx.Message, arg ...interface{}) interface{} { + m := gdb.Message() + if m.Cap("status") != "start" { + return nil + } + for i := len(arg); i > 0; i-- { if gdb.Value(m, arg[:i]...) { if result := kit.Chain(kit.Chain(gdb.Configs["debug"].Value, arg[:i]), []string{"value", "result"}); result != nil { m.Log("error", "done %d %v", len(arg[:i]), arg) return result } + if arg[0] == "trace" { + m.Log("error", "%s", m.Format("full")) + } m.Log("error", "wait %d %v", len(arg[:i]), arg) result := <-gdb.wait m.Log("error", "done %d %v %v", len(arg[:i]), arg, result) return result } } - return <-gdb.wait - return nil } func (gdb *GDB) Goon(result interface{}, arg ...interface{}) { m := gdb.Message() + if m.Cap("status") != "start" { + return + } + m.Log("error", "goon %v %v", arg, result) gdb.wait <- result } @@ -66,70 +78,74 @@ func (gdb *GDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server return s } func (gdb *GDB) Begin(m *ctx.Message, arg ...string) ctx.Server { - gdb.goon = make(chan os.Signal, 10) - gdb.wait = make(chan interface{}, 10) - m.Log("debug", "pid %d", os.Getpid()) - - signal.Notify(gdb.goon, syscall.Signal(19)) - go func() { - for { - select { - case sig := <-gdb.goon: - m.Log("error", "signal %v", sig) - gdb.Goon("hello", "cache", "read", "value") - } - } - }() - return gdb } func (gdb *GDB) Start(m *ctx.Message, arg ...string) bool { - return false + gdb.goon = make(chan os.Signal, 10) + gdb.wait = make(chan interface{}, 10) + m.Log("error", "pid %d", os.Getpid()) + kit.Log("error", "pid %d", os.Getpid()) + signal.Notify(gdb.goon, syscall.Signal(19)) + ioutil.WriteFile(fmt.Sprintf("%s.pid", gdb.Name), []byte(kit.Format(os.Getpid())), 0666) + for { + select { + case sig := <-gdb.goon: + m.Log("error", "signal %v", sig) + gdb.Goon(nil, "cache", "read", "value") + } + } + return true } func (gdb *GDB) Close(m *ctx.Message, arg ...string) bool { switch gdb.Context { case m.Target(): case m.Source(): } - return true + return false } var Index = &ctx.Context{Name: "gdb", Help: "调试中心", Caches: map[string]*ctx.Cache{}, Configs: map[string]*ctx.Config{ - "debug": &ctx.Config{Name: "debug", Value: map[string]interface{}{ - "value": map[string]interface{}{ - "enable": true, + "debug": &ctx.Config{Name: "debug", Value: map[string]interface{}{"value": map[string]interface{}{"enable": false}, + "trace": map[string]interface{}{"value": map[string]interface{}{"enable": true}}, + "context": map[string]interface{}{"value": map[string]interface{}{"enable": false}, + "begin": map[string]interface{}{"value": map[string]interface{}{"enable": false}}, + "start": map[string]interface{}{"value": map[string]interface{}{"enable": false}}, }, - "command": map[string]interface{}{ - "value": map[string]interface{}{ - "enable": true, - }, + "command": map[string]interface{}{"value": map[string]interface{}{"enable": false}, + "demo": map[string]interface{}{"value": map[string]interface{}{"enable": true}}, }, - "config": map[string]interface{}{ - "value": map[string]interface{}{ - "enable": true, - }, - }, - "cache": map[string]interface{}{ - "value": map[string]interface{}{ - "enable": true, - }, - "read": map[string]interface{}{ - "value": map[string]interface{}{ - "enable": true, - }, - "ncontext": map[string]interface{}{ - "value": map[string]interface{}{ - "enable": true, - "result": "hello", - }, - }, + "config": map[string]interface{}{"value": map[string]interface{}{"enable": true}}, + "cache": map[string]interface{}{"value": map[string]interface{}{"enable": false}, + "read": map[string]interface{}{"value": map[string]interface{}{"enable": false}, + "ncontext": map[string]interface{}{"value": map[string]interface{}{"enable": false}}, }, }, }}, }, - Commands: map[string]*ctx.Command{}, + Commands: map[string]*ctx.Command{ + "demo": &ctx.Command{Name: "wait arg...", Help: "等待调试", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + m.Echo("hello world") + return + }}, + "wait": &ctx.Command{Name: "wait arg...", Help: "等待调试", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + if gdb, ok := m.Target().Server.(*GDB); m.Assert(ok) { + switch v := gdb.Wait(m, arg).(type) { + case string: + m.Echo(v) + case nil: + } + } + return + }}, + "goon": &ctx.Command{Name: "goon arg...", Help: "继续运行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + if gdb, ok := m.Target().Server.(*GDB); m.Assert(ok) { + gdb.Goon(arg) + } + return + }}, + }, } func init() { diff --git a/src/contexts/lex/lex.go b/src/contexts/lex/lex.go index 60eadc8b..c61bd876 100644 --- a/src/contexts/lex/lex.go +++ b/src/contexts/lex/lex.go @@ -40,6 +40,9 @@ func (lex *LEX) index(m *ctx.Message, hash string, h string) int { } if x, e := strconv.Atoi(h); e == nil { + if hash == "nhash" { + lex.hash[hash] = x + } m.Assert(hash != "npage" || x < m.Capi("npage")) return x } @@ -49,7 +52,7 @@ func (lex *LEX) index(m *ctx.Message, hash string, h string) int { } which[h] = m.Capi(hash, 1) - m.Assert(hash != "npage" || m.Capi("npage") < m.Capi("nlang")) + m.Assert(hash != "npage" || m.Capi("npage") < m.Confi("info", "nlang")) return which[h] } func (lex *LEX) charset(c byte) []byte { @@ -59,10 +62,11 @@ func (lex *LEX) charset(c byte) []byte { 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)) ss := []int{page} - cn := make([]bool, m.Capi("ncell")) - cc := make([]byte, 0, m.Capi("ncell")) + cn := make([]bool, m.Confi("info", "ncell")) + cc := make([]byte, 0, m.Confi("info", "ncell")) sn := make([]bool, m.Capi("nline")) points := []*Point{} @@ -156,7 +160,7 @@ func (lex *LEX) train(m *ctx.Message, page int, hash int, seed []byte) int { } if state.next == 0 { - if line == 0 || !m.Confs("compact") { + if line == 0 || !m.Confs("info", "compact") { lex.mat = append(lex.mat, make(map[byte]*State)) line = m.Capi("nline", 1) - 1 sn = append(sn, false) @@ -180,12 +184,14 @@ func (lex *LEX) train(m *ctx.Message, page int, hash int, seed []byte) int { } for _, s := range ss { - if s < m.Capi("nlang") || s >= len(lex.mat) { + if s < m.Confi("info", "nlang") || s >= len(lex.mat) { continue } if len(lex.mat[s]) == 0 { - m.Log("debug", "DEL: %d-%d", m.Capi("nline")-1, m.Capi("nline", 0, s)) + last := m.Capi("nline") - 1 + m.Cap("nline", "0") + m.Log("debug", "DEL: %d-%d", last, m.Capi("nline", s)) lex.mat = lex.mat[:s] } } @@ -213,9 +219,11 @@ func (lex *LEX) train(m *ctx.Message, page int, hash int, seed []byte) int { } } + m.Log("debug", "%s %s npage: %v nhash: %v nseed: %v", "train", "lex", m.Capi("npage"), m.Capi("nhash"), m.Capi("nseed")) return hash } func (lex *LEX) parse(m *ctx.Message, page int, line []byte) (hash int, rest []byte, word []byte) { + m.Log("debug", "%s %s page: %v line: %v", "parse", "lex", page, line) pos := 0 for star, s := 0, page; s != 0 && pos < len(line); pos++ { @@ -231,11 +239,11 @@ func (lex *LEX) parse(m *ctx.Message, page int, line []byte) (hash int, rest []b } state := lex.mat[s][c] - m.Log("debug", "(%d,%d): %v", s, c, state) if state == nil { s, star, pos = star, 0, pos-1 continue } + m.Log("debug", "GET (%d,%d): %v", s, c, state) word = append(word, c) @@ -256,6 +264,8 @@ func (lex *LEX) parse(m *ctx.Message, page int, line []byte) (hash int, rest []b pos, word = 0, word[:0] } rest = line[pos:] + + m.Log("debug", "%s %s hash: %v word: %v rest: %v", "parse", "lex", hash, word, rest) return } @@ -268,30 +278,18 @@ 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 { - lex.Caches["ncell"] = &ctx.Cache{Name: "字符上限", Value: "128", Help: "字符集合的最大数量"} - lex.Caches["nlang"] = &ctx.Cache{Name: "词法上限", Value: "64", 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: "64", Help: "状态机状态的数量"} + lex.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: m.Conf("info", "nlang"), Help: "状态机状态的数量"} lex.Caches["nnode"] = &ctx.Cache{Name: "节点数量", Value: "0", Help: "状态机连接的逻辑数量"} lex.Caches["nreal"] = &ctx.Cache{Name: "实点数量", Value: "0", Help: "状态机连接的存储数量"} - lex.Configs["compact"] = &ctx.Config{Name: "紧凑模式", Value: "true", Help: "词法状态的共用"} - - if len(arg) > 0 { - if _, e := strconv.Atoi(arg[0]); e == nil { - m.Cap("nlang", arg[0]) - m.Cap("nline", arg[0]) - } - } - lex.page = map[string]int{"nil": 0} lex.hash = map[string]int{"nil": 0} - lex.mat = make([]map[byte]*State, m.Capi("nlang")) + lex.mat = make([]map[byte]*State, m.Confi("info", "nlang")) lex.state = make(map[State]*State) lex.char = map[byte][]byte{ @@ -323,6 +321,7 @@ var Index = &ctx.Context{Name: "lex", Help: "词法中心", Configs: map[string]*ctx.Config{ "npage": &ctx.Config{Name: "npage", Value: "1", Help: "npage"}, "nhash": &ctx.Config{Name: "nhash", Value: "1", Help: "npage"}, + "info": &ctx.Config{Name: "info", Value: map[string]interface{}{"compact": true, "ncell": 128, "nlang": 64}, Help: "嵌套层级日志的标记"}, }, Commands: map[string]*ctx.Command{ "spawn": &ctx.Command{Name: "spawn", Help: "添加词法规则", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { @@ -338,6 +337,8 @@ var Index = &ctx.Context{Name: "lex", Help: "词法中心", if lex.mat[page] == nil { lex.mat[page] = map[byte]*State{} } + m.Cap("npage", len(lex.page)) + m.Cap("nhash", len(lex.hash)) m.Result(0, lex.train(m, page, hash, []byte(arg[0]))) lex.seed = append(lex.seed, &Seed{page, hash, arg[0]}) @@ -385,7 +386,7 @@ var Index = &ctx.Context{Name: "lex", Help: "词法中心", m.Table() case "mat": for _, v := range lex.mat { - for j := byte(0); j < byte(m.Capi("ncell")); j++ { + for j := byte(0); j < byte(m.Confi("info", "ncell")); j++ { s := v[j] if s == nil { m.Add("append", fmt.Sprintf("%c", j), "") diff --git a/src/contexts/log/log.go b/src/contexts/log/log.go index b900f753..bbed4645 100644 --- a/src/contexts/log/log.go +++ b/src/contexts/log/log.go @@ -2,42 +2,59 @@ package log import ( "contexts/ctx" + "toolkit" + "fmt" "os" - "strings" - "time" ) type LOG struct { - out *os.File + file map[string]*os.File *ctx.Context } -func (log *LOG) LOG(msg *ctx.Message, action string, str string) { - m := log.Context.Message() +func (log *LOG) Value(msg *ctx.Message, arg ...interface{}) map[string]interface{} { + args := append(kit.Trans(arg...), "value") - if m.Confs("silent", action) { - return - } - if msg.Target() == nil { - return - } - if m.Confs("module", fmt.Sprintf("%s.%s", msg.Target().Name, action)) { - return - } + if value, ok := kit.Chain(log.Configs["output"].Value, args).(map[string]interface{}); ok { + if kit.Right(value["source"]) && kit.Format(value["source"]) != msg.Source().Name { + return nil + } - color := 0 - if m.Confs("flag_color") && m.Confs("color", action) { - color = m.Confi("color", action) + if kit.Right(value["target"]) && kit.Format(value["target"]) != msg.Target().Name { + return nil + } + + // kit.Log("error", "value %v %v", kit.Format(args), kit.Format(value)) + return value } + return nil +} +func (log *LOG) Log(msg *ctx.Message, action string, str string, arg ...interface{}) { + m := log.Message() + m.Capi("nlog", 1) - date := time.Now().Format(m.Conf("flag_time")) - action = fmt.Sprintf("%d %s(%s->%s)", msg.Code(), action, msg.Source().Name, msg.Target().Name) + args := kit.Trans(arg...) + for _, v := range []string{action, "bench"} { + for i := len(args); i >= 0; i-- { + if value := log.Value(m, append([]string{v}, args[:i]...)); kit.Right(value) && kit.Right(value["file"]) { + name := kit.Format(value["file"]) + file, ok := log.file[name] + if !ok { + if f, e := os.Create(name); e == nil { + file, log.file[name] = f, f + kit.Log("error", "%s log file %s", "open", name) + } else { + kit.Log("error", "%s log file %s %s", "open", name, e) + continue + } + } - if color > 0 { - log.out.WriteString(fmt.Sprintf("%s\033[%dm%s %s\033[0m\n", date, color, action, str)) - } else { - log.out.WriteString(fmt.Sprintf("%s%s %s\n", date, action, str)) + fmt.Fprintln(file, fmt.Sprintf("%d %s %s%s %s%s", m.Capi("nout", 1), msg.Format(kit.Trans(value["meta"])...), + kit.Format(value["color_begin"]), action, fmt.Sprintf(str, arg...), kit.Format(value["color_end"]))) + return + } + } } } @@ -50,9 +67,7 @@ func (log *LOG) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server return s } func (log *LOG) Begin(m *ctx.Message, arg ...string) ctx.Server { - log.Configs["flag_color"] = &ctx.Config{Name: "flag_color", Value: "true", Help: "模块日志输出颜色"} - log.Configs["flag_time"] = &ctx.Config{Name: "flag_time", Value: "2006/01/02 15:04:05 ", Help: "模块日志输出颜色"} - log.Configs["bench.log"] = &ctx.Config{Name: "bench.log", Value: "bench.log", Help: "模块日志输出的文件"} + log.file = map[string]*os.File{} return log } func (log *LOG) Start(m *ctx.Message, arg ...string) bool { @@ -63,63 +78,30 @@ func (log *LOG) Close(m *ctx.Message, arg ...string) bool { case m.Target(): case m.Source(): } - return true + return false } -var Pulse *ctx.Message var Index = &ctx.Context{Name: "log", Help: "日志中心", Caches: map[string]*ctx.Cache{ - "nlog": &ctx.Cache{Name: "nlog", Value: "0", Help: "日志屏蔽类型"}, + "nlog": &ctx.Cache{Name: "nlog", Value: "0", Help: "日志调用数量"}, + "nout": &ctx.Cache{Name: "nout", Value: "0", Help: "日志输出数量"}, }, Configs: map[string]*ctx.Config{ - "silent": &ctx.Config{Name: "silent", Value: map[string]interface{}{"cb": true, "find": true}, Help: "日志屏蔽类型"}, - "module": &ctx.Config{Name: "module", Value: map[string]interface{}{ - "log": map[string]interface{}{"cmd": true}, - "lex": map[string]interface{}{"cmd": true, "debug": true}, - "yac": map[string]interface{}{"cmd": true, "debug": true}, - "matrix1": map[string]interface{}{"cmd": true, "debug": true}, - }, Help: "日志屏蔽模块"}, - "color": &ctx.Config{Name: "color", Value: map[string]interface{}{ - "debug": 0, "error": 31, "check": 31, - "cmd": 32, "conf": 33, - "search": 35, "find": 35, "cb": 35, "lock": 35, - "begin": 36, "start": 36, "close": 36, - }, Help: "日志输出颜色"}, - "log_name": &ctx.Config{Name: "log_name", Value: "dump", Help: "日志屏蔽类型"}, + "output": &ctx.Config{Name: "output", Value: map[string]interface{}{ + "error": map[string]interface{}{"value": map[string]interface{}{"file": "error.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}}, + "bench": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}}}, + "begin": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}}, + "start": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}}, + "cmd": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"}, + "lex": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"}}, + }, + "debug": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}}}, + }, Help: "日志输出配置"}, }, Commands: map[string]*ctx.Command{ - "init": &ctx.Command{Name: "init file", Help: "输出日志, level: 日志类型, string: 日志内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - if log, ok := m.Target().Server.(*LOG); ok { - log.out = m.Sess("nfs").Cmd("open", m.Confx("bench.log", arg, 0)).Optionv("out").(*os.File) - log.out.Truncate(0) - fmt.Fprintln(log.out, "\n\n") - } - return - }}, "log": &ctx.Command{Name: "log level string...", Help: "输出日志, level: 日志类型, string: 日志内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - if log, ok := m.Target().Server.(*LOG); m.Assert(ok) && log.out != nil { - if m.Confs("silent", arg[0]) { - return - } - msg, ok := m.Optionv("msg").(*ctx.Message) - if !ok { - msg = m - } - if m.Confs("module", fmt.Sprintf("%s.%s", msg.Target().Name, arg[0])) { - return - } - color := 0 - if m.Confs("flag_color") && m.Confs("color", arg[0]) { - color = m.Confi("color", arg[0]) - } - date := time.Now().Format(m.Conf("flag_time")) - action := fmt.Sprintf("%d %s(%s->%s)", msg.Code(), arg[0], msg.Source().Name, msg.Target().Name) - cmd := strings.Join(arg[1:], "") - if color > 0 { - log.out.WriteString(fmt.Sprintf("%s\033[%dm%s %s\033[0m\n", date, color, action, cmd)) - } else { - log.out.WriteString(fmt.Sprintf("%s%s %s\n", date, action, cmd)) - } + if log, ok := m.Target().Server.(*LOG); m.Assert(ok) { + log.Log(m, arg[0], arg[1], arg[2:]) } return }}, diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go index 769a0a85..6ab5b4f5 100644 --- a/src/contexts/nfs/nfs.go +++ b/src/contexts/nfs/nfs.go @@ -18,7 +18,7 @@ import ( "os/exec" "path" "regexp" - "runtime" + // "runtime" "sort" "strconv" "strings" @@ -28,8 +28,9 @@ import ( ) type NFS struct { - in *os.File - out *os.File + in *os.File + out *os.File + pages []string width int height int @@ -207,6 +208,8 @@ func (nfs *NFS) color(str string, attr ...int) *NFS { return nfs } func (nfs *NFS) print(str string) bool { + nfs.out.WriteString(str) + return true ls := strings.Split(str, "\n") for i, l := range ls { rest := "" @@ -237,6 +240,9 @@ func (nfs *NFS) print(str string) bool { } func (nfs *NFS) prompt(arg ...string) string { + nfs.out.WriteString("> ") + return "> " + ps := nfs.Option("prompt") if nfs.Caps("windows") { nfs.color(ps) @@ -585,34 +591,80 @@ func (nfs *NFS) Begin(m *ctx.Message, arg ...string) ctx.Server { return nfs } func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { + if len(arg) > 0 && arg[0] == "scan" { + nfs.Caches["ninput"] = &ctx.Cache{Value: "0"} + nfs.Caches["noutput"] = &ctx.Cache{Value: "0"} + nfs.Configs["input"] = &ctx.Config{Value: []interface{}{}} + nfs.Configs["output"] = &ctx.Config{Value: []interface{}{}} + + if nfs.in = m.Optionv("in").(*os.File); m.Has("out") { + nfs.out = m.Optionv("out").(*os.File) + } + + line, bio := "", bufio.NewScanner(nfs) + for nfs.prompt(); !m.Options("scan_end"); nfs.prompt() { + for bio.Scan() { + if line = line + bio.Text(); !strings.HasSuffix(line, "\\") { + break + } + line = strings.TrimSuffix(line, "\\") + } + + m.Confv("input", -2, map[string]interface{}{"time": time.Now().Unix(), "line": line}) + m.Log("debug", "%s %d %d [%s]", "input", m.Capi("ninput", 1), len(line), line) + + for i := m.Capi("ninput") - 1; i < m.Capi("ninput"); i++ { + line = m.Conf("input", []interface{}{i, "line"}) + + msg := m.Spawn(m.Source()).Set("detail", line).Set("option", "file_pos", i) + m.Back(msg) + + lines := strings.Split(strings.Join(msg.Meta["result"], ""), "\n") + for _, line := range lines { + if line != "" { + m.Log("debug", "%s %d %d [%s]", "output", m.Capi("noutput", 1), len(line), line) + m.Confv("output", -2, map[string]interface{}{"time": time.Now().Unix(), "line": line}) + nfs.print(line) + nfs.print("\n") + } + } + } + + line = "" + } + + return true + } + nfs.Message = m if len(arg) > 0 && arg[0] == "scan" { - nfs.Caches["windows"] = &ctx.Cache{Name: "windows", Value: "false", Help: "termbox"} - nfs.Caches["termbox"] = &ctx.Cache{Name: "termbox", Value: "false", Help: "termbox"} - nfs.Caches["cursor_pos"] = &ctx.Cache{Name: "cursor_pos", Value: "1", Help: "termbox"} - - nfs.Configs["color"] = &ctx.Config{Name: "color", Value: "false", Help: "color"} - nfs.Configs["fgcolor"] = &ctx.Config{Name: "fgcolor", Value: "9", Help: "fgcolor"} - nfs.Configs["bgcolor"] = &ctx.Config{Name: "bgcolor", Value: "9", Help: "bgcolor"} - nfs.Configs["pscolor"] = &ctx.Config{Name: "pscolor", Value: "2", Help: "pscolor"} - nfs.Configs["statusfgcolor"] = &ctx.Config{Name: "statusfgcolor", Value: "1", Help: "pscolor"} - nfs.Configs["statusbgcolor"] = &ctx.Config{Name: "statusbgcolor", Value: "2", Help: "pscolor"} - + // nfs.Caches["windows"] = &ctx.Cache{Name: "windows", Value: "false", Help: "termbox"} + // nfs.Caches["termbox"] = &ctx.Cache{Name: "termbox", Value: "false", Help: "termbox"} + // nfs.Caches["cursor_pos"] = &ctx.Cache{Name: "cursor_pos", Value: "1", Help: "termbox"} + // + // nfs.Configs["color"] = &ctx.Config{Name: "color", Value: "false", Help: "color"} + // nfs.Configs["fgcolor"] = &ctx.Config{Name: "fgcolor", Value: "9", Help: "fgcolor"} + // nfs.Configs["bgcolor"] = &ctx.Config{Name: "bgcolor", Value: "9", Help: "bgcolor"} + // nfs.Configs["pscolor"] = &ctx.Config{Name: "pscolor", Value: "2", Help: "pscolor"} + // nfs.Configs["statusfgcolor"] = &ctx.Config{Name: "statusfgcolor", Value: "1", Help: "pscolor"} + // nfs.Configs["statusbgcolor"] = &ctx.Config{Name: "statusbgcolor", Value: "2", Help: "pscolor"} + // nfs.in = m.Optionv("in").(*os.File) bio := bufio.NewScanner(nfs) + s, e := nfs.in.Stat() m.Assert(e) m.Capi("size", int(s.Size())) if m.Cap("stream", arg[1]) == "stdio" { nfs.out = m.Optionv("out").(*os.File) - if !m.Caps("windows", runtime.GOOS == "windows") { - termbox.Init() - defer termbox.Close() - nfs.width, nfs.height = termbox.Size() - nfs.Cap("termbox", "true") - nfs.Conf("color", "true") - } + // if !m.Caps("windows", runtime.GOOS == "windows") { + // termbox.Init() + // defer termbox.Close() + // nfs.width, nfs.height = termbox.Size() + // nfs.Cap("termbox", "true") + // nfs.Conf("color", "true") + // } // if !m.Options("init.shy") { // // for _, v := range []string{ @@ -640,8 +692,11 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { line := "" for nfs.prompt(); !m.Options("scan_end") && bio.Scan(); nfs.prompt() { + kit.Log("error", "stdio read %v", "text") text := bio.Text() m.Capi("nread", len(text)+1) + kit.Log("error", "stdio read %v", text) + continue if line += text; len(text) > 0 && text[len(text)-1] == '\\' { line = line[:len(line)-1] @@ -669,6 +724,8 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { } line = "" } + + kit.Log("error", "stdio read %v", line) if !m.Options("scan_end") { msg := m.Spawn(m.Source()).Set("detail", "return") m.Back(msg) diff --git a/src/contexts/yac/yac.go b/src/contexts/yac/yac.go index 3f81be91..92fdf753 100644 --- a/src/contexts/yac/yac.go +++ b/src/contexts/yac/yac.go @@ -41,7 +41,9 @@ func (yac *YAC) name(page int) string { } return fmt.Sprintf("yac%d", page) } -func (yac *YAC) train(m *ctx.Message, page, hash int, word []string) (int, []*Point, []*Point) { +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) + ss := []int{page} sn := make([]bool, m.Capi("nline")) points, ends := []*Point{}, []*Point{} @@ -58,7 +60,7 @@ func (yac *YAC) train(m *ctx.Message, page, hash int, word []string) (int, []*Po switch word[i] { case "opt{", "rep{": sn[s] = true - num, point, end := yac.train(m, s, 0, word[i+1:]) + num, point, end := yac.train(m, s, 0, word[i+1:], level+1) n, points = num, append(points, point...) for _, x := range end { @@ -100,11 +102,10 @@ func (yac *YAC) train(m *ctx.Message, page, hash int, word []string) (int, []*Po } else { m.Capi("nnode", 1) } - m.Log("debug", "GET(%d, %d): %v \033[31m(%s)\033[0m", s, c, state, word[i]) if state.next == 0 { state.next = m.Capi("nline", 1) - 1 yac.mat = append(yac.mat, map[byte]*State{}) - for i := 0; i < m.Capi("nlang"); i++ { + for i := 0; i < m.Capi("nline"); i++ { yac.mat[state.next][byte(i)] = nil } sn = append(sn, false) @@ -113,7 +114,6 @@ func (yac *YAC) train(m *ctx.Message, page, hash int, word []string) (int, []*Po yac.mat[s][c] = state ends = append(ends, &Point{s, c}) points = append(points, &Point{s, c}) - m.Log("debug", "SET(%d, %d): %v", s, c, state) } } next: @@ -127,7 +127,7 @@ func (yac *YAC) train(m *ctx.Message, page, hash int, word []string) (int, []*Po } } for _, s := range ss { - if s < m.Capi("nlang") || s >= len(yac.mat) { + if s < m.Confi("info", "nlang") || s >= len(yac.mat) { continue } void := true @@ -138,7 +138,9 @@ func (yac *YAC) train(m *ctx.Message, page, hash int, word []string) (int, []*Po } } if void { - m.Log("debug", "DEL: %d-%d", m.Capi("nline")-1, m.Capi("nline", 0, s)) + last := m.Capi("nline") - 1 + m.Cap("nline", "0") + m.Log("debug", "DEL: %d-%d", last, m.Capi("nline", s)) yac.mat = yac.mat[:s] } } @@ -165,12 +167,13 @@ func (yac *YAC) train(m *ctx.Message, page, hash int, word []string) (int, []*Po } } } + + 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) { - if m.Confs("debug") { - m.Log("debug", "%s\\%d %s(%d): %s", m.Conf("label")[0:level], level, yac.name(page), page, line) - } + m.Log("debug", "%s %s\\%d %s(%d): %s", "parse", strings.Repeat("#", level), level, yac.name(page), page, line) + hash, word := 0, []string{} for star, s := 0, page; s != 0 && len(line) > 0; { //解析空白 @@ -197,8 +200,8 @@ func (yac *YAC) parse(m *ctx.Message, out *ctx.Message, page int, void int, line } } if state == nil { //嵌套语法递归解析 - for i := 0; i < m.Capi("ncell"); i++ { - if x := yac.mat[s][byte(i)]; i < m.Capi("nlang") && x != 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 @@ -224,9 +227,8 @@ func (yac *YAC) parse(m *ctx.Message, out *ctx.Message, page int, void int, line word = msg.Meta["result"] } } - if m.Confs("debug") { - m.Log("debug", "%s/%d %s(%d): %v", m.Conf("label")[0:level], level, yac.name(page), page, word) - } + + m.Log("debug", "%s %s/%d %s(%d): %v", "parse", strings.Repeat("#", level), level, yac.name(page), page, word) return line, word, hash } @@ -242,66 +244,18 @@ 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 { - if len(arg) > 0 && arg[0] == "scan" { - return yac - } - - yac.Caches["ncell"] = &ctx.Cache{Name: "词法上限", Value: "128", Help: "词法集合的最大数量"} - yac.Caches["nlang"] = &ctx.Cache{Name: "语法上限", Value: "32", Help: "语法集合的最大数量"} - yac.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: "32", 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.Capi("nlang")) - yac.state = map[State]*State{} return yac } func (yac *YAC) Start(m *ctx.Message, arg ...string) (close bool) { if len(arg) > 0 && arg[0] == "scan" { - var out *ctx.Message - data := make(chan string, 1) - next := make(chan bool, 1) - close = true - defer func() { - if e := recover(); e != nil { - // m.Option("scan_end", true) - next <- true - } - }() - //加载文件 - nfs := m.Sess("nfs").Call(func(buf *ctx.Message) *ctx.Message { - out = buf - data <- buf.Detail(0) + "; " - <-next + 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:]) - // m.Find("log").Cmd("silent", yac.Context.Name, "debug", true) - //解析循环 - for m.Cap("stream", nfs.Target().Name); !m.Options("scan_end"); next <- true { - line := <-data - if len(line) == 0 { - continue - } - _, word, _ := yac.parse(m, out, m.Optioni("page"), m.Optioni("void"), line, 1) - if len(word) > 0 { - word = word[:len(word)-1] - if last := len(word) - 1; last >= 0 && len(word[last]) > 0 && word[last][len(word[last])-1] != '\n' { - word = append(word, "\n") - } - } - out.Result(0, word) - } - return true + return false } - return false + return true } func (yac *YAC) Close(m *ctx.Message, arg ...string) bool { switch yac.Context { @@ -316,57 +270,76 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", "nparse": &ctx.Cache{Name: "nparse", Value: "0", Help: "解析器数量"}, }, Configs: map[string]*ctx.Config{ - "compact_lex": &ctx.Config{Name: "compact_lex(true/false)", Value: "true", Help: "调试模式,on:打印,off:不打印)"}, - "debug": &ctx.Config{Name: "debug", Value: "false", Help: "词法集合的最大数量"}, - "ncell": &ctx.Config{Name: "词法上限", Value: "128", Help: "词法集合的最大数量"}, - "nlang": &ctx.Config{Name: "语法上限", Value: "32", Help: "语法集合的最大数量"}, - "label": &ctx.Config{Name: "嵌套标记", Value: "####################", 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": "str", "hash": "str", "word": []interface{}{"mul{", "\"[^\"]*\"", "'[^']*'", "}"}}, + map[string]interface{}{"page": "exe", "hash": "exe", "word": []interface{}{"mul{", "$", "@", "}", "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": "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": "cmd", "hash": "cmd", "word": []interface{}{"rep{", "word", "}"}}, + map[string]interface{}{"page": "exe", "hash": "exe", "word": []interface{}{"$", "(", "cmd", ")"}}, + + 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: "嵌套层级日志的标记"}, }, 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) { - m.Cmd("train", "void", "void", "[\t ]+") + 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: "状态机连接的存储数量"} - m.Cmd("train", "key", "key", "[A-Za-z_][A-Za-z_0-9]*") - m.Cmd("train", "num", "num", "mul{", "0", "-?[1-9][0-9]*", "0[0-9]+", "0x[0-9]+", "}") - m.Cmd("train", "str", "str", "mul{", "\"[^\"]*\"", "'[^']*'", "}") - m.Cmd("train", "exe", "exe", "mul{", "$", "@", "}", "key") + 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: "语句类型的数量"} - m.Cmd("train", "op1", "op1", "mul{", "-z", "-n", "}") - m.Cmd("train", "op1", "op1", "mul{", "-e", "-f", "-d", "}") - m.Cmd("train", "op1", "op1", "mul{", "-", "+", "}") - m.Cmd("train", "op2", "op2", "mul{", ":=", "=", "+=", "}") - m.Cmd("train", "op2", "op2", "mul{", "+", "-", "*", "/", "%", "}") - m.Cmd("train", "op2", "op2", "mul{", "<", "<=", ">", ">=", "==", "!=", "}") - m.Cmd("train", "op2", "op2", "mul{", "~", "!~", "}") + 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"} - m.Cmd("train", "val", "val", "opt{", "op1", "}", "mul{", "num", "key", "str", "exe", "}") - m.Cmd("train", "exp", "exp", "val", "rep{", "op2", "val", "}") - m.Cmd("train", "map", "map", "key", ":", "\\[", "rep{", "key", "}", "\\]") - m.Cmd("train", "exp", "exp", "\\{", "rep{", "map", "}", "\\}") - m.Cmd("train", "val", "val", "opt{", "op1", "}", "(", "exp", ")") + yac.mat = make([]map[byte]*State, m.Confi("info", "nlang")) + yac.state = map[State]*State{} - m.Cmd("train", "stm", "var", "var", "key", "opt{", "=", "exp", "}") - m.Cmd("train", "stm", "let", "let", "key", "opt{", "=", "exp", "}") - m.Cmd("train", "stm", "var", "var", "key", "<-") - m.Cmd("train", "stm", "var", "var", "key", "<-", "opt{", "exe", "}") - m.Cmd("train", "stm", "let", "let", "key", "<-", "opt{", "exe", "}") - - m.Cmd("train", "stm", "if", "if", "exp") - m.Cmd("train", "stm", "else", "else") - m.Cmd("train", "stm", "end", "end") - m.Cmd("train", "stm", "for", "for", "opt{", "exp", ";", "}", "exp") - m.Cmd("train", "stm", "for", "for", "index", "exp", "opt{", "exp", "}", "exp") - m.Cmd("train", "stm", "label", "label", "exp") - m.Cmd("train", "stm", "goto", "goto", "exp", "opt{", "exp", "}", "exp") - - m.Cmd("train", "stm", "expr", "expr", "rep{", "exp", "}") - m.Cmd("train", "stm", "return", "return", "rep{", "exp", "}") - - m.Cmd("train", "word", "word", "mul{", "~", "!", "=", "\\?\\?", "\\?", "<", ">$", ">@", ">", "\\|", "%", "exe", "str", "[a-zA-Z0-9_/\\-.:]+", "}") - m.Cmd("train", "cmd", "cmd", "rep{", "word", "}") - m.Cmd("train", "exe", "exe", "$", "(", "cmd", ")") - - m.Cmd("train", "line", "line", "opt{", "mul{", "stm", "cmd", "}", "}", "mul{", ";", "\n", "#[^\n]*\n", "}") + m.Confm("seed", func(line int, seed map[string]interface{}) { + m.Spawn().Cmd("train", seed["page"], seed["hash"], seed["word"]) + }) + } return }}, "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) { @@ -376,10 +349,10 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", page = m.Capi("npage", 1) yac.page[arg[0]] = page yac.word[page] = arg[0] - m.Assert(page < m.Capi("nlang"), "语法集合过多") + m.Assert(page < m.Confi("info", "nlang"), "语法集合过多") yac.mat[page] = map[byte]*State{} - for i := 0; i < m.Capi("nlang"); i++ { + for i := 0; i < m.Confi("info", "nlang"); i++ { yac.mat[page][byte(i)] = nil } } @@ -392,10 +365,10 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", } if yac.lex == nil { - yac.lex = m.Sess("lex", "lex").Cmd("spawn") + yac.lex = m.Cmd("lex.spawn") } - yac.train(m, page, hash, arg[2:]) + 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"))) } @@ -454,7 +427,7 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", m.Sort("code", "int").Table() case "mat": for _, v := range yac.mat { - for j := byte(0); j < byte(m.Capi("ncell")); j++ { + for j := byte(0); j < byte(m.Confi("info", "ncell")); j++ { s := v[j] if s == nil { m.Add("append", fmt.Sprintf("%d", j), "") diff --git a/src/toolkit/kit.go b/src/toolkit/kit.go index f3203fff..2c33ef38 100644 --- a/src/toolkit/kit.go +++ b/src/toolkit/kit.go @@ -22,6 +22,14 @@ func Errorf(str string, args ...interface{}) { } fmt.Fprintf(os.Stderr, str, args...) } +func Log(action string, str string, args ...interface{}) { + if len(args) == 0 { + fmt.Fprintf(os.Stderr, "%s", str) + } else { + fmt.Fprintf(os.Stderr, str, args...) + } + fmt.Fprintln(os.Stderr) +} func Int(arg ...interface{}) int { result := 0 @@ -57,8 +65,9 @@ func Right(arg ...interface{}) bool { case "", "0", "false", "off", "no", "error: ": result = result || false break + default: + result = result || true } - result = result || true case error: result = result || false default: @@ -87,8 +96,8 @@ func Format(arg ...interface{}) string { result = append(result, fmt.Sprintf("%d", int(val))) case time.Time: result = append(result, fmt.Sprintf("%d", val.Format("2006-01-02 15:03:04"))) - case error: - result = append(result, fmt.Sprintf("%v", val)) + // case error: + // result = append(result, fmt.Sprintf("%v", val)) default: if b, e := json.Marshal(val); e == nil { result = append(result, string(b)) @@ -97,10 +106,17 @@ func Format(arg ...interface{}) string { } if len(result) > 1 { + args := []interface{}{} if n := strings.Count(result[0], "%") - strings.Count(result[0], "%%"); len(result) > n+1 { - return fmt.Sprintf(result[0], result[1:n+1]) + strings.Join(result[n+1:], "") + for i := 1; i < n+1; i++ { + args = append(args, result[i]) + } + return fmt.Sprintf(result[0], args...) + strings.Join(result[n+1:], "") } else if len(result) == n+1 { - return fmt.Sprintf(result[0], result[1:]) + for i := 1; i < len(result); i++ { + args = append(args, result[i]) + } + return fmt.Sprintf(result[0], args...) } } return strings.Join(result, "") @@ -109,13 +125,17 @@ func Formats(arg ...interface{}) string { result := []string{} for _, v := range arg { switch val := v.(type) { + case []interface{}: + for _, v := range val { + result = append(result, Format(v)) + } default: if b, e := json.MarshalIndent(val, "", " "); e == nil { result = append(result, string(b)) } } } - return strings.Join(result, "") + return strings.Join(result, " ") } func Trans(arg ...interface{}) []string { ls := []string{} @@ -150,7 +170,9 @@ func Trans(arg ...interface{}) []string { ls = append(ls, k, Format(v)) } case []interface{}: - ls = append(ls, Format(val...)) + for _, v := range val { + ls = append(ls, Format(v)) + } default: ls = append(ls, Format(val)) } @@ -294,16 +316,17 @@ func Chain(root interface{}, args ...interface{}) interface{} { for j, key := range keys { index, e := strconv.Atoi(key) + // Log("error", "chain [%v %v] [%v %v] [%v/%v %v/%v] %v", parent_key, parent_index, key, index, i, len(args), j, len(keys), data) + var next interface{} switch value := data.(type) { case nil: - if j == len(keys)-1 { - next = args[i+1] - } - if i == len(args)-1 { return nil } + if j == len(keys)-1 { + next = args[i+1] + } if e == nil { data, index = []interface{}{next}, 0 @@ -359,13 +382,13 @@ func Chain(root interface{}, args ...interface{}) interface{} { } if index == -1 { - data, index = append([]interface{}{next}, value...), 0 + value, index = append([]interface{}{next}, value...), 0 } else if index == -2 { - data, index = append(value, next), len(value) + value, index = append(value, next), len(value) } else if j == len(keys)-1 { value[index] = next } - next = value[index] + data, next = value, value[index] } switch p := parent.(type) {