moved scanner sources to package 'scan'
This commit is contained in:
+147
@@ -0,0 +1,147 @@
|
||||
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||
// All rights reserved.
|
||||
|
||||
// ast.go
|
||||
package scan
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"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) Root() *Term {
|
||||
return ast.root
|
||||
}
|
||||
|
||||
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) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if errVal, ok := r.(error); ok {
|
||||
err = errVal
|
||||
} else {
|
||||
err = errors.New("unexpected error while evaluating the expression")
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
ast.Finish()
|
||||
|
||||
if ast.root != nil {
|
||||
// initDefaultVars(ctx)
|
||||
if ast.forest != nil {
|
||||
for _, tree := range ast.forest {
|
||||
if result, err = tree.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
|
||||
}
|
||||
Reference in New Issue
Block a user