// ast.go package expr import ( "errors" "fmt" "strings" ) //-------- ast type ast struct { root *term } func NewAst() *ast { return &ast{} } 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) { if t := newTerm(tk, nil); t != nil { err = self.addTerm(t) } else { err = fmt.Errorf("No term constructor for 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() subRoot, err = self.insert(last, node) subRoot.setParent(tree) } else { node.setParent(tree) } } else if !node.isLeaf() { root = node tree.setParent(node) } else { err = fmt.Errorf("two adjacent operators: %q and %q", tree, node) } return } func (self *ast) eval(ctx exprContext) (result any, err error) { if self.root != nil { result, err = self.root.compute(ctx) } else { err = errors.New("empty expression") } return }