package raku import ( "errors" "fmt" "io/ioutil" "os" "github.com/yhirose/go-peg" ) type Parser struct { *peg.Parser } type Result struct { * peg.Ast } func parserCheck(err error) { if perr, ok := err.(*peg.Error); ok { for _, d := range perr.Details { fmt.Println(d) } os.Exit(1) } } var defaultParser *Parser /** Loads a PEG parser from the given file name. */ func LoadParser(filename string) (*Parser, error) { result := &Parser{} data, err := ioutil.ReadFile(filename) if err == nil { result.Parser, err = peg.NewParser(string(data)) if err == nil { result.EnableAst() } return result, err } else { return nil, err } } func InitDefaultParser(peg_filename string) error { var err error defaultParser, err = LoadParser(peg_filename) return err } func wrapResult(wrapme peg.Any) *Result { result := &Result{}; ast, ok := wrapme.(*peg.Ast) if ok { result.Ast = ast return result } return nil } func (parser Parser) Parse(source string) (*Result, error) { ast, err := parser.ParseAndGetValue(source, nil) return wrapResult(ast), err } func (parser Parser) ParseFile(filename string) (*Result, error) { source, err := ioutil.ReadFile(filename) if err == nil { return parser.Parse(string(source)) } else { return nil, err } } func parse(source string) (*Result, error) { if defaultParser == nil { return nil, errors.New("Default parser not initialized!") } return defaultParser.Parse(source) } func parseFile(filename string) (*Result, error) { if defaultParser == nil { return nil, errors.New("Default parser not initialized!") } return defaultParser.ParseFile(filename) } type Method func (raku * Raku, message string, target Object, args ... interface{}) (Object, error) type Command struct { Name string Method } type CommandMap = map[string] Command type Class interface { Object Parent() * Class Selector(name string) * Method } type Object interface { Class() Class Send(raku * Raku, message string, args ... interface {}) (Object, error) } var RootClass * DefaultClass = &DefaultClass{} type DefaultObject struct { class Class * Raku CommandMap } func (object DefaultObject) Selector(name string) Method { command, ok := object.CommandMap[name] if !ok { method := object.class.Selector(name) if method == nil { return nil } return method } return command.Method } func (object DefaultObject) Class() Object { return RootClass } const METHOD_MISSING = "method_missing" func (object DefaultObject) Send(raku * Raku, message string, args ... interface {}) (Object, error) { method := object.Selector(message) if (method != nil) { return method(object.Raku, message, object, args ...) } method = object.Selector(METHOD_MISSING) if (method != nil) { return method(object.Raku, message, object, args ...) } return nil, fmt.Errorf("Cannot send message %s to object %v.", message, object) } type DefaultClass struct { parent * Class DefaultObject } func (class DefaultClass) Parent() Object { return class.parent } type NilClass struct { DefaultClass } var Nil Object = &DefaultObject{NilClass}; var Root * Object = &DefaultObject{RootClass} type Boolean struct { DefaultObject } var True * Boolean = &Boolean{Root} var False * Boolean = &Boolean{Root} func (boolean Boolean) Parent() Object { return Nil } func (boolean Boolean) Send(raku * Raku, message string, args ... interface {}) (Object, error) { return Root.Send(raku, message, args ...); } func (method Method) Parent() Object { return Nil } func (method Method) Send(raku * Raku, message string, args ... interface {}) (Object, error) { return method(raku, message, method, args...) } type Raku struct { * Parser CommandMap Root * Object Nil * NilClass True * Boolean False * Boolean } func New(peg_filename string) (*Raku, error) { var err error result := &Raku{} result.Parser, err = LoadParser(peg_filename) if (err == nil) { } return result, err } func Evaluate(raku * Raku, result Result) { _ }