// divx 实现一个左折叠的 parsex 连除解析器,精度向上适配。 func divx(st px.ParsexState) (interface{}, error) { data, err := px.Try(px.ManyTil(IntValue, px.Eof))(st) if err == nil { ints := data.([]interface{}) root := ints[0].(Int) for _, x := range ints[1:] { root /= x.(Int) } return root, nil } data, err = px.ManyTil(NumberValue, px.Eof)(st) if err == nil { numbers := data.([]interface{}) root := numbers[0].(Float) for _, x := range numbers[1:] { root /= x.(Float) } return root, nil } if nerr, ok := err.(NotNumberError); ok { return nil, TypeSignError{Type: Type{FLOAT, false}, Value: nerr.Value} } return nil, err }
func less(env Env) px.Parser { return func(st px.ParsexState) (interface{}, error) { l, err := px.Bind(px.Choice( px.Try(px.Bind(IntValue, LessThanNumber)), px.Try(px.Bind(NumberValue, LessThanFloat)), px.Try(px.Bind(px.StringVal, LessThanString)), px.Try(px.Bind(TimeValue, LessThanTime)), px.Bind(ListValue, LessThanList(env)), ), func(l interface{}) px.Parser { return func(st px.ParsexState) (interface{}, error) { _, err := px.Eof(st) if err != nil { return nil, ParsexSignErrorf("less args sign error: except eof") } return l, nil } })(st) if err == nil { return l, nil } return nil, ParsexSignErrorf("Except two lessable values compare but error %v", err) } }
// addx 实现一个parsex累加解析器,精度向上适配。我一直觉得应该有一个简单的高效版本,不需要回溯的 // 但是目前还没有找到。 func addx(st px.ParsexState) (interface{}, error) { ints, err := px.Try(px.ManyTil(IntValue, px.Eof))(st) if err == nil { root := Int(0) for _, x := range ints.([]interface{}) { root += x.(Int) } return root, nil } numbers, err := px.ManyTil(NumberValue, px.Eof)(st) if err == nil { root := Float(0) for _, x := range numbers.([]interface{}) { root += x.(Float) } return root, nil } if nerr, ok := err.(NotNumberError); ok { return nil, TypeSignError{Type: FLOATMUST, Value: nerr.Value} } return nil, err }
} }}, "chan<-": SimpleBox{ ParsexSignChecker(px.Binds_( TypeAs(reflect.TypeOf((*reflect.Type)(nil)).Elem()), TypeAs(INT), px.Eof)), func(args ...interface{}) Tasker { return func(env Env) (interface{}, error) { return MakeSendChan(args[0].(reflect.Type), args[1].(Int)), nil } }}, "send": SimpleBox{ ParsexSignChecker(px.Binds_( TypeAs(reflect.TypeOf((*Chan)(nil))), px.Either(px.Try(TypeAs(ANYOPTION)), TypeAs(ANYMUST)), px.Eof)), func(args ...interface{}) Tasker { return func(env Env) (interface{}, error) { ch := args[0].(*Chan) ch.Send(args[1]) return nil, nil } }}, "send?": SimpleBox{ ParsexSignChecker(px.Binds_( TypeAs(reflect.TypeOf((*Chan)(nil))), px.Either(px.Try(TypeAs(ANYOPTION)), TypeAs(ANYMUST)), px.Eof)), func(args ...interface{}) Tasker { return func(env Env) (interface{}, error) {
// 环境做了妥协 var Axiom = Toolkit{ Meta: map[string]interface{}{ "name": "axiom", "category": "package", }, Content: map[string]interface{}{ "quote": LispExpr(func(env Env, args ...interface{}) (Lisp, error) { if len(args) != 1 { return nil, fmt.Errorf("Quote Args Error: except only one arg but %v", args) } return Q(Q(args[0])), nil }), "var": LispExpr(func(env Env, args ...interface{}) (Lisp, error) { st := px.NewStateInMemory(args) _, err := px.Binds_(TypeAs(ATOM), px.Either(px.Try(px.Eof), px.Bind_(px.AnyOne, px.Eof)))(st) if err != nil { return nil, err } first := args[0].(Atom) slot := VarSlot(first.Type) if len(args) == 1 { err := env.Defvar(first.Name, slot) return Q(nil), err } val, err := Eval(env, args[1]) slot.Set(val) err = env.Defvar(first.Name, slot) return Q(val), err }),
}), nil }, "eof": ParsexBox(px.Eof), "nil": ParsexBox(px.Nil), "atimex": ParsexBox(px.TimeVal), "try": func(env Env, args ...interface{}) (Lisp, error) { if len(args) != 1 { return nil, ParsexSignErrorf("Parsex Parser Try Error: only accept one parsex parser as arg but %v", args) } param, err := Eval(env, args[0]) if err != nil { return nil, err } switch parser := param.(type) { case Parsexer: return ParsexBox(px.Try(parser.Parser)), nil default: return nil, ParsexSignErrorf( "Try Arg Error:except 1 parser arg but %v.", reflect.TypeOf(param)) } }, "either": func(env Env, args ...interface{}) (Lisp, error) { ptype := reflect.TypeOf((px.Parser)(nil)) params, err := GetArgs(env, px.UnionAll(TypeAs(ptype), TypeAs(ptype), px.Eof), args) if err != nil { return nil, err } return ParsexBox(px.Either(params[0].(Parsexer).Parser, params[1].(Parsexer).Parser)), nil },
func ExtReverseExpr(expr func(Env) px.Parser) LispExpr { return func(env Env, args ...interface{}) (Lisp, error) { return ParsexReverseExpr(expr(env))(env, args...) } } var addExpr = ParsexExpr(addx) var subExpr = ParsexExpr(subx) var mulExpr = ParsexExpr(mulx) var divExpr = ParsexExpr(divx) var lessExpr = ExtExpr(less) var lsoExpr = ExtExpr(lessOption) var leExpr = OrExtRExpr(equals, less) var leoExpr = OrExtRExpr(equalsOption, lessOption) var cmpExpr = ParsexExpr(compare) var greatExpr = ExtReverseExpr(less) var gtoExpr = ExtReverseExpr(lessOption) var geExpr = OrExtRExpr(equals, less) var geoExpr = func(env Env, args ...interface{}) (Lisp, error) { st := px.NewStateInMemory(args) ret, err := px.Choice(px.Try(NotParsex(less(env))), FalseIfHasNil)(st) if err != nil { return nil, err } return Q(ret), nil } var eqsExpr = ParsexExpr(equals) var eqsoExpr = ParsexExpr(equalsOption) var neqsExpr = NotExpr(eqsExpr) var neqsoExpr = ParsexExpr(neqsOption)