1
0
forked from x/ContextOS

mac add yac 添加了yac模块,重构了cli模块,可以随时修改语法规则

This commit is contained in:
shaoying 2018-01-16 00:45:23 +08:00
parent 2375806ff9
commit 2b0d7e9777
6 changed files with 728 additions and 271 deletions

View File

@ -1,58 +1,4 @@
@lex lex
~cli
@lex lex
~aaa login root root
~ssh dial chat.shylinux.com:9090 true
sleep 1
~host1
~aaa login root root
~web serve
~nfs load usr/sess.txt
var sessid = $result
if -n $sessid
~host1 remote context mpa register $sessid
else
~host1 remote context mpa register terminal shhylinux term term term 1
let sessid $result
end
~host1 cache sessid $sessid
~host1 remote cache sessid $sessid
~nfs save usr/sess.txt $sessid
~nfs genqr usr/sess.png "terminal: " $sessid
return
return
return
# ~ssh dial chat.shylinux.com:9090 true
# ~cli
# remote slaver listen ":9393" tcp
# ~ssh
# listen :9191
~tcp
listen :9393
# ~tcp dial ":9393"
# @debug on
# ~aaa
# login shy shy
# ~mdb
# open chat:chat@/chat mysql
# ~web listen
# @debug on
# ~nfs
# open hi.txt
@debug
~web spawn hi he ./
route template /tpl ./usr/msg.tpl
route script /php ./usr/msg.php
route script /who who
~hi listen ./ ":9494"
master nice
return
login shy shy

View File

@ -20,11 +20,12 @@ import ( // {{{
// }}}
type CLI struct {
type CLI struct { // {{{
out io.WriteCloser
bio *bufio.Reader
lines []string
yac *ctx.Message
lex *ctx.Message
target *ctx.Context
alias map[string][]string
@ -32,6 +33,8 @@ type CLI struct {
*ctx.Context
}
// }}}
func (cli *CLI) print(str string, arg ...interface{}) bool { // {{{
if cli.out != nil {
fmt.Fprintf(cli.out, str, arg...)
@ -45,18 +48,28 @@ func (cli *CLI) parse(m *ctx.Message) (cmd []string) { // {{{
line := m.Cap("next")
if m.Cap("next", ""); line == "" {
if cli.bio == nil {
line = cli.lines[m.Capi("pos")]
m.Capi("pos", 1)
line = cli.lines[m.Capi("pos", 1)-1]
} else {
cli.print(m.Conf("PS1"))
l, e := cli.bio.ReadString('\n')
m.Assert(e)
line = l
if l, e := cli.bio.ReadString('\n'); m.Assert(e) {
line = l
}
}
}
if cli.yac != nil {
if line == "\n" && cli.out != nil {
line = m.Cap("back")
m.Cap("back", "")
}
yac := m.Spawn(cli.yac.Target())
yac.Cmd("parse", "line", "void", line+"\n")
return nil
}
if line = strings.TrimSpace(line); len(line) == 0 && cli.out != nil {
line = m.Cap("back")
m.Cap("back", "")
@ -66,7 +79,18 @@ func (cli *CLI) parse(m *ctx.Message) (cmd []string) { // {{{
}
ls := []string{}
if cli.lex == nil {
if cli.lex != nil {
rest := line
for len(rest) > 0 {
lex := m.Spawn(cli.lex.Target())
lex.Cmd("split", rest, "word", "void")
if !lex.Gets("result") {
break
}
ls = append(ls, lex.Meta["result"][1])
rest = lex.Meta["result"][2]
}
} else {
ls = strings.Split(line, " ")
cs := []string{}
for i := 0; i < len(ls); i++ {
@ -79,10 +103,6 @@ func (cli *CLI) parse(m *ctx.Message) (cmd []string) { // {{{
cs = append(cs, ls[i])
}
ls = cs
} else {
lex := m.Spawn(cli.lex.Target())
m.Assert(lex.Cmd("split", line, "void"))
ls = lex.Meta["result"]
}
if !cli.Has("skip") || !cli.Pulse.Caps("skip") {
@ -277,7 +297,7 @@ func (cli *CLI) check(arg []string) bool { // {{{
// }}}
func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{
c.Caches = map[string]*ctx.Cache{}
c.Configs = map[string]*ctx.Config{}
c.Caches["skip"] = &ctx.Cache{Name: "跳过执行", Value: cli.Pulse.Cap("skip"), Help: "命令只解析不执行"}
@ -285,6 +305,7 @@ func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
s := new(CLI)
s.Context = c
s.lex = cli.lex
s.yac = cli.yac
if m.Has("for") {
s.lines = append(s.lines, cli.lines[cli.Pulse.Capi("pos")-1:]...)
} else {
@ -293,7 +314,8 @@ func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
return s
}
func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server {
// }}}
func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
cli.Caches["target"] = &ctx.Cache{Name: "操作目标", Value: cli.Name, Help: "命令操作的目标"}
cli.Caches["result"] = &ctx.Cache{Name: "执行结果", Value: "", Help: "前一条命令的执行结果"}
cli.Caches["back"] = &ctx.Cache{Name: "前一条指令", Value: "", Help: "前一条指令"}
@ -314,11 +336,11 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server {
m.Assert(lex != nil, "词法解析模块不存在")
if lex.Cap("status") != "start" {
lex.Target().Start(lex)
m.Spawn(lex.Target()).Cmd("train", "'[^']*'")
m.Spawn(lex.Target()).Cmd("train", "\"[^\"]*\"")
m.Spawn(lex.Target()).Cmd("train", "[^ \t\n]+")
m.Spawn(lex.Target()).Cmd("train", "[ \n\t]+", "void", "void")
m.Spawn(lex.Target()).Cmd("train", "#[^\n]*\n", "void", "void")
m.Spawn(lex.Target()).Cmd("train", "'[^']*'", "word", "word")
m.Spawn(lex.Target()).Cmd("train", "\"[^\"]*\"", "word", "word")
m.Spawn(lex.Target()).Cmd("train", "[^\t \n]+", "word", "word")
m.Spawn(lex.Target()).Cmd("train", "[\t \n]+", "void", "void")
m.Spawn(lex.Target()).Cmd("train", "#[^\n]*\n", "help", "void")
}
cli.lex = lex
return arg[0]
@ -326,6 +348,27 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server {
return x.Value
// }}}
}}
cli.Configs["yac"] = &ctx.Config{Name: "词法解析器", Value: "", Help: "命令行词法解析器", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string {
if len(arg) > 0 && len(arg[0]) > 0 { // {{{
cli, ok := m.Target().Server.(*CLI)
m.Assert(ok, "模块类型错误")
yac := m.Find(arg[0], true)
m.Assert(yac != nil, "词法解析模块不存在")
if yac.Cap("status") != "start" {
yac.Target().Start(yac)
m.Spawn(yac.Target()).Cmd("train", "void", "void", "[\t ]+")
m.Spawn(yac.Target()).Cmd("train", "tran", "tran", "mul{", "@", "$", "}", "opt{", "[a-zA-Z0-9]+", "}")
m.Spawn(yac.Target()).Cmd("train", "word", "word", "rep{", "mul{", "~", "!", "tran", "\"[^\"]*\"", "'[^']*'", "[a-zA-Z0-9_/.]+", "}", "}")
m.Spawn(yac.Target()).Cmd("train", "tran", "tran", "$", "(", "word", ")")
m.Spawn(yac.Target()).Cmd("train", "line", "line", "opt{", "word", "}", "mul{", ";", "\n", "#[^\n]*\n", "}")
}
cli.yac = yac
return arg[0]
}
return x.Value
// }}}
}}
cli.Configs["PS1"] = &ctx.Config{Name: "命令行提示符(target/detail)", Value: "target", Help: "命令行提示符target:显示当前模块detail:显示详细信息", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string {
if len(arg) > 0 { // {{{
return arg[0]
@ -383,7 +426,8 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server {
return cli
}
func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
// }}}
func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{
cli.Caches["#"] = &ctx.Cache{Name: "参数个数", Value: fmt.Sprintf("%d", len(arg)), Help: "参数个数"}
for i, v := range arg {
cli.Caches[fmt.Sprintf("%d", i)] = &ctx.Cache{Name: "执行参数", Value: v, Help: "执行参数"}
@ -404,10 +448,11 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
m.Cap("init.shy", arg[0])
}
m.Cap("next", "source "+m.Cap("init.shy"))
m.Cap("next", fmt.Sprintf("source %s\n", m.Cap("init.shy")))
cli.bio = bufio.NewReader(os.Stdin)
cli.out = os.Stdout
m.Conf("lex", "lex")
// m.Conf("lex", "lex")
m.Conf("yac", "yac")
m.Cap("stream", "stdout")
} else if stream, ok := m.Data["file"]; ok {
if bio, ok := stream.(*bufio.Reader); ok {
@ -427,7 +472,8 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
go m.AssertOne(m, true, func(m *ctx.Message) {
for !m.Caps("exit") {
if cmd := cli.parse(m); cmd != nil {
m.Spawn(cli.target).Set("detail", cmd...).Post(cli.Context)
msg := m.Spawn(cli.target).Set("detail", cmd...)
msg.Post(cli.Context)
}
}
}, func(m *ctx.Message) {
@ -443,7 +489,8 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
return !m.Caps("exit")
}
if !msg.Has("result") && cli.Owner == ctx.Index.Owner {
if !msg.Hand && cli.Owner == ctx.Index.Owner {
msg.Hand = true
msg.Log("system", nil, "%v", msg.Meta["detail"])
msg.Set("result").Set("append")
@ -468,11 +515,6 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
}
}
result := strings.TrimRight(strings.Join(msg.Meta["result"], ""), "\n")
if m.Cap("result", result); len(result) > 0 {
cli.print(result + "\n")
}
if msg.Target().Context() != nil || msg.Target() == ctx.Index {
cli.target = msg.Target()
}
@ -489,7 +531,8 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
return !cli.Pulse.Has("save")
}
func (cli *CLI) Close(m *ctx.Message, arg ...string) bool {
// }}}
func (cli *CLI) Close(m *ctx.Message, arg ...string) bool { // {{{
switch cli.Context {
case m.Target():
if p, ok := cli.Context.Context().Server.(*CLI); ok {
@ -519,6 +562,8 @@ func (cli *CLI) Close(m *ctx.Message, arg ...string) bool {
return true
}
// }}}
var Pulse *ctx.Message
var Index = &ctx.Context{Name: "cli", Help: "管理中心",
Caches: map[string]*ctx.Cache{
@ -526,8 +571,57 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
},
Configs: map[string]*ctx.Config{},
Commands: map[string]*ctx.Command{
"tran": &ctx.Command{Name: "tran word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if _, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{
switch len(arg) {
case 2:
switch arg[0] {
case "$":
m.Echo(m.Cap(arg[1]))
case "@":
m.Echo(m.Conf(arg[1]))
}
default:
m.Set("result", arg[2:len(arg)-1]...)
}
} // }}}
}},
"word": &ctx.Command{Name: "word word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{
msg := m.Spawn(cli.target)
if a, ok := cli.alias[arg[0]]; ok {
msg.Set("detail", a...)
msg.Meta["detail"] = append(msg.Meta["detail"], arg[1:]...)
} else {
msg.Set("detail", arg...)
}
msg.Post(cli.Context)
if m.Hand = false; msg.Hand {
m.Hand = true
m.Meta["result"] = msg.Meta["result"]
}
} // }}}
}},
"line": &ctx.Command{Name: "line word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{
arg = arg[:len(arg)-1]
result := strings.TrimRight(strings.Join(arg, ""), "\n")
if m.Cap("result", result); len(result) > 0 {
cli.print(result + "\n")
}
if m.Cap("back", ""); cli.bio != nil {
cli.lines = append(cli.lines, strings.Join(arg, " "))
m.Capi("nline", 1)
m.Capi("pos", 1)
}
} // }}}
}},
"alias": &ctx.Command{Name: "alias [short [long]]|[delete short]", Help: "查看、定义或删除命令别名, short: 命令别名, long: 命令原名, delete: 删除别名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) {
if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{
switch len(arg) {
case 0:
for k, v := range cli.alias {
@ -544,49 +638,49 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
m.Echo("%s: %v\n", arg[0], cli.alias[arg[0]])
}
}
}
} // }}}
}},
"sleep": &ctx.Command{Name: "sleep time", Help: "睡眠, time(ns/us/ms/s/m/h): 时间值(纳秒/微秒/毫秒/秒/分钟/小时)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{
if d, e := time.ParseDuration(arg[0]); m.Assert(e) {
m.Log("info", nil, "sleep %v", d)
time.Sleep(d)
m.Log("info", nil, "sleep %v done", d)
}
}
} // }}}
}},
"var": &ctx.Command{Name: "var a [= exp]", Help: "定义变量, a: 变量名, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{
val := ""
if len(arg) > 2 {
val = cli.express(arg[2:])
}
cli.Pulse.Cap(arg[0], arg[0], val, "临时变量")
}
} // }}}
}},
"let": &ctx.Command{Name: "let a = exp", Help: "设置变量, a: 变量名, exp: 表达式(a {+|-|*|/|%} b)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{
m.Echo(cli.Pulse.Cap(arg[0], cli.express(arg[2:])))
}
} // }}}
}},
"source": &ctx.Command{Name: "source file", Help: "运行脚本, file: 脚本文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{
if f, e := os.Open(arg[0]); m.Assert(e) {
m.Put("option", "file", f).Start(fmt.Sprintf("%s%d", key, Pulse.Capi("level", 1)), "脚本文件")
<-m.Target().Exit
Pulse.Capi("level", -1)
}
}
} // }}}
}},
"return": &ctx.Command{Name: "return result...", Help: "结束脚本, rusult: 返回值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{
call := cli.Requests[len(cli.Requests)-1]
call.Set("result", arg...)
cli.Pulse.Caps("exit", true)
}
} // }}}
}},
"if": &ctx.Command{Name: "if exp", Help: "条件语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{
if m.Target(m.Source()); (cli.Has("skip") && cli.Pulse.Caps("skip")) || !cli.check(arg) {
m.Add("option", "skip")
}
@ -594,33 +688,33 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
m.Put("option", "file", cli.bio).Start(fmt.Sprintf("%s%d", key, Pulse.Capi("level", 1)), "条件语句")
<-m.Target().Exit
Pulse.Capi("level", -1)
}
} // }}}
}},
"elif": &ctx.Command{Name: "elif exp", Help: "条件语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{
if cli.Pulse.Caps("skip", !cli.Pulse.Caps("else")) {
return
}
cli.Pulse.Caps("else", cli.Pulse.Caps("skip", !cli.check(arg)))
}
} // }}}
}},
"else": &ctx.Command{Name: "else", Help: "条件语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{
cli.Pulse.Caps("skip", !cli.Pulse.Caps("else"))
}
} // }}}
}},
"end": &ctx.Command{Name: "end", Help: "结束语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{
if cli.Pulse.Caps("exit", true); cli.Pulse.Has("for") && !cli.Pulse.Caps("skip") {
cli.Pulse.Caps("exit", false)
cli.Pulse.Cap("pos", "0")
}
cli.bio = nil
}
} // }}}
}},
"for": &ctx.Command{Name: "for exp", Help: "循环语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{
if cli.Pulse.Has("for") && cli.Pulse.Capi("pos") == 1 {
cli.Pulse.Caps("skip", !cli.check(arg))
return
@ -632,10 +726,10 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
m.Put("option", "file", cli.bio).Start(fmt.Sprintf("%s%d", key, Pulse.Capi("level", 1)), "循环语句")
<-m.Target().Exit
Pulse.Capi("level", -1)
}
} // }}}
}},
"function": &ctx.Command{Name: "function name", Help: "函数定义, name: 函数名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{
if _, ok := cli.Context.Context().Server.(*CLI); ok {
m.Target(m.Source().Context())
} else {
@ -645,10 +739,10 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
m.Add("option", "skip").Add("option", "save")
m.Put("option", "file", cli.bio).Start(arg[0], "函数定义")
<-m.Target().Exit
}
} // }}}
}},
"call": &ctx.Command{Name: "call name arg...", Help: "函数调用, name: 函数名, arg: 参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
m.Target(m.Source())
m.Target(m.Source()) // {{{
m.BackTrace(func(msg *ctx.Message) bool {
if fun := msg.Find(arg[0], false); fun != nil {
fun.Add("detail", arg[0], arg[1:]...).Target().Start(fun)
@ -657,7 +751,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
return false
}
return true
})
}) // }}}
}},
},
}

View File

@ -443,6 +443,7 @@ func (c *Context) Del(arg ...string) { // {{{
type Message struct {
code int
time time.Time
Hand bool
Recv chan bool
Wait chan bool
@ -973,10 +974,8 @@ func (m *Message) Exec(key string, arg ...string) string { // {{{
arg = m.Meta["args"]
}
m.Hand = true
x.Hand(m.Set("result").Set("append"), s, key, arg...)
if !m.Has("result") {
m.Meta["result"] = nil
}
if x.Appends != nil {
for _, v := range m.Meta["append"] {
@ -1112,7 +1111,7 @@ func (m *Message) Conf(key string, arg ...string) string { // {{{
} else {
x.Value = arg[0]
}
m.Log("conf", s, "%s %v", x.Name, x.Value)
// m.Log("conf", s, "%s %v", x.Name, x.Value)
return x.Value
case 0:
if x.Hand != nil {
@ -1190,10 +1189,10 @@ func (m *Message) Cap(key string, arg ...string) string { // {{{
} else {
x.Value = arg[0]
}
m.Log("debug", s, "%s %s", x.Name, x.Value)
// m.Log("debug", s, "%s %s", x.Name, x.Value)
return x.Value
case 0:
m.Log("debug", s, "%s %s", x.Name, x.Value)
// m.Log("debug", s, "%s %s", x.Name, x.Value)
if x.Hand != nil {
return x.Hand(m, x)
}

View File

@ -1,23 +1,28 @@
package lex
import (
package lex // {{{
// }}}
import ( // {{{
"context"
"fmt"
"strconv"
)
type State struct {
star bool
next int
hash int
}
// }}}
type Seed struct {
type Seed struct { // {{{
page int
hash int
word string
}
type LEX struct {
// }}}
type State struct { // {{{
star bool
next int
hash int
}
// }}}
type LEX struct { // {{{
seed []*Seed
page map[string]int
hash map[string]int
@ -29,52 +34,71 @@ type LEX struct {
*ctx.Context
}
func (lex *LEX) train(seed []byte, arg ...string) {
cell, page, hash := 128, 1, 1
if len(arg) > 0 {
if x, ok := lex.hash[arg[0]]; ok {
hash = x
} else {
hash = lex.Capi("nhash", 1)
lex.hash[arg[0]] = hash
}
}
if len(arg) > 1 {
if x, ok := lex.page[arg[1]]; ok {
page = x
} else {
lex.mat = append(lex.mat, make(map[byte]*State))
page = lex.Capi("nline", 1)
lex.page[arg[1]] = page
lex.Capi("npage", 1)
}
}
lex.Log("debug", nil, "%d %d %v", page, hash, seed)
lex.seed = append(lex.seed, &Seed{page, hash, string(seed)})
lex.Capi("nseed", 1)
lex.Cap("stream", fmt.Sprintf("%s,%s,%s", lex.Cap("nseed"), lex.Cap("npage"), lex.Cap("nhash")))
// }}}
func (lex *LEX) index(hash string, h string) int { // {{{
if x, e := strconv.Atoi(h); e == nil {
return x
}
which := lex.page
switch hash {
case "npage":
which = lex.page
case "nhash":
which = lex.hash
}
if x, ok := which[h]; ok {
return x
}
x := lex.Capi(hash, 1)
which[h] = x
return x
}
// }}}
func (lex *LEX) charset(c byte) []byte { // {{{
switch c {
case 't':
return []byte{'\t'}
case 'n':
return []byte{'\n'}
case 's':
return []byte{'\t', ' ', '\n'}
case 'd':
return []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
case 'x':
return []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F'}
}
return []byte{c}
}
// }}}
func (lex *LEX) train(page int, hash int, seed []byte) int { // {{{
cn := make([]bool, lex.Capi("ncell"))
c := make([]byte, 0, lex.Capi("ncell"))
sn := make([]bool, lex.Capi("nline"))
s := []int{page}
c := make([]byte, 0, cell)
sn := make([]bool, len(lex.mat))
cn := make([]bool, cell)
ends := make([]*State, 0, len(seed))
ends := []*State{}
for p, set := 0, true; p < len(seed); p++ {
for p := 0; p < len(seed); p++ {
switch seed[p] {
case '[':
p++
set := true
if seed[p] == '^' {
set = false
p++
if p++; seed[p] == '^' {
set, p = false, p+1
}
for ; seed[p] != ']'; p++ {
if seed[p] == '\\' {
p++
cn[seed[p]] = true
for _, s := range lex.charset(seed[p]) {
cn[s] = true
}
continue
}
@ -87,6 +111,7 @@ func (lex *LEX) train(seed []byte, arg ...string) {
cn[i] = true
}
p += 2
continue
}
cn[seed[p]] = true
@ -100,18 +125,21 @@ func (lex *LEX) train(seed []byte, arg ...string) {
}
case '.':
for i := 0; i < cell; i++ {
for i := 0; i < len(cn); i++ {
c = append(c, byte(i))
}
case '\\':
p++
fallthrough
for _, s := range lex.charset(seed[p]) {
c = append(c, s)
}
default:
c = append(c, seed[p])
}
lex.Log("debug", nil, "page: \033[31m%v\033[0m", s)
lex.Log("debug", nil, "cell: \033[32m%v\033[0m", c)
lex.Log("debug", nil, "page: \033[31m%d %v\033[0m", len(s), s)
lex.Log("debug", nil, "cell: \033[32m%d %v\033[0m", len(c), c)
flag := '\000'
if p+1 < len(seed) {
@ -125,11 +153,11 @@ func (lex *LEX) train(seed []byte, arg ...string) {
for i := 0; i < len(s); i++ {
for line, j := 0, byte(0); int(j) < len(c); j++ {
state := lex.mat[s[i]][c[j]]
lex.Log("debug", nil, "GET(%d,%d): %v", s[i], c[j], state)
if state == nil {
state = new(State)
state = &State{}
lex.Capi("nnode", 1)
}
lex.Log("debug", nil, "GET(%d,%d): %v", s[i], c[j], state)
switch flag {
case '+':
@ -140,7 +168,7 @@ func (lex *LEX) train(seed []byte, arg ...string) {
case '?':
if sn[s[i]] = true; p == len(seed)-1 {
for _, n := range ends {
if n.next == s[i] && n.hash == 0 {
if n.next == s[i] {
lex.Log("debug", nil, "GET() state:%v", n)
n.hash = hash
lex.Log("debug", nil, "END() state:%v", n)
@ -153,25 +181,26 @@ func (lex *LEX) train(seed []byte, arg ...string) {
state.hash = hash
} else {
if state.next == 0 {
if line == 0 {
line = len(lex.mat)
sn = append(sn, false)
if line == 0 || !lex.Caps("compact") {
lex.mat = append(lex.mat, make(map[byte]*State))
lex.Capi("nline", 1)
line = lex.Capi("nline", 1) - 1
sn = append(sn, false)
}
state.next = line
}
sn[state.next] = true
}
if s, ok := lex.state[*state]; ok {
if s, ok := lex.state[*state]; !ok {
lex.state[*state] = state
lex.Capi("nreal", 1)
} else {
state = s
}
lex.state[*state] = state
lex.mat[s[i]][c[j]] = state
lex.Log("debug", nil, "SET(%d,%d): %v", s[i], c[j], state)
lex.Log("debug", nil, "SET(%d,%d): %v(%s,%s)", s[i], c[j], state, lex.Cap("nnode"), lex.Cap("nreal"))
ends = append(ends, state)
}
}
@ -184,25 +213,20 @@ func (lex *LEX) train(seed []byte, arg ...string) {
sn[i] = false
}
}
return hash
}
func (lex *LEX) parse(line []byte, arg ...string) (word []byte, hash int, rest []byte) {
page, begin, end := 1, 0, 0
if len(arg) > 0 {
if x, ok := lex.page[arg[0]]; ok {
page = x
} else {
return line, 0, nil
}
}
// }}}
func (lex *LEX) parse(page int, line []byte) (hash int, word []byte, rest []byte) { // {{{
for star, s, i := 0, page, 0; s != 0 && i < len(line); i++ {
pos := 0
c := line[i]
if c == '\\' && i < len(line)-1 {
c = 'a'
end++
i++
for star, s := 0, page; s != 0 && pos < len(line); pos++ {
c := line[pos]
if c == '\\' && pos < len(line)-1 {
pos++
c = lex.charset(line[pos])[0]
}
state := lex.mat[s][c]
@ -216,27 +240,31 @@ func (lex *LEX) parse(line []byte, arg ...string) (word []byte, hash int, rest [
break
}
if state, ok := lex.mat[star][c]; star == 0 || !ok || state == nil || !state.star {
if state, ok := lex.mat[star][c]; !ok || state == nil || !state.star {
star = 0
}
if end++; state.star {
if state.star {
star = s
}
word = append(word, c)
if s, hash = state.next, state.hash; s == 0 {
s, star = star, 0
}
}
if hash == 0 {
begin, end = 0, 0
pos, word = 0, word[:0]
}
rest = line[pos:]
word, rest = line[begin:end], line[end:]
lex.Log("debug", nil, "\033[31m[%v]\033[0m %d [%v]", string(word), hash, string(rest))
return
}
func (lex *LEX) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
// }}}
func (lex *LEX) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{
c.Caches = map[string]*ctx.Cache{}
c.Configs = map[string]*ctx.Config{}
@ -245,37 +273,42 @@ 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.Message = m
// }}}
func (lex *LEX) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
if lex.Context == Index {
Pulse = m
}
lex.Caches["ncell"] = &ctx.Cache{Name: "字符上限", Value: "128", Help: "字符上限"}
lex.Caches["nlang"] = &ctx.Cache{Name: "集合上限", Value: "16", Help: "集合上限"}
lex.Caches["nseed"] = &ctx.Cache{Name: "种子数量", Value: "0", Help: "种子数量"}
lex.Caches["npage"] = &ctx.Cache{Name: "集合数量", Value: "1", Help: "集合数量"}
lex.Caches["nhash"] = &ctx.Cache{Name: "类型数量", Value: "1", 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: "1", Help: "状态数量"}
lex.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: "16", Help: "状态数量"}
lex.Caches["nnode"] = &ctx.Cache{Name: "节点数量", Value: "0", Help: "节点数量"}
lex.Caches["npush"] = &ctx.Cache{Name: "节点数量", Value: "0", Help: "节点数量", Hand: func(m *ctx.Message, x *ctx.Cache, arg ...string) string {
return fmt.Sprintf("%d", len(m.Target().Server.(*LEX).state))
}}
lex.Caches["nreal"] = &ctx.Cache{Name: "实点数量", Value: "0", Help: "实点数量"}
lex.Caches["compact"] = &ctx.Cache{Name: "紧凑模式", Value: "true", Help: "实点数量"}
return lex
}
func (lex *LEX) Start(m *ctx.Message, arg ...string) bool {
lex.seed = make([]*Seed, 0, 10)
// }}}
func (lex *LEX) Start(m *ctx.Message, arg ...string) bool { // {{{
lex.Message = m
lex.seed = make([]*Seed, 0, 9)
lex.page = map[string]int{"nil": 0}
lex.hash = map[string]int{"nil": 0}
lex.mat = make([]map[byte]*State, lex.Capi("nlang"))
lex.state = make(map[State]*State)
lex.mat = make([]map[byte]*State, 2, 10)
for i := 0; i < len(lex.mat); i++ {
lex.mat[i] = make(map[byte]*State)
}
lex.Message = m
return false
}
func (lex *LEX) Close(m *ctx.Message, arg ...string) bool {
// }}}
func (lex *LEX) Close(m *ctx.Message, arg ...string) bool { // {{{
switch lex.Context {
case m.Target():
case m.Source():
@ -283,77 +316,90 @@ func (lex *LEX) Close(m *ctx.Message, arg ...string) bool {
return true
}
var Index = &ctx.Context{Name: "lex", Help: "词法解析",
// }}}
var Pulse *ctx.Message
var Index = &ctx.Context{Name: "lex", Help: "词法中心",
Caches: map[string]*ctx.Cache{},
Configs: map[string]*ctx.Config{},
Commands: map[string]*ctx.Command{
"train": &ctx.Command{Name: "train seed [hash [page]", Help: "添加词法规则", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
lex, ok := m.Target().Server.(*LEX)
m.Assert(ok, "模块类型错误")
m.Assert(len(arg) > 0, "参数错误")
if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { // {{{
page, hash := 1, 1
if len(arg) > 2 {
page = lex.index("npage", arg[2])
}
if len(arg) > 1 {
hash = lex.index("nhash", arg[1])
}
lex.train([]byte(arg[0]), arg[1:]...)
if lex.mat[page] == nil {
lex.mat[page] = map[byte]*State{}
}
lex.seed = append(lex.seed, &Seed{page, hash, string(arg[0])})
lex.Log("info", nil, "%d %d %d %v", page, hash, lex.Capi("nseed", 1), arg[0])
lex.Cap("stream", fmt.Sprintf("%s,%s,%s", lex.Cap("nseed"), lex.Cap("npage"), lex.Cap("nhash")))
m.Echo("%d", lex.train(page, hash, []byte(arg[0])))
} // }}}
}},
"parse": &ctx.Command{Name: "parse line [page]", Help: "解析单词", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
lex, ok := m.Target().Server.(*LEX)
m.Assert(ok, "模块类型错误")
m.Assert(len(arg) > 0, "参数错误")
word, hash, rest := lex.parse([]byte(arg[0]), arg[1:]...)
m.Add("result", string(word), fmt.Sprintf("%d", hash), string(rest))
}},
"split": &ctx.Command{Name: "split line page1 [page2]", Help: "分割语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
lex, ok := m.Target().Server.(*LEX)
m.Assert(ok, "模块类型错误")
m.Assert(len(arg) > 1, "参数错误")
for line := arg[0]; len(line) > 0; {
word, hash, rest := lex.parse([]byte(line), arg[1:]...)
line = string(rest)
word, hash, rest = lex.parse([]byte(line), arg[2:]...)
line = string(rest)
if hash == 0 {
break
if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { // {{{
page := 1
if len(arg) > 1 {
page = lex.index("npage", arg[1])
}
if len(word) > 1 {
switch word[0] {
case '"', '\'':
word = word[1 : len(word)-1]
hash, word, rest := lex.parse(page, []byte(arg[0]))
m.Add("result", fmt.Sprintf("%d", hash), string(word), string(rest))
} // }}}
}},
"split": &ctx.Command{Name: "split line page void help", Help: "分割语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { // {{{
page := 1
if len(arg) > 1 {
page = lex.index("npage", arg[1])
}
void := 2
if len(arg) > 2 {
void = lex.index("npage", arg[2])
}
help := 2
if len(arg) > 3 {
help = lex.index("npage", arg[3])
}
rest := []byte(arg[0])
_, _, rest = lex.parse(help, []byte(rest))
_, _, rest = lex.parse(void, []byte(rest))
hash, word, rest := lex.parse(page, []byte(rest))
m.Add("result", fmt.Sprintf("%d", hash), string(word), string(rest))
} // }}}
}},
"info": &ctx.Command{Name: "info", Help: "显示缓存", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { // {{{
for i, v := range lex.seed {
m.Echo("seed: %d %v\n", i, v)
}
for i, v := range lex.page {
m.Echo("page: %s %d\n", i, v)
}
for i, v := range lex.hash {
m.Echo("hash: %s %d\n", i, v)
}
for i, v := range lex.state {
m.Echo("node: %v %v\n", i, v)
}
for i, v := range lex.mat {
for k, v := range v {
m.Echo("node: %v %v %v\n", i, k, v)
}
}
m.Add("result", string(word))
}
} // }}}
}},
"cache": &ctx.Command{Name: "cache", Help: "显示缓存", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
lex, ok := m.Target().Server.(*LEX)
m.Assert(ok, "模块类型错误")
for i, v := range lex.seed {
m.Echo("seed: %d %v\n", i, v)
}
for i, v := range lex.page {
m.Echo("page: %s %d\n", i, v)
}
for i, v := range lex.hash {
m.Echo("hash: %s %d\n", i, v)
}
for i, v := range lex.state {
m.Echo("node: %v %v\n", i, v)
}
for i, v := range lex.mat {
for k, v := range v {
m.Echo("node: %v %v %v\n", i, k, v)
}
}
}},
},
Index: map[string]*ctx.Context{
"void": &ctx.Context{Name: "void",
Commands: map[string]*ctx.Command{"split": &ctx.Command{}},
},
},
}

371
src/context/yac/yac.go Normal file
View File

@ -0,0 +1,371 @@
package yac // {{{
// }}}
import ( // {{{
"context"
"fmt"
"strings"
)
// }}}
type Seed struct { // {{{
page int
hash int
word []string
}
// }}}
type State struct { // {{{
star int
next int
hash int
}
// }}}
type YAC struct { // {{{
seed []*Seed
page map[string]int
hash map[string]int
hand map[int]string
state map[State]*State
mat []map[byte]*State
lex *ctx.Message
*ctx.Message
*ctx.Context
}
// }}}
func (yac *YAC) train(page, hash int, word []string) ([]*State, int) { // {{{
if yac.mat[page] == nil {
yac.mat[page] = map[byte]*State{}
for i := 0; i < yac.Capi("nlang"); i++ {
yac.mat[page][byte(i)] = nil
}
}
sn := make([]bool, yac.Capi("nline"))
ss := []int{page}
begin := page
point := []*State{}
ends := []*State{}
state := []*State{}
mul := false
skip := len(word)
for i, n := 0, 1; i < len(word); i += n {
if !mul {
if hash <= 0 && word[i] == "}" {
if skip = i + 2; hash == -1 {
hash = 0
break
}
return ends, skip
} else {
ends = ends[:0]
}
}
for _, s := range ss {
switch word[i] {
case "opt{":
sn[s] = true
state, n = yac.train(s, 0, word[i+1:])
for _, x := range state {
for i := len(sn); i <= x.next; i++ {
sn = append(sn, false)
}
sn[x.next] = true
point = append(point, x)
}
case "rep{":
sn[s] = true
state, n = yac.train(s, -1, word[i+1:])
for _, x := range state {
x.star = s
sn[x.next] = true
point = append(point, x)
yac.Pulse.Log("info", nil, "END: %v", x)
}
case "mul{":
mul, n = true, 1
goto next
case "}":
if mul {
mul = false
goto next
}
default:
c := byte(0)
if x, ok := yac.page[word[i]]; !ok {
lex := yac.lex.Spawn(yac.lex.Target())
lex.Cmd("parse", word[i], fmt.Sprintf("yac%d", s))
if lex.Gets("result") {
x = lex.Geti("result")
} else {
x = len(yac.mat[s])
lex = yac.lex.Spawn(yac.lex.Target())
lex.Cmd("train", word[i], fmt.Sprintf("%d", x), fmt.Sprintf("yac%d", s))
}
c = byte(x)
} else {
c = byte(x)
}
state := yac.mat[s][c]
yac.Pulse.Log("info", nil, "GET(%d, %d): %v", s, c, state)
if state == nil {
state = &State{}
yac.Pulse.Capi("nnode", 1)
}
if state.next == 0 {
yac.mat = append(yac.mat, map[byte]*State{})
state.next = yac.Pulse.Capi("nline", 1) - 1
for i := 0; i < yac.Capi("nlang"); i++ {
yac.mat[state.next][byte(i)] = nil
}
sn = append(sn, false)
}
sn[state.next] = true
if x, ok := yac.state[*state]; !ok {
yac.Pulse.Capi("nreal", 1)
yac.state[*state] = state
} else {
yac.mat[s][c] = x
}
yac.mat[s][c] = state
yac.Pulse.Log("info", nil, "SET(%d, %d): %v", s, c, state)
ends = append(ends, state)
point = append(point, state)
if s > begin {
begin = s
}
}
}
next:
if !mul {
ss = ss[:0]
for s, b := range sn {
if sn[s] = false; b {
ss = append(ss, s)
}
}
}
}
for _, n := range ss {
if n < yac.Pulse.Capi("nlang") || n >= len(yac.mat) {
continue
}
void := true
for _, x := range yac.mat[n] {
if x != nil {
void = false
break
}
}
if void {
yac.Pulse.Log("info", nil, "DEL: %d %d", yac.Pulse.Capi("nline"), n)
yac.Pulse.Capi("nline", 0, n)
yac.mat = yac.mat[:n]
}
}
for _, n := range ss {
for _, s := range point {
if s.next == n {
yac.Pulse.Log("info", nil, "GET: %v", s)
if s.next >= len(yac.mat) {
s.next = 0
}
if hash > 0 {
s.hash = hash
}
yac.Pulse.Log("info", nil, "SET: %v", s)
}
}
}
return ends, skip
}
// }}}
func (yac *YAC) parse(m *ctx.Message, page, void int, line string) ([]string, string) { // {{{
level := m.Capi("level", 1)
m.Log("info", nil, ">>>%s%d", m.Cap("label")[0:level], level)
hash, word := 0, []string{}
for star, s := 0, page; s != 0 && len(line) > 0; {
lex := yac.lex.Spawn(yac.lex.Target())
lex.Cmd("parse", line, fmt.Sprintf("yac%d", void))
line = lex.Meta["result"][2]
lex = yac.lex.Spawn(yac.lex.Target())
lex.Cmd("parse", line, fmt.Sprintf("yac%d", s))
line = lex.Meta["result"][2]
c := byte(lex.Geti("result"))
state := yac.mat[s][c]
m.Log("info", nil, "get(%d,%d): %s %v", s, c, lex.Meta["result"][1], state)
if state == nil {
for i, x := range yac.mat[s] {
if int(i) >= m.Capi("nlang") || x == nil {
continue
}
m.Log("info", nil, "try(%d,%d): %v", s, i, x)
if w, l := yac.parse(m, int(i), void, line); l != line {
word = append(word, w...)
state = x
line = l
break
}
}
} else {
word = append(word, lex.Meta["result"][1])
}
if state == nil {
s, star = star, 0
continue
}
star, s, hash = state.star, state.next, state.hash
if s == 0 {
s, star = star, 0
}
}
if hash == 0 {
word = word[:0]
} else {
m.Log("info", nil, "%s(%d,%d): %d %v %v", yac.hand[page], page, hash, len(word), word, line)
msg := m.Spawn(m.Source()).Add("detail", yac.hand[page], word...)
if msg.Cmd(); msg.Hand {
word = msg.Meta["result"]
}
m.Log("info", nil, "end(%d,%d): %d %v %v", page, hash, len(word), word, line)
}
m.Log("info", nil, "<<<%s%d", m.Cap("label")[0:level], level)
level = m.Capi("level", -1)
return word, line
}
// }}}
func (yac *YAC) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{
c.Caches = map[string]*ctx.Cache{}
c.Configs = map[string]*ctx.Config{}
s := new(YAC)
s.Context = c
return s
}
// }}}
func (yac *YAC) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
yac.Message = m
if yac.Context == Index {
Pulse = m
}
yac.Caches["ncell"] = &ctx.Cache{Name: "单词上限", Value: "128", Help: "单词上限"}
yac.Caches["nlang"] = &ctx.Cache{Name: "集合上限", Value: "16", Help: "集合上限"}
yac.Caches["nseed"] = &ctx.Cache{Name: "种子数量", Value: "0", Help: "种子数量"}
yac.Caches["npage"] = &ctx.Cache{Name: "集合数量", Value: "0", Help: "集合数量"}
yac.Caches["nhash"] = &ctx.Cache{Name: "类型数量", Value: "0", Help: "类型数量"}
yac.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: "16", Help: "状态数量"}
yac.Caches["nnode"] = &ctx.Cache{Name: "节点数量", Value: "0", Help: "节点数量"}
yac.Caches["nreal"] = &ctx.Cache{Name: "实点数量", Value: "0", Help: "实点数量"}
yac.Caches["level"] = &ctx.Cache{Name: "嵌套层级", Value: "0", Help: "嵌套层级"}
yac.Caches["label"] = &ctx.Cache{Name: "嵌套标记", Value: "####################", Help: "嵌套层级"}
yac.page = map[string]int{"nil": 0}
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) bool { // {{{
yac.Message = m
return false
}
// }}}
func (yac *YAC) Close(m *ctx.Message, arg ...string) bool { // {{{
switch yac.Context {
case m.Target():
case m.Source():
}
return true
}
// }}}
var Pulse *ctx.Message
var Index = &ctx.Context{Name: "yac", Help: "语法中心",
Caches: map[string]*ctx.Cache{},
Configs: map[string]*ctx.Config{},
Commands: map[string]*ctx.Command{
"train": &ctx.Command{Name: "train page hash word...", Help: "添加语法规则, page: 语法集合, hash: 语句类型, word: 语法模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { // {{{
page, ok := yac.page[arg[0]]
if !ok {
page = m.Capi("npage", 1)
yac.page[arg[0]] = page
}
hash, ok := yac.hash[arg[1]]
if !ok {
hash = m.Capi("nhash", 1)
yac.hash[arg[0]] = hash
yac.hand[hash] = arg[0]
}
if yac.lex == nil {
lex := m.Find("lex", true)
lex.Start("lyacc", "语法词法")
yac.lex = lex
}
yac.seed = append(yac.seed, &Seed{page, hash, arg[2:]})
yac.Capi("nseed", 1)
yac.train(page, hash, arg[2:])
} // }}}
}},
"parse": &ctx.Command{Name: "parse page void word...", Help: "解析语句, page: 语法集合, void: 空白语法集合, word: 语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { // {{{
page, ok := yac.page[arg[0]]
m.Assert(ok)
void, ok := yac.page[arg[1]]
m.Assert(ok)
word, rest := yac.parse(m, page, void, strings.Join(arg[2:], " "))
m.Add("result", rest, word...)
} // }}}
}},
},
}
func init() {
yac := &YAC{}
yac.Context = Index
ctx.Index.Register(Index, yac)
}

View File

@ -12,6 +12,7 @@ import (
_ "context/web"
_ "context/lex"
_ "context/yac"
"os"
)