func formtokNode(ns []parsec.ParsecNode) parsec.ParsecNode { switch n := ns[0].(type) { case *parsec.Terminal: switch n.Name { case "TERM": return termNode(n) case "REF": return refNode(n) case "FORMTOK": return common.NewForm( "##formtok", func(_ common.Scope, _ ...interface{}) interface{} { return n.Value }) } case string: str := n[1 : len(n)-1] return common.NewForm( "##string", func(_ common.Scope, _ ...interface{}) interface{} { return str }) case *common.Form: return n } panic(fmt.Errorf("unknown form type %T\n", ns[0])) }
func formNode(ns []parsec.ParsecNode) parsec.ParsecNode { name := ns[1].(*parsec.Terminal).Value ns = ns[2].([]parsec.ParsecNode) form, ok := builtins[name] if ok { // apply builtin form. return common.NewForm( name, func(scope common.Scope, _ ...interface{}) interface{} { args := make([]interface{}, 0, len(ns)) for _, n := range ns { args = append(args, n.(*common.Form).Eval(scope)) } return form.Eval(scope, args...) }) } // apply non-terminal return common.NewForm( "#"+name, func(scope common.Scope, _ ...interface{}) interface{} { forms, ok := scope.GetNonTerminal(name) if ok { val := EvalForms(name, scope, forms) scope.Set(name, val, false /*global*/) return val } panic(fmt.Errorf("unknown form name %v\n", name)) }) }
func ruletokNode(ns []parsec.ParsecNode) parsec.ParsecNode { switch n := ns[0].(type) { case *parsec.Terminal: switch n.Name { case "IDENT": return identNode(n) case "TERM": return termNode(n) case "REF": return refNode(n) case "STRING": str := n.Value[1 : len(n.Value)-1] return common.NewForm( "##string", func(_ common.Scope, _ ...interface{}) interface{} { return str }) default: panic(fmt.Errorf("unknown terminal name %v\n", n.Name)) } case string: str := n[1 : len(n)-1] return common.NewForm( "##string", func(_ common.Scope, _ ...interface{}) interface{} { return str }) case *common.Form: return n } panic(fmt.Errorf("unknown form type %T\n", ns[0])) }
func ruleNode(ns []parsec.ParsecNode) parsec.ParsecNode { // compute rule weight. var weight, restrain float64 if len(ns) > 1 { if weigh := ns[0].(*common.Form); weigh.Name == "weigh" { rs := weigh.Eval(make(common.Scope)).([]interface{}) weight, restrain = rs[0].(float64), rs[1].(float64) ns = ns[1:] } } // compose rule-form. rats := make([]*common.Form, 0, len(ns)) for _, n := range ns { rats = append(rats, n.(*common.Form)) } form := common.NewForm( "##rule", func(scope common.Scope, _ ...interface{}) interface{} { str := "" for i, rat := range rats { val := rat.Eval(scope) if val == nil { return nil } scope.Set("#"+strconv.Itoa(i), val, false /*global*/) str += fmt.Sprintf("%v", val) } return str }) form.SetWeight(weight, restrain) return form }
func varNode(n *parsec.Terminal) *common.Form { return common.NewForm( "##var", func(scope common.Scope, _ ...interface{}) interface{} { val, _, ok := scope.Get(n.Value) if !ok { panic(fmt.Errorf("unknown variable %v\n", n.Value)) } return val }) }
func litNode(ns []parsec.ParsecNode) parsec.ParsecNode { if ns == nil || len(ns) == 0 { return nil } if s, ok := ns[0].(string); ok { return s } var val interface{} var err error t := ns[0].(*parsec.Terminal) switch t.Name { case "INT": val, err = strconv.ParseInt(t.Value, 10, 64) if err != nil { panic(fmt.Errorf("cannot parse %v for integer\n", t)) } case "HEX": val, err = strconv.ParseInt(t.Value, 16, 64) if err != nil { panic(fmt.Errorf("cannot parse %v for hexadecimal\n", t)) } case "OCT": val, err = strconv.ParseInt(t.Value, 8, 64) if err != nil { panic(fmt.Errorf("cannot parse %v for octal\n", t)) } case "FLOAT": val, err = strconv.ParseFloat(t.Value, 64) if err != nil { panic(fmt.Errorf("cannot parse %v for float64\n", t)) } case "STRING": val = t.Value[1 : len(t.Value)-1] case "TRUE": val = true case "FALSE": val = false } return common.NewForm( "##literaltok", func(_ common.Scope, _ ...interface{}) interface{} { return val }) }
func identNode(n *parsec.Terminal) *common.Form { return common.NewForm( "##ident", func(scope common.Scope, _ ...interface{}) interface{} { name := n.Value forms, ok := scope.GetNonTerminal(name) if ok { val := EvalForms(name, scope, forms) scope.Set(n.Value, val, false /*global*/) return val } panic(fmt.Errorf("unknown nonterminal %v\n", n.Value)) }) }
func refNode(n *parsec.Terminal) *common.Form { return common.NewForm( "##ref", func(scope common.Scope, _ ...interface{}) interface{} { switch n.Value[0] { case '$': val, _, ok := scope.Get(n.Value[1:]) if !ok { panic(fmt.Errorf("unknown reference %v\n", n.Value)) } return val case '#': val, _, ok := scope.Get(n.Value) if !ok { panic(fmt.Errorf("unknown argument %v\n", n.Value)) } return val } panic(fmt.Errorf("unknown form %v as part of rule\n", n.Value)) }) }
func initBuiltins() { builtins["let"] = common.NewForm("let", builtin.Let) builtins["letr"] = common.NewForm("letr", builtin.Letr) builtins["global"] = common.NewForm("global", builtin.Global) builtins["weigh"] = common.NewForm("weigh", builtin.Weigh) builtins["bag"] = common.NewForm("bag", builtin.Bag) builtins["range"] = common.NewForm("range", builtin.Range) builtins["rangef"] = common.NewForm("rangef", builtin.Rangef) builtins["ranget"] = common.NewForm("ranget", builtin.Ranget) builtins["choice"] = common.NewForm("choice", builtin.Choice) builtins["uuid"] = common.NewForm("uuid", builtin.Uuid) builtins["inc"] = common.NewForm("inc", builtin.Inc) builtins["dec"] = common.NewForm("dec", builtin.Dec) builtins["len"] = common.NewForm("len", builtin.Len) builtins["sprintf"] = common.NewForm("sprintf", builtin.Sprintf) }
func termNode(n *parsec.Terminal) *common.Form { str, _ := literals[n.Value] return common.NewForm( "##term", func(_ common.Scope, _ ...interface{}) interface{} { return str }) }