github.com/MontFerret/ferret@v0.18.0/pkg/compiler/compiler.go (about) 1 package compiler 2 3 import ( 4 "github.com/pkg/errors" 5 6 "github.com/MontFerret/ferret/pkg/parser" 7 "github.com/MontFerret/ferret/pkg/runtime" 8 "github.com/MontFerret/ferret/pkg/runtime/core" 9 "github.com/MontFerret/ferret/pkg/stdlib" 10 ) 11 12 type Compiler struct { 13 *NamespaceContainer 14 } 15 16 func New(setters ...Option) *Compiler { 17 c := &Compiler{} 18 c.NamespaceContainer = newRootNamespace() 19 c.funcs = core.NewFunctions() 20 21 opts := &Options{} 22 23 for _, setter := range setters { 24 setter(opts) 25 } 26 27 if !opts.noStdlib { 28 if err := stdlib.RegisterLib(c.NamespaceContainer); err != nil { 29 panic(err) 30 } 31 } 32 33 return c 34 } 35 36 func (c *Compiler) Compile(query string) (program *runtime.Program, err error) { 37 if query == "" { 38 return nil, ErrEmptyQuery 39 } 40 41 defer func() { 42 if r := recover(); r != nil { 43 // find out exactly what the error was and set err 44 switch x := r.(type) { 45 case string: 46 err = errors.New(x) 47 case error: 48 err = x 49 default: 50 err = errors.New("unknown panic") 51 } 52 53 program = nil 54 } 55 }() 56 57 p := parser.New(query) 58 p.AddErrorListener(newErrorListener()) 59 60 l := newVisitor(query, c.funcs) 61 62 res := p.Visit(l).(*result) 63 64 if res.Ok() { 65 program = res.Data().(*runtime.Program) 66 } else { 67 err = res.Error() 68 } 69 70 return program, err 71 } 72 73 func (c *Compiler) MustCompile(query string) *runtime.Program { 74 program, err := c.Compile(query) 75 76 if err != nil { 77 panic(err) 78 } 79 80 return program 81 }