diff --git a/base/base.go b/base/base.go index f620ab45..85ff98ff 100644 --- a/base/base.go +++ b/base/base.go @@ -9,6 +9,7 @@ import ( _ "github.com/shylinux/icebergs/base/gdb" _ "github.com/shylinux/icebergs/base/lex" _ "github.com/shylinux/icebergs/base/log" + _ "github.com/shylinux/icebergs/base/yac" _ "github.com/shylinux/icebergs/base/mdb" diff --git a/base/lex/lex.go b/base/lex/lex.go index 43e15625..d52e30dd 100644 --- a/base/lex/lex.go +++ b/base/lex/lex.go @@ -22,11 +22,10 @@ const LEX = "lex" var Index = &ice.Context{Name: LEX, Help: "词法模块", Commands: map[string]*ice.Command{ ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - // m.Load() - // _lex_load(m) + // _lex_load(m.Load()) }}, ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - // m.Save() + m.Save() }}, }, } diff --git a/base/lex/matrix.go b/base/lex/matrix.go index ff492e2b..c23c413f 100644 --- a/base/lex/matrix.go +++ b/base/lex/matrix.go @@ -1,6 +1,8 @@ package lex import ( + "bytes" + "io" "strconv" "strings" @@ -10,6 +12,35 @@ import ( kit "github.com/shylinux/toolkits" ) +type Stream struct { + r io.Reader + b []byte + P int +} + +func NewStream(r io.Reader) *Stream { + return &Stream{r: r} +} +func (s *Stream) Scan() bool { + if s.P < len(s.b) { + return true + } + buf := make([]byte, 1024) + if n, e := s.r.Read(buf); e == nil && n > 0 { + s.b = append(s.b, buf[:n]...) + } + return s.P < len(s.b) +} +func (s *Stream) Next() { + s.P++ +} +func (s *Stream) Char() byte { + if s.Scan() { + return s.b[s.P] + } + return 0 +} + type Point struct { s int c byte @@ -80,7 +111,7 @@ func (mat *Matrix) index(m *ice.Message, hash string, h string) int { return which[h] } func (mat *Matrix) Train(m *ice.Message, npage, nhash string, seed string) int { - m.Debug("%s %s page: %v hash: %v seed: %v", TRAIN, LEX, npage, nhash, seed) + // m.Debug("%s %s page: %v hash: %v seed: %v", TRAIN, LEX, npage, nhash, seed) page := mat.index(m, NPAGE, npage) hash := mat.index(m, NHASH, nhash) @@ -147,8 +178,8 @@ func (mat *Matrix) Train(m *ice.Message, npage, nhash string, seed string) int { cc = append(cc, seed[i]) // 普通字符 } - m.Debug("page: \033[31m%d %v\033[0m", len(ss), ss) - m.Debug("cell: \033[32m%d %v\033[0m", len(cc), cc) + // m.Debug("page: \033[31m%d %v\033[0m", len(ss), ss) + // m.Debug("cell: \033[32m%d %v\033[0m", len(cc), cc) flag := '\000' if i+1 < len(seed) { // 次数 @@ -163,7 +194,7 @@ func (mat *Matrix) Train(m *ice.Message, npage, nhash string, seed string) int { if state == nil { state = &State{} } - m.Debug("GET(%d,%d): %#v", s, c, state) + // m.Debug("GET(%d,%d): %#v", s, c, state) if cb(state); state.next == 0 { sn = append(sn, true) @@ -175,7 +206,7 @@ func (mat *Matrix) Train(m *ice.Message, npage, nhash string, seed string) int { mat.mat[s][c] = state points = append(points, &Point{s, c}) - m.Debug("SET(%d,%d): %#v", s, c, state) + // m.Debug("SET(%d,%d): %#v", s, c, state) } for _, s := range ss { @@ -231,31 +262,33 @@ func (mat *Matrix) Train(m *ice.Message, npage, nhash string, seed string) int { break } } - m.Debug("DEL: %v", trans) + // m.Debug("DEL: %v", trans) for _, p := range points { // 去尾 p.s = trans[p.s] state := mat.mat[p.s][p.c] if state.next = trans[state.next]; state.next == 0 { - m.Debug("GET(%d, %d): %#v", p.s, p.c, state) + // m.Debug("GET(%d, %d): %#v", p.s, p.c, state) state.hash = hash - m.Debug("SET(%d, %d): %#v", p.s, p.c, state) + // m.Debug("SET(%d, %d): %#v", p.s, p.c, state) } } - m.Debug("%s %s npage: %v nhash: %v", "train", "lex", len(mat.page), len(mat.hash)) + // m.Debug("%s %s npage: %v nhash: %v", TRAIN, LEX, len(mat.page), len(mat.hash)) return hash } -func (mat *Matrix) Parse(m *ice.Message, npage string, line []byte) (hash int, word []byte, rest []byte) { - // m.Debug("%s %s page: %v line: %v", "parse", "lex", npage, line) +func (mat *Matrix) Parse(m *ice.Message, npage string, stream *Stream) (hash int, word []byte) { + // m.Debug("%s %s page: %v pos: %v", LEX, PARSE, npage, stream.P) page := mat.index(m, NPAGE, npage) - pos := 0 - for star, s := 0, page; s != 0 && pos < len(line); pos++ { - c := line[pos] - if c == '\\' && pos < len(line)-1 { //跳过转义 - pos++ - c = mat.char(line[pos])[0] + pos := stream.P + for star, s := 0, page; stream.Scan() && s != 0; stream.Next() { + c := stream.Char() + if c == '\\' { //跳过转义 + if stream.Next(); !stream.Scan() { + break + } + c = mat.char(stream.Char())[0] } if c > 127 { //跳过中文 word = append(word, c) @@ -264,7 +297,7 @@ func (mat *Matrix) Parse(m *ice.Message, npage string, line []byte) (hash int, w state := mat.mat[s][c] if state == nil { - s, star, pos = star, 0, pos-1 + s, star, stream.P = star, 0, stream.P-1 continue } // m.Debug("GET (%d,%d): %v", s, c, state) @@ -281,11 +314,10 @@ func (mat *Matrix) Parse(m *ice.Message, npage string, line []byte) (hash int, w } if hash == 0 { - pos, word = 0, word[:0] + stream.P, word = pos, word[:0] } - rest = line[pos:] - // m.Debug("%s %s hash: %v word: %v rest: %v", "parse", "lex", hash, word, rest) + // m.Debug("%s %s hash: %v word: %v", LEX, PARSE, mat.word[hash], string(word)) return } func (mat *Matrix) show(m *ice.Message) { @@ -379,10 +411,11 @@ func init() { value = kit.GetMeta(value) mat, _ := value[MATRIX].(*Matrix) - hash, word, rest := mat.Parse(m, m.Option(NPAGE), []byte(m.Option(kit.MDB_TEXT))) + stream := NewStream(bytes.NewBufferString(m.Option(kit.MDB_TEXT))) + hash, word := mat.Parse(m, m.Option(NPAGE), stream) m.Push(NHASH, kit.Select(kit.Format("%d", hash), mat.word[hash])) m.Push("word", string(word)) - m.Push("rest", string(rest)) + m.Push("rest", string(stream.b[stream.P:])) }) m.ProcessInner() }}, @@ -417,11 +450,10 @@ func init() { return } - hash, word, rest := mat.Parse(m, arg[1], []byte(arg[2])) + hash, word := mat.Parse(m, arg[1], NewStream(bytes.NewBufferString(arg[2]))) m.Push(kit.MDB_TIME, m.Time()) m.Push(kit.MDB_HASH, mat.word[hash]) m.Push("word", string(word)) - m.Push("rest", string(rest)) }) }}, }, diff --git a/base/yac/matrix.go b/base/yac/matrix.go index ded7cb6f..44f6a6da 100644 --- a/base/yac/matrix.go +++ b/base/yac/matrix.go @@ -1,6 +1,7 @@ package yac import ( + "bytes" "fmt" "strconv" "strings" @@ -137,7 +138,7 @@ func (mat *Matrix) train(m *ice.Message, page, hash int, word []string, level in default: c, ok := mat.page[word[i]] if !ok { - if c, _, _ = mat.lex.Parse(m, mat.name(mat.hand, s), []byte(word[i])); c == 0 { + if c, _ = mat.lex.Parse(m, mat.name(mat.hand, s), lex.NewStream(bytes.NewBufferString(word[i]))); c == 0 { // c = mat.lex.Train(m, mat.name(s), fmt.Sprintf("%d", len(mat.mat[s])+1), []byte(word[i])) c = kit.Int(m.Cmdx("lex.matrix", mdb.INSERT, mat.lex_key, mat.name(mat.hand, s), len(mat.mat[s]), word[i])) mat.mat[s] = append(mat.mat[s], nil) @@ -211,16 +212,17 @@ func (mat *Matrix) train(m *ice.Message, page, hash int, word []string, level in return len(word), points, ends } -func (mat *Matrix) Parse(m *ice.Message, rewrite Rewrite, page int, line []byte, level int) (hash int, word []string, rest []byte) { - m.Debug("%s %s\\%d %s(%d): %s", PARSE, strings.Repeat("#", level), level, mat.name(mat.hand, page), page, string(line)) +func (mat *Matrix) Parse(m *ice.Message, rewrite Rewrite, page int, stream *lex.Stream, level int) (hash int, word []string) { + // m.Debug("%s %s\\%d %s(%d)", PARSE, strings.Repeat("#", level), level, mat.name(mat.hand, page), page) - rest = line - h, w, r := 0, []byte{}, []byte{} - for p, i := 0, page; i > 0 && len(rest) > 0; { + begin := stream.P + h, w := 0, []byte{} + for p, i := 0, page; stream.Scan() && i > 0; { // 解析空白 - h, w, r = mat.lex.Parse(m, "space", rest) + h, w = mat.lex.Parse(m, "space", stream) // 解析单词 - h, w, r = mat.lex.Parse(m, mat.name(mat.hand, i), r) + begin := stream.P + h, w = mat.lex.Parse(m, mat.name(mat.hand, i), stream) // 解析状态 var s *State if h < len(mat.mat[i]) { @@ -228,8 +230,11 @@ func (mat *Matrix) Parse(m *ice.Message, rewrite Rewrite, page int, line []byte, } if s != nil { // 全局语法检查 - if hh, ww, _ := mat.lex.Parse(m, "key", rest); hh == 0 || len(ww) <= len(w) { - word, rest = append(word, string(w)), r + hold := stream.P + stream.P = begin + if hh, ww := mat.lex.Parse(m, "key", stream); hh == 0 || len(ww) <= len(w) { + stream.P = hold + word = append(word, string(w)) } else { s = nil } @@ -238,14 +243,14 @@ func (mat *Matrix) Parse(m *ice.Message, rewrite Rewrite, page int, line []byte, if s == nil { // 嵌套语法递归解析 for j := 1; j < len(mat.mat[i]); j++ { if n := mat.mat[i][j]; j < mat.nlang && n != nil { - if _, w, r := mat.Parse(m, rewrite, j, rest, level+1); len(r) != len(rest) { - s, word, rest = n, append(word, w...), r + if h, w := mat.Parse(m, rewrite, j, stream, level+1); h != 0 { + s, word = n, append(word, w...) break } } } } else { - m.Debug("%s %s|%d GET \033[33m%s\033[0m %#v", PARSE, strings.Repeat("#", level), level, w, s) + // m.Debug("%s %s|%d GET \033[33m%s\033[0m %#v", PARSE, strings.Repeat("#", level), level, w, s) } //语法切换 @@ -257,13 +262,13 @@ func (mat *Matrix) Parse(m *ice.Message, rewrite Rewrite, page int, line []byte, } if hash == 0 { - word, rest = word[:0], line + word, stream.P = word[:0], begin } else { - hash, word, rest = rewrite(m, mat.word[hash], hash, word, rest) + hash, word = rewrite(m, mat.word[hash], hash, word, begin, stream) } - m.Debug("%s %s/%d %s(%d): %v %v", PARSE, strings.Repeat("#", level), level, mat.hand[hash], hash, word, rest) - return hash, word, rest + // m.Debug("%s %s/%d %s(%d): %v %v", PARSE, strings.Repeat("#", level), level, mat.hand[hash], hash, word, stream.P) + return hash, word } func (mat *Matrix) show(m *ice.Message) { showCol := map[int]bool{} // 有效列 @@ -304,7 +309,7 @@ func (mat *Matrix) show(m *ice.Message) { m.Status(NLANG, mat.nlang, NCELL, mat.ncell, NPAGE, len(mat.page), NHASH, len(mat.hash)) } -type Rewrite func(m *ice.Message, nhash string, hash int, word []string, rest []byte) (int, []string, []byte) +type Rewrite func(m *ice.Message, nhash string, hash int, word []string, begin int, stream *lex.Stream) (int, []string) const ( NLANG = "nlang" @@ -351,6 +356,7 @@ func init() { mat.mat[page] = make([]*State, mat.ncell) } + m.Option(kit.MDB_TEXT, strings.ReplaceAll(m.Option(kit.MDB_TEXT), "\\", "\\\\")) text := kit.Split(m.Option(kit.MDB_TEXT), " ", " ", " ") mat.train(m, page, hash, text, 1) m.Grow(m.Prefix(MATRIX), kit.Keys(kit.MDB_HASH, key), kit.Dict( @@ -369,15 +375,16 @@ func init() { value = kit.GetMeta(value) mat, _ := value[MATRIX].(*Matrix) - for text := []byte(m.Option(kit.MDB_TEXT)); len(text) > 0; { - hash, _, rest := mat.Parse(m, func(m *ice.Message, nhash string, hash int, word []string, rest []byte) (int, []string, []byte) { + for stream := lex.NewStream(bytes.NewBufferString(m.Option(kit.MDB_TEXT))); stream.Scan(); { + hash, _ := mat.Parse(m, func(m *ice.Message, nhash string, hash int, word []string, begin int, stream *lex.Stream) (int, []string) { switch cb := m.Optionv(kit.Keycb(MATRIX)).(type) { - case func(string, int, []string, []byte) (int, []string, []byte): - return cb(nhash, hash, word, rest) + case func(string, int, []string, int, *lex.Stream) (int, []string): + return cb(nhash, hash, word, begin, stream) } - return hash, word, rest - }, mat.index(m, NPAGE, m.Option(NPAGE)), text, 1) - if text = rest; hash == 0 { + return hash, word + }, mat.index(m, NPAGE, m.Option(NPAGE)), stream, 1) + + if hash == 0 { break } } @@ -392,6 +399,7 @@ func init() { m.ProcessInner() }}, }, Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + m.Option(mdb.CACHE_LIMIT, -1) if m.Action(mdb.CREATE); len(arg) == 0 { // 矩阵列表 m.Fields(len(arg) == 0, "time,name,npage,nhash") m.Cmdy(mdb.SELECT, m.Prefix(MATRIX), "", mdb.HASH) @@ -406,24 +414,10 @@ func init() { return } + // 词法矩阵 m.Richs(m.Prefix(MATRIX), "", arg[0], func(key string, value map[string]interface{}) { value = kit.GetMeta(value) - mat, _ := value[MATRIX].(*Matrix) - - if len(arg) == 2 { // 词法矩阵 - mat.show(m) - return - } - - hash, word, rest := mat.Parse(m, func(m *ice.Message, nhash string, hash int, word []string, rest []byte) (int, []string, []byte) { - m.Debug("\033[32mrun --- %v %v %v\033[0m", nhash, word, rest) - return hash, word, rest - }, mat.index(m, NPAGE, arg[1]), []byte(arg[2]), 1) - - m.Push(kit.MDB_TIME, m.Time()) - m.Push(kit.MDB_HASH, mat.word[hash]) - m.Push("word", kit.Format(word)) - m.Push("rest", string(rest)) + value[MATRIX].(*Matrix).show(m) }) }}, }, diff --git a/base/yac/script.go b/base/yac/script.go index 241ee726..95c54aa3 100644 --- a/base/yac/script.go +++ b/base/yac/script.go @@ -1,21 +1,23 @@ package yac import ( + "io/ioutil" "strconv" "strings" ice "github.com/shylinux/icebergs" "github.com/shylinux/icebergs/base/cli" + "github.com/shylinux/icebergs/base/lex" "github.com/shylinux/icebergs/base/mdb" kit "github.com/shylinux/toolkits" ) type frame struct { + pos int key string skip bool data map[string]string } - type stack struct { fs []*frame res []string @@ -26,6 +28,20 @@ func (s *stack) push(f *frame) *stack { s.fs = append(s.fs, f) return s } +func (s *stack) pop() *frame { + last := s.fs[len(s.fs)-1] + s.fs = s.fs[:len(s.fs)-1] + return last +} +func (s *stack) can_run(nhash string) bool { + switch nhash { + case "if", "for", "end": + return true + } + + return !s.fs[len(s.fs)-1].skip +} + func (s *stack) define(key, value string) { if len(s.fs) > 0 { s.fs[len(s.fs)-1].data[key] = value @@ -39,31 +55,41 @@ func (s *stack) value(key string) string { } return "" } +func (s *stack) let(key, value string) string { + for i := len(s.fs) - 1; i >= 0; i-- { + if val, ok := s.fs[i].data[key]; ok { + s.fs[i].data[key] = value + return val + } + } + return "" +} +func (s *stack) echo(arg ...interface{}) { + s.res = append(s.res, kit.Simple(arg...)...) +} -func _script_push_stack(m *ice.Message, f *frame) { - stack := m.Optionv("stack").(*stack) - stack.push(f) +func _get_stack(m *ice.Message) *stack { + return m.Optionv("stack").(*stack) } -func _script_define(m *ice.Message, key, value string) { - stack := m.Optionv("stack").(*stack) - stack.define(key, value) +func _push_stack(m *ice.Message, f *frame) { + f.pos = kit.Int(m.Option("begin")) + _get_stack(m).push(f) } -func _script_runing(m *ice.Message, nhash string) bool { - switch nhash { - case "if", "for", "end": +func _pop_stack(m *ice.Message) *frame { + return _get_stack(m).pop() +} + +func _exp_true(m *ice.Message, arg string) bool { + if arg == "true" { return true } - - stack := m.Optionv("stack").(*stack) - return !stack.fs[len(stack.fs)-1].skip -} -func _script_pop_stack(m *ice.Message) { - stack := m.Optionv("stack").(*stack) - stack.fs = stack.fs[:len(stack.fs)-1] -} -func _script_res(m *ice.Message, arg ...interface{}) { - stack := m.Optionv("stack").(*stack) - stack.res = append(stack.res, kit.Simple(arg...)...) + if arg == "false" { + return false + } + if n1, e1 := strconv.ParseInt(arg, 10, 64); e1 == nil { + return n1 != 0 + } + return false } const SCRIPT = "script" @@ -71,24 +97,21 @@ const SCRIPT = "script" func init() { Index.Merge(&ice.Context{Commands: map[string]*ice.Command{ SCRIPT: {Name: "script name npage text:textarea auto create", Help: "脚本解析", Action: map[string]*ice.Action{ - mdb.CREATE: {Name: "create name=shy", Help: "创建", Hand: func(m *ice.Message, arg ...string) { + mdb.CREATE: {Name: "create name=shy text=etc/yac.txt", Help: "创建", Hand: func(m *ice.Message, arg ...string) { m.Cmd(MATRIX, mdb.CREATE, m.Option(kit.MDB_NAME)) - for _, p := range [][]string{ - []string{"num", "num", "[0-9]+"}, - []string{"key", "key", "[abc]+"}, - []string{"op2", "op2", "[+\\\\-*/%]"}, - []string{"op2", "op2", "[>=<]"}, - []string{"val", "val", "mul{ num key }"}, - []string{"exp", "exp", "val"}, - []string{"exp", "exp", "val op2 val"}, - []string{"stm", "var", "var key = exp"}, - []string{"stm", "for", "for exp"}, - []string{"stm", "if", "if exp"}, - []string{"stm", "cmd", "pwd"}, - []string{"stm", "end", "end"}, - []string{"script", "script", "rep{ stm }"}, - } { - m.Cmdx(MATRIX, mdb.INSERT, m.Option(kit.MDB_NAME), p) + if buf, err := ioutil.ReadFile(m.Option(kit.MDB_TEXT)); err == nil { + m.Option(kit.MDB_TEXT, string(buf)) + } + + m.Option(kit.MDB_TEXT, strings.ReplaceAll(m.Option(kit.MDB_TEXT), "\\", "\\\\")) + for _, line := range kit.Split(m.Option(kit.MDB_TEXT), "\n", "\n", "\n") { + if strings.HasPrefix(strings.TrimSpace(line), "#") { + continue + } + line = strings.ReplaceAll(line, "\\", "\\\\") + if list := kit.Split(line, " ", " ", " "); len(list) > 2 { + m.Cmdx(MATRIX, mdb.INSERT, m.Option(kit.MDB_NAME), list[0], list[1], strings.Join(list[2:], " ")) + } } }}, "exp": {Name: "exp num op2 num", Help: "创建", Hand: func(m *ice.Message, arg ...string) { @@ -101,10 +124,8 @@ func init() { } arg[2] = kit.Select(arg[2], stack.value(arg[2])) - m.Debug(" %v %v %v", arg[0], arg[1], arg[2]) n1, e1 := strconv.ParseInt(arg[0], 10, 64) n2, e2 := strconv.ParseInt(arg[2], 10, 64) - m.Debug(" %v %v %v", n1, arg[1], n2) switch arg[1] { case ">": if e1 == nil && e2 == nil { @@ -112,6 +133,12 @@ func init() { } else { m.Echo("%t", arg[0] > arg[2]) } + case "<": + if e1 == nil && e2 == nil { + m.Echo("%t", n1 < n2) + } else { + m.Echo("%t", arg[0] < arg[2]) + } case "+": if e1 == nil && e2 == nil { m.Echo("%d", n1+n2) @@ -146,33 +173,27 @@ func init() { m.Echo(arg[0], arg[1], arg[2]) } }}, - "if": {Name: "if exp", Help: "判断", Hand: func(m *ice.Message, arg ...string) { - if arg[1] == "true" { - _script_push_stack(m, &frame{key: arg[0], skip: false}) - return - } - if arg[1] == "false" { - _script_push_stack(m, &frame{key: arg[0], skip: true}) - return - } - if n1, e1 := strconv.ParseInt(arg[1], 10, 64); e1 == nil { - _script_push_stack(m, &frame{key: arg[0], skip: n1 == 0}) - m.Echo("%t", n1 != 0) - } else { - _script_push_stack(m, &frame{skip: len(arg[1]) == 0}) - m.Echo("%t", len(arg[1]) > 0) - } - }}, "var": {Name: "var key = exp", Help: "变量", Hand: func(m *ice.Message, arg ...string) { - _script_define(m, arg[1], arg[3]) + _get_stack(m).define(arg[1], arg[3]) }}, - "for": {Name: "for exp", Help: "循环", Hand: func(m *ice.Message, arg ...string) { + "let": {Name: "let key = exp", Help: "变量", Hand: func(m *ice.Message, arg ...string) { + _get_stack(m).let(arg[1], arg[3]) }}, "cmd": {Name: "cmd", Help: "命令", Hand: func(m *ice.Message, arg ...string) { - _script_res(m, m.Cmdx(cli.SYSTEM, arg)) + _get_stack(m).echo(m.Cmdx(cli.SYSTEM, arg)) + }}, + "if": {Name: "if exp", Help: "判断", Hand: func(m *ice.Message, arg ...string) { + _push_stack(m, &frame{key: arg[0], skip: !_exp_true(m, arg[1])}) + }}, + "for": {Name: "for exp", Help: "循环", Hand: func(m *ice.Message, arg ...string) { + _push_stack(m, &frame{key: arg[0], skip: !_exp_true(m, arg[1])}) }}, "end": {Name: "end", Help: "结束", Hand: func(m *ice.Message, arg ...string) { - _script_pop_stack(m) + frame := _pop_stack(m) + if frame.key == "for" && !frame.skip { + stream := m.Optionv("stream").(*lex.Stream) + stream.P = frame.pos + } }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) < 2 { @@ -183,13 +204,13 @@ func init() { stack := &stack{} stack.push(&frame{}) m.Option("stack", stack) - m.Cmdy(MATRIX, PARSE, arg[0], arg[1], arg[2], func(nhash string, hash int, word []string, rest []byte) (int, []string, []byte) { - m.Debug("script %v %v", nhash, word) - if _, ok := c.Commands[SCRIPT].Action[nhash]; ok && _script_runing(m, nhash) { - msg := m.Cmd(SCRIPT, nhash, word) - return hash, msg.Resultv(), rest + m.Cmdy(MATRIX, PARSE, arg[0], arg[1], arg[2], func(nhash string, hash int, word []string, begin int, stream *lex.Stream) (int, []string) { + m.Option("stream", stream) + if _, ok := c.Commands[SCRIPT].Action[nhash]; ok && stack.can_run(nhash) { + msg := m.Cmd(SCRIPT, nhash, word, ice.Option{"begin", begin}) + return hash, msg.Resultv() } - return hash, word, rest + return hash, word }) m.Resultv(stack.res) }},