// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. // ast.go package expr import ( "strings" "git.portale-stac.it/go-pkg/expr/kern" ) //-------- ast type ast struct { forest []*term root *term } func NewAst() *ast { return &ast{} } func (ast *ast) TypeName() string { return "Expression" } func (ast *ast) ToForest() { if ast.root != nil { if ast.forest == nil { ast.forest = make([]*term, 0) } ast.forest = append(ast.forest, ast.root) ast.root = nil } } func (ast *ast) String() string { var sb strings.Builder if ast.root == nil { sb.WriteString("(nil)") } else { ast.root.toString(&sb) } return sb.String() } func (ast *ast) addTokens(tokens ...*Token) (err error) { for _, tk := range tokens { if _, err = ast.addToken(tk); err != nil { break } } return } // func (expr *ast) addToken(tk *Token) (err error) { // _, err = expr.addToken2(tk) // return // } func (ast *ast) addToken(tk *Token) (t *term, err error) { if t = newTerm(tk); t != nil { err = ast.addTerm(t) } else { err = tk.Errorf("unexpected token %q", tk.String()) } return } func (ast *ast) addTerm(node *term) (err error) { if ast.root == nil { ast.root = node } else { ast.root, err = ast.insert(ast.root, node) } return } func (ast *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 = ast.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 (ast *ast) Finish() { if ast.root == nil && ast.forest != nil && len(ast.forest) >= 1 { ast.root = ast.forest[len(ast.forest)-1] ast.forest = ast.forest[0 : len(ast.forest)-1] } } func (ast *ast) Eval(ctx kern.ExprContext) (result any, err error) { ast.Finish() if ast.root != nil { // initDefaultVars(ctx) if ast.forest != nil { for _, root := range ast.forest { if result, err = root.Compute(ctx); err == nil { ctx.UnsafeSetVar(kern.ControlLastResult, result) } else { //err = fmt.Errorf("error in expression nr %d: %v", i+1, err) break } } } if err == nil { if result, err = ast.root.Compute(ctx); err == nil { ctx.UnsafeSetVar(kern.ControlLastResult, result) } } // } else { // err = errors.New("empty expression") } return }