mirror of
https://shylinux.com/x/icebergs
synced 2025-04-25 17:18:05 +08:00
230 lines
6.2 KiB
Go
230 lines
6.2 KiB
Go
package yac
|
|
|
|
import (
|
|
"io"
|
|
"strings"
|
|
|
|
ice "shylinux.com/x/icebergs"
|
|
"shylinux.com/x/icebergs/base/nfs"
|
|
kit "shylinux.com/x/toolkits"
|
|
)
|
|
|
|
const (
|
|
LET = "let"
|
|
IF = "if"
|
|
ELSE = "else"
|
|
FOR = "for"
|
|
BREAK = "break"
|
|
CONTINUE = "continue"
|
|
SWITCH = "switch"
|
|
CASE = "case"
|
|
DEFAULT = "default"
|
|
FUNC = "func"
|
|
CALL = "call"
|
|
RETURN = "return"
|
|
SOURCE = "source"
|
|
INFO = "info"
|
|
PWD = "pwd"
|
|
)
|
|
const (
|
|
KEYWORD = "keyword"
|
|
FUNCTION = "function"
|
|
)
|
|
|
|
func init() {
|
|
Index.MergeCommands(ice.Commands{
|
|
LET: {Name: "let a, b = 1, 2", Hand: func(m *ice.Message, arg ...string) { m.Cmd(EXPR) }},
|
|
IF: {Name: "if a = 1; a > 1 {", Hand: func(m *ice.Message, arg ...string) {
|
|
s, f := _parse_frame(m)
|
|
res := s.expr(m)
|
|
kit.If(s.token() == SPLIT, func() { res = s.expr(m) })
|
|
kit.If(res == ice.FALSE, func() { f.status = DISABLE })
|
|
}},
|
|
ELSE: {Name: "else if a = 1; a > 1 {", Hand: func(m *ice.Message, arg ...string) {
|
|
s, f := _parse_frame(m)
|
|
if s.last.status == DISABLE {
|
|
f.status = 0
|
|
} else {
|
|
f.status, f.pop = DISABLE, func() { f.status = 0 }
|
|
}
|
|
s.reads(m, func(k string) bool {
|
|
if k == IF {
|
|
res := s.expr(m)
|
|
kit.If(s.token() == SPLIT, func() { res = s.expr(m) })
|
|
kit.If(res == ice.FALSE, func() { f.status = DISABLE })
|
|
}
|
|
return true
|
|
})
|
|
}},
|
|
FOR: {Name: "for a = 1; a < 10; a++ {", Hand: func(m *ice.Message, arg ...string) {
|
|
s, f := _parse_frame(m)
|
|
list, status := []Position{s.Position}, f.status
|
|
for f.status = DISABLE; s.token() != BEGIN; list = append(list, s.Position) {
|
|
s.expr(m)
|
|
}
|
|
f.status = status
|
|
res := ice.TRUE
|
|
if len(list) == 1 {
|
|
|
|
} else if len(list) == 2 {
|
|
res = s.expr(m, list[0])
|
|
} else {
|
|
if s.last == nil || s.last.line != s.line {
|
|
res = s.expr(m, list[0])
|
|
} else {
|
|
kit.For(s.last.value, func(k string, v Any) { f.value[k] = v })
|
|
}
|
|
res = s.expr(m, list[1])
|
|
}
|
|
kit.If(res == ice.FALSE, func() { f.status = DISABLE })
|
|
s.Position, f.pop = list[len(list)-1], func() {
|
|
if s.runable() {
|
|
kit.If(len(list) > 3, func() { s.expr(m, list[2]) })
|
|
s.Position = list[0]
|
|
s.Position.skip--
|
|
}
|
|
}
|
|
}},
|
|
BREAK: {Name: "break", Hand: func(m *ice.Message, arg ...string) {
|
|
s := _parse_stack(m)
|
|
if !s.runable() {
|
|
return
|
|
}
|
|
s.stack(func(f *Frame, i int) bool {
|
|
f.status = DISABLE
|
|
defer s.popf(m)
|
|
switch f.key {
|
|
case FOR:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
})
|
|
}},
|
|
CONTINUE: {Name: "continue", Hand: func(m *ice.Message, arg ...string) {
|
|
s := _parse_stack(m)
|
|
if !s.runable() {
|
|
return
|
|
}
|
|
s.stack(func(f *Frame, i int) bool {
|
|
defer s.popf(m)
|
|
switch f.key {
|
|
case FOR:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
})
|
|
}},
|
|
SWITCH: {Name: "switch a = 1; a {", Hand: func(m *ice.Message, arg ...string) {
|
|
s, f := _parse_frame(m)
|
|
res := s.cals(m)
|
|
kit.If(s.token() == SPLIT, func() { res = s.cals(m) })
|
|
f.value["_switch"], f.value["_case"] = res, ""
|
|
}},
|
|
CASE: {Name: "case b:", Hand: func(m *ice.Message, arg ...string) {
|
|
s := _parse_stack(m)
|
|
f := s.peekf()
|
|
f.status = 0
|
|
v := s.cals(m)
|
|
f.status = DISABLE
|
|
if res, ok := v.(Operater); ok {
|
|
if res, ok := res.Operate("==", trans(s.value(m, "_switch"))).(Boolean); ok && res.value {
|
|
f.status, f.value["_case"] = 0, "done"
|
|
}
|
|
}
|
|
}},
|
|
DEFAULT: {Name: "default:", Hand: func(m *ice.Message, arg ...string) {
|
|
s := _parse_stack(m)
|
|
f := s.peekf()
|
|
if f.status = 0; f.value["_case"] == "done" {
|
|
f.status = DISABLE
|
|
}
|
|
s.skip++
|
|
}},
|
|
FUNC: {Name: "func show(a, b) (c, d)", Hand: func(m *ice.Message, arg ...string) {
|
|
s := _parse_stack(m)
|
|
list, key, kind := [][]string{[]string{}}, "", ""
|
|
push := func() { kit.If(key, func() { list[len(list)-1], key, kind = append(list[len(list)-1], key), "", "" }) }
|
|
s.reads(m, func(k string) bool {
|
|
switch k {
|
|
case OPEN:
|
|
defer kit.If(key != "" || len(list) > 1, func() { list = append(list, []string{}) })
|
|
case FIELD, CLOSE:
|
|
case BEGIN:
|
|
return true
|
|
default:
|
|
kit.If(key, func() { kind = k }, func() { key = k })
|
|
return false
|
|
}
|
|
push()
|
|
return false
|
|
})
|
|
kit.If(len(list) < 2, func() { list = append(list, []string{}) })
|
|
kit.If(len(list) < 3, func() { list = append(list, []string{}) })
|
|
s.value(m, kit.Select("", list[0], -1), Function{obj: list[0], arg: list[1], res: list[2], Position: s.Position})
|
|
s.pushf(m, "").status = DISABLE
|
|
}},
|
|
RETURN: {Name: "return show", Hand: func(m *ice.Message, arg ...string) {
|
|
s := _parse_stack(m)
|
|
res := kit.Simple(trans(s.value(m, "_res")))
|
|
if v := s.cals(m); len(res) == 0 {
|
|
f := s.peekf()
|
|
f.value["_return"] = v
|
|
} else {
|
|
switch v := v.(type) {
|
|
case Value:
|
|
kit.For(res, func(i int, k string) { kit.If(i < len(v.list), func() { s.value(m, k, v.list[i]) }) })
|
|
default:
|
|
s.value(m, kit.Select("_res", res, 0), v)
|
|
}
|
|
}
|
|
s.stack(func(f *Frame, i int) bool {
|
|
f.status = DISABLE
|
|
switch f.key {
|
|
case FUNC:
|
|
|
|
case CALL:
|
|
|
|
case STACK:
|
|
s.input = nil
|
|
case SOURCE:
|
|
s.input = nil
|
|
default:
|
|
return false
|
|
}
|
|
return true
|
|
})
|
|
}},
|
|
SOURCE: {Name: "source", Hand: func(m *ice.Message, arg ...string) {
|
|
s := _parse_stack(m)
|
|
u := kit.ParseURL(s.expr(m))
|
|
nfs.Open(m, u.Path, func(r io.Reader, p string) {
|
|
f := s.parse(m, p, r, func(f *Frame) { kit.For(u.Query(), func(k string, v []string) { f.value[k] = v[0] }) }).popf(m)
|
|
s.Position = f.Position
|
|
s.skip = len(s.rest)
|
|
})
|
|
}},
|
|
INFO: {Name: "info", Hand: func(m *ice.Message, arg ...string) {
|
|
_parse_stack(m).stack(func(f *Frame, i int) bool {
|
|
m.EchoLine("frame: %s %v:%v:%v", f.key, f.Position.name, f.Position.line, f.Position.skip)
|
|
kit.For(f.value, func(k string, v Any) {
|
|
m.EchoLine(" %s: %#v", k, v)
|
|
})
|
|
return false
|
|
})
|
|
}},
|
|
PWD: {Name: "pwd", Hand: func(m *ice.Message, arg ...string) {
|
|
s := _parse_stack(m)
|
|
res := []string{kit.Format("%d:%d", s.line, s.skip)}
|
|
s.stack(func(f *Frame, i int) bool {
|
|
kit.If(i > 0, func() {
|
|
res = append(res, kit.Format("%s:%d:%d %s %v", f.name, f.line, f.skip, f.key, kit.Select(ice.FALSE, ice.TRUE, f.status > DISABLE)))
|
|
})
|
|
return false
|
|
})
|
|
m.Echo(strings.Join(res, " / ")).Echo(ice.NL)
|
|
}},
|
|
})
|
|
}
|