// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. // ast.go package expr import ( "strings" ) type Expr interface { Eval(ctx ExprContext) (result any, err error) eval(ctx ExprContext, preset bool) (result any, err error) String() string } //-------- ast type ast struct { forest []*term root *term } func NewAst() *ast { return &ast{} } func (self *ast) ToForest() { if self.root != nil { if self.forest == nil { self.forest = make([]*term, 0) } self.forest = append(self.forest, self.root) self.root = nil } } func (self *ast) String() string { var sb strings.Builder if self.root == nil { sb.WriteString("(nil)") } else { self.root.toString(&sb) } return sb.String() } func (self *ast) addTokens(tokens ...*Token) (err error) { for _, tk := range tokens { if err = self.addToken(tk); err != nil { break } } return } func (self *ast) addToken(tk *Token) (err error) { _, err = self.addToken2(tk) return } func (self *ast) addToken2(tk *Token) (t *term, err error) { if t = newTerm(tk, nil); t != nil { err = self.addTerm(t) } else { err = tk.Errorf("unexpected token %q", tk.String()) } return } func (self *ast) addTerm(node *term) (err error) { if self.root == nil { self.root = node } else { self.root, err = self.insert(self.root, node) } return } func (self *ast) insert(tree, node *term) (root *term, err error) { if tree.getPriority() < node.getPriority() { root = tree if tree.isComplete() { var subRoot *term last := tree.removeLastChild() if subRoot, err = self.insert(last, node); err == nil { subRoot.setParent(tree) } } else { node.setParent(tree) } } else if !node.isLeaf() { root = node tree.setParent(node) } else { err = node.Errorf("two adjacent operators: %q and %q", tree, node) } return } func (self *ast) Finish() { if self.root == nil && self.forest != nil && len(self.forest) >= 1 { self.root = self.forest[len(self.forest)-1] self.forest = self.forest[0 : len(self.forest)-1] } } func (self *ast) Eval(ctx ExprContext) (result any, err error) { return self.eval(ctx, true) } func (self *ast) eval(ctx ExprContext, preset bool) (result any, err error) { self.Finish() if self.root != nil { if preset { initDefaultVars(ctx) } if self.forest != nil { for _, root := range self.forest { if result, err = root.compute(ctx); err == nil { ctx.setVar(ControlLastResult, result) } else { //err = fmt.Errorf("error in expression nr %d: %v", i+1, err) break } } } if err == nil { result, err = self.root.compute(ctx) } // } else { // err = errors.New("empty expression") } return }