forked from x/icebergs
opt yac
This commit is contained in:
parent
ddf87b921d
commit
bb7f1360e8
@ -9,6 +9,7 @@ import (
|
|||||||
_ "github.com/shylinux/icebergs/base/gdb"
|
_ "github.com/shylinux/icebergs/base/gdb"
|
||||||
_ "github.com/shylinux/icebergs/base/lex"
|
_ "github.com/shylinux/icebergs/base/lex"
|
||||||
_ "github.com/shylinux/icebergs/base/log"
|
_ "github.com/shylinux/icebergs/base/log"
|
||||||
|
|
||||||
_ "github.com/shylinux/icebergs/base/yac"
|
_ "github.com/shylinux/icebergs/base/yac"
|
||||||
|
|
||||||
_ "github.com/shylinux/icebergs/base/mdb"
|
_ "github.com/shylinux/icebergs/base/mdb"
|
||||||
|
@ -22,11 +22,10 @@ const LEX = "lex"
|
|||||||
var Index = &ice.Context{Name: LEX, Help: "词法模块",
|
var Index = &ice.Context{Name: LEX, Help: "词法模块",
|
||||||
Commands: map[string]*ice.Command{
|
Commands: map[string]*ice.Command{
|
||||||
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) {
|
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) {
|
||||||
// m.Load()
|
// _lex_load(m.Load())
|
||||||
// _lex_load(m)
|
|
||||||
}},
|
}},
|
||||||
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) {
|
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) {
|
||||||
// m.Save()
|
m.Save()
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package lex
|
package lex
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -10,6 +12,35 @@ import (
|
|||||||
kit "github.com/shylinux/toolkits"
|
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 {
|
type Point struct {
|
||||||
s int
|
s int
|
||||||
c byte
|
c byte
|
||||||
@ -80,7 +111,7 @@ func (mat *Matrix) index(m *ice.Message, hash string, h string) int {
|
|||||||
return which[h]
|
return which[h]
|
||||||
}
|
}
|
||||||
func (mat *Matrix) Train(m *ice.Message, npage, nhash string, seed string) int {
|
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)
|
page := mat.index(m, NPAGE, npage)
|
||||||
hash := mat.index(m, NHASH, nhash)
|
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]) // 普通字符
|
cc = append(cc, seed[i]) // 普通字符
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Debug("page: \033[31m%d %v\033[0m", len(ss), ss)
|
// 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("cell: \033[32m%d %v\033[0m", len(cc), cc)
|
||||||
|
|
||||||
flag := '\000'
|
flag := '\000'
|
||||||
if i+1 < len(seed) { // 次数
|
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 {
|
if state == nil {
|
||||||
state = &State{}
|
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 {
|
if cb(state); state.next == 0 {
|
||||||
sn = append(sn, true)
|
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
|
mat.mat[s][c] = state
|
||||||
points = append(points, &Point{s, c})
|
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 {
|
for _, s := range ss {
|
||||||
@ -231,31 +262,33 @@ func (mat *Matrix) Train(m *ice.Message, npage, nhash string, seed string) int {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.Debug("DEL: %v", trans)
|
// m.Debug("DEL: %v", trans)
|
||||||
|
|
||||||
for _, p := range points { // 去尾
|
for _, p := range points { // 去尾
|
||||||
p.s = trans[p.s]
|
p.s = trans[p.s]
|
||||||
state := mat.mat[p.s][p.c]
|
state := mat.mat[p.s][p.c]
|
||||||
if state.next = trans[state.next]; state.next == 0 {
|
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
|
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
|
return hash
|
||||||
}
|
}
|
||||||
func (mat *Matrix) Parse(m *ice.Message, npage string, line []byte) (hash int, word []byte, rest []byte) {
|
func (mat *Matrix) Parse(m *ice.Message, npage string, stream *Stream) (hash int, word []byte) {
|
||||||
// m.Debug("%s %s page: %v line: %v", "parse", "lex", npage, line)
|
// m.Debug("%s %s page: %v pos: %v", LEX, PARSE, npage, stream.P)
|
||||||
page := mat.index(m, NPAGE, npage)
|
page := mat.index(m, NPAGE, npage)
|
||||||
|
|
||||||
pos := 0
|
pos := stream.P
|
||||||
for star, s := 0, page; s != 0 && pos < len(line); pos++ {
|
for star, s := 0, page; stream.Scan() && s != 0; stream.Next() {
|
||||||
c := line[pos]
|
c := stream.Char()
|
||||||
if c == '\\' && pos < len(line)-1 { //跳过转义
|
if c == '\\' { //跳过转义
|
||||||
pos++
|
if stream.Next(); !stream.Scan() {
|
||||||
c = mat.char(line[pos])[0]
|
break
|
||||||
|
}
|
||||||
|
c = mat.char(stream.Char())[0]
|
||||||
}
|
}
|
||||||
if c > 127 { //跳过中文
|
if c > 127 { //跳过中文
|
||||||
word = append(word, c)
|
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]
|
state := mat.mat[s][c]
|
||||||
if state == nil {
|
if state == nil {
|
||||||
s, star, pos = star, 0, pos-1
|
s, star, stream.P = star, 0, stream.P-1
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// m.Debug("GET (%d,%d): %v", s, c, state)
|
// 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 {
|
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
|
return
|
||||||
}
|
}
|
||||||
func (mat *Matrix) show(m *ice.Message) {
|
func (mat *Matrix) show(m *ice.Message) {
|
||||||
@ -379,10 +411,11 @@ func init() {
|
|||||||
value = kit.GetMeta(value)
|
value = kit.GetMeta(value)
|
||||||
mat, _ := value[MATRIX].(*Matrix)
|
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(NHASH, kit.Select(kit.Format("%d", hash), mat.word[hash]))
|
||||||
m.Push("word", string(word))
|
m.Push("word", string(word))
|
||||||
m.Push("rest", string(rest))
|
m.Push("rest", string(stream.b[stream.P:]))
|
||||||
})
|
})
|
||||||
m.ProcessInner()
|
m.ProcessInner()
|
||||||
}},
|
}},
|
||||||
@ -417,11 +450,10 @@ func init() {
|
|||||||
return
|
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_TIME, m.Time())
|
||||||
m.Push(kit.MDB_HASH, mat.word[hash])
|
m.Push(kit.MDB_HASH, mat.word[hash])
|
||||||
m.Push("word", string(word))
|
m.Push("word", string(word))
|
||||||
m.Push("rest", string(rest))
|
|
||||||
})
|
})
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package yac
|
package yac
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -137,7 +138,7 @@ func (mat *Matrix) train(m *ice.Message, page, hash int, word []string, level in
|
|||||||
default:
|
default:
|
||||||
c, ok := mat.page[word[i]]
|
c, ok := mat.page[word[i]]
|
||||||
if !ok {
|
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 = 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]))
|
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)
|
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
|
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) {
|
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): %s", PARSE, strings.Repeat("#", level), level, mat.name(mat.hand, page), page, string(line))
|
// m.Debug("%s %s\\%d %s(%d)", PARSE, strings.Repeat("#", level), level, mat.name(mat.hand, page), page)
|
||||||
|
|
||||||
rest = line
|
begin := stream.P
|
||||||
h, w, r := 0, []byte{}, []byte{}
|
h, w := 0, []byte{}
|
||||||
for p, i := 0, page; i > 0 && len(rest) > 0; {
|
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
|
var s *State
|
||||||
if h < len(mat.mat[i]) {
|
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 s != nil { // 全局语法检查
|
||||||
if hh, ww, _ := mat.lex.Parse(m, "key", rest); hh == 0 || len(ww) <= len(w) {
|
hold := stream.P
|
||||||
word, rest = append(word, string(w)), r
|
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 {
|
} else {
|
||||||
s = nil
|
s = nil
|
||||||
}
|
}
|
||||||
@ -238,14 +243,14 @@ func (mat *Matrix) Parse(m *ice.Message, rewrite Rewrite, page int, line []byte,
|
|||||||
if s == nil { // 嵌套语法递归解析
|
if s == nil { // 嵌套语法递归解析
|
||||||
for j := 1; j < len(mat.mat[i]); j++ {
|
for j := 1; j < len(mat.mat[i]); j++ {
|
||||||
if n := mat.mat[i][j]; j < mat.nlang && n != nil {
|
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) {
|
if h, w := mat.Parse(m, rewrite, j, stream, level+1); h != 0 {
|
||||||
s, word, rest = n, append(word, w...), r
|
s, word = n, append(word, w...)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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 {
|
if hash == 0 {
|
||||||
word, rest = word[:0], line
|
word, stream.P = word[:0], begin
|
||||||
} else {
|
} 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)
|
// m.Debug("%s %s/%d %s(%d): %v %v", PARSE, strings.Repeat("#", level), level, mat.hand[hash], hash, word, stream.P)
|
||||||
return hash, word, rest
|
return hash, word
|
||||||
}
|
}
|
||||||
func (mat *Matrix) show(m *ice.Message) {
|
func (mat *Matrix) show(m *ice.Message) {
|
||||||
showCol := map[int]bool{} // 有效列
|
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))
|
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 (
|
const (
|
||||||
NLANG = "nlang"
|
NLANG = "nlang"
|
||||||
@ -351,6 +356,7 @@ func init() {
|
|||||||
mat.mat[page] = make([]*State, mat.ncell)
|
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), " ", " ", " ")
|
text := kit.Split(m.Option(kit.MDB_TEXT), " ", " ", " ")
|
||||||
mat.train(m, page, hash, text, 1)
|
mat.train(m, page, hash, text, 1)
|
||||||
m.Grow(m.Prefix(MATRIX), kit.Keys(kit.MDB_HASH, key), kit.Dict(
|
m.Grow(m.Prefix(MATRIX), kit.Keys(kit.MDB_HASH, key), kit.Dict(
|
||||||
@ -369,15 +375,16 @@ func init() {
|
|||||||
value = kit.GetMeta(value)
|
value = kit.GetMeta(value)
|
||||||
mat, _ := value[MATRIX].(*Matrix)
|
mat, _ := value[MATRIX].(*Matrix)
|
||||||
|
|
||||||
for text := []byte(m.Option(kit.MDB_TEXT)); len(text) > 0; {
|
for stream := lex.NewStream(bytes.NewBufferString(m.Option(kit.MDB_TEXT))); stream.Scan(); {
|
||||||
hash, _, rest := mat.Parse(m, func(m *ice.Message, nhash string, hash int, word []string, rest []byte) (int, []string, []byte) {
|
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) {
|
switch cb := m.Optionv(kit.Keycb(MATRIX)).(type) {
|
||||||
case func(string, int, []string, []byte) (int, []string, []byte):
|
case func(string, int, []string, int, *lex.Stream) (int, []string):
|
||||||
return cb(nhash, hash, word, rest)
|
return cb(nhash, hash, word, begin, stream)
|
||||||
}
|
}
|
||||||
return hash, word, rest
|
return hash, word
|
||||||
}, mat.index(m, NPAGE, m.Option(NPAGE)), text, 1)
|
}, mat.index(m, NPAGE, m.Option(NPAGE)), stream, 1)
|
||||||
if text = rest; hash == 0 {
|
|
||||||
|
if hash == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -392,6 +399,7 @@ func init() {
|
|||||||
m.ProcessInner()
|
m.ProcessInner()
|
||||||
}},
|
}},
|
||||||
}, Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) {
|
}, 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 { // 矩阵列表
|
if m.Action(mdb.CREATE); len(arg) == 0 { // 矩阵列表
|
||||||
m.Fields(len(arg) == 0, "time,name,npage,nhash")
|
m.Fields(len(arg) == 0, "time,name,npage,nhash")
|
||||||
m.Cmdy(mdb.SELECT, m.Prefix(MATRIX), "", mdb.HASH)
|
m.Cmdy(mdb.SELECT, m.Prefix(MATRIX), "", mdb.HASH)
|
||||||
@ -406,24 +414,10 @@ func init() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 词法矩阵
|
||||||
m.Richs(m.Prefix(MATRIX), "", arg[0], func(key string, value map[string]interface{}) {
|
m.Richs(m.Prefix(MATRIX), "", arg[0], func(key string, value map[string]interface{}) {
|
||||||
value = kit.GetMeta(value)
|
value = kit.GetMeta(value)
|
||||||
mat, _ := value[MATRIX].(*Matrix)
|
value[MATRIX].(*Matrix).show(m)
|
||||||
|
|
||||||
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))
|
|
||||||
})
|
})
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
|
@ -1,21 +1,23 @@
|
|||||||
package yac
|
package yac
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
ice "github.com/shylinux/icebergs"
|
ice "github.com/shylinux/icebergs"
|
||||||
"github.com/shylinux/icebergs/base/cli"
|
"github.com/shylinux/icebergs/base/cli"
|
||||||
|
"github.com/shylinux/icebergs/base/lex"
|
||||||
"github.com/shylinux/icebergs/base/mdb"
|
"github.com/shylinux/icebergs/base/mdb"
|
||||||
kit "github.com/shylinux/toolkits"
|
kit "github.com/shylinux/toolkits"
|
||||||
)
|
)
|
||||||
|
|
||||||
type frame struct {
|
type frame struct {
|
||||||
|
pos int
|
||||||
key string
|
key string
|
||||||
skip bool
|
skip bool
|
||||||
data map[string]string
|
data map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
type stack struct {
|
type stack struct {
|
||||||
fs []*frame
|
fs []*frame
|
||||||
res []string
|
res []string
|
||||||
@ -26,6 +28,20 @@ func (s *stack) push(f *frame) *stack {
|
|||||||
s.fs = append(s.fs, f)
|
s.fs = append(s.fs, f)
|
||||||
return s
|
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) {
|
func (s *stack) define(key, value string) {
|
||||||
if len(s.fs) > 0 {
|
if len(s.fs) > 0 {
|
||||||
s.fs[len(s.fs)-1].data[key] = value
|
s.fs[len(s.fs)-1].data[key] = value
|
||||||
@ -39,31 +55,41 @@ func (s *stack) value(key string) string {
|
|||||||
}
|
}
|
||||||
return ""
|
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) {
|
func _get_stack(m *ice.Message) *stack {
|
||||||
stack := m.Optionv("stack").(*stack)
|
return m.Optionv("stack").(*stack)
|
||||||
stack.push(f)
|
|
||||||
}
|
}
|
||||||
func _script_define(m *ice.Message, key, value string) {
|
func _push_stack(m *ice.Message, f *frame) {
|
||||||
stack := m.Optionv("stack").(*stack)
|
f.pos = kit.Int(m.Option("begin"))
|
||||||
stack.define(key, value)
|
_get_stack(m).push(f)
|
||||||
}
|
}
|
||||||
func _script_runing(m *ice.Message, nhash string) bool {
|
func _pop_stack(m *ice.Message) *frame {
|
||||||
switch nhash {
|
return _get_stack(m).pop()
|
||||||
case "if", "for", "end":
|
}
|
||||||
|
|
||||||
|
func _exp_true(m *ice.Message, arg string) bool {
|
||||||
|
if arg == "true" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if arg == "false" {
|
||||||
stack := m.Optionv("stack").(*stack)
|
return false
|
||||||
return !stack.fs[len(stack.fs)-1].skip
|
}
|
||||||
}
|
if n1, e1 := strconv.ParseInt(arg, 10, 64); e1 == nil {
|
||||||
func _script_pop_stack(m *ice.Message) {
|
return n1 != 0
|
||||||
stack := m.Optionv("stack").(*stack)
|
}
|
||||||
stack.fs = stack.fs[:len(stack.fs)-1]
|
return false
|
||||||
}
|
|
||||||
func _script_res(m *ice.Message, arg ...interface{}) {
|
|
||||||
stack := m.Optionv("stack").(*stack)
|
|
||||||
stack.res = append(stack.res, kit.Simple(arg...)...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SCRIPT = "script"
|
const SCRIPT = "script"
|
||||||
@ -71,24 +97,21 @@ const SCRIPT = "script"
|
|||||||
func init() {
|
func init() {
|
||||||
Index.Merge(&ice.Context{Commands: map[string]*ice.Command{
|
Index.Merge(&ice.Context{Commands: map[string]*ice.Command{
|
||||||
SCRIPT: {Name: "script name npage text:textarea auto create", Help: "脚本解析", Action: map[string]*ice.Action{
|
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))
|
m.Cmd(MATRIX, mdb.CREATE, m.Option(kit.MDB_NAME))
|
||||||
for _, p := range [][]string{
|
if buf, err := ioutil.ReadFile(m.Option(kit.MDB_TEXT)); err == nil {
|
||||||
[]string{"num", "num", "[0-9]+"},
|
m.Option(kit.MDB_TEXT, string(buf))
|
||||||
[]string{"key", "key", "[abc]+"},
|
}
|
||||||
[]string{"op2", "op2", "[+\\\\-*/%]"},
|
|
||||||
[]string{"op2", "op2", "[>=<]"},
|
m.Option(kit.MDB_TEXT, strings.ReplaceAll(m.Option(kit.MDB_TEXT), "\\", "\\\\"))
|
||||||
[]string{"val", "val", "mul{ num key }"},
|
for _, line := range kit.Split(m.Option(kit.MDB_TEXT), "\n", "\n", "\n") {
|
||||||
[]string{"exp", "exp", "val"},
|
if strings.HasPrefix(strings.TrimSpace(line), "#") {
|
||||||
[]string{"exp", "exp", "val op2 val"},
|
continue
|
||||||
[]string{"stm", "var", "var key = exp"},
|
}
|
||||||
[]string{"stm", "for", "for exp"},
|
line = strings.ReplaceAll(line, "\\", "\\\\")
|
||||||
[]string{"stm", "if", "if exp"},
|
if list := kit.Split(line, " ", " ", " "); len(list) > 2 {
|
||||||
[]string{"stm", "cmd", "pwd"},
|
m.Cmdx(MATRIX, mdb.INSERT, m.Option(kit.MDB_NAME), list[0], list[1], strings.Join(list[2:], " "))
|
||||||
[]string{"stm", "end", "end"},
|
}
|
||||||
[]string{"script", "script", "rep{ stm }"},
|
|
||||||
} {
|
|
||||||
m.Cmdx(MATRIX, mdb.INSERT, m.Option(kit.MDB_NAME), p)
|
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
"exp": {Name: "exp num op2 num", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
"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]))
|
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)
|
n1, e1 := strconv.ParseInt(arg[0], 10, 64)
|
||||||
n2, e2 := strconv.ParseInt(arg[2], 10, 64)
|
n2, e2 := strconv.ParseInt(arg[2], 10, 64)
|
||||||
m.Debug(" %v %v %v", n1, arg[1], n2)
|
|
||||||
switch arg[1] {
|
switch arg[1] {
|
||||||
case ">":
|
case ">":
|
||||||
if e1 == nil && e2 == nil {
|
if e1 == nil && e2 == nil {
|
||||||
@ -112,6 +133,12 @@ func init() {
|
|||||||
} else {
|
} else {
|
||||||
m.Echo("%t", arg[0] > arg[2])
|
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 "+":
|
case "+":
|
||||||
if e1 == nil && e2 == nil {
|
if e1 == nil && e2 == nil {
|
||||||
m.Echo("%d", n1+n2)
|
m.Echo("%d", n1+n2)
|
||||||
@ -146,33 +173,27 @@ func init() {
|
|||||||
m.Echo(arg[0], arg[1], arg[2])
|
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) {
|
"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) {
|
"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) {
|
"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) {
|
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
if len(arg) < 2 {
|
if len(arg) < 2 {
|
||||||
@ -183,13 +204,13 @@ func init() {
|
|||||||
stack := &stack{}
|
stack := &stack{}
|
||||||
stack.push(&frame{})
|
stack.push(&frame{})
|
||||||
m.Option("stack", stack)
|
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.Cmdy(MATRIX, PARSE, arg[0], arg[1], arg[2], func(nhash string, hash int, word []string, begin int, stream *lex.Stream) (int, []string) {
|
||||||
m.Debug("script %v %v", nhash, word)
|
m.Option("stream", stream)
|
||||||
if _, ok := c.Commands[SCRIPT].Action[nhash]; ok && _script_runing(m, nhash) {
|
if _, ok := c.Commands[SCRIPT].Action[nhash]; ok && stack.can_run(nhash) {
|
||||||
msg := m.Cmd(SCRIPT, nhash, word)
|
msg := m.Cmd(SCRIPT, nhash, word, ice.Option{"begin", begin})
|
||||||
return hash, msg.Resultv(), rest
|
return hash, msg.Resultv()
|
||||||
}
|
}
|
||||||
return hash, word, rest
|
return hash, word
|
||||||
})
|
})
|
||||||
m.Resultv(stack.res)
|
m.Resultv(stack.res)
|
||||||
}},
|
}},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user