├── .gitignore ├── LICENSE ├── README.md ├── args.go ├── atom.go ├── atom_test.go ├── avg.go ├── axiom.go ├── axiom_test.go ├── bool.go ├── bool_test.go ├── brace.go ├── bracket.go ├── bracket_test.go ├── channel.go ├── compare.go ├── compare_test.go ├── ctags ├── dict.go ├── dot.go ├── dot_test.go ├── examples └── overload.lisp ├── float.go ├── float_test.go ├── function.go ├── function_test.go ├── functor.go ├── ginq.go ├── ginq_test.go ├── gisp.go ├── int.go ├── int_test.go ├── lambda.go ├── let.go ├── linq.go ├── list.go ├── list_test.go ├── math.go ├── math_test.go ├── parsec.go ├── parsec_test.go ├── parser.go ├── parser_test.go ├── parses.go ├── parsex.go ├── parsex_test.go ├── proposition.go ├── quote.go ├── rune.go ├── suffix.go ├── tags ├── task.go ├── time.go ├── toolkit.go ├── type.go ├── type_test.go ├── types.go ├── types_test.go ├── utils.go ├── var.go └── var_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | 25 | .idea 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Dwarf Artisan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | gisp 2 | ==== 3 | 4 | The gisp is a lisp like micro language parser. It is a toolbox for golang 5 | programmer. I don't want to create a power script language. I want to make some 6 | jobs in golang can be easier and happy. 7 | 8 | Document 9 | ============= 10 | 11 | http://bms.tratao.com/desktop/doc/61b7935e92ab4c827d92cadf3f1fb6cf 12 | -------------------------------------------------------------------------------- /args.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | px "github.com/Dwarfartisan/goparsec/parsex" 8 | ) 9 | 10 | func typeis(x Atom) func(int, interface{}) (interface{}, error) { 11 | return func(pos int, data interface{}) (interface{}, error) { 12 | if data == nil { 13 | if x.Type.Option() { 14 | return data, nil 15 | } 16 | return nil, fmt.Errorf("%v's type not match %v", data, x.Type) 17 | } 18 | if reflect.DeepEqual(x.Type.Type, ANY) { 19 | return data, nil 20 | } 21 | if reflect.DeepEqual(x.Type.Type, reflect.TypeOf(data)) { 22 | return data, nil 23 | } 24 | return data, TypeSignError{x.Type, data} 25 | } 26 | } 27 | 28 | // TypeAs 函数根据反射对 Gisp 数据进行类型判断 29 | func TypeAs(typ reflect.Type) px.Parser { 30 | return func(st px.ParsexState) (interface{}, error) { 31 | obj, err := st.Next(px.Always) 32 | if err != nil { 33 | return nil, err 34 | } 35 | otype := reflect.TypeOf(obj) 36 | if otype == typ { 37 | return obj, nil 38 | } 39 | return nil, fmt.Errorf("Args Type Sign Check: excpet %v but %v is", 40 | typ, obj, otype) 41 | } 42 | } 43 | 44 | // argParser 构造一个 parsex 解析器,判断输入数据是否与给定类型一致,如果判断成功,构造对应的 45 | // Var。 46 | func argParser(atom Atom) px.Parser { 47 | one := func(st px.ParsexState) (interface{}, error) { 48 | var err error 49 | if data, err := st.Next(typeis(atom)); err == nil { 50 | slot := VarSlot(atom.Type) 51 | slot.Set(data) 52 | return slot, nil 53 | } 54 | return nil, err 55 | } 56 | if atom.Name == "..." { 57 | return px.Many(one) 58 | } 59 | return one 60 | } 61 | 62 | // argRing 组成参数解析链的的后续逻辑,供 parsex.Binds 调用 63 | func argRing(atom Atom) func(interface{}) px.Parser { 64 | return func(x interface{}) px.Parser { 65 | return func(st px.ParsexState) (interface{}, error) { 66 | ring, err := argParser(atom)(st) 67 | if err == nil { 68 | return append(x.([]Var), ring.([]Var)...), nil 69 | } 70 | return nil, err 71 | } 72 | } 73 | } 74 | 75 | // GetArgs 方法为将传入的 args 的 gisp 值从指定环境中解析出来,然后传入 parser 。 76 | func GetArgs(env Env, parser px.Parser, args []interface{}) ([]interface{}, error) { 77 | ret, err := Evals(env, args...) 78 | if err != nil { 79 | return nil, err 80 | } 81 | st := px.NewStateInMemory(ret) 82 | _, err = parser(st) 83 | if err != nil { 84 | return nil, fmt.Errorf("Args Type Sign Check got error:%v", err) 85 | } 86 | return ret, nil 87 | } 88 | -------------------------------------------------------------------------------- /atom.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "fmt" 5 | 6 | p "github.com/Dwarfartisan/goparsec" 7 | ) 8 | 9 | // Atom 类型表达基础的 atom 类型 10 | type Atom struct { 11 | Name string 12 | Type Type 13 | } 14 | 15 | // AA 构造一个指定命名的Atom,类型为 ANYOPTION 16 | func AA(name string) Atom { 17 | return Atom{Name: name, Type: ANYOPTION} 18 | } 19 | 20 | func (atom Atom) String() string { 21 | return fmt.Sprintf("%v::%v", atom.Name, atom.Type) 22 | } 23 | 24 | // Eval 方法实现 atom 实例的求值行为 25 | func (atom Atom) Eval(env Env) (interface{}, error) { 26 | if s, ok := env.Lookup(atom.Name); ok { 27 | switch slot := s.(type) { 28 | case Var: 29 | value := slot.Get() 30 | return value, nil 31 | case TaskExpr: 32 | return slot(env) 33 | default: 34 | return slot, nil 35 | } 36 | } 37 | return nil, fmt.Errorf("value of atom %s not found", atom.Name) 38 | } 39 | 40 | func atomNameParser(st p.ParseState) (interface{}, error) { 41 | ret, err := p.Bind(p.Many1(p.NoneOf("'[]() \t\r\n\".:")), 42 | p.ReturnString)(st) 43 | if err != nil { 44 | return nil, err 45 | } 46 | test := p.MemoryParseState(ret.(string)) 47 | _, err = p.Bind_(p.Many1(p.Digit), p.Eof)(test) 48 | if err == nil { 49 | return nil, fmt.Errorf("atom name can't be a int like %s", ret.(string)) 50 | } 51 | return ret, nil 52 | } 53 | 54 | // AtomParserExt 生成带扩展包的 Atom 55 | func AtomParserExt(env Env) p.Parser { 56 | return func(st p.ParseState) (interface{}, error) { 57 | a, err := atomNameParser(st) 58 | if err != nil { 59 | return nil, err 60 | } 61 | t, err := p.Try(ExtTypeParser(env))(st) 62 | if err == nil { 63 | return Atom{a.(string), t.(Type)}, nil 64 | } 65 | return Atom{a.(string), ANYMUST}, nil 66 | } 67 | } 68 | 69 | // AtomParser 生成 Atom 对象,但是它不带扩展环境 70 | func AtomParser(st p.ParseState) (interface{}, error) { 71 | a, err := atomNameParser(st) 72 | if err != nil { 73 | return nil, err 74 | } 75 | t, err := p.Try(TypeParser)(st) 76 | if err == nil { 77 | return Atom{a.(string), t.(Type)}, nil 78 | } 79 | return Atom{a.(string), ANYMUST}, nil 80 | } 81 | -------------------------------------------------------------------------------- /atom_test.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | 7 | p "github.com/Dwarfartisan/goparsec" 8 | ) 9 | 10 | func TestAtomParse0(t *testing.T) { 11 | data := "x" 12 | state := p.MemoryParseState(data) 13 | a, err := AtomParser(state) 14 | if err == nil { 15 | test := Atom{"x", Type{ANY, false}} 16 | if !reflect.DeepEqual(test, a) { 17 | t.Fatalf("except Atom{\"x\", ANY} but %v", a) 18 | } 19 | } else { 20 | t.Fatalf("except Atom{\"x\", ANY} but %v", err) 21 | } 22 | } 23 | 24 | func TestAtomParse1(t *testing.T) { 25 | data := "x::atom" 26 | state := p.MemoryParseState(data) 27 | a, err := AtomParser(state) 28 | if err == nil { 29 | test := Atom{"x", Type{ATOM, false}} 30 | if !reflect.DeepEqual(test, a) { 31 | t.Fatalf("except Atom{\"x\", ATOM} but %v", a) 32 | } 33 | } else { 34 | t.Fatalf("except Atom{\"x\", ATOM} but %v", err) 35 | } 36 | } 37 | 38 | func TestAtomParse2(t *testing.T) { 39 | data := "x::any" 40 | state := p.MemoryParseState(data) 41 | a, err := AtomParser(state) 42 | if err == nil { 43 | test := Atom{"x", Type{ANY, false}} 44 | if !reflect.DeepEqual(test, a) { 45 | t.Fatalf("except Atom{\"x\", ANY} but %v", a) 46 | } 47 | } else { 48 | t.Fatalf("except Atom{\"x\", ANY} but %v", err) 49 | } 50 | } 51 | 52 | func TestAtomParse3(t *testing.T) { 53 | data := "x::int" 54 | state := p.MemoryParseState(data) 55 | a, err := AtomParser(state) 56 | if err == nil { 57 | test := Atom{"x", Type{INT, false}} 58 | if !reflect.DeepEqual(test, a) { 59 | t.Fatalf("except Atom{\"x\", INT} but %v", a) 60 | } 61 | } else { 62 | t.Fatalf("except Atom{\"x\", INT} but %v", err) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /avg.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | // MinInts 在多个 int 中找出最小的一个 4 | func MinInts(data ...Int) Int { 5 | if len(data) == 0 { 6 | panic("Min Ints except ints more than zero.") 7 | } 8 | min := data[0] 9 | for _, item := range data[1:] { 10 | if item < min { 11 | min = item 12 | } 13 | } 14 | return min 15 | } 16 | 17 | // MaxInts 在多个 int 中找到最大的一个 18 | func MaxInts(data ...Int) Int { 19 | if len(data) == 0 { 20 | panic("Max Ints except ints more than zero.") 21 | } 22 | max := data[0] 23 | for _, item := range data[1:] { 24 | if max < item { 25 | max = item 26 | } 27 | } 28 | return max 29 | } 30 | -------------------------------------------------------------------------------- /axiom.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | px "github.com/Dwarfartisan/goparsec/parsex" 8 | ) 9 | 10 | // Axiom 是基本的 LISP 公理实现,尽可能贴近原始的 LISP 公理描述,但是部分实现对实际的 golang 11 | // 环境做了妥协 12 | var Axiom = Toolkit{ 13 | Meta: map[string]interface{}{ 14 | "name": "axiom", 15 | "category": "package", 16 | }, 17 | Content: map[string]interface{}{ 18 | "quote": LispExpr(func(env Env, args ...interface{}) (Lisp, error) { 19 | if len(args) != 1 { 20 | return nil, fmt.Errorf("Quote Args Error: except only one arg but %v", args) 21 | } 22 | return Q(Q(args[0])), nil 23 | }), 24 | "var": LispExpr(func(env Env, args ...interface{}) (Lisp, error) { 25 | st := px.NewStateInMemory(args) 26 | _, err := px.Binds_(TypeAs(ATOM), px.Either(px.Try(px.Eof), 27 | px.Bind_(px.AnyOne, px.Eof)))(st) 28 | if err != nil { 29 | return nil, err 30 | } 31 | first := args[0].(Atom) 32 | slot := VarSlot(first.Type) 33 | if len(args) == 1 { 34 | err := env.Defvar(first.Name, slot) 35 | return Q(nil), err 36 | } 37 | val, err := Eval(env, args[1]) 38 | slot.Set(val) 39 | err = env.Defvar(first.Name, slot) 40 | return Q(val), err 41 | }), 42 | "set": LispExpr(func(env Env, args ...interface{}) (Lisp, error) { 43 | st := px.NewStateInMemory(args) 44 | _, err := px.Binds_(px.Either(px.Try(TypeAs(ATOM)), 45 | TypeAs(QUOTE)), px.AnyOne, px.Eof)(st) 46 | if err != nil { 47 | return nil, err 48 | } 49 | val, err := Eval(env, args[1]) 50 | if err != nil { 51 | return nil, err 52 | } 53 | ret, err := set(env, args[0], val) 54 | if err != nil { 55 | return nil, err 56 | } 57 | return Q(ret), err 58 | }), 59 | "equal": TaskExpr(func(env Env, args ...interface{}) (Tasker, error) { 60 | if len(args) != 2 { 61 | return nil, fmt.Errorf("args error: equal need two args but only", 62 | args) 63 | } 64 | return func(env Env) (interface{}, error) { 65 | return reflect.DeepEqual(args[0], args[1]), nil 66 | }, nil 67 | }), 68 | "cond": TaskExpr(func(env Env, args ...interface{}) (Tasker, error) { 69 | cases := args[0].([]interface{}) 70 | l := len(args) 71 | var els interface{} 72 | if l > 1 { 73 | els = args[1] 74 | } else { 75 | els = nil 76 | } 77 | 78 | for _, b := range cases { // FIXME: need a else 79 | branch := b.([]interface{}) 80 | cond := branch[0].(List) 81 | result, err := Eval(env, cond) 82 | if err != nil { 83 | return nil, err 84 | } 85 | if ok := result.(bool); ok { 86 | return func(env Env) (interface{}, error) { 87 | return Eval(env, branch[1]) 88 | }, nil 89 | } 90 | } 91 | // else branch 92 | if els != nil { 93 | return func(env Env) (interface{}, error) { 94 | return Eval(env, els) 95 | }, nil 96 | } 97 | return nil, nil 98 | }), 99 | "car": TaskExpr(func(env Env, args ...interface{}) (Tasker, error) { 100 | if lisp, ok := args[0].(List); ok { 101 | return Q(lisp[0]).Eval, nil 102 | } 103 | return nil, ParsexSignErrorf("car args error: excpet a list but %v", args) 104 | }), 105 | "cdr": TaskExpr(func(env Env, args ...interface{}) (Tasker, error) { 106 | if lisp, ok := args[0].(List); ok { 107 | return Q(lisp[1:]).Eval, nil 108 | } 109 | return nil, ParsexSignErrorf("car args error: excpet a list but %v", args) 110 | }), 111 | // atom while true both lisp atom or go value 112 | "atom": LispExpr(func(env Env, args ...interface{}) (Lisp, error) { 113 | arg := args[0] 114 | if l, ok := arg.(List); ok { 115 | return Q(len(l) == 0), nil 116 | } 117 | return Q(true), nil 118 | }), 119 | // 照搬 cons 运算符对于 golang 嵌入没有足够的收益,这里的 concat 是一个 cons 的变形, 120 | // 它总是返回包含所有参数的 List 。 121 | "concat": TaskExpr(func(env Env, args ...interface{}) (Tasker, error) { 122 | return func(env Env) (interface{}, error) { 123 | return Q(List(args)).Eval, nil 124 | }, nil 125 | }), 126 | }, 127 | } 128 | 129 | func set(env Env, slot, arg interface{}) (interface{}, error) { 130 | switch setter := slot.(type) { 131 | case Atom: 132 | err := env.Setvar(setter.Name, arg) 133 | if err == nil { 134 | return nil, err 135 | } 136 | return arg, nil 137 | case Bracket: 138 | return setter.SetItemBy(env, arg) 139 | case List: 140 | s, err := Eval(env, setter) 141 | if err != nil { 142 | return nil, err 143 | } 144 | return set(env, s, arg) 145 | case Quote: 146 | s, err := Eval(env, setter) 147 | if err != nil { 148 | return nil, err 149 | } 150 | return set(env, s, arg) 151 | default: 152 | return arg, fmt.Errorf("set error: set %v(%v) as %v is invalid", 153 | slot, reflect.TypeOf(slot), arg) 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /axiom_test.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | // tm "time" 7 | ) 8 | 9 | func TestQuoteFound(t *testing.T) { 10 | ret, ok := Axiom.Lookup("quote") 11 | if !ok || ret == nil { 12 | t.Fatalf("except found quote in axioms") 13 | } 14 | } 15 | 16 | func TestQuoteCall(t *testing.T) { 17 | gisp := NewGisp(map[string]Toolbox{ 18 | "axioms": Axiom, 19 | }) 20 | list := L(Int(1), Int(1), Int(2), Int(3), Int(5), Int(8), Int(13), Int(21)) 21 | q, ok := gisp.Lookup("quote") 22 | if !ok { 23 | t.Fatalf("except found quote in axioms") 24 | } 25 | var fb interface{} 26 | switch quote := q.(type) { 27 | case Functor: 28 | quoted, err := quote.Task(gisp, list) 29 | if err != nil { 30 | t.Fatalf("except quote task but %v", err) 31 | } 32 | fb, err = quoted.Eval(gisp) 33 | if err != nil { 34 | t.Fatalf("except quote the list but %v", err) 35 | } 36 | case TaskExpr: 37 | quoted, err := quote(gisp, list) 38 | if err != nil { 39 | t.Fatalf("except quote task but %v", err) 40 | } 41 | fb, err = quoted(gisp) 42 | if err != nil { 43 | t.Fatalf("except quote the list but %v", err) 44 | } 45 | case LispExpr: 46 | quoted, err := quote(gisp, list) 47 | if err != nil { 48 | t.Fatalf("except quote task but %v", err) 49 | } 50 | fb, err = quoted.Eval(gisp) 51 | if err != nil { 52 | t.Fatalf("except quote the list but %v", err) 53 | } 54 | } 55 | 56 | fbq := Quote{list} 57 | if !reflect.DeepEqual(fb, fbq) { 58 | t.Fatalf("except quote (1 1 2 3 5 8 13 21) got %v but %v", fbq, fb) 59 | } 60 | } 61 | 62 | func TestQuoteEval(t *testing.T) { 63 | g := NewGisp(map[string]Toolbox{ 64 | "axioms": Axiom, 65 | }) 66 | gisp := *g 67 | list := L(Int(1), Int(1), Int(2), Int(3), Int(5), Int(8), Int(13), Int(21)) 68 | re, err := gisp.Eval(Quote{list}) 69 | if err != nil { 70 | t.Fatalf("except eval quote got a list but error %v", err) 71 | } 72 | if !reflect.DeepEqual(list, re) { 73 | t.Fatalf("except Eval (quote (1 1 2 3 5 8 13 21)) got %v but %v", list, re) 74 | } 75 | } 76 | 77 | func TestGetEval(t *testing.T) { 78 | gisp := NewGisp(map[string]Toolbox{ 79 | "axioms": Axiom, 80 | }) 81 | _, err := gisp.Parse("(var pi 3.14)") 82 | if err != nil { 83 | t.Fatalf("except var pi as 3.14 but error: %v", err) 84 | } 85 | pi, err := gisp.Eval(Atom{"pi", FLOATMUST}) 86 | if err != nil { 87 | t.Fatalf("except got pi is 3.14 but error: %v", err) 88 | } 89 | if !reflect.DeepEqual(pi, Float(3.14)) { 90 | t.Fatalf("except got pi is 3.14 but %v", pi) 91 | } 92 | } 93 | 94 | func TestVarEval(t *testing.T) { 95 | g := NewGisp(map[string]Toolbox{ 96 | "axioms": Axiom, 97 | }) 98 | gisp := *g 99 | _, err := gisp.Parse("(var pi 3.14)") 100 | if err != nil { 101 | t.Fatalf("except var pi as 3.14 but error: %v", err) 102 | } 103 | pi, err := gisp.Eval(Atom{"pi", FLOATMUST}) 104 | if err != nil { 105 | t.Fatalf("except got pi is 3.14 but error: %v", err) 106 | } 107 | if !reflect.DeepEqual(pi, Float(3.14)) { 108 | t.Fatalf("except got pi is 3.14 but %v", pi) 109 | } 110 | } 111 | 112 | func TestSetBracket(t *testing.T) { 113 | gisp := NewGisp(map[string]Toolbox{ 114 | "axioms": Axiom, 115 | }) 116 | err := gisp.DefAs("box", map[string]interface{}{ 117 | "a": "abc", 118 | "b": "bcd", 119 | "c": 3.14, 120 | "d": 99, 121 | }) 122 | if err != nil { 123 | t.Fatalf("except var pi as 3.14 but error: %v", err) 124 | } 125 | pi, err := gisp.Parse("box[\"c\"]") 126 | if err != nil { 127 | t.Fatalf("except got pi is 3.14 but error: %v", err) 128 | } 129 | if !reflect.DeepEqual(pi, Float(3.14)) { 130 | t.Fatalf("except got pi is 3.14 but %v", pi) 131 | } 132 | _, err = gisp.Parse("(set 'box[\"c\"] 3.14)") 133 | if err != nil { 134 | t.Fatalf("except got pi is 3.14 but error: %v", err) 135 | } 136 | pi, err = gisp.Parse("box[\"c\"]") 137 | if err != nil { 138 | t.Fatalf("except got pi is 3.14 but error: %v", err) 139 | } 140 | if !reflect.DeepEqual(pi, Float(3.14)) { 141 | t.Fatalf("except got pi is 3.14 but %v", pi) 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /bool.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "fmt" 5 | 6 | p "github.com/Dwarfartisan/goparsec" 7 | ) 8 | 9 | // Bool 是内置的 bool 类型的封装 10 | type Bool bool 11 | 12 | // BoolParser 解析 bool 13 | var BoolParser = p.Bind(p.Choice(p.String("true"), p.String("false")), func(input interface{}) p.Parser { 14 | return func(st p.ParseState) (interface{}, error) { 15 | switch input.(string) { 16 | case "true": 17 | return Bool(true), nil 18 | case "false": 19 | return Bool(false), nil 20 | default: 21 | return nil, fmt.Errorf("Unexcept bool token %v", input) 22 | } 23 | } 24 | }) 25 | 26 | // NilParser 解析 nil 27 | var NilParser = p.Bind_(p.String("nil"), p.Return(nil)) 28 | 29 | // Nil 类型定义空值行为 30 | type Nil struct { 31 | } 32 | 33 | // Eval 方法实现 Lisp 值的 Eval 。 Nil 的 Eval 总是返回空值 34 | func (n Nil) Eval(env Env) (interface{}, error) { 35 | return nil, nil 36 | } 37 | -------------------------------------------------------------------------------- /bool_test.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "testing" 5 | 6 | p "github.com/Dwarfartisan/goparsec" 7 | ) 8 | 9 | func TestingBoolParse0(t *testing.T) { 10 | data := "true" 11 | st := p.MemoryParseState(data) 12 | o, err := BoolParser(st) 13 | if err != nil { 14 | t.Fatalf("except bool but error %v", err) 15 | } 16 | if b, ok := o.(Bool); ok { 17 | if !b { 18 | t.Fatalf("except bool true but %v", b) 19 | } 20 | } else { 21 | t.Fatalf("excpet bool but %v", o) 22 | } 23 | } 24 | 25 | func TestingBoolParse1(t *testing.T) { 26 | data := "false" 27 | st := p.MemoryParseState(data) 28 | o, err := BoolParser(st) 29 | if err != nil { 30 | t.Fatalf("except bool but error %v", err) 31 | } 32 | if b, ok := o.(bool); ok { 33 | if !b { 34 | t.Fatalf("except bool true but %v", b) 35 | } 36 | } else { 37 | t.Fatalf("excpet bool but %v", o) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /brace.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | -------------------------------------------------------------------------------- /bracket.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | p "github.com/Dwarfartisan/goparsec" 8 | px "github.com/Dwarfartisan/goparsec/parsex" 9 | ) 10 | 11 | // Bracket 实现中括号表达式的解析,包括序列索引、切割,字典的key查找 12 | type Bracket struct { 13 | obj interface{} 14 | expr []interface{} 15 | } 16 | 17 | // Eval 方法实现 Bracket 表达式的求值 18 | func (bracket Bracket) Eval(env Env) (interface{}, error) { 19 | obj, err := Eval(env, bracket.obj) 20 | if err != nil { 21 | return nil, err 22 | } 23 | val := reflect.ValueOf(obj) 24 | switch val.Kind() { 25 | case reflect.Slice, reflect.String, reflect.Array: 26 | switch len(bracket.expr) { 27 | case 1: 28 | return bracket.evalIndex(env, val) 29 | case 2, 3: 30 | return bracket.evalSlice(env, val) 31 | default: 32 | return nil, fmt.Errorf("Unknow howto index or slice:%v[%v]", 33 | bracket.obj, bracket.expr) 34 | } 35 | 36 | case reflect.Map: 37 | if len(bracket.expr) == 1 { 38 | key := reflect.ValueOf(bracket.expr[0]) 39 | v := val.MapIndex(key) 40 | return bracket.inter(v), nil 41 | } 42 | return nil, fmt.Errorf("Unknow howto parse map %v[%v]", 43 | bracket.obj, bracket.expr) 44 | } 45 | return nil, fmt.Errorf("Unknow howto parse formal as %v[%v]", 46 | bracket.obj, bracket.expr) 47 | } 48 | 49 | func (bracket Bracket) inter(value reflect.Value) interface{} { 50 | if value.IsValid() { 51 | return Value(value.Interface()) 52 | } 53 | return nil 54 | } 55 | 56 | func (bracket Bracket) evalIndex(env Env, val reflect.Value) (interface{}, error) { 57 | i, err := Eval(env, bracket.expr[0]) 58 | if err != nil { 59 | return nil, err 60 | } 61 | if idx, ok := i.(Int); ok { 62 | v := val.Index(int(idx)) 63 | return bracket.inter(v), nil 64 | } 65 | return nil, fmt.Errorf("Index for slice %v[%v] is invalid data: %v", 66 | bracket.obj, bracket.expr, i) 67 | } 68 | 69 | func (bracket Bracket) evalSlice(env Env, val reflect.Value) (interface{}, error) { 70 | items, err := Evals(env, bracket.expr...) 71 | if err != nil { 72 | return nil, err 73 | } 74 | indexs, err := bracket.computeIndexs(val, items) 75 | if err != nil { 76 | return nil, err 77 | } 78 | switch len(indexs) { 79 | case 2: 80 | v := val.Slice(indexs[0], indexs[1]) 81 | return bracket.inter(v), nil 82 | case 3: 83 | v := val.Slice3(indexs[0], indexs[1], indexs[2]) 84 | return bracket.inter(v), nil 85 | } 86 | 87 | return nil, fmt.Errorf("Index for slice %v[%v] is invalid", 88 | bracket.obj, bracket.expr) 89 | } 90 | func (bracket Bracket) computeIndexs(val reflect.Value, input []interface{}) ([]int, error) { 91 | indexs := make([]int, len(input)) 92 | for idx, item := range input { 93 | if idx < 2 { 94 | i, err := bracket.computeIndex(val, item) 95 | if err != nil { 96 | return nil, err 97 | } 98 | indexs[idx] = i 99 | } 100 | } 101 | return indexs, nil 102 | } 103 | 104 | func (bracket Bracket) computeIndex(val reflect.Value, input interface{}) (int, error) { 105 | l := val.Len() 106 | if index, ok := input.(Int); ok { 107 | i := int(index) 108 | if i < 0 { 109 | i = l - i 110 | } 111 | if i < 0 || i > l-1 { 112 | return 0, fmt.Errorf("Try to slice %v[%v] but %v out range", 113 | bracket.obj, bracket.expr, index) 114 | } 115 | return i, nil 116 | } 117 | return 0, fmt.Errorf("Try to slice %v[%v] but %v is invalid", 118 | bracket.obj, bracket.expr, input) 119 | } 120 | 121 | // SetItemBy 根据传值对括号表达式引用的容器进行写操作,即 col[x] = y => (set col[x] y) 122 | func (bracket Bracket) SetItemBy(env Env, item interface{}) (interface{}, error) { 123 | obj, err := Eval(env, bracket.obj) 124 | if err != nil { 125 | return nil, err 126 | } 127 | val := reflect.ValueOf(obj) 128 | switch val.Kind() { 129 | case reflect.Map: 130 | return bracket.SetMapIndex(val, env, item) 131 | case reflect.Slice: 132 | return bracket.SetSliceIndex(val, env, item) 133 | default: 134 | return nil, fmt.Errorf("Excpet %v[%v]=%v but %v is neither slice nor map", 135 | obj, item, bracket.expr, obj) 136 | } 137 | } 138 | 139 | // SetMapIndex 是给 Map 类型写入键值的特化实现 140 | func (bracket Bracket) SetMapIndex(val reflect.Value, env Env, item interface{}) (interface{}, error) { 141 | if len(bracket.expr) != 1 { 142 | return nil, fmt.Errorf("Excpet %v[%v]=%v but %v has error items(only accept one key)", 143 | val.Interface(), bracket.expr, item, bracket.expr) 144 | } 145 | k, err := Eval(env, bracket.expr[0]) 146 | if err != nil { 147 | return nil, err 148 | } 149 | key := reflect.ValueOf(k) 150 | value := reflect.ValueOf(item) 151 | val.SetMapIndex(key, value) 152 | return val.Interface(), nil 153 | } 154 | 155 | // SetSliceIndex 是为线性序列切片进行写操作的实现 156 | func (bracket Bracket) SetSliceIndex(val reflect.Value, env Env, item interface{}) (interface{}, error) { 157 | if len(bracket.expr) < 1 { 158 | return nil, fmt.Errorf("excpet %v[%v]=%v but %v has error items(only accept one or two key)", 159 | val.Interface(), bracket.expr, item, bracket.expr) 160 | } 161 | item, err := Eval(env, bracket.expr[0]) 162 | if err != nil { 163 | return nil, err 164 | } 165 | index, err := bracket.computeIndex(val, item) 166 | if err != nil { 167 | return nil, err 168 | } 169 | value := reflect.ValueOf(item) 170 | val.Index(index).Set(value) 171 | return val.Interface(), nil 172 | } 173 | 174 | // IntVal 尝试将 state 中的下一个数据解为 int 175 | func IntVal(st px.ParsexState) (interface{}, error) { 176 | x, err := st.Next(px.Always) 177 | if err != nil { 178 | return nil, err 179 | } 180 | if _, ok := x.(Int); ok { 181 | return x, nil 182 | } 183 | return nil, fmt.Errorf("except a Int value but got %v", x) 184 | } 185 | 186 | // BracketParser 尝试将 state 中下一个值解析为中括号表达式 187 | func BracketParser(st p.ParseState) (interface{}, error) { 188 | return p.Between(p.Rune('['), p.Rune(']'), 189 | p.SepBy1(ValueParser, p.Rune(':')), 190 | )(st) 191 | } 192 | 193 | // BracketParserExt 在带有 Ext 的环境下对中括号表达式求值 194 | func BracketParserExt(env Env) p.Parser { 195 | return p.Between(p.Rune('['), p.Rune(']'), 196 | p.SepBy1(ValueParserExt(env), p.Rune(':')), 197 | ) 198 | } 199 | 200 | //BracketExpr 结构实现中括号表达式的 201 | type BracketExpr struct { 202 | Expr []interface{} 203 | } 204 | 205 | // Task 的实现会返回 Bracket 对象 206 | func (be BracketExpr) Task(env Env, args ...interface{}) (Lisp, error) { 207 | if len(args) != 1 { 208 | return nil, ParsexSignErrorf("Bracket Expression Args Error: except a arg but %v", args) 209 | } 210 | return Bracket{args[0], be.Expr}, nil 211 | } 212 | 213 | // BracketExprParserExt 返回带 Ext 环境的 BracketExpr 。 214 | func BracketExprParserExt(env Env) p.Parser { 215 | return func(st p.ParseState) (interface{}, error) { 216 | expr, err := BracketParserExt(env)(st) 217 | if err != nil { 218 | return nil, err 219 | } 220 | return BracketExpr{expr.([]interface{})}, nil 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /bracket_test.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | 7 | p "github.com/Dwarfartisan/goparsec" 8 | ) 9 | 10 | func TestBracketParser(t *testing.T) { 11 | data := "dict[\"meta\"]" 12 | st := p.MemoryParseState(data) 13 | re, err := p.Bind(AtomParser, BracketSuffixParser)(st) 14 | if err != nil { 15 | t.Fatalf("except a Dot but error %v", err) 16 | } 17 | t.Log(re) 18 | } 19 | 20 | func TestBracketBasic(t *testing.T) { 21 | g := NewGisp(map[string]Toolbox{ 22 | "axioms": Axiom, 23 | "props": Propositions, 24 | }) 25 | g.Defvar("entry", VarSlot(ANYOPTION)) 26 | g.Setvar("entry", map[string]interface{}{ 27 | "meta": "meta data", 28 | }) 29 | data, err := g.Parse(`entry["meta"]`) 30 | if err != nil { 31 | t.Fatalf("excpet got meta from entry but error: %v", err) 32 | } 33 | if !reflect.DeepEqual(data, "meta data") { 34 | t.Fatalf(`excpet got "meta data" from entry["meta"] but got %v`, data) 35 | } 36 | } 37 | 38 | func TestBracketExpression(t *testing.T) { 39 | g := NewGisp(map[string]Toolbox{ 40 | "axioms": Axiom, 41 | "props": Propositions, 42 | }) 43 | l := L(3.14, 1.414, 1.735, 2.718) 44 | g.DefAs("list", l) 45 | pi, err := g.Parse("([0] list)") 46 | if err != nil { 47 | t.Fatalf("except got pi but error: %v", err) 48 | } 49 | if pi.(Float) != Float(3.14) { 50 | t.Fatalf("excpet got pi as float 3.14 but %v", pi) 51 | } 52 | } 53 | 54 | func TestBracketExpressionMap(t *testing.T) { 55 | box := Box{ 56 | "a": Quote{AA("a")}, 57 | "b": Quote{AA("bb")}, 58 | "c": Quote{AA("ccc")}, 59 | } 60 | bv := reflect.ValueOf(box) 61 | get := bv.MethodByName("Get") 62 | res := get.Call([]reflect.Value{reflect.ValueOf("b")}) 63 | if !reflect.DeepEqual(res[0].Interface(), box["b"]) { 64 | t.Fatalf("except %v but got %v", box["b"], res[0].Interface()) 65 | } 66 | g := NewGisp(map[string]Toolbox{ 67 | "axioms": Axiom, 68 | "props": Propositions, 69 | }) 70 | g.DefAs("box", box) 71 | c, err := g.Parse(`(["c"] box)`) 72 | if err != nil { 73 | t.Fatalf("excpet got b but error %v", err) 74 | } 75 | if !reflect.DeepEqual(c, box["c"]) { 76 | t.Fatalf("except %v but gt %v", box["c"], c) 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /channel.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "reflect" 5 | 6 | px "github.com/Dwarfartisan/goparsec/parsex" 7 | ) 8 | 9 | // Chan 封装 golang 的 channel 功能 10 | type Chan struct { 11 | Type reflect.Type 12 | Dir reflect.ChanDir 13 | value reflect.Value 14 | } 15 | 16 | // MakeChan 实现 chan 的构造 17 | func MakeChan(typ reflect.Type, dir reflect.ChanDir, buf Int) *Chan { 18 | return &Chan{typ, dir, reflect.MakeChan(typ, int(buf))} 19 | } 20 | 21 | // MakeRecvChan 实现一个单向的 recv chan 22 | func MakeRecvChan(typ reflect.Type, buf Int) *Chan { 23 | return MakeChan(typ, reflect.RecvDir, buf) 24 | } 25 | 26 | // MakeSendChan 实现一个单向的 Send chan 27 | func MakeSendChan(typ reflect.Type, buf Int) *Chan { 28 | return MakeChan(typ, reflect.SendDir, buf) 29 | } 30 | 31 | // MakeBothChan 构造一个双向 chan 32 | func MakeBothChan(typ reflect.Type, buf Int) *Chan { 33 | return MakeChan(typ, reflect.BothDir, buf) 34 | } 35 | 36 | // Send 方法实现 chan x <- v 37 | func (ch *Chan) Send(x interface{}) { 38 | ch.value.Send(reflect.ValueOf(x)) 39 | } 40 | 41 | // Recv 方法实现 v <- chan x 42 | func (ch *Chan) Recv() (x interface{}, ok bool) { 43 | val, ok := ch.value.Recv() 44 | if val.IsValid() { 45 | return val.Interface(), ok 46 | } 47 | return nil, ok 48 | } 49 | 50 | // TrySend 实现试写入(带状态返回) 51 | func (ch *Chan) TrySend(x interface{}) { 52 | ch.value.TrySend(reflect.ValueOf(x)) 53 | } 54 | 55 | // TryRecv 实现试接收(带状态返回) 56 | func (ch *Chan) TryRecv() (x interface{}, ok bool) { 57 | val, ok := ch.value.TryRecv() 58 | if val.IsValid() { 59 | return val.Interface(), ok 60 | } 61 | return nil, ok 62 | } 63 | 64 | var channel = Toolkit{ 65 | Meta: map[string]interface{}{ 66 | "category": "toolkit", 67 | "name": "channel", 68 | }, 69 | Content: map[string]interface{}{ 70 | "chan": SimpleBox{ 71 | ParsexSignChecker(px.Binds_( 72 | TypeAs(reflect.TypeOf((*reflect.Type)(nil)).Elem()), 73 | TypeAs(INT), 74 | px.Eof)), 75 | func(args ...interface{}) Tasker { 76 | return func(env Env) (interface{}, error) { 77 | return MakeBothChan(args[0].(reflect.Type), args[1].(Int)), nil 78 | } 79 | }}, 80 | "chan->": SimpleBox{ 81 | ParsexSignChecker(px.Binds_( 82 | TypeAs(reflect.TypeOf((*reflect.Type)(nil)).Elem()), 83 | TypeAs(INT), 84 | px.Eof)), 85 | func(args ...interface{}) Tasker { 86 | return func(env Env) (interface{}, error) { 87 | return MakeRecvChan(args[0].(reflect.Type), args[1].(Int)), nil 88 | } 89 | }}, 90 | "chan<-": SimpleBox{ 91 | ParsexSignChecker(px.Binds_( 92 | TypeAs(reflect.TypeOf((*reflect.Type)(nil)).Elem()), 93 | TypeAs(INT), 94 | px.Eof)), 95 | func(args ...interface{}) Tasker { 96 | return func(env Env) (interface{}, error) { 97 | return MakeSendChan(args[0].(reflect.Type), args[1].(Int)), nil 98 | } 99 | }}, 100 | "send": SimpleBox{ 101 | ParsexSignChecker(px.Binds_( 102 | TypeAs(reflect.TypeOf((*Chan)(nil))), 103 | px.Either(px.Try(TypeAs(ANYOPTION)), TypeAs(ANYMUST)), 104 | px.Eof)), 105 | func(args ...interface{}) Tasker { 106 | return func(env Env) (interface{}, error) { 107 | ch := args[0].(*Chan) 108 | ch.Send(args[1]) 109 | return nil, nil 110 | } 111 | }}, 112 | "send?": SimpleBox{ 113 | ParsexSignChecker(px.Binds_( 114 | TypeAs(reflect.TypeOf((*Chan)(nil))), 115 | px.Either(px.Try(TypeAs(ANYOPTION)), TypeAs(ANYMUST)), 116 | px.Eof)), 117 | func(args ...interface{}) Tasker { 118 | return func(env Env) (interface{}, error) { 119 | ch := args[0].(*Chan) 120 | ch.TrySend(args[1]) 121 | return nil, nil 122 | } 123 | }}, 124 | "recv": SimpleBox{ 125 | ParsexSignChecker(px.Binds_( 126 | TypeAs(reflect.TypeOf((*Chan)(nil))), 127 | px.Either(px.Try(TypeAs(ANYOPTION)), TypeAs(ANYMUST)), 128 | px.Eof)), 129 | func(args ...interface{}) Tasker { 130 | return func(env Env) (interface{}, error) { 131 | ch := args[0].(*Chan) 132 | data, ok := ch.Recv() 133 | return List{data, ok}, nil 134 | } 135 | }}, 136 | "recv?": SimpleBox{ 137 | ParsexSignChecker(px.Binds_( 138 | TypeAs(reflect.TypeOf((*Chan)(nil))), 139 | px.Either(px.Try(TypeAs(ANYOPTION)), TypeAs(ANYMUST)), 140 | px.Eof)), 141 | func(args ...interface{}) Tasker { 142 | return func(env Env) (interface{}, error) { 143 | ch := args[0].(*Chan) 144 | data, ok := ch.TryRecv() 145 | return List{data, ok}, nil 146 | } 147 | }}, 148 | }, 149 | } 150 | -------------------------------------------------------------------------------- /compare.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "reflect" 7 | tm "time" 8 | 9 | px "github.com/Dwarfartisan/goparsec/parsex" 10 | ) 11 | 12 | // FalseIfHasNil 实现一个 is nil 判断 13 | func FalseIfHasNil(st px.ParsexState) (interface{}, error) { 14 | for { 15 | val, err := px.AnyOne(st) 16 | if err != nil { 17 | if err == io.EOF { 18 | return nil, fmt.Errorf("False If Nil Error: Found EOF.") 19 | } 20 | return nil, err 21 | } 22 | if val == nil { 23 | return false, err 24 | } 25 | } 26 | } 27 | 28 | // LessThanNil 实现三值 Less 29 | func LessThanNil(x interface{}) px.Parser { 30 | return func(st px.ParsexState) (interface{}, error) { 31 | val, _ := px.AnyOne(st) 32 | if x == nil || val == nil { 33 | return false, nil 34 | } 35 | return nil, ParsexSignErrorf("except nil value but: %v", val) 36 | } 37 | } 38 | 39 | // ListValue 检查 state 中下一个值是否是列表 40 | func ListValue(st px.ParsexState) (interface{}, error) { 41 | val, err := px.AnyOne(st) 42 | if err == nil { 43 | if _, ok := val.(List); ok { 44 | return val, nil 45 | } 46 | return nil, ParsexSignErrorf("except a list value but %v ", val) 47 | } 48 | return nil, ParsexSignErrorf("except a list value but error: %v", err) 49 | } 50 | 51 | // LessThanList 从最近的环境中找到 < 的实现并调用其进行比较,这样用户可以自己实现特化的比较 52 | func LessThanList(env Env) func(x interface{}) px.Parser { 53 | lessp, ok := env.Lookup("<") 54 | return func(x interface{}) px.Parser { 55 | return func(st px.ParsexState) (interface{}, error) { 56 | if !ok { 57 | return nil, fmt.Errorf("Less Than List Error: opreator < not found") 58 | } 59 | y, err := ListValue(st) 60 | if err != nil { 61 | return nil, err 62 | } 63 | for _, item := range ZipLess(x.(List), y.(List)) { 64 | b, err := Eval(env, L(lessp, item.(List)[0], item.(List)[1])) 65 | if err != nil { 66 | return nil, err 67 | } 68 | if b.(bool) { 69 | return true, nil 70 | } 71 | } 72 | return len(x.(List)) < len(y.(List)), nil 73 | } 74 | } 75 | } 76 | 77 | // LessThanListOption 允许返回 nil 78 | func LessThanListOption(env Env) func(x interface{}) px.Parser { 79 | lessp, ok := env.Lookup(" 10 x[1]))) 190 | ) 191 | `) 192 | if err != nil { 193 | t.Fatalf("except got a ginq query but error %v ", err) 194 | } 195 | re, err := g.Eval(L(ginq, data)) 196 | if err != nil { 197 | t.Fatalf("except got group sum from data but error: %v", err) 198 | } 199 | t.Logf("ginq group sum select got %v", re) 200 | } 201 | 202 | func TestGinqGroupByMaxSelect(t *testing.T) { 203 | data := QL( 204 | L(0, 1, 2, 3, 4, 5), 205 | L(1, 2, 3, 4, 5, 6), 206 | L(0, 1, 2, 3, 4, 5), 207 | L(1, 2, 3, 4, 5, 6), 208 | L(2, 3, 4, 5, 6, 7), 209 | L(1, 2, 3, 4, 5, 6), 210 | L(2, 3, 4, 5, 6, 7), 211 | L(3, 4, 5, 6, 7, 8)) 212 | g := NewGispWith( 213 | map[string]Toolbox{"axiom": Axiom, "props": Propositions, "utils": Utils}, 214 | map[string]Toolbox{"time": Time}) 215 | g.DefAs("data", data) 216 | ginq, err := g.Parse(` 217 | (ginq 218 | (groupby [0] (maxs [5])) 219 | ) 220 | `) 221 | if err != nil { 222 | t.Fatalf("except got a ginq query but error %v ", err) 223 | } 224 | re, err := g.Eval(L(ginq, data)) 225 | if err != nil { 226 | t.Fatalf("except got group max from data but error: %v", err) 227 | } 228 | t.Logf("ginq group max select got %v", re) 229 | } 230 | 231 | func TestGinqGroupByMinSelect(t *testing.T) { 232 | data := QL( 233 | L(0, 1, 2, 3, 4, 5), 234 | L(1, 2, 3, 4, 5, 6), 235 | L(0, 1, 2, 3, 4, 2), 236 | L(1, 2, 3, 4, 5, 6), 237 | L(2, 3, 4, 5, 6, 7), 238 | L(1, 2, 3, 4, 5, 3), 239 | L(2, 3, 4, 5, 6, 4), 240 | L(3, 4, 5, 6, 7, 8)) 241 | g := NewGispWith( 242 | map[string]Toolbox{"axiom": Axiom, "props": Propositions, "utils": Utils}, 243 | map[string]Toolbox{"time": Time}) 244 | g.DefAs("data", data) 245 | ginq, err := g.Parse(` 246 | (ginq 247 | (groupby [0] (mins [5])) 248 | ) 249 | `) 250 | if err != nil { 251 | t.Fatalf("except got a ginq query but error %v ", err) 252 | } 253 | re, err := g.Eval(L(ginq, data)) 254 | if err != nil { 255 | t.Fatalf("except got group min from data but error: %v", err) 256 | } 257 | t.Logf("ginq group min select got %v", re) 258 | } 259 | 260 | func TestGinqGroupByCount(t *testing.T) { 261 | data := QL( 262 | L(0, 1, 2, 3, 4, 5), 263 | L(1, 2, 3, 4, 5, 6), 264 | L(0, 1, 2, 3, 4, 2), 265 | L(1, 2, 3, 4, 5, 6), 266 | L(2, 3, 4, 5, 6, 7), 267 | L(1, 2, 3, 4, 5, 3), 268 | L(2, 3, 4, 5, 6, 4), 269 | L(3, 4, 5, 6, 7, 8)) 270 | g := NewGispWith( 271 | map[string]Toolbox{"axiom": Axiom, "props": Propositions, "utils": Utils}, 272 | map[string]Toolbox{"time": Time}) 273 | g.DefAs("data", data) 274 | ginq, err := g.Parse(` 275 | (ginq 276 | (groupby [0] count) 277 | ) 278 | `) 279 | if err != nil { 280 | t.Fatalf("except got a ginq query but error %v ", err) 281 | } 282 | re, err := g.Eval(L(ginq, data)) 283 | if err != nil { 284 | t.Fatalf("except got group count from data but error: %v", err) 285 | } 286 | t.Logf("ginq group count select got %v", re) 287 | } 288 | 289 | func TestGinqSort(t *testing.T) { 290 | data := QL( 291 | L(0, 1, 2, 3, 4, 5), 292 | L(1, 2, 3, 4, 5, 6), 293 | L(0, 1, 2, 3, 4, 2), 294 | L(1, 2, 3, 4, 5, 6), 295 | L(2, 3, 4, 5, 6, 7), 296 | L(1, 2, 3, 4, 5, 3), 297 | L(2, 3, 4, 5, 6, 4), 298 | L(3, 4, 5, 6, 7, 8)) 299 | g := NewGispWith( 300 | map[string]Toolbox{"axiom": Axiom, "props": Propositions, "utils": Utils}, 301 | map[string]Toolbox{"time": Time}) 302 | g.DefAs("data", data) 303 | ginq, err := g.Parse(` 304 | (ginq 305 | (select [4]) 306 | sort 307 | ) 308 | `) 309 | if err != nil { 310 | t.Fatalf("except got a ginq sort but error %v ", err) 311 | } 312 | re, err := g.Eval(L(ginq, data)) 313 | if err != nil { 314 | t.Fatalf("except got ginq sort from data but error: %v", err) 315 | } 316 | t.Logf("ginq sort got %v", re) 317 | } 318 | 319 | func TestGinqSortBy(t *testing.T) { 320 | data := QL( 321 | L(0, 1, 2, 3, 4, 5), 322 | L(1, 2, 3, 4, 5, 6), 323 | L(0, 1, 2, 3, 4, 2), 324 | L(1, 2, 3, 4, 5, 6), 325 | L(2, 3, 4, 5, 6, 7), 326 | L(1, 2, 3, 4, 5, 3), 327 | L(2, 3, 4, 5, 6, 4), 328 | L(3, 4, 5, 6, 7, 8)) 329 | g := NewGispWith( 330 | map[string]Toolbox{"axiom": Axiom, "props": Propositions, "utils": Utils}, 331 | map[string]Toolbox{"time": Time}) 332 | g.DefAs("data", data) 333 | ginq, err := g.Parse(` 334 | (ginq 335 | (select (fs [3] [1] [5])) 336 | (sortby (lambda (x y) (< x[2] y[2]))) 337 | ) 338 | `) 339 | if err != nil { 340 | t.Fatalf("except got a ginq sortby but error %v ", err) 341 | } 342 | re, err := g.Eval(L(ginq, data)) 343 | if err != nil { 344 | t.Fatalf("except got ginq sortby from data but error: %v", err) 345 | } 346 | t.Logf("ginq sort got %v", re) 347 | } 348 | 349 | func TestGinqReverse(t *testing.T) { 350 | data := QL( 351 | L(0, 1, 2, 3, 4, 5), 352 | L(1, 2, 3, 4, 5, 6), 353 | L(0, 1, 2, 3, 4, 2), 354 | L(1, 2, 3, 4, 5, 6), 355 | L(2, 3, 4, 5, 6, 7), 356 | L(1, 2, 3, 4, 5, 3), 357 | L(2, 3, 4, 5, 6, 4), 358 | L(3, 4, 5, 6, 7, 8)) 359 | g := NewGispWith( 360 | map[string]Toolbox{"axiom": Axiom, "props": Propositions, "utils": Utils}, 361 | map[string]Toolbox{"time": Time}) 362 | g.DefAs("data", data) 363 | ginq, err := g.Parse(` 364 | (ginq 365 | (select (fs [3] [1] [5])) 366 | (sortby (lambda (x y) (< x[2] y[2]))) 367 | reverse 368 | ) 369 | `) 370 | if err != nil { 371 | t.Fatalf("except got a ginq sortby but error %v ", err) 372 | } 373 | re, err := g.Eval(L(ginq, data)) 374 | if err != nil { 375 | t.Fatalf("except got ginq reverse from data but error: %v", err) 376 | } 377 | t.Logf("ginq sort by then reverse got %v", re) 378 | } 379 | -------------------------------------------------------------------------------- /gisp.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | // Lisp 基础数据结构封装,Gisp 总是调用这个接口来解析数据 4 | type Lisp interface { 5 | Eval(env Env) (interface{}, error) 6 | } 7 | 8 | // Toolbox 是 gisp 的基础数据结构 9 | type Toolbox interface { 10 | Lookup(name string) (interface{}, bool) 11 | Local(name string) (interface{}, bool) 12 | Global(name string) (interface{}, bool) 13 | } 14 | 15 | // Env 是带环境的 Toolbox ,也就是说它有变量作用域 16 | type Env interface { 17 | Toolbox 18 | Defvar(name string, slot Var) error 19 | Setvar(name string, value interface{}) error 20 | Defun(name string, functor Functor) error 21 | } 22 | 23 | // Parser 是解释器的通用接口,用它将解释器与执行的逻辑正交分解。 24 | type Parser interface { 25 | Parse(string) (interface{}, error) 26 | Eval(lisps ...interface{}) (interface{}, error) 27 | } 28 | 29 | // Tasker 定义了可执行的函数形式 30 | type Tasker func(env Env) (interface{}, error) 31 | 32 | // TaskExpr 是带参数的可执行定义, Tasker可以是包装后的 TaskerExpr 33 | type TaskExpr func(env Env, args ...interface{}) (Tasker, error) 34 | 35 | // LispExpr 是带参数的 Lisp 执行体 36 | type LispExpr func(env Env, args ...interface{}) (Lisp, error) 37 | -------------------------------------------------------------------------------- /int.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | // Int 是 gisp 系统的 整形实现 4 | type Int int64 5 | -------------------------------------------------------------------------------- /int_test.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | p "github.com/Dwarfartisan/goparsec" 5 | "testing" 6 | ) 7 | 8 | func TestIntParser0(t *testing.T) { 9 | data := "12" 10 | st := p.MemoryParseState(data) 11 | o, err := IntParser(st) 12 | if err != nil { 13 | t.Fatalf("except a Int but error %v", err) 14 | } 15 | if i, ok := o.(Int); ok { 16 | if i != Int(12) { 17 | t.Fatalf("except a Int 12 but %v", i) 18 | } 19 | } else { 20 | t.Fatalf("except Int but %v", o) 21 | } 22 | } 23 | 24 | func TestIntParser1(t *testing.T) { 25 | data := "i234" 26 | st := p.MemoryParseState(data) 27 | o, err := IntParser(st) 28 | if err == nil { 29 | t.Fatalf("except a Int parse error but got %v", o) 30 | } 31 | } 32 | 33 | func TestIntParser2(t *testing.T) { 34 | data := ".234" 35 | st := p.MemoryParseState(data) 36 | o, err := IntParser(st) 37 | if err == nil { 38 | t.Fatalf("except a Float parse error but got %v", o) 39 | } 40 | } 41 | 42 | func TestIntParser3(t *testing.T) { 43 | data := "3.14" 44 | st := p.MemoryParseState(data) 45 | o, err := p.Bind_(IntParser, p.Eof)(st) 46 | if err == nil { 47 | t.Fatalf("except a Float parse error but got %v", o) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lambda.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "fmt" 5 | 6 | px "github.com/Dwarfartisan/goparsec/parsex" 7 | ) 8 | 9 | // Lambda 实现基本的 Lambda 行为 10 | type Lambda struct { 11 | Meta map[string]interface{} 12 | Content List 13 | } 14 | 15 | // DeclareLambda 构造 Lambda 表达式 (lambda (args...) body) 16 | func DeclareLambda(env Env, args List, lisps ...interface{}) (*Lambda, error) { 17 | ret := Lambda{map[string]interface{}{ 18 | "category": "lambda", 19 | "local": map[string]interface{}{}, 20 | }, List{}} 21 | ret.prepareArgs(args) 22 | prepare := map[string]bool{} 23 | for _, lisp := range lisps { 24 | err := ret.prepare(env, prepare, lisp) 25 | if err != nil { 26 | return nil, err 27 | } 28 | } 29 | return &ret, nil 30 | } 31 | 32 | // LambdaExpr 生成一个封装后的 Lambda 表达式 33 | func LambdaExpr(env Env, args ...interface{}) (Tasker, error) { 34 | st := px.NewStateInMemory(args) 35 | _, err := TypeAs(LIST)(st) 36 | if err != nil { 37 | return nil, ParsexSignErrorf("Lambda Args Error: except args list but error: %v", err) 38 | } 39 | lptr, err := DeclareLambda(env, args[0].(List), args[1:]...) 40 | if err != nil { 41 | return nil, fmt.Errorf("Lambda Args Error: except lambda tasker but error: %v", err) 42 | } 43 | return Q(lptr).Eval, nil 44 | } 45 | 46 | func (lambda *Lambda) prepareArgs(args List) { 47 | l := len(args) 48 | formals := make(List, len(args)) 49 | if l == 0 { 50 | lambda.Meta["parameters parsex"] = []Var{} 51 | return 52 | } 53 | lidx := l - 1 54 | last := args[lidx].(Atom) 55 | // variadic function args formal as (last[::Type] ... ) 56 | isVariadic := false 57 | if last.Name == "..." && len(args) > 1 { 58 | isVariadic = true 59 | } 60 | lambda.Meta["is variadic"] = isVariadic 61 | ps := make([]px.Parser, l+1) 62 | for idx, arg := range args[:lidx] { 63 | ps[idx] = argParser(arg.(Atom)) 64 | formals[idx] = arg 65 | } 66 | if isVariadic { 67 | varArg := args[l-2].(Atom) 68 | ps[lidx] = px.Many(argParser(last)) 69 | larg := Atom{varArg.Name, varArg.Type} 70 | formals[lidx] = larg 71 | } else { 72 | ps[lidx] = argParser(last) 73 | formals[lidx] = last 74 | } 75 | ps[l] = px.Eof 76 | lambda.Meta["formal parameters"] = formals 77 | lambda.Meta["parameter parsexs"] = ps 78 | } 79 | 80 | func (lambda *Lambda) prepare(env Env, prepare map[string]bool, content interface{}) error { 81 | next := map[string]bool{} 82 | for key := range prepare { 83 | next[key] = true 84 | } 85 | var err error 86 | switch lisp := content.(type) { 87 | case Atom: 88 | err = lambda.prepareAtom(env, next, lisp) 89 | return err 90 | case List: 91 | err = lambda.prepareList(env, next, lisp) 92 | } 93 | if err == nil { 94 | lambda.Content = append(lambda.Content, content) 95 | } 96 | return err 97 | } 98 | 99 | func (lambda Lambda) prepareAtom(env Env, prepare map[string]bool, one Atom) error { 100 | if _, ok := prepare[one.Name]; ok { 101 | return nil 102 | } 103 | next := map[string]bool{} 104 | for key := range prepare { 105 | next[key] = true 106 | } 107 | 108 | for _, arg := range lambda.Meta["formal parameters"].(List) { 109 | if (arg.(Atom)).Name == one.Name { 110 | return nil 111 | } 112 | } 113 | if _, ok := prepare[one.Name]; !ok { 114 | if v, ok := env.Lookup(one.Name); ok { 115 | local := (lambda.Meta["local"]).(map[string]interface{}) 116 | local[one.Name] = v 117 | } else { 118 | return fmt.Errorf("%s not found", one.Name) 119 | } 120 | } 121 | return nil 122 | } 123 | 124 | func (lambda Lambda) prepareList(env Env, prepare map[string]bool, content List) error { 125 | next := map[string]bool{} 126 | for key := range prepare { 127 | next[key] = true 128 | } 129 | var err error 130 | fun := content[0].(Atom) 131 | switch fun.Name { 132 | case "var": 133 | name := content[1].(string) 134 | if err != nil { 135 | return err 136 | } 137 | next[name] = true 138 | case "lambda": 139 | args := content[1].(List) 140 | for _, a := range args { 141 | arg := a.(Atom) 142 | next[arg.Name] = true 143 | } 144 | case "let": 145 | for _, def := range content[1].(List) { 146 | define := def.(List) 147 | name := define[0].(string) 148 | next[name] = true 149 | } 150 | } 151 | for _, l := range content { 152 | switch lisp := l.(type) { 153 | case List: 154 | err = lambda.prepareList(env, next, lisp) 155 | case Atom: 156 | err = lambda.prepareAtom(env, next, lisp) 157 | } 158 | } 159 | return err 160 | } 161 | 162 | // TypeSign 生成反射类型签名 163 | func (lambda Lambda) TypeSign() []Type { 164 | formals := lambda.Meta["formal parameters"].(List) 165 | types := make([]Type, len(formals)) 166 | for idx, formal := range formals { 167 | types[idx] = formal.(Atom).Type 168 | } 169 | return types 170 | } 171 | 172 | // MatchArgsSign 校验参数是否匹配 173 | func (lambda Lambda) MatchArgsSign(env Env, args ...interface{}) (interface{}, error) { 174 | params := make([]interface{}, len(args)) 175 | for idx, arg := range args { 176 | param, err := Eval(env, arg) 177 | if err != nil { 178 | return nil, err 179 | } 180 | params[idx] = param 181 | } 182 | pxs := lambda.Meta["parameter parsexs"].([]px.Parser) 183 | st := px.NewStateInMemory(params) 184 | return px.UnionAll(pxs...)(st) 185 | } 186 | 187 | // Task create a lambda s-Expr can be eval 188 | func (lambda Lambda) Task(env Env, args ...interface{}) (Lisp, error) { 189 | meta := map[string]interface{}{} 190 | for k, v := range lambda.Meta { 191 | meta[k] = v 192 | } 193 | actuals, err := lambda.MatchArgsSign(env, args...) 194 | if err != nil { 195 | return Nil{}, err 196 | } 197 | meta["actual parameters"] = actuals 198 | meta["my"] = map[string]Var{} 199 | l := len(lambda.Content) 200 | content := make([]interface{}, l) 201 | for idx, data := range lambda.Content { 202 | content[idx] = data 203 | } 204 | return &Task{meta, content}, nil 205 | } 206 | -------------------------------------------------------------------------------- /let.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "fmt" 5 | 6 | px "github.com/Dwarfartisan/goparsec/parsex" 7 | ) 8 | 9 | // Let 实现 let 环境 10 | type Let struct { 11 | Meta map[string]interface{} 12 | Content List 13 | } 14 | 15 | // LetFunc 构造一个 Let 环境 16 | func LetFunc(env Env, args ...interface{}) (Lisp, error) { 17 | st := px.NewStateInMemory(args) 18 | _, err := TypeAs(LIST)(st) 19 | if err != nil { 20 | return nil, ParsexSignErrorf("Let Args Error: except args list but error: %v", err) 21 | } 22 | 23 | local := map[string]Var{} 24 | vars := args[0].(List) 25 | for _, v := range vars { 26 | declares := v.(List) 27 | varb := declares[0].(Atom) 28 | slot := VarSlot(varb.Type) 29 | value, err := Eval(env, (declares[1])) 30 | if err != nil { 31 | return nil, err 32 | } 33 | slot.Set(value) 34 | local[varb.Name] = slot 35 | } 36 | meta := map[string]interface{}{ 37 | "local": local, 38 | } 39 | let := Let{meta, args} 40 | return let, nil 41 | } 42 | 43 | // LetExpr 将 let => (let ((a, value), (b, value)...) ...) 形式构造为一个 let 环境 44 | func LetExpr(env Env, args ...interface{}) (Tasker, error) { 45 | var ( 46 | vars List 47 | ok bool 48 | ) 49 | if len(args) < 1 { 50 | return nil, ParsexSignErrorf("let args error: except vars list at last but a empty let as (let )") 51 | } 52 | if vars, ok = args[0].(List); !ok { 53 | return nil, ParsexSignErrorf("let args error: except vars list but %v", args[0]) 54 | } 55 | return func(env Env) (interface{}, error) { 56 | local := map[string]Var{} 57 | for _, v := range vars { 58 | declares := v.(List) 59 | varb := declares[0].(Atom) 60 | slot := VarSlot(varb.Type) 61 | value, err := Eval(env, (declares[1])) 62 | if err != nil { 63 | return nil, err 64 | } 65 | slot.Set(value) 66 | local[varb.Name] = slot 67 | } 68 | meta := map[string]interface{}{ 69 | "local": local, 70 | } 71 | let := Let{meta, args[1:]} 72 | return let.Eval(env) 73 | }, nil 74 | } 75 | 76 | // Defvar 实现 Env.Defvar 77 | func (let Let) Defvar(name string, slot Var) error { 78 | if _, ok := let.Local(name); ok { 79 | return fmt.Errorf("local name %s is exists", name) 80 | } 81 | local := let.Meta["local"].(map[string]Var) 82 | local[name] = slot 83 | return nil 84 | } 85 | 86 | // Defun 实现 Env.Defun 87 | func (let Let) Defun(name string, functor Functor) error { 88 | if s, ok := let.Local(name); ok { 89 | switch slot := s.(type) { 90 | case Func: 91 | slot.Overload(functor) 92 | case Var: 93 | return fmt.Errorf("%s defined as a var", name) 94 | default: 95 | return fmt.Errorf("exists name %s isn't Expr", name) 96 | } 97 | } 98 | local := let.Meta["local"].(map[string]interface{}) 99 | local[name] = NewFunction(name, let, functor) 100 | return nil 101 | } 102 | 103 | // Setvar 实现 Env.Setvar 104 | func (let Let) Setvar(name string, value interface{}) error { 105 | if _, ok := let.Local(name); ok { 106 | local := let.Meta["local"].(map[string]Var) 107 | local[name].Set(value) 108 | return nil 109 | } 110 | global := let.Meta["global"].(Env) 111 | return global.Setvar(name, value) 112 | } 113 | 114 | // Local 实现 Env.Local 115 | func (let Let) Local(name string) (interface{}, bool) { 116 | local := let.Meta["local"].(map[string]Var) 117 | if slot, ok := local[name]; ok { 118 | return slot.Get(), true 119 | } 120 | return nil, false 121 | } 122 | 123 | // Lookup 实现 Env.Lookup 124 | func (let Let) Lookup(name string) (interface{}, bool) { 125 | if value, ok := let.Local(name); ok { 126 | return value, true 127 | } 128 | return let.Global(name) 129 | 130 | } 131 | 132 | // Global 实现 Env.Global 133 | func (let Let) Global(name string) (interface{}, bool) { 134 | global := let.Meta["global"].(Env) 135 | return global.Lookup(name) 136 | } 137 | 138 | // Eval 实现 Lisp.Eval 139 | func (let Let) Eval(env Env) (interface{}, error) { 140 | let.Meta["global"] = env 141 | l := len(let.Content) 142 | switch l { 143 | case 0: 144 | return nil, nil 145 | case 1: 146 | return Eval(let, let.Content[0]) 147 | default: 148 | for _, Expr := range let.Content[:l-1] { 149 | _, err := Eval(let, Expr) 150 | if err != nil { 151 | return nil, err 152 | } 153 | } 154 | Expr := let.Content[l-1] 155 | return Eval(let, Expr) 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /linq.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | // T 是 interface{} 的简写 4 | type T interface{} 5 | 6 | // Linq 定义了 linq 接口 7 | type Linq interface { 8 | From(input T) Linq 9 | Range(start, count int) 10 | All(f func(T) (bool, error)) (all bool, err error) 11 | Any() (exists bool, err error) 12 | AnyWith(f func(T) (bool, error)) (exists bool, err error) 13 | Average() (avg float64, err error) 14 | Count() (count int, err error) 15 | CountBy(f func(T) (bool, error)) (c int, err error) 16 | Distinct() Linq 17 | DistinctBy(f func(T, T) (bool, error)) Linq 18 | ElementAt(i int) (elem T, found bool, err error) 19 | Except(inputSlice T) Linq 20 | First() (elem T, found bool, err error) 21 | FirstBy(f func(T) (bool, error)) (elem T, found bool, err error) 22 | GroupBy(keySelector func(T) T, valueSelector func(T) T) (map[T][]T, error) 23 | GroupJoin(innerSlice T, outerKeySelector func(T) T, innerKeySelector func(T) T, resultSelector func(outer T, inners []T) T) Linq 24 | Intersect(inputSlice T) Linq 25 | Join(innerSlice T, outerKeySelector func(T) T, innerKeySelector func(T) T, resultSelector func(outer T, inner T) T) Linq 26 | Last() (elem T, found bool, err error) 27 | LastBy(f func(T) (bool, error)) (elem T, found bool, err error) 28 | Max() (max T, err error) 29 | Min() (min T, err error) 30 | OrderBy(less func(this T, that T) bool) Linq 31 | Order(func(x, y T) (bool, error)) Linq 32 | Results() (List, error) 33 | Reverse() Linq 34 | Select(f func(T) (T, error)) Linq 35 | Single(f func(T) (bool, error)) (single T, err error) 36 | Skip(n int) Linq 37 | SkipWhile(f func(T) (bool, error)) Linq 38 | Sum() (sum float64, err error) 39 | Take(n int) Linq 40 | TakeWhile(f func(T) (bool, error)) Linq 41 | Union(inputSlice T) Linq 42 | Where(f func(T) (bool, error)) Linq 43 | } 44 | -------------------------------------------------------------------------------- /list.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | "strings" 7 | ) 8 | 9 | // List 实现基本的 List 类型 10 | type List []interface{} 11 | 12 | func (list List) String() string { 13 | frags := []string{} 14 | for _, item := range list { 15 | frags = append(frags, fmt.Sprintf("%v", item)) 16 | } 17 | body := strings.Join(frags, " ") 18 | return fmt.Sprintf("(%s)", body) 19 | } 20 | 21 | // Eval 实现 Lisp.Eval 方法 22 | func (list List) Eval(env Env) (interface{}, error) { 23 | l := len(list) 24 | if l == 0 { 25 | return nil, nil 26 | } 27 | var lisp interface{} 28 | switch fun := list[0].(type) { 29 | case Atom: 30 | var ok bool 31 | if lisp, ok = env.Lookup(fun.Name); !ok { 32 | return nil, fmt.Errorf("any callable named %s not found", fun.Name) 33 | } 34 | case List: 35 | var err error 36 | lisp, err = fun.Eval(env) 37 | if err != nil { 38 | return nil, err 39 | } 40 | case Functor: 41 | lisp = fun 42 | case TaskExpr: 43 | lisp = fun 44 | case LispExpr: 45 | lisp = fun 46 | case Dot: 47 | lisp = fun 48 | case reflect.Value: 49 | if fun.Kind() == reflect.Func { 50 | lisp = fun 51 | } 52 | } 53 | switch item := lisp.(type) { 54 | case TaskExpr: 55 | task, err := item(env, list[1:]...) 56 | if err != nil { 57 | return nil, err 58 | } 59 | return task(env) 60 | case LispExpr: 61 | lisp, err := item(env, list[1:]...) 62 | if err != nil { 63 | return nil, err 64 | } 65 | return lisp.Eval(env) 66 | case Task: 67 | return item.Eval(env) 68 | case Functor: 69 | task, err := item.Task(env, list[1:]...) 70 | if err != nil { 71 | return nil, err 72 | } 73 | return task.Eval(env) 74 | case Let: 75 | return item.Eval(env) 76 | case Dot: 77 | v, err := item.Eval(env) 78 | if err != nil { 79 | return nil, err 80 | } 81 | if expr, ok := v.(TaskExpr); ok { 82 | tasker, err := expr(env, list[1:]...) 83 | if err != nil { 84 | return nil, err 85 | } 86 | return tasker(env) 87 | } 88 | //if expr, ok := v.(LispExpr); ok { 89 | if expr, ok := v.(func(Env, ...interface{}) (Lisp, error)); ok { 90 | lisp, err := expr(env, list[1:]...) 91 | if err != nil { 92 | return nil, err 93 | } 94 | return lisp.Eval(env) 95 | } 96 | if functor, ok := v.(Functor); ok { 97 | tasker, err := functor.Task(env, list[1:]...) 98 | if err != nil { 99 | return nil, err 100 | } 101 | return tasker.Eval(env) 102 | } 103 | value := v.(reflect.Value) 104 | if value.Kind() == reflect.Func { 105 | args, err := Evals(env, list[1:]...) 106 | if err != nil { 107 | return nil, err 108 | } 109 | values := make([]reflect.Value, len(args)) 110 | for idx, arg := range args { 111 | values[idx] = reflect.ValueOf(arg) 112 | } 113 | var revs []reflect.Value 114 | if value.Type().IsVariadic() { 115 | revs = value.CallSlice(values) 116 | } else { 117 | revs = value.Call(values) 118 | } 119 | res, err := InReflects(revs) 120 | if err != nil { 121 | return nil, err 122 | } 123 | if len(res) == 1 { 124 | return res[0], nil 125 | } 126 | return res, nil 127 | } 128 | case reflect.Value: 129 | args, err := Evals(env, list[1:]...) 130 | if err != nil { 131 | return nil, err 132 | } 133 | values := make([]reflect.Value, len(args)) 134 | for idx, arg := range args { 135 | values[idx] = reflect.ValueOf(arg) 136 | } 137 | var revs []reflect.Value 138 | if item.Type().IsVariadic() { 139 | revs = item.CallSlice(values) 140 | } else { 141 | revs = item.Call(values) 142 | } 143 | res, err := InReflects(revs) 144 | if err != nil { 145 | return nil, err 146 | } 147 | data, err := Evals(env, res...) 148 | if err != nil { 149 | return nil, err 150 | } 151 | if len(data) == 1 { 152 | return data[0], nil 153 | } 154 | return data, nil 155 | } 156 | return nil, fmt.Errorf("List %v Eval Error: %v(%v):%v is't callable", 157 | list, list[0], lisp, reflect.TypeOf(lisp)) 158 | } 159 | 160 | func (list List) indexn(index Int) interface{} { 161 | idx, err := list.Anchor(index) 162 | if err == nil { 163 | return list[idx.(int)] 164 | } 165 | return nil 166 | } 167 | 168 | // Anchor 是 IndexIs 的 parser 版本,可以用于 Eval 或 gisp code 169 | func (list List) Anchor(index Int) (interface{}, error) { 170 | idx := list.IndexIs(index) 171 | if idx == -1 { 172 | return nil, fmt.Errorf("List Index Anchor Error: %v out range (0, %d)", 173 | index, len(list)) 174 | } 175 | return idx, nil 176 | } 177 | 178 | // IndexIs 将负索引正规化, 返回正负索引对应的正规化索引[0, length)。如果索引index不在[-length, length)的范围内,返回-1 179 | func (list List) IndexIs(index Int) int { 180 | idx := int(index) 181 | ll := len(list) 182 | if 0 <= idx || idx < ll { 183 | return idx 184 | } 185 | if -ll <= idx || idx < 0 { 186 | return ll + idx 187 | } 188 | return -1 189 | } 190 | 191 | // Index 实现基本的索引操作 192 | func (list List) Index(index Int) (interface{}, error) { 193 | idx, err := list.Anchor(index) 194 | if err != nil { 195 | return nil, err 196 | } 197 | return list[idx.(int)], nil 198 | } 199 | 200 | // Zip 合并两个 List 201 | func Zip(x, y List) List { 202 | xlen := len(x) 203 | ylen := len(y) 204 | max := MaxInts(Int(xlen), Int(ylen)) 205 | min := MinInts(Int(xlen), Int(ylen)) 206 | ret := ZipLess(x, y) 207 | nils := make(List, max-min) 208 | for idx := range nils { 209 | nils[idx] = nil 210 | } 211 | if xlen > int(min) { 212 | ret = append(ret, ZipLess(x[min:], nils)...) 213 | } 214 | if ylen > int(min) { 215 | ret = append(ret, ZipLess(nils, y[min:])...) 216 | } 217 | return ret 218 | } 219 | 220 | // ZipLess 在 Zip 时放弃超出的部分,类似 inner join 的效果 221 | func ZipLess(x, y List) List { 222 | xlen := len(x) 223 | ylen := len(y) 224 | l := MinInts(Int(xlen), Int(ylen)) 225 | ret := make(List, l) 226 | for i := 0; i < int(l); i++ { 227 | ret[i] = L(x[i], y[i]) 228 | } 229 | return ret 230 | } 231 | 232 | // L 构造一个 List 233 | func L(data ...interface{}) List { 234 | l := make(List, len(data)) 235 | for idx, item := range data { 236 | l[idx] = item 237 | } 238 | return l 239 | } 240 | -------------------------------------------------------------------------------- /list_test.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | func TestZip(t *testing.T) { 9 | xlist := L("a", "b", "c") 10 | ylist := L(3.14, 1.414, 0) 11 | zlist := Zip(xlist, ylist) 12 | data := L(L("a", 3.14), L("b", 1.414), L("c", 0)) 13 | if !reflect.DeepEqual(zlist, data) { 14 | t.Fatalf("excpet zip(%v, %v) got %v but %v", 15 | xlist, ylist, data, zlist) 16 | } 17 | } 18 | 19 | func TestZipNil(t *testing.T) { 20 | xlist := L("a", "b", "c", "d") 21 | ylist := L(3.14, 1.414, 0) 22 | zlist := Zip(xlist, ylist) 23 | data := L(L("a", 3.14), L("b", 1.414), L("c", 0), L("d", nil)) 24 | if !reflect.DeepEqual(zlist, data) { 25 | t.Fatalf("excpet zip(%v, %v) got %v but %v", 26 | xlist, ylist, data, zlist) 27 | } 28 | zlist = Zip(ylist, xlist) 29 | data = L(L(3.14, "a"), L(1.414, "b"), L(0, "c"), L(nil, "d")) 30 | if !reflect.DeepEqual(zlist, data) { 31 | t.Fatalf("excpet zip(%v, %v) got %v but %v", 32 | ylist, xlist, data, zlist) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /math.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | px "github.com/Dwarfartisan/goparsec/parsex" 8 | ) 9 | 10 | // TypeMatchError 定了类型匹配错误 11 | type TypeMatchError struct { 12 | Value interface{} 13 | Type reflect.Type 14 | } 15 | 16 | func (err TypeMatchError) Error() string { 17 | return fmt.Sprintf("%v not match type %v", err.Value, err.Type) 18 | } 19 | 20 | // NotIntError 定了预期为整型但是校验失败的错误 21 | type NotIntError struct { 22 | Value interface{} 23 | } 24 | 25 | func (err NotIntError) Error() string { 26 | return fmt.Sprintf("%v is't a valid Int", err.Value) 27 | } 28 | 29 | // NotFloatError 定义了预期为浮点数但是校验失败的错误 30 | type NotFloatError struct { 31 | Value interface{} 32 | } 33 | 34 | func (err NotFloatError) Error() string { 35 | return fmt.Sprintf("%v is't a valid Float", err.Value) 36 | } 37 | 38 | // NotNumberError 定义了预期为数值但是校验失败的错误 39 | type NotNumberError struct { 40 | Value interface{} 41 | } 42 | 43 | func (err NotNumberError) Error() string { 44 | return fmt.Sprintf("%v is't a valid Number", err.Value) 45 | } 46 | 47 | // IntValue 将所有整型处理为 Int ,其它类型不接受 48 | func IntValue(st px.ParsexState) (interface{}, error) { 49 | v, err := st.Next(px.Always) 50 | if err != nil { 51 | return nil, err 52 | } 53 | switch val := v.(type) { 54 | case int: 55 | return Int(val), nil 56 | case int8: 57 | return Int(val), nil 58 | case int16: 59 | return Int(val), nil 60 | case int32: 61 | return Int(val), nil 62 | case int64: 63 | return Int(val), nil 64 | case Int: 65 | return val, nil 66 | default: 67 | return nil, NotIntError{v} 68 | } 69 | } 70 | 71 | // FloatValue 将所有浮点型处理为 Float ,其它类型不接受 72 | func FloatValue(st px.ParsexState) (interface{}, error) { 73 | v, err := st.Next(px.Always) 74 | if err != nil { 75 | return nil, err 76 | } 77 | switch val := v.(type) { 78 | case float32: 79 | return Float(val), nil 80 | case float64: 81 | return Float(val), nil 82 | case Float: 83 | return val, nil 84 | default: 85 | return nil, NotFloatError{v} 86 | } 87 | } 88 | 89 | // NumberValue 将所有整型和浮点型处理为 Float ,其它类型不接受 90 | func NumberValue(st px.ParsexState) (interface{}, error) { 91 | v, err := st.Next(px.Always) 92 | if err != nil { 93 | return nil, err 94 | } 95 | switch val := v.(type) { 96 | case int: 97 | return Float(val), nil 98 | case int8: 99 | return Float(val), nil 100 | case int16: 101 | return Float(val), nil 102 | case int32: 103 | return Float(val), nil 104 | case int64: 105 | return Float(val), nil 106 | case Int: 107 | return Float(val), nil 108 | case float32: 109 | return Float(val), nil 110 | case float64: 111 | return Float(val), nil 112 | case Float: 113 | return val, nil 114 | default: 115 | return nil, NotNumberError{v} 116 | } 117 | } 118 | 119 | // Int2Values 获取多个 int 120 | var Int2Values = px.Bind(IntValue, func(x interface{}) px.Parser { 121 | return func(st px.ParsexState) (interface{}, error) { 122 | y, err := IntValue(st) 123 | if err != nil { 124 | return nil, err 125 | } 126 | return []interface{}{x, y}, nil 127 | } 128 | }) 129 | 130 | // Num2Values 获取多个 int 131 | var Num2Values = px.Bind(NumberValue, func(x interface{}) px.Parser { 132 | return func(st px.ParsexState) (interface{}, error) { 133 | y, err := NumberValue(st) 134 | if err != nil { 135 | return nil, err 136 | } 137 | return []interface{}{x, y}, nil 138 | } 139 | }) 140 | 141 | func xEOF(x interface{}) px.Parser { 142 | return px.Bind_(px.Eof, px.Return(x)) 143 | } 144 | 145 | // addx 实现一个parsex累加解析器,精度向上适配。我一直觉得应该有一个简单的高效版本,不需要回溯的 146 | // 但是目前还没有找到。 147 | func addx(st px.ParsexState) (interface{}, error) { 148 | ints, err := px.Try(px.ManyTil(IntValue, px.Eof))(st) 149 | if err == nil { 150 | root := Int(0) 151 | for _, x := range ints.([]interface{}) { 152 | root += x.(Int) 153 | } 154 | return root, nil 155 | } 156 | numbers, err := px.ManyTil(NumberValue, px.Eof)(st) 157 | if err == nil { 158 | root := Float(0) 159 | for _, x := range numbers.([]interface{}) { 160 | root += x.(Float) 161 | } 162 | return root, nil 163 | } 164 | 165 | if nerr, ok := err.(NotNumberError); ok { 166 | return nil, TypeSignError{Type: FLOATMUST, Value: nerr.Value} 167 | } 168 | return nil, err 169 | } 170 | 171 | func addInts(ints ...interface{}) (interface{}, error) { 172 | root := ints[0].(Int) 173 | for _, i := range ints[1:] { 174 | root += i.(Int) 175 | } 176 | return root, nil 177 | } 178 | 179 | func addFloats(floats ...interface{}) (interface{}, error) { 180 | root := floats[0].(Float) 181 | for _, f := range floats[1:] { 182 | root += f.(Float) 183 | } 184 | return root, nil 185 | } 186 | 187 | // subx 实现一个左折叠的 parsex 连减解析器,精度向上适配。 188 | func subx(st px.ParsexState) (interface{}, error) { 189 | data, err := px.Try(px.ManyTil(IntValue, px.Eof))(st) 190 | if err == nil { 191 | ints := data.([]interface{}) 192 | root := ints[0].(Int) 193 | for _, x := range ints[1:] { 194 | root -= x.(Int) 195 | } 196 | return root, nil 197 | } 198 | data, err = px.ManyTil(NumberValue, px.Eof)(st) 199 | if err == nil { 200 | numbers := data.([]interface{}) 201 | root := numbers[0].(Float) 202 | for _, x := range numbers[1:] { 203 | root -= x.(Float) 204 | } 205 | return root, nil 206 | } 207 | 208 | if nerr, ok := err.(NotNumberError); ok { 209 | return nil, TypeSignError{Type: Type{FLOAT, false}, Value: nerr.Value} 210 | } 211 | return nil, err 212 | } 213 | 214 | // mulx 实现一个 parsex 累乘解析器,精度向上适配。 215 | func mulx(st px.ParsexState) (interface{}, error) { 216 | data, err := px.Try(px.ManyTil(IntValue, px.Eof))(st) 217 | if err == nil { 218 | ints := data.([]interface{}) 219 | root := ints[0].(Int) 220 | for _, x := range ints[1:] { 221 | root *= x.(Int) 222 | } 223 | return root, nil 224 | } 225 | data, err = px.ManyTil(NumberValue, px.Eof)(st) 226 | if err == nil { 227 | numbers := data.([]interface{}) 228 | root := numbers[0].(Float) 229 | for _, x := range numbers[1:] { 230 | root *= x.(Float) 231 | } 232 | return root, nil 233 | } 234 | if nerr, ok := err.(NotNumberError); ok { 235 | return nil, TypeSignError{Type: Type{FLOAT, false}, Value: nerr.Value} 236 | } 237 | return nil, err 238 | } 239 | 240 | // divx 实现一个左折叠的 parsex 连除解析器,精度向上适配。 241 | func divx(st px.ParsexState) (interface{}, error) { 242 | data, err := px.Try(px.ManyTil(IntValue, px.Eof))(st) 243 | if err == nil { 244 | ints := data.([]interface{}) 245 | root := ints[0].(Int) 246 | for _, x := range ints[1:] { 247 | root /= x.(Int) 248 | } 249 | return root, nil 250 | } 251 | data, err = px.ManyTil(NumberValue, px.Eof)(st) 252 | if err == nil { 253 | numbers := data.([]interface{}) 254 | root := numbers[0].(Float) 255 | for _, x := range numbers[1:] { 256 | root /= x.(Float) 257 | } 258 | return root, nil 259 | } 260 | 261 | if nerr, ok := err.(NotNumberError); ok { 262 | return nil, TypeSignError{Type: Type{FLOAT, false}, Value: nerr.Value} 263 | } 264 | return nil, err 265 | } 266 | -------------------------------------------------------------------------------- /math_test.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | px "github.com/Dwarfartisan/goparsec/parsex" 5 | "testing" 6 | ) 7 | 8 | func TestAddx0(t *testing.T) { 9 | var data = []interface{}{0, 1, 2, 3, 4, 5, 6} 10 | st := px.NewStateInMemory(data) 11 | s, err := addx(st) 12 | if err != nil { 13 | t.Fatalf("except error is nil but %v", err) 14 | } 15 | if s.(Int) != 21 { 16 | t.Fatalf("except sum 0~6 is 21 but got %v", s) 17 | } 18 | } 19 | 20 | func TestAddx1(t *testing.T) { 21 | var data = []interface{}{0, 1, 2, 3.14, 4, 5, 6} 22 | st := px.NewStateInMemory(data) 23 | s, err := addx(st) 24 | if err != nil { 25 | t.Fatalf("except error is nil but %v", err) 26 | } 27 | if s.(Float) != 21.14 { 28 | t.Fatalf("except sum 0, 1, 2, 3.14, 4, 5, 6 is 21.14 but got %v", s) 29 | } 30 | } 31 | 32 | func TestAddExpr(t *testing.T) { 33 | gisp := NewGisp(map[string]Toolbox{ 34 | "axioms": Axiom, 35 | "props": Propositions, 36 | }) 37 | adds, err := gisp.Parse("+") 38 | if err != nil { 39 | t.Fatalf("except add operator but error %v", err) 40 | } 41 | var expr = []interface{}{adds, 0, 1, 2, 3.14, 4, 5, 6} 42 | ret, err := gisp.Eval(List(expr)) 43 | if err != nil { 44 | t.Fatalf("except add data %v but got error %v", expr[1:], err) 45 | } 46 | if ret.(Float) != 21.14 { 47 | t.Fatalf("except sum 0, 1, 2, 3.14, 4, 5, 6 is 21.14 but got %v", ret) 48 | } 49 | } 50 | 51 | func TestMulExpr(t *testing.T) { 52 | gisp := NewGisp(map[string]Toolbox{ 53 | "axioms": Axiom, 54 | "props": Propositions, 55 | }) 56 | mulx, err := gisp.Parse("*") 57 | if err != nil { 58 | t.Fatalf("except add operator but error %v", err) 59 | } 60 | var expr = L(mulx, 1, 2, 3.14, 4, 5, 6) 61 | ret, err := gisp.Eval(expr) 62 | if err != nil { 63 | t.Fatalf("except add data %v but got error %v", expr[1], err) 64 | } 65 | if ret.(Float) != 753.6 { 66 | t.Fatalf("except multi 1, 2, 3.14, 4, 5, 6 is 753.6 but got %v", ret) 67 | } 68 | expr = L(mulx, 2, 3, 4, 5, 6) 69 | ret, err = gisp.Eval(expr) 70 | if err != nil { 71 | t.Fatalf("except add data %v but got error %v", expr[1:], err) 72 | 73 | } 74 | if ret.(Int) != 720 { 75 | t.Fatalf("except multi %v is %d but got %v", expr[1:], 720, ret) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /parsec.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | p "github.com/Dwarfartisan/goparsec" 8 | px "github.com/Dwarfartisan/goparsec/parsex" 9 | ) 10 | 11 | // Parsec 定义了 parsec 包的结构 12 | var Parsec = Toolkit{ 13 | Meta: map[string]interface{}{ 14 | "name": "parsex", 15 | "category": "package", 16 | }, 17 | Content: map[string]interface{}{ 18 | "state": func(env Env, args ...interface{}) (Lisp, error) { 19 | if len(args) != 1 { 20 | return nil, ParsexSignErrorf("Parsex Arg Error:except args has 1 arg.") 21 | } 22 | param, err := Eval(env, args[0]) 23 | if err != nil { 24 | return nil, err 25 | } 26 | switch data := param.(type) { 27 | case string: 28 | return Q(p.MemoryParseState(data)), nil 29 | default: 30 | return nil, fmt.Errorf("Parsex Error: Except create a state from a string or List but %v", data) 31 | } 32 | }, 33 | "s2str": func(env Env, args ...interface{}) (Lisp, error) { 34 | if len(args) != 1 { 35 | return nil, ParsexSignErrorf("Slice to string Arg Error:except args has 1 arg.") 36 | } 37 | param, err := Eval(env, args[0]) 38 | if err != nil { 39 | return nil, err 40 | } 41 | var ( 42 | slice []interface{} 43 | ok bool 44 | ) 45 | if slice, ok = param.([]interface{}); !ok { 46 | return nil, ParsexSignErrorf("s2str Arg Error:except 1 []interface{} arg.") 47 | } 48 | return Q(p.ExtractString(slice)), nil 49 | }, 50 | "str": func(env Env, args ...interface{}) (Lisp, error) { 51 | if len(args) != 1 { 52 | return nil, ParsexSignErrorf("Str Arg Error:except args has 1 arg.") 53 | } 54 | param, err := Eval(env, args[0]) 55 | if err != nil { 56 | return nil, err 57 | } 58 | var ( 59 | data string 60 | ok bool 61 | ) 62 | if data, ok = param.(string); !ok { 63 | return nil, ParsexSignErrorf("Str Arg Error:except args has 1 string arg.") 64 | } 65 | return ParsecBox(p.String(data)), nil 66 | }, 67 | "rune": func(env Env, args ...interface{}) (Lisp, error) { 68 | if len(args) != 1 { 69 | return nil, ParsexSignErrorf("Rune Arg Error:except args has 1 arg.") 70 | } 71 | param, err := Eval(env, args[0]) 72 | if err != nil { 73 | return nil, err 74 | } 75 | var ( 76 | data Rune 77 | ok bool 78 | ) 79 | if data, ok = param.(Rune); !ok { 80 | return nil, ParsexSignErrorf("One Arg Error:except args has 1 rune arg but %v.", reflect.TypeOf(param)) 81 | } 82 | return ParsecBox(p.Rune(rune(data))), nil 83 | }, 84 | "anyone": ParsecBox(p.AnyRune), 85 | "int": ParsecBox(p.Int), 86 | "float": ParsecBox(p.Float), 87 | "digit": ParsecBox(p.Digit), 88 | "eof": ParsecBox(p.Eof), 89 | "try": func(env Env, args ...interface{}) (Lisp, error) { 90 | if len(args) != 1 { 91 | return nil, ParsexSignErrorf("Parsec Parser Try Error: only accept one Parsec Parser as arg but %v", args) 92 | } 93 | param, err := Eval(env, args[0]) 94 | if err != nil { 95 | return nil, err 96 | } 97 | switch parser := param.(type) { 98 | case Parsecer: 99 | return ParsecBox(p.Try(parser.Parser)), nil 100 | default: 101 | return nil, ParsexSignErrorf( 102 | "Try Arg Error:except 1 parser arg but %v.", 103 | reflect.TypeOf(param)) 104 | } 105 | 106 | }, 107 | "either": func(env Env, args ...interface{}) (Lisp, error) { 108 | ptype := reflect.TypeOf((px.Parser)(nil)) 109 | params, err := GetArgs(env, px.UnionAll(TypeAs(ptype), TypeAs(ptype), px.Eof), args) 110 | if err != nil { 111 | return nil, err 112 | } 113 | return ParsecBox(p.Either(params[0].(Parsecer).Parser, params[1].(Parsecer).Parser)), nil 114 | }, 115 | "choice": func(env Env, args ...interface{}) (Lisp, error) { 116 | ptype := reflect.TypeOf((px.Parser)(nil)) 117 | params, err := GetArgs(env, px.ManyTil(TypeAs(ptype), px.Eof), args) 118 | if err != nil { 119 | return nil, err 120 | } 121 | parsers := make([]p.Parser, len(params)) 122 | for idx, prs := range params { 123 | if parser, ok := prs.(Parsecer); ok { 124 | parsers[idx] = parser.Parser 125 | } 126 | return nil, ParsexSignErrorf("Choice Args Error:except parsec parsers but %v is %v", 127 | prs, reflect.TypeOf(prs)) 128 | } 129 | return ParsecBox(p.Choice(parsers...)), nil 130 | }, 131 | "return": func(env Env, args ...interface{}) (Lisp, error) { 132 | if len(args) != 1 { 133 | return nil, ParsexSignErrorf("Parsec Parser Return Error: only accept one Parsec Parser as arg but %v", args) 134 | } 135 | param, err := Eval(env, args[0]) 136 | if err != nil { 137 | return nil, err 138 | } 139 | return ParsecBox(p.Return(param)), nil 140 | }, 141 | "option": func(env Env, args ...interface{}) (Lisp, error) { 142 | if len(args) != 2 { 143 | return nil, ParsexSignErrorf("Parsec Parser Option Error: only accept two Parsec Parser as arg but %v", args) 144 | } 145 | data, err := Eval(env, args[0]) 146 | if err != nil { 147 | return nil, err 148 | } 149 | param, err := Eval(env, args[1]) 150 | if err != nil { 151 | return nil, err 152 | } 153 | switch parser := param.(type) { 154 | case Parsecer: 155 | return ParsecBox(p.Option(data, parser.Parser)), nil 156 | default: 157 | return nil, ParsexSignErrorf( 158 | "Many Arg Error:except 1 parser arg but %v.", 159 | reflect.TypeOf(param)) 160 | } 161 | }, 162 | "many1": func(env Env, args ...interface{}) (Lisp, error) { 163 | if len(args) != 1 { 164 | return nil, ParsexSignErrorf("Parsec Parser Many1 Erroparserr: only accept one Parsec Parser as arg but %v", args) 165 | } 166 | param, err := Eval(env, args[0]) 167 | if err != nil { 168 | return nil, err 169 | } 170 | switch parser := param.(type) { 171 | case Parsecer: 172 | return ParsecBox(p.Many1(parser.Parser)), nil 173 | default: 174 | return nil, ParsexSignErrorf( 175 | "Many1 Arg Error:except 1 parser arg but %v.", 176 | reflect.TypeOf(param)) 177 | } 178 | }, 179 | "many": func(env Env, args ...interface{}) (Lisp, error) { 180 | if len(args) != 1 { 181 | return nil, ParsexSignErrorf("Parsec Parser Many Error: only accept one Parsec Parser as arg but %v", args) 182 | } 183 | param, err := Eval(env, args[0]) 184 | if err != nil { 185 | return nil, err 186 | } 187 | switch parser := param.(type) { 188 | case Parsecer: 189 | return ParsecBox(p.Many(parser.Parser)), nil 190 | default: 191 | return nil, ParsexSignErrorf( 192 | "Many Arg Error:except 1 parser arg but %v.", 193 | reflect.TypeOf(param)) 194 | } 195 | }, 196 | "failed": func(env Env, args ...interface{}) (Lisp, error) { 197 | if len(args) != 1 { 198 | return nil, ParsexSignErrorf("Parsec Parser Failed Error: only accept one string as arg but %v", args) 199 | } 200 | param, err := Eval(env, args[0]) 201 | if err != nil { 202 | return nil, err 203 | } 204 | var str string 205 | var ok bool 206 | if str, ok = param.(string); !ok { 207 | return nil, ParsexSignErrorf("Failed Arg Error:except 1 string arg.") 208 | } 209 | return ParsecBox(p.Fail(str)), nil 210 | }, 211 | "oneof": func(env Env, args ...interface{}) (Lisp, error) { 212 | if len(args) != 1 { 213 | return nil, ParsexSignErrorf("OneOf Arg Error:except args has 1 arg.") 214 | } 215 | param, err := Eval(env, args[0]) 216 | if err != nil { 217 | return nil, err 218 | } 219 | var ( 220 | data string 221 | ok bool 222 | ) 223 | if data, ok = param.(string); !ok { 224 | return nil, ParsexSignErrorf("OneOf Arg Error:except args has 1 string arg.") 225 | } 226 | return ParsecBox(p.OneOf(data)), nil 227 | }, 228 | "noneof": func(env Env, args ...interface{}) (Lisp, error) { 229 | if len(args) != 1 { 230 | return nil, ParsexSignErrorf("NoneOf Arg Error:except args has 1 arg.") 231 | } 232 | param, err := Eval(env, args[0]) 233 | if err != nil { 234 | return nil, err 235 | } 236 | var ( 237 | data string 238 | ok bool 239 | ) 240 | if data, ok = param.(string); !ok { 241 | return nil, ParsexSignErrorf("NoneOf Arg Error:except args has 1 string arg.") 242 | } 243 | return ParsecBox(p.NoneOf(data)), nil 244 | }, 245 | "between": func(env Env, args ...interface{}) (Lisp, error) { 246 | ptype := reflect.TypeOf((*Parsecer)(nil)).Elem() 247 | params, err := GetArgs(env, px.UnionAll(TypeAs(ptype), TypeAs(ptype), TypeAs(ptype), px.Eof), args) 248 | if err != nil { 249 | return nil, err 250 | } 251 | return ParsecBox(p.Between(params[0].(Parsecer).Parser, params[1].(Parsecer).Parser, params[2].(Parsecer).Parser)), nil 252 | }, 253 | "bind": func(env Env, args ...interface{}) (Lisp, error) { 254 | if len(args) != 2 { 255 | return nil, ParsexSignErrorf("Bind Args Error:except 2 args.") 256 | } 257 | prs, err := Eval(env, args[0]) 258 | if err != nil { 259 | return nil, err 260 | } 261 | var parser Parsecer 262 | var ok bool 263 | if parser, ok = prs.(Parsecer); !ok { 264 | return nil, ParsexSignErrorf("Bind Args Error:except first arg is a parsecer.") 265 | } 266 | f, err := Eval(env, args[1]) 267 | if err != nil { 268 | return nil, err 269 | } 270 | switch fun := f.(type) { 271 | case func(interface{}) p.Parser: 272 | return ParsecBox(p.Bind(parser.Parser, fun)), nil 273 | case Functor: 274 | return ParsecBox(p.Bind(parser.Parser, func(x interface{}) p.Parser { 275 | tasker, err := fun.Task(env, x) 276 | if err != nil { 277 | return func(st p.ParseState) (interface{}, error) { 278 | return nil, err 279 | } 280 | } 281 | pr, err := tasker.Eval(env) 282 | if err != nil { 283 | return func(st p.ParseState) (interface{}, error) { 284 | return nil, err 285 | } 286 | } 287 | switch parser := pr.(type) { 288 | case p.Parser: 289 | return parser 290 | case Parsecer: 291 | return parser.Parser 292 | default: 293 | return func(st p.ParseState) (interface{}, error) { 294 | return nil, ParsexSignErrorf("excpet got a parser but %v", pr) 295 | } 296 | } 297 | })), nil 298 | default: 299 | return nil, ParsexSignErrorf("excpet got a parser but %v", prs) 300 | } 301 | }, 302 | "bind_": func(env Env, args ...interface{}) (Lisp, error) { 303 | ptype := reflect.TypeOf((*Parsecer)(nil)).Elem() 304 | params, err := GetArgs(env, px.UnionAll(TypeAs(ptype), TypeAs(ptype), px.Eof), args) 305 | if err != nil { 306 | return nil, err 307 | } 308 | return ParsecBox(p.Bind_(params[0].(Parsecer).Parser, params[1].(Parsecer).Parser)), nil 309 | }, 310 | "sepby1": func(env Env, args ...interface{}) (Lisp, error) { 311 | ptype := reflect.TypeOf((*Parsecer)(nil)).Elem() 312 | params, err := GetArgs(env, px.UnionAll(TypeAs(ptype), TypeAs(ptype), px.Eof), args) 313 | if err != nil { 314 | return nil, err 315 | } 316 | return ParsecBox(p.SepBy1(params[0].(Parsecer).Parser, params[1].(Parsecer).Parser)), nil 317 | }, 318 | "sepby": func(env Env, args ...interface{}) (Lisp, error) { 319 | ptype := reflect.TypeOf((*Parsecer)(nil)).Elem() 320 | params, err := GetArgs(env, px.UnionAll(TypeAs(ptype), TypeAs(ptype), px.Eof), args) 321 | if err != nil { 322 | return nil, err 323 | } 324 | return ParsecBox(p.SepBy(params[0].(Parsecer).Parser, params[1].(Parsecer).Parser)), nil 325 | }, 326 | "manytil": func(env Env, args ...interface{}) (Lisp, error) { 327 | ptype := reflect.TypeOf((*Parsecer)(nil)).Elem() 328 | params, err := GetArgs(env, px.UnionAll(TypeAs(ptype), TypeAs(ptype), px.Eof), args) 329 | if err != nil { 330 | return nil, err 331 | } 332 | return ParsecBox(p.ManyTil(params[0].(Parsecer).Parser, params[1].(Parsecer).Parser)), nil 333 | }, 334 | "maybe": func(env Env, args ...interface{}) (Lisp, error) { 335 | if len(args) != 1 { 336 | return nil, ParsexSignErrorf("Parsec Parser Maybe Error: only accept one parsec parser as arg but %v", args) 337 | } 338 | param, err := Eval(env, args[0]) 339 | if err != nil { 340 | return nil, err 341 | } 342 | switch parser := param.(type) { 343 | case Parsecer: 344 | return ParsecBox(p.Maybe(parser.Parser)), nil 345 | default: 346 | return nil, ParsexSignErrorf( 347 | "Manybe Arg Error:except 1 parser arg but %v.", 348 | reflect.TypeOf(param)) 349 | } 350 | }, 351 | "skip": func(env Env, args ...interface{}) (Lisp, error) { 352 | if len(args) != 1 { 353 | return nil, ParsexSignErrorf("Parsec Parser Skip Error: only accept one parsec parser as arg but %v", args) 354 | } 355 | param, err := Eval(env, args[0]) 356 | if err != nil { 357 | return nil, err 358 | } 359 | switch parser := param.(type) { 360 | case Parsecer: 361 | return ParsecBox(p.Skip(parser.Parser)), nil 362 | default: 363 | return nil, ParsexSignErrorf( 364 | "Skip Arg Error:except 1 parser arg but %v.", 365 | reflect.TypeOf(param)) 366 | } 367 | }, 368 | }, 369 | } 370 | 371 | // Parsecer 定了一个对 Parsec 解释器的封装 372 | type Parsecer struct { 373 | Parser p.Parser 374 | } 375 | 376 | // Task 实现了其求值逻辑 377 | func (parsec Parsecer) Task(env Env, args ...interface{}) (Lisp, error) { 378 | if len(args) != 1 { 379 | return nil, ParsexSignErrorf( 380 | "Parsec Parser Exprission Error: only accept one parsec state as arg but %v", 381 | args[0]) 382 | } 383 | param, err := Eval(env, args[0]) 384 | if err != nil { 385 | return nil, err 386 | } 387 | var st p.ParseState 388 | var ok bool 389 | if st, ok = param.(p.ParseState); !ok { 390 | return nil, ParsexSignErrorf( 391 | "Parsec Parser Exprission Error: only accept one parsec state as arg but %v", 392 | reflect.TypeOf(args[0])) 393 | } 394 | return ParsecTask{parsec.Parser, st}, nil 395 | } 396 | 397 | // Eval 实现了 Parsecer 的求值解析 398 | func (parsec Parsecer) Eval(env Env) (interface{}, error) { 399 | return parsec, nil 400 | } 401 | 402 | // ParsecBox 返回一个封装的 paer 403 | func ParsecBox(parser p.Parser) Lisp { 404 | return Parsecer{parser} 405 | } 406 | 407 | // ParsecTask 是延迟执行 Parsec 逻辑的封装 408 | type ParsecTask struct { 409 | Parser p.Parser 410 | State p.ParseState 411 | } 412 | 413 | // Eval 实现了求值 414 | func (pt ParsecTask) Eval(env Env) (interface{}, error) { 415 | return pt.Parser(pt.State) 416 | } 417 | -------------------------------------------------------------------------------- /parsec_test.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | 7 | p "github.com/Dwarfartisan/goparsec" 8 | ) 9 | 10 | func TestParsecBasic(t *testing.T) { 11 | g := NewGispWith( 12 | map[string]Toolbox{ 13 | "axiom": Axiom, "props": Propositions, "time": Time}, 14 | map[string]Toolbox{"time": Time, "p": Parsec}) 15 | 16 | digit := p.Bind(p.Many1(p.Digit), p.ReturnString) 17 | data := "344932454094325" 18 | state := p.MemoryParseState(data) 19 | pre, err := digit(state) 20 | if err != nil { 21 | t.Fatalf("except \"%v\" pass test many1 digit but error:%v", data, err) 22 | } 23 | 24 | src := "(let ((st (p.state \"" + data + `"))) 25 | (var data ((p.many1 p.digit) st)) 26 | (p.s2str data)) 27 | ` 28 | gre, err := g.Parse(src) 29 | if err != nil { 30 | t.Fatalf("except \"%v\" pass gisp many1 digit but error:%v", src, err) 31 | } 32 | t.Logf("from gisp: %v", gre) 33 | t.Logf("from parsec: %v", pre) 34 | if !reflect.DeepEqual(pre, gre) { 35 | t.Fatalf("except got \"%v\" from gisp equal \"%v\" from parsec", gre, pre) 36 | } 37 | } 38 | 39 | func TestParsecRune(t *testing.T) { 40 | g := NewGispWith( 41 | map[string]Toolbox{ 42 | "axiom": Axiom, "props": Propositions, "time": Time}, 43 | map[string]Toolbox{"time": Time, "p": Parsec}) 44 | //data := "Here is a Rune : 'a' and a is't a rune. It is a word in sentence." 45 | data := "'a' and a is't a rune. It is a word in sentence." 46 | state := p.MemoryParseState(data) 47 | pre, err := p.Between(p.Rune('\''), p.Rune('\''), p.AnyRune)(state) 48 | if err != nil { 49 | t.Fatalf("except found rune expr from \"%v\" but error:%v", data, err) 50 | } 51 | src := ` 52 | (let ((st (p.state "` + data + `"))) 53 | ((p.between (p.rune '\'') (p.rune '\'') p.anyone) st)) 54 | ` 55 | 56 | //fmt.Println(src) 57 | gre, err := g.Parse(src) 58 | if err != nil { 59 | t.Fatalf("except \"%v\" pass gisp '' but error:%v", src, err) 60 | } 61 | t.Logf("from gisp: %v", gre) 62 | t.Logf("from parsec: %v", pre) 63 | if !reflect.DeepEqual(pre, gre) { 64 | t.Fatalf("except got \"%v\" from gisp equal \"%v\" from parsec", gre, pre) 65 | } 66 | } 67 | 68 | func TestParsecRune2(t *testing.T) { 69 | g := NewGispWith( 70 | map[string]Toolbox{ 71 | "axiom": Axiom, "props": Propositions, "time": Time}, 72 | map[string]Toolbox{"time": Time, "p": Parsec}) 73 | //data := "Here is a Rune : 'a' and a is't a rune. It is a word in sentence." 74 | data := "'a' and a is't a rune. It is a word in sentence." 75 | state := p.MemoryParseState(data) 76 | pre, err := p.Between(p.Rune('\''), p.Rune('\''), p.AnyRune)(state) 77 | if err != nil { 78 | t.Fatalf("except found rune expr from \"%v\" but error:%v", data, err) 79 | } 80 | src := ` 81 | (let ((st (p.state "` + data + `"))) 82 | ((p.rune '\'') st) 83 | (var data (p.anyone st)) 84 | ((p.rune '\'') st) 85 | data) 86 | ` 87 | 88 | //fmt.Println(src) 89 | gre, err := g.Parse(src) 90 | if err != nil { 91 | t.Fatalf("except \"%v\" pass gisp '' but error:%v", src, err) 92 | } 93 | t.Logf("from gisp: %v", gre) 94 | t.Logf("from parsec: %v", pre) 95 | if !reflect.DeepEqual(pre, gre) { 96 | t.Fatalf("except got \"%v\" from gisp equal \"%v\" from parsec", gre, pre) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /parser.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | p "github.com/Dwarfartisan/goparsec" 8 | ) 9 | 10 | // Gisp 实现一个基本的 gisp 解释器 11 | type Gisp struct { 12 | Meta map[string]interface{} 13 | Content map[string]interface{} 14 | } 15 | 16 | // NewGisp 给定若干可以组合的基准环境,用于构造环境 17 | func NewGisp(buildins map[string]Toolbox) *Gisp { 18 | ret := Gisp{ 19 | Meta: map[string]interface{}{ 20 | "category": "gisp", 21 | "buildins": buildins, 22 | }, 23 | Content: map[string]interface{}{}, 24 | } 25 | return &ret 26 | } 27 | 28 | // NewGispWith 允许用户在构造 gisp 环境时指定使用的包 29 | func NewGispWith(buildins map[string]Toolbox, ext map[string]Toolbox) *Gisp { 30 | gisp := NewGisp(buildins) 31 | if ext == nil { 32 | return gisp 33 | } 34 | for k, v := range ext { 35 | gisp.DefAs(k, v) 36 | } 37 | return gisp 38 | } 39 | 40 | // DefAs : def as = def var + set var 41 | func (gisp *Gisp) DefAs(name string, value interface{}) error { 42 | t := Type{reflect.TypeOf(value), false} 43 | slot := VarSlot(t) 44 | slot.Set(value) 45 | return gisp.Defvar(name, slot) 46 | } 47 | 48 | // DefOptAs : def option as = def var? + set var 49 | func (gisp *Gisp) DefOptAs(name string, value interface{}) error { 50 | t := Type{reflect.TypeOf(value), true} 51 | slot := VarSlot(t) 52 | slot.Set(value) 53 | return gisp.Defvar(name, slot) 54 | } 55 | 56 | // Defvar 实现 Env.Defvar 57 | func (gisp *Gisp) Defvar(name string, slot Var) error { 58 | if _, ok := gisp.Content[name]; ok { 59 | return fmt.Errorf("var %s exists", name) 60 | } 61 | gisp.Content[name] = slot 62 | return nil 63 | } 64 | 65 | // Defun 实现 Env.Defun 66 | func (gisp *Gisp) Defun(name string, functor Functor) error { 67 | if s, ok := gisp.Local(name); ok { 68 | switch slot := s.(type) { 69 | case Func: 70 | slot.Overload(functor) 71 | case Var: 72 | return fmt.Errorf("%s defined as a var") 73 | default: 74 | return fmt.Errorf("exists name %s isn't Expr", name) 75 | } 76 | } 77 | gisp.Content[name] = &Function{ 78 | Atom{name, Type{ANY, false}}, 79 | gisp, 80 | []Functor{functor}, 81 | } 82 | return nil 83 | } 84 | 85 | // Setvar 实现 Env.Set 接口 86 | func (gisp *Gisp) Setvar(name string, value interface{}) error { 87 | if s, ok := gisp.Content[name]; ok { 88 | switch slot := s.(type) { 89 | case Var: 90 | slot.Set(value) 91 | return nil 92 | case Function: 93 | return fmt.Errorf("%v is a Expr", name) 94 | default: 95 | return fmt.Errorf("%v is't a var canbe set", name) 96 | } 97 | } else { 98 | return fmt.Errorf("Setable var %s not found", name) 99 | } 100 | } 101 | 102 | // Local 实现了对命名的本地查找定位 103 | func (gisp Gisp) Local(name string) (interface{}, bool) { 104 | if value, ok := gisp.Content[name]; ok { 105 | if slot, ok := value.(Var); ok { 106 | return slot.Get(), true 107 | } 108 | return value, true 109 | } 110 | return nil, false 111 | } 112 | 113 | // Lookup 允许向上查找 114 | func (gisp Gisp) Lookup(name string) (interface{}, bool) { 115 | if value, ok := gisp.Local(name); ok { 116 | return value, true 117 | } 118 | return gisp.Global(name) 119 | } 120 | 121 | // Global look up in buildins 122 | func (gisp Gisp) Global(name string) (interface{}, bool) { 123 | buildins := gisp.Meta["buildins"].(map[string]Toolbox) 124 | for _, env := range buildins { 125 | if v, ok := env.Lookup(name); ok { 126 | return v, true 127 | } 128 | } 129 | return nil, false 130 | } 131 | 132 | // Parse 解释执行一段文本 133 | func (gisp *Gisp) Parse(code string) (interface{}, error) { 134 | st := p.MemoryParseState(code) 135 | var v interface{} 136 | var e error 137 | for { 138 | Skip(st) 139 | _, err := p.Eof(st) 140 | if err == nil { 141 | break 142 | } 143 | value, err := ValueParserExt(gisp)(st) 144 | if err != nil { 145 | return nil, err 146 | } 147 | switch lisp := value.(type) { 148 | case Lisp: 149 | v, e = lisp.Eval(gisp) 150 | default: 151 | v = lisp 152 | e = nil 153 | } 154 | } 155 | return v, e 156 | } 157 | 158 | // Eval 解释执行一串 Lisp 序列 159 | func (gisp *Gisp) Eval(lisps ...interface{}) (interface{}, error) { 160 | var ret interface{} 161 | var err error 162 | for _, l := range lisps { 163 | switch lisp := l.(type) { 164 | case Lisp: 165 | ret, err = lisp.Eval(gisp) 166 | if err != nil { 167 | return nil, err 168 | } 169 | default: 170 | ret = lisp 171 | } 172 | } 173 | return ret, nil 174 | } 175 | -------------------------------------------------------------------------------- /parser_test.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | tm "time" 7 | ) 8 | 9 | func TestParseString(t *testing.T) { 10 | g := NewGisp(map[string]Toolbox{}) 11 | gisp := *g 12 | data := `"I'm a string"` 13 | str, err := gisp.Parse(data) 14 | if err != nil { 15 | t.Fatalf("except string but error: %v", err) 16 | } 17 | if str.(string) != `I'm a string` { 18 | t.Fatalf("except got \"I'm a string\" but \"%v\"", str) 19 | } 20 | } 21 | 22 | func TestParseFloat(t *testing.T) { 23 | g := NewGisp(map[string]Toolbox{}) 24 | gisp := *g 25 | data := "3.14" 26 | ret, err := gisp.Parse(data) 27 | if err != nil { 28 | t.Fatalf("except Float(3.14) but error: %v", err) 29 | } 30 | if ret.(Float) != Float(3.14) { 31 | t.Fatalf("except got Float(3.14) but %v", ret) 32 | } 33 | } 34 | 35 | func TestParseExt(t *testing.T) { 36 | g := NewGispWith( 37 | map[string]Toolbox{"axiom": Axiom, "props": Propositions}, 38 | map[string]Toolbox{"time": Time}) 39 | gisp := *g 40 | ret, err := gisp.Parse("(time.now)") 41 | if err != nil { 42 | t.Fatalf("except got time.Now() but error: %v", err) 43 | } 44 | if now, ok := ret.(tm.Time); ok { 45 | t.Logf("got now time is %v", now) 46 | } else { 47 | t.Fatalf("except got now time but %v", now) 48 | } 49 | } 50 | 51 | func TestParseCallToolkitFunction(t *testing.T) { 52 | g := NewGispWith( 53 | map[string]Toolbox{"axiom": Axiom, "props": Propositions}, 54 | map[string]Toolbox{"time": Time}) 55 | gisp := *g 56 | ret, err := gisp.Parse(`(time.parseDuration "24h")`) 57 | if err != nil { 58 | t.Fatalf("except got time.Duration 24 hours but error: %v", err) 59 | } 60 | dur, err := tm.ParseDuration("24h") 61 | if err != nil { 62 | t.Fatalf("except got time.Duration 24 hours but error: %v", err) 63 | } 64 | if !reflect.DeepEqual(dur, ret) { 65 | t.Fatalf("except got time.Duration 24 hours but got: %v", ret) 66 | } 67 | t.Logf("parse duration \"24h\" got %v\n", ret) 68 | } 69 | -------------------------------------------------------------------------------- /parses.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | "strconv" 7 | 8 | p "github.com/Dwarfartisan/goparsec" 9 | ) 10 | 11 | // Ext 扩展表示扩展环境 12 | 13 | // Space 即空格判定 14 | var Space = p.Space 15 | 16 | // Skip 忽略匹配指定算子的内容 17 | var Skip = p.Skip(Space) 18 | 19 | // IntParser 解析整数 20 | func IntParser(st p.ParseState) (interface{}, error) { 21 | i, err := p.Int(st) 22 | if err == nil { 23 | val, err := strconv.Atoi(i.(string)) 24 | if err == nil { 25 | return Int(val), nil 26 | } 27 | return nil, err 28 | } 29 | return nil, err 30 | 31 | } 32 | 33 | // 用于string 34 | var EscapeChars = p.Bind_(p.Rune('\\'), func(st p.ParseState) (interface{}, error) { 35 | r, err := p.OneOf("nrt\"\\")(st) 36 | if err == nil { 37 | ru := r.(rune) 38 | switch ru { 39 | case 'r': 40 | return '\r', nil 41 | case 'n': 42 | return '\n', nil 43 | case '"': 44 | return '"', nil 45 | case '\\': 46 | return '\\', nil 47 | case 't': 48 | return '\t', nil 49 | default: 50 | return nil, st.Trap("Unknown escape sequence \\%c", r) 51 | } 52 | } else { 53 | return nil, err 54 | } 55 | }) 56 | 57 | //用于rune 58 | var EscapeCharr = p.Bind_(p.Rune('\\'), func(st p.ParseState) (interface{}, error) { 59 | r, err := p.OneOf("nrt'\\")(st) 60 | if err == nil { 61 | ru := r.(rune) 62 | switch ru { 63 | case 'r': 64 | return '\r', nil 65 | case 'n': 66 | return '\n', nil 67 | case '\'': 68 | return '\'', nil 69 | case '\\': 70 | return '\\', nil 71 | case 't': 72 | return '\t', nil 73 | default: 74 | return nil, st.Trap("Unknown escape sequence \\%c", r) 75 | } 76 | } else { 77 | return nil, err 78 | } 79 | }) 80 | 81 | // RuneParser 实现 rune 的解析 82 | var RuneParser = p.Bind( 83 | p.Between(p.Rune('\''), p.Rune('\''), 84 | p.Either(p.Try(EscapeCharr), p.NoneOf("'"))), 85 | func(x interface{}) p.Parser { 86 | return p.Return(Rune(x.(rune))) 87 | }, 88 | ) 89 | 90 | // StringParser 实现字符串解析 91 | var StringParser = p.Bind( 92 | p.Between(p.Rune('"'), p.Rune('"'), 93 | p.Many(p.Either(p.Try(EscapeChars), p.NoneOf("\"")))), 94 | p.ReturnString) 95 | 96 | func bodyParser(st p.ParseState) (interface{}, error) { 97 | value, err := p.SepBy(ValueParser, p.Many1(Space))(st) 98 | return value, err 99 | } 100 | 101 | func bodyParserExt(env Env) p.Parser { 102 | return func(st p.ParseState) (interface{}, error) { 103 | value, err := p.Many(p.Bind(ValueParserExt(env), func(x interface{}) p.Parser { 104 | return p.Bind_(Skip, p.Return(x)) 105 | }))(st) 106 | return value, err 107 | } 108 | } 109 | 110 | // ListParser 实现列表解析器 111 | func ListParser(st p.ParseState) (interface{}, error) { 112 | left := p.Bind_(p.Rune('('), Skip) 113 | right := p.Bind_(Skip, p.Rune(')')) 114 | empty := p.Between(left, right, Skip) 115 | list, err := p.Between(left, right, bodyParser)(st) 116 | if err == nil { 117 | switch l := list.(type) { 118 | case List: 119 | return L(l), nil 120 | case []interface{}: 121 | return list.([]interface{}), nil 122 | default: 123 | return nil, fmt.Errorf("List Parser Error: %v type is unexcepted: %v", list, reflect.TypeOf(list)) 124 | } 125 | } else { 126 | _, e := empty(st) 127 | if e == nil { 128 | return List{}, nil 129 | } 130 | return nil, err 131 | } 132 | } 133 | 134 | // ListParserExt 实现带扩展的列表解析器 135 | func ListParserExt(env Env) p.Parser { 136 | left := p.Bind_(p.Rune('('), Skip) 137 | right := p.Bind_(Skip, p.Rune(')')) 138 | empty := p.Between(left, right, Skip) 139 | return func(st p.ParseState) (interface{}, error) { 140 | list, err := p.Between(left, right, bodyParserExt(env))(st) 141 | if err == nil { 142 | switch l := list.(type) { 143 | case List: 144 | return L(l), nil 145 | case []interface{}: 146 | return List(l), nil 147 | default: 148 | return nil, fmt.Errorf("List Parser(ext) Error: %v type is unexcepted: %v", list, reflect.TypeOf(list)) 149 | } 150 | } else { 151 | _, e := empty(st) 152 | if e == nil { 153 | return List{}, nil 154 | } 155 | return nil, err 156 | } 157 | } 158 | } 159 | 160 | // QuoteParser 实现 Quote 语法的解析 161 | func QuoteParser(st p.ParseState) (interface{}, error) { 162 | lisp, err := p.Bind_(p.Rune('\''), 163 | p.Choice( 164 | p.Try(p.Bind(AtomParser, SuffixParser)), 165 | p.Bind(ListParser, SuffixParser), 166 | ))(st) 167 | if err == nil { 168 | return Quote{lisp}, nil 169 | } 170 | return nil, err 171 | } 172 | 173 | // QuoteParserExt 实现带扩展的 Quote 语法的解析 174 | func QuoteParserExt(env Env) p.Parser { 175 | return func(st p.ParseState) (interface{}, error) { 176 | lisp, err := p.Bind_(p.Rune('\''), 177 | p.Choice( 178 | p.Try(p.Bind(AtomParserExt(env), SuffixParser)), 179 | p.Bind(ListParserExt(env), SuffixParser), 180 | ))(st) 181 | if err == nil { 182 | return Quote{lisp}, nil 183 | } 184 | return nil, err 185 | } 186 | } 187 | 188 | // ValueParser 实现简单的值解释器 189 | func ValueParser(st p.ParseState) (interface{}, error) { 190 | value, err := p.Choice(p.Try(StringParser), 191 | p.Try(FloatParser), 192 | p.Try(IntParser), 193 | p.Try(RuneParser), 194 | p.Try(StringParser), 195 | p.Try(BoolParser), 196 | p.Try(NilParser), 197 | p.Try(p.Bind(AtomParser, SuffixParser)), 198 | p.Try(p.Bind(ListParser, SuffixParser)), 199 | p.Try(DotExprParser), 200 | QuoteParser, 201 | )(st) 202 | return value, err 203 | } 204 | 205 | // ValueParserExt 表示带扩展的值解释器 206 | func ValueParserExt(env Env) p.Parser { 207 | return func(st p.ParseState) (interface{}, error) { 208 | value, err := p.Choice(p.Try(StringParser), 209 | p.Try(FloatParser), 210 | p.Try(IntParser), 211 | p.Try(RuneParser), 212 | p.Try(StringParser), 213 | p.Try(BoolParser), 214 | p.Try(NilParser), 215 | p.Try(p.Bind(AtomParserExt(env), SuffixParserExt(env))), 216 | p.Try(p.Bind(ListParserExt(env), SuffixParserExt(env))), 217 | p.Try(DotExprParser), 218 | p.Try(BracketExprParserExt(env)), 219 | QuoteParserExt(env), 220 | )(st) 221 | return value, err 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /parsex.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "fmt" 5 | // p "github.com/Dwarfartisan/goparsec/parsex" 6 | "reflect" 7 | 8 | px "github.com/Dwarfartisan/goparsec/parsex" 9 | ) 10 | 11 | // Parsex 包为 gisp 解释器提供 parsex 解析工具 12 | var Parsex = Toolkit{ 13 | Meta: map[string]interface{}{ 14 | "name": "parsex", 15 | "category": "package", 16 | }, 17 | Content: map[string]interface{}{ 18 | "state": func(env Env, args ...interface{}) (Lisp, error) { 19 | if len(args) != 1 { 20 | return nil, ParsexSignErrorf("Parsex Arg Error:except args has 1 arg.") 21 | } 22 | param, err := Eval(env, args[0]) 23 | if err != nil { 24 | return nil, err 25 | } 26 | switch data := param.(type) { 27 | case string: 28 | return Q(NewStringState(data)), nil 29 | case List: 30 | return Q(px.NewStateInMemory(data)), nil 31 | default: 32 | return nil, fmt.Errorf("Parsex Error: Except create a state from a string or List but %v", data) 33 | } 34 | }, 35 | "s2str": func(env Env, args ...interface{}) (Lisp, error) { 36 | if len(args) != 1 { 37 | return nil, ParsexSignErrorf("Slice to string Arg Error:except args has 1 arg.") 38 | } 39 | param, err := Eval(env, args[0]) 40 | if err != nil { 41 | return nil, err 42 | } 43 | var ( 44 | slice []interface{} 45 | ok bool 46 | ) 47 | if slice, ok = param.([]interface{}); !ok { 48 | return nil, ParsexSignErrorf("s2str Arg Error:except 1 []interface{} arg.") 49 | } 50 | return Q(px.ExtractString(slice)), nil 51 | }, 52 | "anyone": ParsexBox(px.AnyOne), 53 | "one": func(env Env, args ...interface{}) (Lisp, error) { 54 | if len(args) != 1 { 55 | return nil, ParsexSignErrorf("One Arg Error:except args has 1 arg.") 56 | } 57 | param, err := Eval(env, args[0]) 58 | if err != nil { 59 | return nil, err 60 | } 61 | return ParsexBox(px.TheOne(param)), nil 62 | }, 63 | "str": func(env Env, args ...interface{}) (Lisp, error) { 64 | if len(args) != 1 { 65 | return nil, ParsexSignErrorf("One Arg Error:except args has 1 arg.") 66 | } 67 | param, err := Eval(env, args[0]) 68 | if err != nil { 69 | return nil, err 70 | } 71 | return ParsexBox(px.String(param.(string))), nil 72 | }, 73 | "rune": func(env Env, args ...interface{}) (Lisp, error) { 74 | if len(args) != 1 { 75 | return nil, ParsexSignErrorf("Rune Arg Error:except args has 1 arg.") 76 | } 77 | param, err := Eval(env, args[0]) 78 | if err != nil { 79 | return nil, err 80 | } 81 | return ParsexBox(px.Rune(rune(param.(Rune)))), nil 82 | }, 83 | "anyrune": ParsexBox(px.AnyRune), 84 | "anyintx": ParsexBox(px.AnyInt), 85 | "anyfloatx": ParsexBox(px.AnyFloat64), 86 | "anystringx": ParsexBox(px.StringVal), 87 | "anyint": ParsexBox(px.AnyInt), 88 | "anyfloat": ParsexBox(px.AnyFloat64), 89 | "aint": ParsexBox(px.Int), 90 | "afloat": ParsexBox(px.Float), 91 | "astring": ParsexBox(px.StringVal), 92 | "string": func(env Env, args ...interface{}) (Lisp, error) { 93 | if len(args) != 1 { 94 | return nil, ParsexSignErrorf("string Arg Error:except args has 1 arg.") 95 | } 96 | param, err := Eval(env, args[0]) 97 | if err != nil { 98 | return nil, err 99 | } 100 | var str string 101 | var ok bool 102 | if str, ok = param.(string); !ok { 103 | return nil, ParsexSignErrorf("stringx Arg Error:except 1 string arg.") 104 | } 105 | return ParsexBox(px.Str(str)), nil 106 | }, 107 | "stringx": func(env Env, args ...interface{}) (Lisp, error) { 108 | if len(args) != 1 { 109 | return nil, ParsexSignErrorf("stringx Arg Error:except args has 1 arg.") 110 | } 111 | param, err := Eval(env, args[0]) 112 | if err != nil { 113 | return nil, err 114 | } 115 | var str string 116 | var ok bool 117 | if str, ok = param.(string); !ok { 118 | return nil, ParsexSignErrorf("stringx Arg Error:except 1 string arg.") 119 | } 120 | return ParsexBox(px.String(str)), nil 121 | }, 122 | "digit": ParsexBox(px.Digit), 123 | "int": func(env Env, args ...interface{}) (Lisp, error) { 124 | if len(args) != 1 { 125 | return nil, ParsexSignErrorf("int Arg Error:except args has 1 arg.") 126 | } 127 | param, err := Eval(env, args[0]) 128 | if err != nil { 129 | return nil, err 130 | } 131 | var i Int 132 | var ok bool 133 | if i, ok = param.(Int); !ok { 134 | return nil, ParsexSignErrorf("int Arg Error:except 1 string arg.") 135 | } 136 | return ParsexBox(func(st px.ParsexState) (interface{}, error) { 137 | data, err := px.Int(st) 138 | if err != nil { 139 | return nil, st.Trap("gisp parsex error:except a int but error: %v", err) 140 | } 141 | if Int(data.(int)) != i { 142 | return nil, st.Trap("gisp parsex error:except a Int but %v", data) 143 | } 144 | return data, nil 145 | }), nil 146 | }, 147 | "float": func(env Env, args ...interface{}) (Lisp, error) { 148 | if len(args) != 1 { 149 | return nil, ParsexSignErrorf("float Arg Error:except args has 1 arg.") 150 | } 151 | param, err := Eval(env, args[0]) 152 | if err != nil { 153 | return nil, err 154 | } 155 | var f Float 156 | var ok bool 157 | if f, ok = param.(Float); !ok { 158 | return nil, ParsexSignErrorf("float Arg Error:except 1 string arg.") 159 | } 160 | return ParsexBox(func(st px.ParsexState) (interface{}, error) { 161 | data, err := px.Float(st) 162 | if err != nil { 163 | return nil, st.Trap("gisp parsex error:except a float but error: %v", err) 164 | } 165 | if Float(data.(float64)) != f { 166 | return nil, st.Trap("gisp parsex error:except a Float but %v", data) 167 | } 168 | return data, nil 169 | }), nil 170 | }, 171 | "eof": ParsexBox(px.Eof), 172 | "nil": ParsexBox(px.Nil), 173 | "atimex": ParsexBox(px.TimeVal), 174 | "try": func(env Env, args ...interface{}) (Lisp, error) { 175 | if len(args) != 1 { 176 | return nil, ParsexSignErrorf("Parsex Parser Try Error: only accept one parsex parser as arg but %v", args) 177 | } 178 | param, err := Eval(env, args[0]) 179 | if err != nil { 180 | return nil, err 181 | } 182 | switch parser := param.(type) { 183 | case Parsexer: 184 | return ParsexBox(px.Try(parser.Parser)), nil 185 | default: 186 | return nil, ParsexSignErrorf( 187 | "Try Arg Error:except 1 parser arg but %v.", 188 | reflect.TypeOf(param)) 189 | } 190 | 191 | }, 192 | "either": func(env Env, args ...interface{}) (Lisp, error) { 193 | ptype := reflect.TypeOf((px.Parser)(nil)) 194 | params, err := GetArgs(env, px.UnionAll(TypeAs(ptype), TypeAs(ptype), px.Eof), args) 195 | if err != nil { 196 | return nil, err 197 | } 198 | return ParsexBox(px.Either(params[0].(Parsexer).Parser, params[1].(Parsexer).Parser)), nil 199 | }, 200 | "choice": func(env Env, args ...interface{}) (Lisp, error) { 201 | ptype := reflect.TypeOf((px.Parser)(nil)) 202 | params, err := GetArgs(env, px.ManyTil(TypeAs(ptype), px.Eof), args) 203 | if err != nil { 204 | return nil, err 205 | } 206 | parsers := make([]px.Parser, len(params)) 207 | for idx, prs := range params { 208 | if parser, ok := prs.(Parsexer); ok { 209 | parsers[idx] = parser.Parser 210 | } 211 | return nil, ParsexSignErrorf("Choice Args Error:except parsec parsers but %v is %v", 212 | prs, reflect.TypeOf(prs)) 213 | } 214 | return ParsexBox(px.Choice(parsers...)), nil 215 | }, 216 | "return": func(env Env, args ...interface{}) (Lisp, error) { 217 | if len(args) != 1 { 218 | return nil, ParsexSignErrorf("Parsex Parser Return Error: only accept one parsex parser as arg but %v", args) 219 | } 220 | param, err := Eval(env, args[0]) 221 | if err != nil { 222 | return nil, err 223 | } 224 | return ParsexBox(px.Return(param)), nil 225 | }, 226 | "option": func(env Env, args ...interface{}) (Lisp, error) { 227 | if len(args) != 2 { 228 | return nil, ParsexSignErrorf("Parsex Parser Option Error: only accept two parsex parser as arg but %v", args) 229 | } 230 | data, err := Eval(env, args[0]) 231 | if err != nil { 232 | return nil, err 233 | } 234 | param, err := Eval(env, args[1]) 235 | if err != nil { 236 | return nil, err 237 | } 238 | switch parser := param.(type) { 239 | case Parsexer: 240 | return ParsexBox(px.Option(data, parser.Parser)), nil 241 | default: 242 | return nil, ParsexSignErrorf( 243 | "Many Arg Error:except 1 parser arg but %v.", 244 | reflect.TypeOf(param)) 245 | } 246 | }, 247 | "many1": func(env Env, args ...interface{}) (Lisp, error) { 248 | if len(args) != 1 { 249 | return nil, ParsexSignErrorf("Parsex Parser Many1 Erroparserr: only accept one parsex parser as arg but %v", args) 250 | } 251 | param, err := Eval(env, args[0]) 252 | if err != nil { 253 | return nil, err 254 | } 255 | switch parser := param.(type) { 256 | case Parsexer: 257 | return ParsexBox(px.Many1(parser.Parser)), nil 258 | default: 259 | return nil, ParsexSignErrorf( 260 | "Many1 Arg Error:except 1 parser arg but %v.", 261 | reflect.TypeOf(param)) 262 | } 263 | }, 264 | "many": func(env Env, args ...interface{}) (Lisp, error) { 265 | if len(args) != 1 { 266 | return nil, ParsexSignErrorf("Parsex Parser Many Error: only accept one parsex parser as arg but %v", args) 267 | } 268 | param, err := Eval(env, args[0]) 269 | if err != nil { 270 | return nil, err 271 | } 272 | switch parser := param.(type) { 273 | case Parsexer: 274 | return ParsexBox(px.Many(parser.Parser)), nil 275 | default: 276 | return nil, ParsexSignErrorf( 277 | "Many Arg Error:except 1 parser arg but %v.", 278 | reflect.TypeOf(param)) 279 | } 280 | }, 281 | "failed": func(env Env, args ...interface{}) (Lisp, error) { 282 | if len(args) != 1 { 283 | return nil, ParsexSignErrorf("Parsex Parser Failed Error: only accept one string as arg but %v", args) 284 | } 285 | param, err := Eval(env, args[0]) 286 | if err != nil { 287 | return nil, err 288 | } 289 | var str string 290 | var ok bool 291 | if str, ok = param.(string); !ok { 292 | return nil, ParsexSignErrorf("Failed Arg Error:except 1 string arg.") 293 | } 294 | return ParsexBox(px.Fail(str)), nil 295 | }, 296 | "oneof": func(env Env, args ...interface{}) (Lisp, error) { 297 | params, err := Evals(env, args...) 298 | if err != nil { 299 | return nil, err 300 | } 301 | return ParsexBox(px.OneOf(params...)), nil 302 | }, 303 | "noneof": func(env Env, args ...interface{}) (Lisp, error) { 304 | params, err := Evals(env, args...) 305 | if err != nil { 306 | return nil, err 307 | } 308 | return ParsexBox(px.NoneOf(params)), nil 309 | }, 310 | "between": func(env Env, args ...interface{}) (Lisp, error) { 311 | ptype := reflect.TypeOf((*Parsexer)(nil)).Elem() 312 | params, err := GetArgs(env, px.UnionAll(TypeAs(ptype), TypeAs(ptype), TypeAs(ptype), px.Eof), args) 313 | if err != nil { 314 | return nil, err 315 | } 316 | return ParsexBox(px.Between(params[0].(Parsexer).Parser, params[1].(Parsexer).Parser, params[2].(Parsexer).Parser)), nil 317 | }, 318 | "bind": func(env Env, args ...interface{}) (Lisp, error) { 319 | if len(args) != 2 { 320 | return nil, ParsexSignErrorf("Bind Args Error:except 2 args.") 321 | } 322 | prs, err := Eval(env, args[0]) 323 | if err != nil { 324 | return nil, err 325 | } 326 | var parser Parsexer 327 | var ok bool 328 | if parser, ok = prs.(Parsexer); !ok { 329 | return nil, ParsexSignErrorf("Bind Args Error:except first arg is a parsexer.") 330 | } 331 | f, err := Eval(env, args[1]) 332 | if err != nil { 333 | return nil, err 334 | } 335 | switch fun := f.(type) { 336 | case func(interface{}) px.Parser: 337 | return ParsexBox(px.Bind(parser.Parser, fun)), nil 338 | case Functor: 339 | return ParsexBox(px.Bind(parser.Parser, func(x interface{}) px.Parser { 340 | tasker, err := fun.Task(env, x) 341 | if err != nil { 342 | return func(st px.ParsexState) (interface{}, error) { 343 | return nil, err 344 | } 345 | } 346 | pr, err := tasker.Eval(env) 347 | if err != nil { 348 | return func(st px.ParsexState) (interface{}, error) { 349 | return nil, err 350 | } 351 | } 352 | switch parser := pr.(type) { 353 | case px.Parser: 354 | return parser 355 | case Parsexer: 356 | return parser.Parser 357 | default: 358 | return func(st px.ParsexState) (interface{}, error) { 359 | return nil, ParsexSignErrorf("excpet got a parser but %v", pr) 360 | } 361 | } 362 | })), nil 363 | default: 364 | return nil, ParsexSignErrorf("excpet got a parser but %v", prs) 365 | } 366 | }, 367 | "bind_": func(env Env, args ...interface{}) (Lisp, error) { 368 | ptype := reflect.TypeOf((*Parsecer)(nil)).Elem() 369 | params, err := GetArgs(env, px.UnionAll(TypeAs(ptype), TypeAs(ptype), px.Eof), args) 370 | if err != nil { 371 | return nil, err 372 | } 373 | return ParsexBox(px.Bind_(params[0].(Parsexer).Parser, params[1].(Parsexer).Parser)), nil 374 | }, 375 | "sepby1": func(env Env, args ...interface{}) (Lisp, error) { 376 | ptype := reflect.TypeOf((*Parsexer)(nil)).Elem() 377 | params, err := GetArgs(env, px.UnionAll(TypeAs(ptype), TypeAs(ptype), px.Eof), args) 378 | if err != nil { 379 | return nil, err 380 | } 381 | return ParsexBox(px.SepBy1(params[0].(Parsexer).Parser, params[1].(Parsexer).Parser)), nil 382 | }, 383 | "sepby": func(env Env, args ...interface{}) (Lisp, error) { 384 | ptype := reflect.TypeOf((*Parsexer)(nil)).Elem() 385 | params, err := GetArgs(env, px.UnionAll(TypeAs(ptype), TypeAs(ptype), px.Eof), args) 386 | if err != nil { 387 | return nil, err 388 | } 389 | return ParsexBox(px.SepBy(params[0].(Parsexer).Parser, params[1].(Parsexer).Parser)), nil 390 | }, 391 | "manytil": func(env Env, args ...interface{}) (Lisp, error) { 392 | ptype := reflect.TypeOf((*Parsexer)(nil)).Elem() 393 | params, err := GetArgs(env, px.UnionAll(TypeAs(ptype), TypeAs(ptype), px.Eof), args) 394 | if err != nil { 395 | return nil, err 396 | } 397 | return ParsexBox(px.ManyTil(params[0].(Parsexer).Parser, params[1].(Parsexer).Parser)), nil 398 | }, 399 | "maybe": func(env Env, args ...interface{}) (Lisp, error) { 400 | if len(args) != 1 { 401 | return nil, ParsexSignErrorf("Parsex Parser Maybe Error: only accept one parsex parser as arg but %v", args) 402 | } 403 | param, err := Eval(env, args[0]) 404 | if err != nil { 405 | return nil, err 406 | } 407 | switch parser := param.(type) { 408 | case Parsexer: 409 | return ParsexBox(px.Maybe(parser.Parser)), nil 410 | default: 411 | return nil, ParsexSignErrorf( 412 | "Manybe Arg Error:except 1 parser arg but %v.", 413 | reflect.TypeOf(param)) 414 | } 415 | }, 416 | "skip": func(env Env, args ...interface{}) (Lisp, error) { 417 | if len(args) != 1 { 418 | return nil, ParsexSignErrorf("Parsex Parser Skip Error: only accept one parsex parser as arg but %v", args) 419 | } 420 | param, err := Eval(env, args[0]) 421 | if err != nil { 422 | return nil, err 423 | } 424 | switch parser := param.(type) { 425 | case Parsexer: 426 | return ParsexBox(px.Skip(parser.Parser)), nil 427 | default: 428 | return nil, ParsexSignErrorf( 429 | "Skip Arg Error:except 1 parser arg but %v.", 430 | reflect.TypeOf(param)) 431 | } 432 | }, 433 | }, 434 | } 435 | 436 | // NewStringState 构造一个新的基于字符串的 state 437 | func NewStringState(data string) *px.StateInMemory { 438 | buf := make([]interface{}, len(data)) 439 | for idx, r := range data { 440 | buf[idx] = r 441 | } 442 | return px.NewStateInMemory(buf) 443 | } 444 | 445 | // Parsexer 实现一个 parsex 封装 446 | type Parsexer struct { 447 | Parser px.Parser 448 | } 449 | 450 | // Task 定义了 parsex 的求值 451 | func (parsex Parsexer) Task(env Env, args ...interface{}) (Lisp, error) { 452 | if len(args) != 1 { 453 | return nil, ParsexSignErrorf( 454 | "Parsex Parser Exprission Error: only accept one parsex state as arg but %v", 455 | args[0]) 456 | } 457 | param, err := Eval(env, args[0]) 458 | if err != nil { 459 | return nil, err 460 | } 461 | var st px.ParsexState 462 | var ok bool 463 | if st, ok = param.(px.ParsexState); !ok { 464 | return nil, ParsexSignErrorf( 465 | "Parsex Parser Exprission Error: only accept one parsex state as arg but %v", 466 | reflect.TypeOf(args[0])) 467 | } 468 | return ParsexTask{parsex.Parser, st}, nil 469 | } 470 | 471 | // Eval 定义了其解析求值时直接返回 parsex 472 | func (parsex Parsexer) Eval(env Env) (interface{}, error) { 473 | return parsex, nil 474 | } 475 | 476 | // ParsexBox 定义了一个 Parsexer 的封装 477 | func ParsexBox(parser px.Parser) Lisp { 478 | return Parsexer{parser} 479 | } 480 | 481 | // ParsexTask 定义了延迟执行 Parsex 的行为 482 | type ParsexTask struct { 483 | Parser px.Parser 484 | State px.ParsexState 485 | } 486 | 487 | // Eval 定义了 parsex task 的解析求值 488 | func (pt ParsexTask) Eval(env Env) (interface{}, error) { 489 | return pt.Parser(pt.State) 490 | } 491 | -------------------------------------------------------------------------------- /parsex_test.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | //"fmt" 5 | "reflect" 6 | "testing" 7 | 8 | px "github.com/Dwarfartisan/goparsec/parsex" 9 | ) 10 | 11 | func TestParsexBasic(t *testing.T) { 12 | g := NewGispWith( 13 | map[string]Toolbox{ 14 | "axiom": Axiom, "props": Propositions, "time": Time}, 15 | map[string]Toolbox{"time": Time, "px": Parsex}) 16 | 17 | digit := px.Bind(px.Many1(px.Digit), px.ReturnString) 18 | data := "344932454094325" 19 | state := NewStringState(data) 20 | pxre, err := digit(state) 21 | if err != nil { 22 | t.Fatalf("except \"%v\" pass test many1 digit but error:%v", data, err) 23 | } 24 | 25 | src := "(let ((st (px.state \"" + data + `"))) 26 | (var data ((px.many1 px.digit) st)) 27 | (px.s2str data)) 28 | ` 29 | gre, err := g.Parse(src) 30 | if err != nil { 31 | t.Fatalf("except \"%v\" pass gisp many1 digit but error:%v", src, err) 32 | } 33 | t.Logf("from gisp: %v", gre) 34 | t.Logf("from parsex: %v", pxre) 35 | if !reflect.DeepEqual(pxre, gre) { 36 | t.Fatalf("except got \"%v\" from gisp equal \"%v\" from parsex", gre, pxre) 37 | } 38 | } 39 | 40 | func TestParsexRune(t *testing.T) { 41 | g := NewGispWith( 42 | map[string]Toolbox{ 43 | "axiom": Axiom, "props": Propositions, "time": Time}, 44 | map[string]Toolbox{"time": Time, "px": Parsex}) 45 | //data := "Here is a Rune : 'a' and a is't a rune. It is a word in sentence." 46 | data := "'a' and a is't a rune. It is a word in sentence." 47 | state := NewStringState(data) 48 | pre, err := px.Between(px.Rune('\''), px.Rune('\''), px.AnyRune)(state) 49 | if err != nil { 50 | t.Fatalf("except found rune expr from \"%v\" but error:%v", data, err) 51 | } 52 | src := ` 53 | (let ((st (px.state "` + data + `"))) 54 | ((px.between (px.rune '\'') (px.rune '\'') px.anyone) st)) 55 | ` 56 | 57 | //fmt.Println(src) 58 | gre, err := g.Parse(src) 59 | if err != nil { 60 | t.Fatalf("except \"%v\" pass gisp '' but error:%v", src, err) 61 | } 62 | t.Logf("from gisp: %v", gre) 63 | t.Logf("from parsec: %v", pre) 64 | if !reflect.DeepEqual(pre, gre) { 65 | t.Fatalf("except got \"%v\" from gisp equal \"%v\" from parsec", gre, pre) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /proposition.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | px "github.com/Dwarfartisan/goparsec/parsex" 5 | ) 6 | 7 | // Propositions 给出了一组常用的操作 8 | var Propositions = Toolkit{ 9 | Meta: map[string]interface{}{ 10 | "name": "propositions", 11 | "category": "package", 12 | }, 13 | Content: map[string]interface{}{ 14 | "lambda": BoxExpr(LambdaExpr), 15 | "let": BoxExpr(LetExpr), 16 | "+": EvalExpr(ParsexExpr(addx)), 17 | "add": EvalExpr(ParsexExpr(addx)), 18 | "-": EvalExpr(ParsexExpr(subx)), 19 | "sub": EvalExpr(ParsexExpr(subx)), 20 | "*": EvalExpr(ParsexExpr(mulx)), 21 | "mul": EvalExpr(ParsexExpr(mulx)), 22 | "/": EvalExpr(ParsexExpr(divx)), 23 | "div": EvalExpr(ParsexExpr(divx)), 24 | "cmp": EvalExpr(cmpExpr), 25 | "less": EvalExpr(lessExpr), 26 | "<": EvalExpr(lessExpr), 27 | "": EvalExpr(greatExpr), 31 | ">?": EvalExpr(gtoExpr), 32 | ">=": EvalExpr(geExpr), 33 | ">=?": EvalExpr(geoExpr), 34 | "==": EvalExpr(eqsExpr), 35 | "==?": EvalExpr(eqsoExpr), 36 | "!=": EvalExpr(neqsExpr), 37 | "!=?": EvalExpr(neqsoExpr), 38 | }, 39 | } 40 | 41 | // ParsexExpr 是 parsex 算子的解析表达式 42 | func ParsexExpr(pxExpr px.Parser) LispExpr { 43 | return func(env Env, args ...interface{}) (Lisp, error) { 44 | data, err := Evals(env, args...) 45 | if err != nil { 46 | return nil, err 47 | } 48 | st := px.NewStateInMemory(data) 49 | ret, err := pxExpr(st) 50 | if err != nil { 51 | return nil, err 52 | } 53 | return Q(ret), nil 54 | } 55 | } 56 | 57 | // ExtExpr 带扩展环境 58 | func ExtExpr(extExpr func(env Env) px.Parser) LispExpr { 59 | return func(env Env, args ...interface{}) (Lisp, error) { 60 | data, err := Evals(env, args...) 61 | if err != nil { 62 | return nil, err 63 | } 64 | st := px.NewStateInMemory(data) 65 | ret, err := extExpr(env)(st) 66 | if err != nil { 67 | return nil, err 68 | } 69 | return Q(ret), nil 70 | } 71 | } 72 | 73 | // NotParsex 是 not 运算符 74 | func NotParsex(pxExpr px.Parser) px.Parser { 75 | return func(st px.ParsexState) (interface{}, error) { 76 | b, err := pxExpr(st) 77 | if err != nil { 78 | return nil, err 79 | } 80 | if boolean, ok := b.(bool); ok { 81 | return !boolean, nil 82 | } 83 | return nil, ParsexSignErrorf("Unknow howto not %v", b) 84 | } 85 | } 86 | 87 | // ParsexReverseExpr 是倒排运算 88 | func ParsexReverseExpr(pxExpr px.Parser) LispExpr { 89 | return func(env Env, args ...interface{}) (Lisp, error) { 90 | data, err := Evals(env, args...) 91 | if err != nil { 92 | return nil, err 93 | } 94 | l := len(data) 95 | last := l - 1 96 | datax := make([]interface{}, l) 97 | for idx, item := range data { 98 | datax[last-idx] = item 99 | } 100 | st := px.NewStateInMemory(data) 101 | x, err := pxExpr(st) 102 | if err != nil { 103 | return nil, err 104 | } 105 | return Q(x), nil 106 | } 107 | } 108 | 109 | // NotExpr 定义了 not 表达式 110 | func NotExpr(expr LispExpr) LispExpr { 111 | return func(env Env, args ...interface{}) (Lisp, error) { 112 | element, err := expr(env, args...) 113 | if err != nil { 114 | return nil, err 115 | } 116 | ret, err := element.Eval(env) 117 | if err != nil { 118 | return nil, err 119 | } 120 | var b bool 121 | if b, ok := ret.(bool); ok { 122 | return Q(!b), nil 123 | } 124 | return nil, ParsexSignErrorf("Unknow howto not %v", b) 125 | } 126 | } 127 | 128 | // OrExpr 是 or 表达式 129 | func OrExpr(x, y px.Parser) LispExpr { 130 | return func(env Env, args ...interface{}) (Lisp, error) { 131 | data, err := Evals(env, args...) 132 | if err != nil { 133 | return nil, err 134 | } 135 | st := px.NewStateInMemory(data) 136 | rex, err := x(st) 137 | if err != nil { 138 | return nil, err 139 | } 140 | if b, ok := rex.(bool); ok { 141 | if b { 142 | return Q(true), nil 143 | } 144 | st.SeekTo(0) 145 | rex, err = y(st) 146 | if err != nil { 147 | return nil, err 148 | } 149 | return Q(rex), nil 150 | } 151 | return nil, ParsexSignErrorf("Unknow howto combine %v or %v for %v", x, y, data) 152 | } 153 | } 154 | 155 | // OrExtExpr 定了带环境扩展的 or 表达式 156 | func OrExtExpr(x, y func(Env) px.Parser) LispExpr { 157 | return func(env Env, args ...interface{}) (Lisp, error) { 158 | return OrExpr(x(env), y(env))(env, args...) 159 | } 160 | } 161 | 162 | // OrExtRExpr 定了带环境扩展的 or 逆向表达式 163 | func OrExtRExpr(x px.Parser, y func(Env) px.Parser) LispExpr { 164 | return func(env Env, args ...interface{}) (Lisp, error) { 165 | return OrExpr(x, y(env))(env, args...) 166 | } 167 | } 168 | 169 | // ExtReverseExpr 定了带环境扩展的倒排表达式 170 | func ExtReverseExpr(expr func(Env) px.Parser) LispExpr { 171 | return func(env Env, args ...interface{}) (Lisp, error) { 172 | return ParsexReverseExpr(expr(env))(env, args...) 173 | } 174 | } 175 | 176 | var addExpr = ParsexExpr(addx) 177 | var subExpr = ParsexExpr(subx) 178 | var mulExpr = ParsexExpr(mulx) 179 | var divExpr = ParsexExpr(divx) 180 | var lessExpr = ExtExpr(less) 181 | var lsoExpr = ExtExpr(lessOption) 182 | var leExpr = OrExtRExpr(equals, less) 183 | var leoExpr = OrExtRExpr(equalsOption, lessOption) 184 | var cmpExpr = ParsexExpr(compare) 185 | var greatExpr = ExtReverseExpr(less) 186 | var gtoExpr = ExtReverseExpr(lessOption) 187 | var geExpr = OrExtRExpr(equals, less) 188 | var geoExpr = func(env Env, args ...interface{}) (Lisp, error) { 189 | st := px.NewStateInMemory(args) 190 | ret, err := px.Choice(px.Try(NotParsex(less(env))), FalseIfHasNil)(st) 191 | if err != nil { 192 | return nil, err 193 | } 194 | return Q(ret), nil 195 | } 196 | var eqsExpr = ParsexExpr(equals) 197 | var eqsoExpr = ParsexExpr(equalsOption) 198 | var neqsExpr = NotExpr(eqsExpr) 199 | var neqsoExpr = ParsexExpr(neqsOption) 200 | -------------------------------------------------------------------------------- /quote.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | // Quote 定义了 Lisp Quote 4 | type Quote struct { 5 | Lisp interface{} 6 | } 7 | 8 | // Eval 实现了 Eval 行为 9 | func (this Quote) Eval(env Env) (interface{}, error) { 10 | return this.Lisp, nil 11 | } 12 | 13 | // Q 得到一个 Quote 14 | func Q(x interface{}) Quote { 15 | return Quote{x} 16 | } 17 | 18 | // QL 得到一个 Quote 后的列表 19 | func QL(args ...interface{}) Quote { 20 | return Q(L(args...)) 21 | } 22 | -------------------------------------------------------------------------------- /rune.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | // Rune 是 rune 的简单封装 4 | type Rune rune 5 | -------------------------------------------------------------------------------- /suffix.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | p "github.com/Dwarfartisan/goparsec" 5 | ) 6 | 7 | // DotSuffix 表示带 dot 分割的后缀的表达式 8 | func DotSuffix(x interface{}) p.Parser { 9 | return func(st p.ParseState) (interface{}, error) { 10 | d, err := DotParser(st) 11 | if err != nil { 12 | return nil, err 13 | } 14 | return dotSuffix(Dot{x, d.(Atom)})(st) 15 | } 16 | } 17 | 18 | func dotSuffix(x interface{}) p.Parser { 19 | return func(st p.ParseState) (interface{}, error) { 20 | d, err := p.Try(DotParser)(st) 21 | if err != nil { 22 | return x, nil 23 | } 24 | return dotSuffix(Dot{x, d.(Atom)})(st) 25 | } 26 | } 27 | 28 | // BracketSuffix 表示带 [] 后缀的表达式 29 | func BracketSuffix(x interface{}) p.Parser { 30 | return func(st p.ParseState) (interface{}, error) { 31 | b, err := p.Try(BracketParser)(st) 32 | if err != nil { 33 | return nil, err 34 | } 35 | return bracketSuffix(Bracket{x, b.([]interface{})})(st) 36 | } 37 | } 38 | 39 | // BracketSuffixExt 带扩展环境,可以在指定的环境中解释[]中的token 40 | func BracketSuffixExt(env Env) func(interface{}) p.Parser { 41 | return func(x interface{}) p.Parser { 42 | return func(st p.ParseState) (interface{}, error) { 43 | b, err := p.Try(BracketParserExt(env))(st) 44 | if err != nil { 45 | return nil, err 46 | } 47 | return bracketSuffixExt(env)(Bracket{x, b.([]interface{})})(st) 48 | } 49 | } 50 | } 51 | 52 | func bracketSuffix(x interface{}) p.Parser { 53 | return func(st p.ParseState) (interface{}, error) { 54 | b, err := BracketParser(st) 55 | if err != nil { 56 | return x, nil 57 | } 58 | return Bracket{x, b.([]interface{})}, nil 59 | } 60 | } 61 | 62 | func bracketSuffixExt(env Env) func(interface{}) p.Parser { 63 | return func(x interface{}) p.Parser { 64 | return func(st p.ParseState) (interface{}, error) { 65 | b, err := BracketParserExt(env)(st) 66 | if err != nil { 67 | return x, nil 68 | } 69 | return Bracket{x, b.([]interface{})}, nil 70 | } 71 | } 72 | } 73 | 74 | // DotSuffixParser 定义 dot 表达式判定 75 | func DotSuffixParser(x interface{}) p.Parser { 76 | return p.Either(p.Try(DotSuffix(x)), p.Return(x)) 77 | } 78 | 79 | // BracketSuffixParser 定义 bracket 表达式判定 80 | func BracketSuffixParser(x interface{}) p.Parser { 81 | return p.Either(p.Try(BracketSuffix(x)), p.Return(x)) 82 | } 83 | 84 | // SuffixParser 定义了后缀表达式的通用判定 85 | func SuffixParser(prefix interface{}) p.Parser { 86 | suffix := p.Either(p.Try(DotSuffix(prefix)), BracketSuffix(prefix)) 87 | return func(st p.ParseState) (interface{}, error) { 88 | s, err := suffix(st) 89 | if err != nil { 90 | return prefix, nil 91 | } 92 | return SuffixParser(s)(st) 93 | } 94 | } 95 | 96 | // SuffixParserExt 在后缀表达式判定中允许传入环境 97 | func SuffixParserExt(env Env) func(interface{}) p.Parser { 98 | return func(prefix interface{}) p.Parser { 99 | suffix := p.Either(p.Try(DotSuffix(prefix)), BracketSuffixExt(env)(prefix)) 100 | return func(st p.ParseState) (interface{}, error) { 101 | s, err := suffix(st) 102 | if err != nil { 103 | return prefix, nil 104 | } 105 | return SuffixParser(s)(st) 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /tags: -------------------------------------------------------------------------------- 1 | AA atom.go /^func AA(name string) Atom {$/ 2 | AtomParserExt atom.go /^func AtomParserExt(env Env) p.Parser {$/ 3 | Bind compare.go /^var String2Values = px.Bind(StringValue, func(x in/ 4 | Bind_ bool.go /^var NilParser = p.Bind_(p.String("nil"), p.Return(/ 5 | BoxExpr functor.go /^func BoxExpr(expr TaskExpr) TaskerBox {$/ 6 | BoxExprx functor.go /^func BoxExprx(asign ArgsSignChecker, expr TaskExpr/ 7 | BracketSuffix suffix.go /^func BracketSuffix(x interface{}) p.Parser {$/ 8 | BracketSuffixParser suffix.go /^func BracketSuffixParser(x interface{}) p.Parser {/ 9 | CmpFloat compare.go /^func CmpFloat(x interface{}) px.Parser {$/ 10 | CmpInt compare.go /^func CmpInt(x interface{}) px.Parser {$/ 11 | CmpNumber compare.go /^func CmpNumber(x interface{}) px.Parser {$/ 12 | CmpString compare.go /^func CmpString(x interface{}) px.Parser {$/ 13 | CmpTime compare.go /^func CmpTime(x interface{}) px.Parser {$/ 14 | DefOption var.go /^func DefOption(typ reflect.Type) OptionVar {$/ 15 | DefStrict var.go /^func DefStrict(typ reflect.Type) StrictVar {$/ 16 | DotSuffixParser suffix.go /^func DotSuffixParser(x interface{}) p.Parser {$/ 17 | Elem types.go /^ ANY = reflect.TypeOf((*interface{})(nil)).El/ 18 | EvalExpr functor.go /^func EvalExpr(expr LispExpr) EvalBox {$/ 19 | ExtExpr proposition.go /^func ExtExpr(extExpr func(env Env) px.Parser) Lisp/ 20 | ExtReverseExpr proposition.go /^func ExtReverseExpr(expr func(Env) px.Parser) Lisp/ 21 | ExtTypeParser type.go /^func ExtTypeParser(env Env) p.Parser {$/ 22 | LessThanFloat compare.go /^func LessThanFloat(x interface{}) px.Parser {$/ 23 | LessThanInt compare.go /^func LessThanInt(x interface{}) px.Parser {$/ 24 | LessThanList compare.go /^func LessThanList(env Env) func(x interface{}) px./ 25 | LessThanListOption compare.go /^func LessThanListOption(env Env) func(x interface{/ 26 | LessThanNil compare.go /^func LessThanNil(x interface{}) px.Parser {$/ 27 | LessThanNumber compare.go /^func LessThanNumber(x interface{}) px.Parser {$/ 28 | LessThanString compare.go /^func LessThanString(x interface{}) px.Parser {$/ 29 | LessThanTime compare.go /^func LessThanTime(x interface{}) px.Parser {$/ 30 | ListParserExt parses.go /^func ListParserExt(env Env) p.Parser {$/ 31 | Logf parsec_test.go /^ t.Logf("from gisp: %v", gre)$/ 32 | MapTypeParserExt type.go /^func MapTypeParserExt(env Env) p.Parser {$/ 33 | MaxInts avg.go /^func MaxInts(data ...Int) Int {$/ 34 | MinInts avg.go /^func MinInts(data ...Int) Int {$/ 35 | NotExpr proposition.go /^func NotExpr(expr LispExpr) LispExpr {$/ 36 | NotParsex proposition.go /^func NotParsex(pxExpr px.Parser) px.Parser {$/ 37 | OrExpr proposition.go /^func OrExpr(x, y px.Parser) LispExpr {$/ 38 | OrExtExpr proposition.go /^func OrExtExpr(x, y func(Env) px.Parser) LispExpr / 39 | OrExtRExpr proposition.go /^func OrExtRExpr(x px.Parser, y func(Env) px.Parser/ 40 | ParsecBox parsec.go /^func ParsecBox(parser p.Parser) Lisp {$/ 41 | ParsexBox parsex.go /^func ParsexBox(parser px.Parser) Lisp {$/ 42 | ParsexExpr proposition.go /^func ParsexExpr(pxExpr px.Parser) LispExpr {$/ 43 | ParsexReverseExpr proposition.go /^func ParsexReverseExpr(pxExpr px.Parser) LispExpr / 44 | ParsexSignErrorf function.go /^func ParsexSignErrorf(message string, args ...inte/ 45 | Q quote.go /^func Q(x interface{}) Quote {$/ 46 | QuoteParserExt parses.go /^func QuoteParserExt(env Env) p.Parser {$/ 47 | StrictVarAs var.go /^func StrictVarAs(x interface{}) StrictVar {$/ 48 | SuffixParser suffix.go /^func SuffixParser(prefix interface{}) p.Parser {$/ 49 | TestAddExpr math_test.go /^func TestAddExpr(t *testing.T) {$/ 50 | TestAddx1 math_test.go /^func TestAddx1(t *testing.T) {$/ 51 | TestAtomParse1 atom_test.go /^func TestAtomParse1(t *testing.T) {$/ 52 | TestAtomParse2 atom_test.go /^func TestAtomParse2(t *testing.T) {$/ 53 | TestAtomParse3 atom_test.go /^func TestAtomParse3(t *testing.T) {$/ 54 | TestBracketBasic bracket_test.go /^func TestBracketBasic(t *testing.T) {$/ 55 | TestDotMap dot_test.go /^func TestDotMap(t *testing.T) {$/ 56 | TestDotParser dot_test.go /^func TestDotParser(t *testing.T) {$/ 57 | TestFloatParser1 float_test.go /^func TestFloatParser1(t *testing.T) {$/ 58 | TestFloatParser2 float_test.go /^func TestFloatParser2(t *testing.T) {$/ 59 | TestFloatParser3 float_test.go /^func TestFloatParser3(t *testing.T) {$/ 60 | TestFloatParser4 float_test.go /^func TestFloatParser4(t *testing.T) {$/ 61 | TestFloatParser5 float_test.go /^func TestFloatParser5(t *testing.T) {$/ 62 | TestGetEval axiom_test.go /^func TestGetEval(t *testing.T) {$/ 63 | TestIntParser1 int_test.go /^func TestIntParser1(t *testing.T) {$/ 64 | TestIntParser2 int_test.go /^func TestIntParser2(t *testing.T) {$/ 65 | TestIntParser3 int_test.go /^func TestIntParser3(t *testing.T) {$/ 66 | TestLessList compare_test.go /^func TestLessList(t *testing.T) {$/ 67 | TestLessNumber compare_test.go /^func TestLessNumber(t *testing.T) {$/ 68 | TestLessOptionList compare_test.go /^func TestLessOptionList(t *testing.T) {$/ 69 | TestLessOrEqualList compare_test.go /^func TestLessOrEqualList(t *testing.T) {$/ 70 | TestLessString compare_test.go /^func TestLessString(t *testing.T) {$/ 71 | TestMoneyMul function_test.go /^func TestMoneyMul(t *testing.T) {$/ 72 | TestMulAutoOverload function_test.go /^func TestMulAutoOverload(t *testing.T) {$/ 73 | TestMulExpr math_test.go /^func TestMulExpr(t *testing.T) {$/ 74 | TestOptionGetNil var_test.go /^func TestOptionGetNil(t *testing.T) {$/ 75 | TestOptionGetNilType var_test.go /^func TestOptionGetNilType(t *testing.T) {$/ 76 | TestOptionSetNil var_test.go /^func TestOptionSetNil(t *testing.T) {$/ 77 | TestOptionSetValid var_test.go /^func TestOptionSetValid(t *testing.T) {$/ 78 | TestParseCallToolkitFunction parser_test.go /^func TestParseCallToolkitFunction(t *testing.T) {$/ 79 | TestParseExt parser_test.go /^func TestParseExt(t *testing.T) {$/ 80 | TestParseFloat parser_test.go /^func TestParseFloat(t *testing.T) {$/ 81 | TestQuoteCall axiom_test.go /^func TestQuoteCall(t *testing.T) {$/ 82 | TestQuoteEval axiom_test.go /^func TestQuoteEval(t *testing.T) {$/ 83 | TestSetBracket axiom_test.go /^func TestSetBracket(t *testing.T) {$/ 84 | TestStrictGetNil var_test.go /^func TestStrictGetNil(t *testing.T) {$/ 85 | TestStrictGetNilType var_test.go /^func TestStrictGetNilType(t *testing.T) {$/ 86 | TestStrictSet var_test.go /^func TestStrictSet(t *testing.T) {$/ 87 | TestStrictSetNil var_test.go /^func TestStrictSetNil(t *testing.T) {$/ 88 | TestStrictSetValid var_test.go /^func TestStrictSetValid(t *testing.T) {$/ 89 | TestTypeAny types_test.go /^func TestTypeAny(t *testing.T) {$/ 90 | TestTypeAtom types_test.go /^func TestTypeAtom(t *testing.T) {$/ 91 | TestTypeFloat types_test.go /^func TestTypeFloat(t *testing.T) {$/ 92 | TestTypeInt types_test.go /^func TestTypeInt(t *testing.T) {$/ 93 | TestTypeString types_test.go /^func TestTypeString(t *testing.T) {$/ 94 | TestVarEval axiom_test.go /^func TestVarEval(t *testing.T) {$/ 95 | TestZipNil list_test.go /^func TestZipNil(t *testing.T) {$/ 96 | TestingBoolParse1 bool_test.go /^func TestingBoolParse1(t *testing.T) {$/ 97 | TypeAs args.go /^func TypeAs(typ reflect.Type) px.Parser {$/ 98 | ValueParserExt parses.go /^func ValueParserExt(env Env) p.Parser {$/ 99 | VarSlot var.go /^func VarSlot(typ Type) Var {$/ 100 | argParser args.go /^func argParser(atom Atom) px.Parser {$/ 101 | argRing args.go /^func argRing(atom Atom) func(interface{}) px.Parse/ 102 | bodyParserExt parses.go /^func bodyParserExt(env Env) p.Parser {$/ 103 | bracketSuffix suffix.go /^func bracketSuffix(x interface{}) p.Parser {$/ 104 | cmpFloat compare.go /^func cmpFloat(x, y Float) Int {$/ 105 | cmpInt compare.go /^func cmpInt(x, y Int) Int {$/ 106 | cmpString compare.go /^func cmpString(x, y string) Int {$/ 107 | cmpTime compare.go /^func cmpTime(x, y tm.Time) Int {$/ 108 | dotSuffix suffix.go /^func dotSuffix(x interface{}) p.Parser {$/ 109 | eqs compare.go /^func eqs(x interface{}) px.Parser {$/ 110 | eqsOption compare.go /^func eqsOption(x interface{}) px.Parser {$/ 111 | floatSignError function_test.go /^func floatSignError(value interface{}) error {$/ 112 | func atom.go /^func (atom Atom) String() string {$/ 113 | import args.go /^import ($/ 114 | lambda lambda.go /^\/\/ DeclareLambda 构造 Lambda 表达式 (lambda/ 115 | less compare.go /^func less(env Env) px.Parser {$/ 116 | lessOption compare.go /^func lessOption(env Env) px.Parser {$/ 117 | moneySignError function_test.go /^func moneySignError(value interface{}) error {$/ 118 | mrmul function_test.go /^func mrmul() mrMul {$/ 119 | neqs compare.go /^func neqs(x interface{}) px.Parser {$/ 120 | stopWord type.go /^func stopWord(x interface{}) p.Parser {$/ 121 | typeName type.go /^func typeName(word string) p.Parser {$/ 122 | xEOF math.go /^func xEOF(x interface{}) px.Parser {$/ 123 | -------------------------------------------------------------------------------- /task.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // Task 定义了可执行的通用结构 8 | type Task struct { 9 | Meta map[string]interface{} 10 | Content []interface{} 11 | } 12 | 13 | // Local 定义了 task 本地环境中的变量查找 14 | func (task Task) Local(name string) (interface{}, bool) { 15 | my := task.Meta["my"].(map[string]Var) 16 | if slot, ok := my[name]; ok { 17 | return slot.Get(), true 18 | } 19 | if value, ok := task.ParameterValue(name); ok { 20 | return value, true 21 | } 22 | 23 | local := task.Meta["local"].(map[string]interface{}) 24 | value, ok := local[name] 25 | return value, ok 26 | } 27 | 28 | // ParameterValue 获取指定参数 29 | func (task Task) ParameterValue(name string) (interface{}, bool) { 30 | formals := task.Meta["formal parameters"].(List) 31 | actuals := task.Meta["actual parameters"].([]interface{}) 32 | lastIdx := len(actuals) - 1 33 | for idx := range formals { 34 | formal := formals[idx].(Atom) 35 | if formal.Name == name { 36 | slot := actuals[idx] 37 | if idx == lastIdx { 38 | isVariadic := task.Meta["is variadic"].(bool) 39 | if isVariadic { 40 | slots := actuals[lastIdx].([]Var) 41 | value := make([]interface{}, len(slots)) 42 | for idx, slot := range slots { 43 | value[idx] = slot.Get() 44 | } 45 | return value, true 46 | } 47 | } 48 | return slot.(Var).Get(), true 49 | } 50 | } 51 | return nil, false 52 | } 53 | 54 | // Global 在外部环境中查找 55 | func (task Task) Global(name string) (interface{}, bool) { 56 | global := task.Meta["global"].(Env) 57 | return global.Lookup(name) 58 | } 59 | 60 | // Lookup 执行自内而外的查找 61 | func (task Task) Lookup(name string) (interface{}, bool) { 62 | if value, ok := task.Local(name); ok { 63 | return value, true 64 | } 65 | return task.Global(name) 66 | } 67 | 68 | // Setvar 实现赋值行为 69 | func (task Task) Setvar(name string, value interface{}) error { 70 | mine := task.Meta["my"].(map[string]Var) 71 | if _, ok := mine[name]; ok { 72 | mine[name].Set(value) 73 | return nil 74 | } 75 | local := task.Meta["local"].(map[string]Var) 76 | if _, ok := local[name]; ok { 77 | local[name].Set(value) 78 | return nil 79 | } 80 | return fmt.Errorf("can't found var named %s", name) 81 | } 82 | 83 | // Defvar 定义新变量 84 | func (task Task) Defvar(name string, slot Var) error { 85 | mine := task.Meta["my"].(map[string]Var) 86 | if _, ok := mine[name]; ok { 87 | return fmt.Errorf("%s was exists", name) 88 | } 89 | mine[name] = slot 90 | return nil 91 | } 92 | 93 | // Defun 实现 Env.Defun 94 | func (task Task) Defun(name string, functor Functor) error { 95 | if s, ok := task.Local(name); ok { 96 | switch slot := s.(type) { 97 | case Func: 98 | slot.Overload(functor) 99 | case Var: 100 | return fmt.Errorf("%s defined as a var", name) 101 | default: 102 | return fmt.Errorf("exists name %s isn't Expr", name) 103 | } 104 | } 105 | my := task.Meta["my"].(map[string]interface{}) 106 | my[name] = NewFunction(name, task, functor) 107 | return nil 108 | } 109 | 110 | // Eval 实现求值逻辑 111 | func (task Task) Eval(env Env) (interface{}, error) { 112 | formals := task.Meta["formal parameters"].(List) 113 | actuals := task.Meta["actual parameters"].([]interface{}) 114 | values := make([]Var, len(actuals)) 115 | for idx, atom := range formals { 116 | formal := atom.(Atom) 117 | slot := VarSlot(formal.Type) 118 | val, err := Eval(task, actuals[idx]) 119 | if err != nil { 120 | return nil, err 121 | } 122 | slot.Set(val) 123 | values[idx] = slot 124 | } 125 | task.Meta["actual values"] = values 126 | 127 | task.Meta["global"] = env 128 | l := len(task.Content) 129 | switch l { 130 | case 0: 131 | return nil, nil 132 | case 1: 133 | return Eval(task, task.Content[0]) 134 | default: 135 | for _, Expr := range task.Content[:l-2] { 136 | _, err := Eval(task, Expr) 137 | if err != nil { 138 | return nil, err 139 | } 140 | } 141 | return Eval(task, task.Content[l-1]) 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /time.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | tm "time" 5 | 6 | px "github.com/Dwarfartisan/goparsec/parsex" 7 | ) 8 | 9 | // Time 包引入了go的time包功能 10 | var Time = Toolkit{ 11 | Meta: map[string]interface{}{ 12 | "category": "toolkit", 13 | "name": "time", 14 | }, 15 | Content: map[string]interface{}{ 16 | "now": SimpleBox{ 17 | ParsexSignChecker(px.Eof), 18 | func(args ...interface{}) Tasker { 19 | return func(env Env) (interface{}, error) { 20 | return tm.Now(), nil 21 | } 22 | }}, 23 | "parseDuration": SimpleBox{ 24 | ParsexSignChecker(px.Bind_(StringValue, px.Eof)), 25 | func(args ...interface{}) Tasker { 26 | return func(env Env) (interface{}, error) { 27 | return tm.ParseDuration(args[0].(string)) 28 | } 29 | }}, 30 | "parseTime": SimpleBox{ 31 | ParsexSignChecker(px.Binds_(StringValue, StringValue, px.Eof)), 32 | func(args ...interface{}) Tasker { 33 | return func(env Env) (interface{}, error) { 34 | return tm.Parse(args[0].(string), args[1].(string)) 35 | } 36 | }}, 37 | }, 38 | } 39 | -------------------------------------------------------------------------------- /toolkit.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | //"fmt" 5 | "reflect" 6 | ) 7 | 8 | // Toolkit 实现了一个基本环境,它没有 Define 和 Set ,用于封装只读的环境。 9 | type Toolkit struct { 10 | Meta map[string]interface{} 11 | Content map[string]interface{} 12 | } 13 | 14 | // Lookup 实现了基本的 Env.Lookup 策略:现在 Local 中查找,否则向上查找 Gobal 15 | func (tk Toolkit) Lookup(name string) (interface{}, bool) { 16 | if v, ok := tk.Local(name); ok { 17 | return v, true 18 | } 19 | return tk.Global(name) 20 | } 21 | 22 | // Local 实现 Env.Local 23 | func (tk Toolkit) Local(name string) (interface{}, bool) { 24 | if value, ok := tk.Content[name]; ok { 25 | if slot, ok := value.(Var); ok { 26 | return slot.Get(), true 27 | } 28 | return value, true 29 | } 30 | return nil, false 31 | } 32 | 33 | // Global 实现 Env.Global 。如果 Meta 中没有注册 global ,视作顶层环境,返回notfound 34 | func (tk Toolkit) Global(name string) (interface{}, bool) { 35 | if o, ok := tk.Meta["global"]; ok { 36 | outer := o.(Env) 37 | return outer.Lookup(name) 38 | } 39 | return nil, false 40 | } 41 | 42 | // Eval 函数在给定环境中执行 lisp 对象进行求值 43 | func Eval(env Env, lisp interface{}) (interface{}, error) { 44 | // a lisp data or go value 45 | switch o := lisp.(type) { 46 | case Lisp: 47 | value, err := o.Eval(env) 48 | return value, err 49 | default: 50 | return Value(o), nil 51 | } 52 | } 53 | 54 | // Evals 执行多个 lisp 对象 55 | func Evals(env Env, args ...interface{}) ([]interface{}, error) { 56 | data := make([]interface{}, len(args)) 57 | for idx, arg := range args { 58 | ret, err := Eval(env, arg) 59 | if err != nil { 60 | return nil, err 61 | } 62 | data[idx] = ret 63 | } 64 | return data, nil 65 | } 66 | 67 | // Value 函数对 golang 基本类型做封装,目前仅止将整型转为 Int, 将浮点型转为 Float, 68 | // 将 rune 转为 Rune, 其它不做处理 69 | func Value(x interface{}) interface{} { 70 | switch v := x.(type) { 71 | case bool: 72 | return Bool(v) 73 | case float32: 74 | return Float(v) 75 | case float64: 76 | return Float(v) 77 | case int8: 78 | return Int(v) 79 | case int16: 80 | return Int(v) 81 | case int32: 82 | return Int(v) 83 | case int64: 84 | return Int(v) 85 | case int: 86 | return Int(v) 87 | default: 88 | return v 89 | } 90 | } 91 | 92 | //InReflects 从反射对象中取值 93 | func InReflects(values []reflect.Value) ([]interface{}, error) { 94 | res := make([]interface{}, len(values)) 95 | for idx, value := range values { 96 | if value.CanInterface() { 97 | res[idx] = value.Interface() 98 | } 99 | if !value.IsValid() || value.Kind() == reflect.Ptr && value.IsNil() { 100 | res[idx] = nil 101 | } 102 | res[idx] = value.Interface() 103 | } 104 | return res, nil 105 | } 106 | -------------------------------------------------------------------------------- /type.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "reflect" 5 | 6 | p "github.com/Dwarfartisan/goparsec" 7 | ) 8 | 9 | //Type 对象定义了一个可空的反射类型,用于 Lisp 对象定义 10 | type Type struct { 11 | reflect.Type 12 | option bool 13 | } 14 | 15 | func (typ Type) String() string { 16 | str := typ.Type.String() 17 | if typ.option { 18 | return str + "?" 19 | } 20 | return str 21 | } 22 | 23 | // Option 指示类型是否是可空的 24 | func (typ Type) Option() bool { 25 | return typ.option 26 | } 27 | 28 | func stop(st p.ParseState) (interface{}, error) { 29 | pos := st.Pos() 30 | defer st.SeekTo(pos) 31 | r, err := p.Choice( 32 | p.Try(p.Space), 33 | p.Try(p.NewLine), 34 | p.Try(p.OneOf(":.()[]{}?")), 35 | p.Try(p.Eof), 36 | )(st) 37 | if err != nil { 38 | return nil, err 39 | } 40 | return r, nil 41 | } 42 | 43 | func stopWord(x interface{}) p.Parser { 44 | return p.Bind_(stop, p.Return(x)) 45 | } 46 | 47 | func typeName(word string) p.Parser { 48 | return p.Bind(p.String(word), stopWord) 49 | } 50 | 51 | var anyType = p.Bind(p.Bind(p.Many1(p.Either(p.Try(p.Digit), p.Letter)), stopWord), p.ReturnString) 52 | 53 | // SliceTypeParserExt 定义了带环境的序列类型解析逻辑 54 | func SliceTypeParserExt(env Env) p.Parser { 55 | return func(st p.ParseState) (interface{}, error) { 56 | t, err := p.Bind_(p.String("[]"), ExtTypeParser(env))(st) 57 | if err != nil { 58 | return nil, err 59 | } 60 | return reflect.SliceOf(t.(Type).Type), nil 61 | } 62 | } 63 | 64 | // MapTypeParserExt 定义了带环境的映射类型解析逻辑 65 | func MapTypeParserExt(env Env) p.Parser { 66 | return func(st p.ParseState) (interface{}, error) { 67 | key, err := p.Between(p.String("map["), p.Rune(']'), ExtTypeParser(env))(st) 68 | if err != nil { 69 | return nil, err 70 | } 71 | value, err := ExtTypeParser(env)(st) 72 | if err != nil { 73 | return nil, err 74 | } 75 | return reflect.MapOf(key.(Type).Type, value.(Type).Type), nil 76 | } 77 | } 78 | 79 | // MapTypeParser 定义了序列类型解析逻辑 80 | func MapTypeParser(st p.ParseState) (interface{}, error) { 81 | key, err := p.Between(p.String("map["), p.Rune(']'), TypeParser)(st) 82 | if err != nil { 83 | return nil, err 84 | } 85 | value, err := TypeParser(st) 86 | if err != nil { 87 | return nil, err 88 | } 89 | return reflect.MapOf(key.(Type).Type, value.(Type).Type), nil 90 | } 91 | 92 | // ExtTypeParser 定义了带环境的类型解释器 93 | func ExtTypeParser(env Env) p.Parser { 94 | return func(st p.ParseState) (interface{}, error) { 95 | _, err := p.String("::")(st) 96 | if err != nil { 97 | return nil, err 98 | } 99 | buildin := p.Choice( 100 | p.Try(p.Bind_(typeName("bool"), p.Return(BOOL))), 101 | p.Try(p.Bind_(typeName("float"), p.Return(FLOAT))), 102 | p.Try(p.Bind_(typeName("int"), p.Return(INT))), 103 | p.Try(p.Bind_(typeName("string"), p.Return(STRING))), 104 | p.Try(p.Bind_(typeName("time"), p.Return(TIME))), 105 | p.Try(p.Bind_(typeName("duration"), p.Return(DURATION))), 106 | p.Try(p.Bind_(typeName("any"), p.Return(ANY))), 107 | p.Try(p.Bind_(typeName("atom"), p.Return(ATOM))), 108 | p.Try(p.Bind_(p.String("list"), p.Return(LIST))), 109 | p.Try(p.Bind_(typeName("quote"), p.Return(QUOTE))), 110 | p.Try(p.Bind_(p.String("dict"), p.Return(DICT))), 111 | p.Try(MapTypeParserExt(env)), 112 | ) 113 | ext := func(st p.ParseState) (interface{}, error) { 114 | n, err := anyType(st) 115 | if err != nil { 116 | return nil, err 117 | } 118 | t, ok := env.Lookup(n.(string)) 119 | if !ok { 120 | return nil, st.Trap("type %v not found", n) 121 | } 122 | if typ, ok := t.(reflect.Type); ok { 123 | return typ, nil 124 | } 125 | return nil, st.Trap("var %v is't a type. It is %v", n, reflect.TypeOf(t)) 126 | } 127 | t, err := p.Either(buildin, ext)(st) 128 | if err != nil { 129 | return nil, err 130 | } 131 | _, err = p.Try(p.Rune('?'))(st) 132 | option := err == nil 133 | return Type{t.(reflect.Type), option}, nil 134 | } 135 | } 136 | 137 | // TypeParser 定义了一个基本的类型解释器 138 | func TypeParser(st p.ParseState) (interface{}, error) { 139 | t, err := p.Bind_(p.String("::"), 140 | p.Choice( 141 | p.Try(p.Bind_(p.String("bool"), p.Return(BOOL))), 142 | p.Try(p.Bind_(p.String("float"), p.Return(FLOAT))), 143 | p.Try(p.Bind_(p.String("int"), p.Return(INT))), 144 | p.Try(p.Bind_(p.String("string"), p.Return(STRING))), 145 | p.Try(p.Bind_(p.String("time"), p.Return(TIME))), 146 | p.Try(p.Bind_(p.String("duration"), p.Return(DURATION))), 147 | p.Try(p.Bind_(p.String("any"), p.Return(ANY))), 148 | p.Try(p.Bind_(p.String("atom"), p.Return(ATOM))), 149 | p.Try(p.Bind_(p.String("list"), p.Return(LIST))), 150 | p.Try(p.Bind_(p.String("quote"), p.Return(QUOTE))), 151 | p.Try(p.Bind_(p.String("dict"), p.Return(DICT))), 152 | MapTypeParser, 153 | ))(st) 154 | if err != nil { 155 | return nil, err 156 | } 157 | _, err = p.Try(p.Rune('?'))(st) 158 | option := err == nil 159 | return Type{t.(reflect.Type), option}, nil 160 | } 161 | -------------------------------------------------------------------------------- /type_test.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | func TestTypeFound(t *testing.T) { 9 | m := money{9.99, "USD"} 10 | g := NewGisp(map[string]Toolbox{ 11 | "axioms": Axiom, 12 | "props": Propositions, 13 | }) 14 | g.DefAs("money", reflect.TypeOf(m)) 15 | _, err := g.Parse("(var bill::money)") 16 | if err != nil { 17 | t.Fatalf("except define a money var but error: %v", err) 18 | } 19 | g.Setvar("bill", m) 20 | 21 | mny, ok := g.Lookup("bill") 22 | if !ok { 23 | t.Fatalf("money var bill as %v not found ", m) 24 | } 25 | if !reflect.DeepEqual(m, mny) { 26 | t.Fatalf("except got money var bill as %v but %v", m, mny) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /types.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "reflect" 5 | t "time" 6 | ) 7 | 8 | var ( 9 | // BOOL 类型 10 | BOOL = reflect.TypeOf((*bool)(nil)).Elem() 11 | // STRING 是字符串类型 12 | STRING = reflect.TypeOf((*string)(nil)).Elem() 13 | // INT 整型 14 | INT = reflect.TypeOf((*Int)(nil)).Elem() 15 | // FLOAT 浮点型 16 | FLOAT = reflect.TypeOf((*Float)(nil)).Elem() 17 | // TIME 时间类型 18 | TIME = reflect.TypeOf((*t.Time)(nil)).Elem() 19 | // DURATION 时段类型 20 | DURATION = reflect.TypeOf((*t.Duration)(nil)).Elem() 21 | // ANY 是 interface{} 的封装 22 | ANY = reflect.TypeOf((*interface{})(nil)).Elem() 23 | // ATOM 原子类型 24 | ATOM = reflect.TypeOf((*Atom)(nil)).Elem() 25 | // LIST 序列类型 26 | LIST = reflect.TypeOf((*List)(nil)).Elem() 27 | // QUOTE 是 lisp quote 类型 28 | QUOTE = reflect.TypeOf((*Quote)(nil)).Elem() 29 | // DICT 是 map[string]interface{} 的封装 30 | DICT = reflect.TypeOf((*map[string]interface{})(nil)).Elem() 31 | 32 | // BOOLOPTION 是可空的 BOOL 33 | BOOLOPTION = Type{BOOL, true} 34 | // INTOPTION 是可空的 INT 35 | INTOPTION = Type{INT, true} 36 | // FLOATOPTION 是可空的 FLOAT 37 | FLOATOPTION = Type{FLOAT, true} 38 | // STRINGOPTION 是可空的 STRING 39 | STRINGOPTION = Type{STRING, true} 40 | // TIMEOPTION 是可空的 TIME 41 | TIMEOPTION = Type{TIME, true} 42 | // DURATIONOPTION 是可空的 DURATIONOPTION 43 | DURATIONOPTION = Type{DURATION, true} 44 | // ANYOPTION 是可空的 ANY 45 | ANYOPTION = Type{ANY, true} 46 | // ATOMOPTION 是可空的 ATOM 47 | ATOMOPTION = Type{ATOM, true} 48 | // LISTOPTION 是可空的 LIST 49 | LISTOPTION = Type{LIST, true} 50 | // QUOTEOPTION 是可空的 QUOTE 51 | QUOTEOPTION = Type{QUOTE, true} 52 | // DICTOPTION 是可空的 DICT 53 | DICTOPTION = Type{DICT, true} 54 | 55 | // BOOLMUST 是不可空的 BOOL 56 | BOOLMUST = Type{BOOL, false} 57 | // INTMUST 是不可空的 INT 58 | INTMUST = Type{INT, false} 59 | // FLOATMUST 是不可空的 FLOAT 60 | FLOATMUST = Type{FLOAT, false} 61 | // STRINGMUST 是不可空的 STRING 62 | STRINGMUST = Type{STRING, false} 63 | // TIMEMUST 是不可空的 TIME 64 | TIMEMUST = Type{TIME, false} 65 | // DURATIONMUST 是不可空的 DURATION 66 | DURATIONMUST = Type{DURATION, false} 67 | // ANYMUST 是不可空的 ANY 68 | ANYMUST = Type{ANY, false} 69 | // ATOMMUST 是不可空的 ATOM 70 | ATOMMUST = Type{ATOM, false} 71 | // LISTMUST 是不可空的 LISTMUST 72 | LISTMUST = Type{LIST, false} 73 | // QUOTEMUST 是不可空的 QUOTE 74 | QUOTEMUST = Type{QUOTE, false} 75 | // DICTMUST 是不可空的 DICT 76 | DICTMUST = Type{DICT, false} 77 | ) 78 | 79 | // var TypeBox = Gearbox{ 80 | // Meta: map[string]interface{}{ 81 | // "category": "package", 82 | // "name": "types", 83 | // }, 84 | // Content: map[string]interface{}{ 85 | // "int": INTMUST, 86 | // "int?": INTOPTION, 87 | // "float": FLOATMUST, 88 | // "float?": FLOATOPTION, 89 | // "string": STRINGMUST, 90 | // "string?": STRINGOPTION, 91 | // "time": TIMEMUST, 92 | // "time?": TIMEOPTION, 93 | // "dict": DICTMUST, 94 | // "dict?": DICTMUST, 95 | // "duration": DURATIONMUST, 96 | // "duration?": DURATIONOPTION, 97 | // "list": LISTMUST, 98 | // "list?": LISTOPTION, 99 | // "atom": ATOM, 100 | // "atom?": ATOMOPTION, 101 | // "quote": QUOTEMUST, 102 | // "quote!": QUOTEOPTION, 103 | // "any": ANYMUST, 104 | // "any?": ANYOPTION, 105 | // }, 106 | // } 107 | -------------------------------------------------------------------------------- /types_test.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | func TestTypeBool(t *testing.T) { 9 | var b = true 10 | if !reflect.DeepEqual(reflect.TypeOf(b), BOOL) { 11 | t.Fatalf("except %v equal string reflect type.", BOOL) 12 | } 13 | } 14 | 15 | func TestTypeString(t *testing.T) { 16 | var str = "" 17 | if !reflect.DeepEqual(reflect.TypeOf(str), STRING) { 18 | t.Fatalf("except %v equal string reflect type.", STRING) 19 | } 20 | } 21 | 22 | func TestTypeInt(t *testing.T) { 23 | var i Int 24 | if !reflect.DeepEqual(reflect.TypeOf(i), INT) { 25 | t.Fatalf("except %v equal Int reflect type.", INT) 26 | } 27 | } 28 | 29 | func TestTypeFloat(t *testing.T) { 30 | var f Float 31 | if !reflect.DeepEqual(reflect.TypeOf(f), FLOAT) { 32 | t.Fatalf("except %v equal Float reflect type.", FLOAT) 33 | } 34 | } 35 | 36 | func TestTypeAny(t *testing.T) { 37 | var it interface{} 38 | it = "" 39 | typ := reflect.TypeOf(&it).Elem() 40 | if !reflect.DeepEqual(typ, ANY) { 41 | t.Fatalf("except %v equal interface{} reflect type %v.", ANY, typ) 42 | } 43 | } 44 | 45 | func TestTypeAtom(t *testing.T) { 46 | var atom = Atom{"any", Type{reflect.TypeOf(0), true}} 47 | if !reflect.DeepEqual(reflect.TypeOf(atom), ATOM) { 48 | t.Fatalf("except %v equal Atom reflect type.", ATOM) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /utils.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | //px "github.com/Dwarfartisan/goparsec/parsex" 5 | "fmt" 6 | ) 7 | 8 | // Utils 提供了一个常用函数工具包 9 | var Utils = Toolkit{ 10 | Meta: map[string]interface{}{ 11 | "name": "utils", 12 | "category": "package", 13 | }, 14 | Content: map[string]interface{}{ 15 | "errorf": func(env Env, args ...interface{}) (Tasker, error) { 16 | if len(args) < 1 { 17 | return nil, ParsexSignErrorf("Errorf Empty Arg Error:except args has 1 arg a last.") 18 | } 19 | params, err := Evals(env, args...) 20 | if err != nil { 21 | return nil, err 22 | } 23 | if tmpl, ok := params[0].(string); ok { 24 | return func(env Env) (interface{}, error) { 25 | return nil, fmt.Errorf(tmpl, params[1:]...) 26 | }, nil 27 | } 28 | return nil, ParsexSignErrorf("Errorf Arg Error:except first arg is a string but %v.", args[0]) 29 | }, 30 | "error": func(env Env, args ...interface{}) (Tasker, error) { 31 | if len(args) != 1 { 32 | return nil, ParsexSignErrorf("Error Arg Error:except args has 1 arg.") 33 | } 34 | params, err := Evals(env, args...) 35 | if err != nil { 36 | return nil, err 37 | } 38 | return func(env Env) (interface{}, error) { 39 | return nil, params[0].(error) 40 | }, nil 41 | }, 42 | "printf": printf, 43 | "ginq": LispExpr(func(env Env, args ...interface{}) (Lisp, error) { 44 | return Q(NewGinq(args...)), nil 45 | }), 46 | }, 47 | } 48 | 49 | func printf(env Env, args ...interface{}) (Tasker, error) { 50 | if len(args) < 1 { 51 | return nil, ParsexSignErrorf("Printf Empty Arg Error:except args has 1 arg a last.") 52 | } 53 | params, err := Evals(env, args...) 54 | if err != nil { 55 | return nil, err 56 | } 57 | if tmpl, ok := params[0].(string); ok { 58 | return func(env Env) (interface{}, error) { 59 | return fmt.Printf(tmpl, params[1:]...) 60 | }, nil 61 | } 62 | return nil, ParsexSignErrorf("Printf Arg Error:except first arg is a string but %v.", args[0]) 63 | } 64 | -------------------------------------------------------------------------------- /var.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "reflect" 5 | ) 6 | 7 | // Var 定义了变量的结构 8 | type Var interface { 9 | Get() interface{} 10 | Set(interface{}) 11 | Type() reflect.Type 12 | } 13 | 14 | // OptionVar 定义了可空变量 15 | type OptionVar struct { 16 | slot reflect.Value 17 | } 18 | 19 | // Get 提供变量值或者 nul 20 | func (optVar OptionVar) Get() interface{} { 21 | if optVar.slot.Elem().IsNil() { 22 | return nil 23 | } 24 | return reflect.Indirect(optVar.slot).Elem().Interface() 25 | } 26 | 27 | // Set 实现了赋值逻辑 28 | func (optVar *OptionVar) Set(value interface{}) { 29 | if value == nil { 30 | null := reflect.Zero(reflect.PtrTo(optVar.Type())) 31 | optVar.slot.Elem().Set(null) 32 | return 33 | } 34 | val := reflect.New(optVar.Type()) 35 | val.Elem().Set(reflect.ValueOf(value)) 36 | reflect.Indirect(optVar.slot).Set(val) 37 | } 38 | 39 | // Type 实现了类型访问 40 | func (optVar OptionVar) Type() reflect.Type { 41 | return optVar.slot.Type().Elem().Elem() 42 | } 43 | 44 | // DefOption 构造一个可空的变量 45 | func DefOption(typ reflect.Type) OptionVar { 46 | slot := reflect.New(reflect.PtrTo(typ)) 47 | null := reflect.Zero(reflect.PtrTo(typ)) 48 | slot.Elem().Set(null) 49 | return OptionVar{slot} 50 | } 51 | 52 | // StrictVar 定了非 Option 的变量,它简单的封装了 reflect.Value 53 | type StrictVar struct { 54 | slot reflect.Value 55 | } 56 | 57 | // Get 提供了变量值 58 | func (svar StrictVar) Get() interface{} { 59 | if svar.slot.IsNil() { 60 | return nil 61 | } 62 | return svar.slot.Elem().Interface() 63 | } 64 | 65 | // Set 实现了赋值行为 66 | func (svar *StrictVar) Set(value interface{}) { 67 | svar.slot.Elem().Set(reflect.ValueOf(value)) 68 | } 69 | 70 | // Type 给出变量给类型 71 | func (svar StrictVar) Type() reflect.Type { 72 | return svar.slot.Type().Elem() 73 | } 74 | 75 | // DefStrict 构造 Strict 变量 76 | func DefStrict(typ reflect.Type) StrictVar { 77 | slot := reflect.New(typ) 78 | return StrictVar{slot} 79 | } 80 | 81 | // StrictVarAs 按照值的类型构造对应的 slot 82 | func StrictVarAs(x interface{}) StrictVar { 83 | slot := DefStrict(reflect.TypeOf(x)) 84 | slot.Set(x) 85 | return slot 86 | } 87 | 88 | // VarSlot 构造一个指定类型的 slot 89 | func VarSlot(typ Type) Var { 90 | if typ.Option() { 91 | ret := DefOption(typ.Type) 92 | return &ret 93 | } 94 | ret := DefStrict(typ.Type) 95 | return &ret 96 | } 97 | -------------------------------------------------------------------------------- /var_test.go: -------------------------------------------------------------------------------- 1 | package gisp 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestOptionSet(t *testing.T) { 8 | var slot = DefOption(INT) 9 | slot.Set(Int(10)) 10 | t.Logf("create a new var %v slot as %v", slot.Type(), slot.Get()) 11 | } 12 | 13 | func TestOptionSetNil(t *testing.T) { 14 | var slot = DefOption(INT) 15 | slot.Set(nil) 16 | t.Logf("create a new var %v slot as %v", slot.Type(), slot.Get()) 17 | } 18 | 19 | func TestOptionGetNil(t *testing.T) { 20 | var slot = DefOption(INT) 21 | val := slot.Get() 22 | if val != nil { 23 | t.Fatalf("except nil but %v", val) 24 | } 25 | } 26 | 27 | func TestOptionGetNilType(t *testing.T) { 28 | var slot = DefOption(INT) 29 | typ := slot.Type() 30 | if typ != INT { 31 | t.Fatalf("except INT type but %v", typ) 32 | } 33 | } 34 | func TestOptionSetValid(t *testing.T) { 35 | defer func() { 36 | if re := recover(); re == nil { 37 | t.Fatal("excpet a panic when set a int to a float value") 38 | } 39 | }() 40 | var slot = DefOption(FLOAT) 41 | slot.Set(Int(34)) 42 | } 43 | 44 | func TestStrictSet(t *testing.T) { 45 | var slot = DefStrict(INT) 46 | slot.Set(Int(10)) 47 | t.Logf("create a new var %v slot as %v", slot.Type(), slot.Get()) 48 | } 49 | 50 | func TestStrictSetNil(t *testing.T) { 51 | defer func() { 52 | if re := recover(); re == nil { 53 | t.Fatal("excpet a panic when set nil to a strict value not pointer") 54 | } 55 | }() 56 | var slot = DefStrict(INT) 57 | slot.Set(nil) 58 | } 59 | 60 | func TestStrictGetNil(t *testing.T) { 61 | var slot = DefStrict(INT) 62 | val := slot.Get() 63 | if val == nil { 64 | t.Fatal("except zero value when init but nil") 65 | } 66 | } 67 | 68 | func TestStrictGetNilType(t *testing.T) { 69 | var slot = DefStrict(INT) 70 | typ := slot.Type() 71 | if typ != INT { 72 | t.Fatalf("except INT type but %v", typ) 73 | } 74 | } 75 | 76 | func TestStrictSetValid(t *testing.T) { 77 | defer func() { 78 | if re := recover(); re == nil { 79 | t.Fatal("excpet a panic when set a int to a float value") 80 | } 81 | }() 82 | var slot = DefStrict(FLOAT) 83 | slot.Set(Int(34)) 84 | } 85 | --------------------------------------------------------------------------------