forked from x/icebergs
155 lines
3.0 KiB
Go
155 lines
3.0 KiB
Go
package yac
|
|
|
|
import (
|
|
"strings"
|
|
|
|
ice "shylinux.com/x/icebergs"
|
|
kit "shylinux.com/x/toolkits"
|
|
)
|
|
|
|
type Map struct {
|
|
value Any
|
|
key Any
|
|
}
|
|
type Slice struct {
|
|
value Any
|
|
}
|
|
type Interface struct {
|
|
index map[string]Function
|
|
name string
|
|
}
|
|
type Struct struct {
|
|
index map[string]Any
|
|
name string
|
|
}
|
|
type Field struct {
|
|
types Any
|
|
tags map[string]string
|
|
name string
|
|
}
|
|
|
|
func (s Field) MarshalJSON() ([]byte, error) {
|
|
return []byte(kit.Format("%q", s.Format())), nil
|
|
}
|
|
func (s Field) Format() string {
|
|
if len(s.tags) == 0 {
|
|
return kit.Format("%s", s.types)
|
|
}
|
|
res := []string{}
|
|
kit.For(s.tags, func(k, v string) { res = append(res, kit.Format("%s:\"%s\"", k, v)) })
|
|
return kit.Format("%s `%s`", s.types, strings.Join(res, ice.SP))
|
|
}
|
|
|
|
type Object struct {
|
|
value Operater
|
|
index Struct
|
|
}
|
|
|
|
func (s Object) Operate(op string, v Any) Any {
|
|
switch op {
|
|
case "&", "*":
|
|
return s
|
|
case INSTANCEOF:
|
|
if t, ok := v.(Struct); ok {
|
|
return Value{list: []Any{s, s.index.name == t.name}}
|
|
}
|
|
return Value{list: []Any{s, false}}
|
|
case IMPLEMENTS:
|
|
if t, ok := v.(Interface); ok {
|
|
for k, v := range t.index {
|
|
if _v, ok := s.index.index[k].(Function); ok {
|
|
for i, field := range v.arg {
|
|
if i < len(_v.arg) && _v.arg[i].types == field.types {
|
|
continue
|
|
}
|
|
return Value{list: []Any{s, false}}
|
|
}
|
|
for i, field := range v.res {
|
|
if i < len(_v.res) && _v.res[i].types == field.types {
|
|
continue
|
|
}
|
|
return Value{list: []Any{s, false}}
|
|
}
|
|
} else {
|
|
return Value{list: []Any{s, false}}
|
|
}
|
|
}
|
|
}
|
|
return Value{list: []Any{s, true}}
|
|
case SUBS:
|
|
switch v := s.index.index[kit.Format(v)].(type) {
|
|
case Function:
|
|
v.object = s
|
|
return v
|
|
}
|
|
fallthrough
|
|
default:
|
|
return s.value.Operate(op, v)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
const (
|
|
MAP = "map"
|
|
SLICE = "slice"
|
|
STRUCT = "struct"
|
|
INTERFACE = "interface"
|
|
STRING = "string"
|
|
INT = "int"
|
|
|
|
INSTANCEOF = "instanceof"
|
|
IMPLEMENTS = "implements"
|
|
|
|
CONST = "const"
|
|
TYPE = "type"
|
|
VAR = "var"
|
|
)
|
|
|
|
func init() {
|
|
Index.MergeCommands(ice.Commands{
|
|
CONST: {Name: "const a = 1", Hand: func(m *ice.Message, arg ...string) {
|
|
if s := _parse_stack(m); s.next(m) == OPEN {
|
|
for s.token() != CLOSE {
|
|
s.nextLine(m)
|
|
s.skip--
|
|
s.cals(m, CLOSE)
|
|
}
|
|
} else {
|
|
s.skip--
|
|
s.cals(m)
|
|
}
|
|
}},
|
|
TYPE: {Name: "type student struct {", Hand: func(m *ice.Message, arg ...string) {
|
|
s := _parse_stack(m)
|
|
switch name := s.next(m); s.next(m) {
|
|
case ASSIGN:
|
|
s.next(m)
|
|
fallthrough
|
|
default:
|
|
switch t := s.types(m).(type) {
|
|
case Interface:
|
|
t.name = name
|
|
s.value(m, name, t)
|
|
case Struct:
|
|
t.name = name
|
|
s.value(m, name, t)
|
|
default:
|
|
s.value(m, name, t)
|
|
}
|
|
}
|
|
}},
|
|
VAR: {Name: "var a = 1", Hand: func(m *ice.Message, arg ...string) {
|
|
if s := _parse_stack(m); s.next(m) == OPEN {
|
|
for s.token() != CLOSE {
|
|
s.nextLine(m)
|
|
s.skip--
|
|
s.cals(m, CLOSE)
|
|
}
|
|
} else {
|
|
s.skip--
|
|
s.cals(m)
|
|
}
|
|
}},
|
|
})
|
|
}
|