From 7f34ccf95582be2b319b56fb589db641a380c493 Mon Sep 17 00:00:00 2001 From: Celestino Amoroso Date: Sun, 3 May 2026 14:19:17 +0200 Subject: [PATCH] moved scanner sources to package 'scan' --- bind-expr-functions.go | 4 +- builtin-base.go | 5 +- builtin-import.go | 7 +- function.go | 9 +- helpers.go | 9 +- expr.go => kern/expr.go | 10 +- operand-dict.go | 21 +- operand-expr.go | 25 +- operand-func.go | 63 ++-- operand-iterator.go | 49 +-- operand-list.go | 23 +- operand-literal.go | 33 +- operand-selector-case.go | 31 +- operand-var.go | 23 +- operator-assign.go | 119 +++--- operator-bitwise.go | 95 ++--- operator-bool.go | 93 ++--- operator-builtin.go | 21 +- operator-but.go | 21 +- operator-context.go | 27 +- operator-ctrl.go | 19 +- operator-default.go | 79 ++-- operator-digest.go | 25 +- operator-dot.go | 45 +-- operator-fact.go | 23 +- operator-filter.go | 25 +- operator-fraction.go | 24 +- operator-groupby.go | 29 +- operator-in.go | 23 +- operator-include.go | 23 +- operator-index.go | 35 +- operator-insert.go | 53 +-- operator-iter-value.go | 23 +- operator-join.go | 25 +- operator-length.go | 23 +- operator-map.go | 25 +- operator-plugin.go | 21 +- operator-post-inc-dec.go | 59 ++- operator-pre-inc-dec.go | 56 +-- operator-prod.go | 105 +++--- operator-range.go | 39 +- operator-rel.go | 125 +++---- operator-selector.go | 33 +- operator-shift.go | 49 +-- operator-sign.go | 45 ++- operator-sum.go | 49 +-- operator-unset.go | 25 +- parser.go | 343 +++++++++--------- ast.go => scan/ast.go | 52 +-- scanner.go => scan/scanner.go | 143 ++++---- scan/symbol-map.go | 231 ++++++++++++ symbol.go => scan/symbol.go | 2 +- t_scanner_test.go => scan/t_scanner_test.go | 2 +- .../term-constructor-registry.go | 10 +- scan/term.go | 301 +++++++++++++++ token.go => scan/token.go | 14 +- symbol-map.go | 231 ------------ t_ast_test.go | 32 +- t_common_test.go | 5 +- t_dict_test.go | 9 +- t_symbol_test.go | 3 +- t_term_test.go | 28 +- t_token_test.go | 14 +- term.go | 300 --------------- byte-slider.go => util/byte-slider.go | 2 +- util/utils-unix.go | 4 +- 66 files changed, 1793 insertions(+), 1726 deletions(-) rename expr.go => kern/expr.go (56%) rename ast.go => scan/ast.go (71%) rename scanner.go => scan/scanner.go (81%) create mode 100644 scan/symbol-map.go rename symbol.go => scan/symbol.go (99%) rename t_scanner_test.go => scan/t_scanner_test.go (99%) rename term-constuctor-registry.go => scan/term-constructor-registry.go (72%) create mode 100644 scan/term.go rename token.go => scan/token.go (94%) delete mode 100644 symbol-map.go delete mode 100644 term.go rename byte-slider.go => util/byte-slider.go (98%) diff --git a/bind-expr-functions.go b/bind-expr-functions.go index b1e7c06..04eac28 100644 --- a/bind-expr-functions.go +++ b/bind-expr-functions.go @@ -12,7 +12,7 @@ import ( type exprFunctor struct { kern.BaseFunctor params []kern.ExprFuncParam - expr Expr + expr kern.Expr defCtx kern.ExprContext } @@ -20,7 +20,7 @@ func (functor *exprFunctor) GetParams() (params []kern.ExprFuncParam) { return functor.params } -func newExprFunctor(e Expr, params []kern.ExprFuncParam, ctx kern.ExprContext) *exprFunctor { +func newExprFunctor(e kern.Expr, params []kern.ExprFuncParam, ctx kern.ExprContext) *exprFunctor { var defCtx kern.ExprContext if ctx != nil { defCtx = ctx diff --git a/builtin-base.go b/builtin-base.go index 91a27a8..840669a 100644 --- a/builtin-base.go +++ b/builtin-base.go @@ -11,6 +11,7 @@ import ( "strings" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) const ( @@ -199,7 +200,7 @@ func fractFunc(ctx kern.ExprContext, name string, args map[string]any) (result a func evalFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { if source, ok := args[kern.ParamSource].(string); ok { - var ast Expr + var ast kern.Expr parser := NewParser() if ctx == nil { @@ -207,7 +208,7 @@ func evalFunc(ctx kern.ExprContext, name string, args map[string]any) (result an } r := strings.NewReader(source) - scanner := NewScanner(r, DefaultTranslations()) + scanner := scan.NewScanner(r, scan.DefaultTranslations()) if ast, err = parser.Parse(scanner); err == nil { CtrlEnable(ctx, kern.ControlExportAll) diff --git a/builtin-import.go b/builtin-import.go index 50eab83..ae27d17 100644 --- a/builtin-import.go +++ b/builtin-import.go @@ -9,6 +9,7 @@ import ( "os" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) func importFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { @@ -43,10 +44,10 @@ func doImport(ctx kern.ExprContext, name string, dirList []string, it kern.Itera var file *os.File if file, err = os.Open(sourceFilepath); err == nil { defer file.Close() - var expr *ast - scanner := NewScanner(file, DefaultTranslations()) + var expr *scan.Ast + scanner := scan.NewScanner(file, scan.DefaultTranslations()) parser := NewParser() - if expr, err = parser.parseGeneral(scanner, allowMultiExpr|allowVarRef, SymEos); err == nil { + if expr, err = parser.parseGeneral(scanner, allowMultiExpr|allowVarRef, scan.SymEos); err == nil { result, err = expr.Eval(ctx) } if err != nil { diff --git a/function.go b/function.go index 640cd8b..a419101 100644 --- a/function.go +++ b/function.go @@ -9,6 +9,7 @@ import ( "strings" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) // ---- Function template @@ -223,7 +224,7 @@ func (info *funcInfo) ParamSpec(paramName string) kern.ExprFuncParam { return nil } -func initActualParams(ctx kern.ExprContext, info kern.ExprFunc, callTerm *term) (actualParams map[string]any, err error) { +func initActualParams(ctx kern.ExprContext, info kern.ExprFunc, callTerm *scan.Term) (actualParams map[string]any, err error) { var varArgs []any var varName string @@ -235,7 +236,7 @@ func initActualParams(ctx kern.ExprContext, info kern.ExprFunc, callTerm *term) return } - for i, tree := range callTerm.children { + for i, tree := range callTerm.Children { var paramValue any paramCtx := ctx.Clone() if paramValue, err = tree.Compute(paramCtx); err != nil { @@ -254,14 +255,14 @@ func initActualParams(ctx kern.ExprContext, info kern.ExprFunc, callTerm *term) } else if i < len(formalParams) { spec := formalParams[i] if spec.IsRepeat() { - varArgs = make([]any, 0, len(callTerm.children)-i) + varArgs = make([]any, 0, len(callTerm.Children)-i) varArgs = append(varArgs, paramValue) varName = spec.Name() } else { actualParams[spec.Name()] = paramValue } } else { - err = kern.ErrTooManyParams(info.Name(), len(formalParams), len(callTerm.children)) + err = kern.ErrTooManyParams(info.Name(), len(formalParams), len(callTerm.Children)) break } } else { diff --git a/helpers.go b/helpers.go index cc8df30..bccde1d 100644 --- a/helpers.go +++ b/helpers.go @@ -11,14 +11,15 @@ import ( "strings" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/util" ) func EvalString(ctx kern.ExprContext, source string) (result any, err error) { - var tree *ast + var tree *scan.Ast r := strings.NewReader(source) - scanner := NewScanner(r, DefaultTranslations()) + scanner := scan.NewScanner(r, scan.DefaultTranslations()) parser := NewParser() if tree, err = parser.Parse(scanner); err == nil { @@ -69,8 +70,8 @@ func EvalStringV(source string, args []Arg) (result any, err error) { } func EvalStream(ctx kern.ExprContext, r io.Reader) (result any, err error) { - var tree *ast - scanner := NewScanner(r, DefaultTranslations()) + var tree *scan.Ast + scanner := scan.NewScanner(r, scan.DefaultTranslations()) parser := NewParser() if tree, err = parser.Parse(scanner); err == nil { diff --git a/expr.go b/kern/expr.go similarity index 56% rename from expr.go rename to kern/expr.go index 5323181..401172a 100644 --- a/expr.go +++ b/kern/expr.go @@ -2,15 +2,11 @@ // All rights reserved. // expr.go -package expr - -import ( - kern "git.portale-stac.it/go-pkg/expr/kern" -) +package kern // ----Expression interface type Expr interface { - kern.Typer - Eval(ctx kern.ExprContext) (result any, err error) + Typer + Eval(ctx ExprContext) (result any, err error) String() string } diff --git a/operand-dict.go b/operand-dict.go index 5220892..a9025f1 100644 --- a/operand-dict.go +++ b/operand-dict.go @@ -6,23 +6,24 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) // -------- dict term -func newDictTerm(args map[any]*term) *term { - return &term{ - tk: *NewValueToken(0, 0, SymDict, "{}", args), - parent: nil, - children: nil, - position: posLeaf, - priority: priValue, - evalFunc: evalDict, +func newDictTerm(args map[any]*scan.Term) *scan.Term { + return &scan.Term{ + Tk: *scan.NewValueToken(0, 0, scan.SymDict, "{}", args), + Parent: nil, + Children: nil, + Position: scan.PosLeaf, + Priority: scan.PriValue, + EvalFunc: evalDict, } } // -------- dict func -func evalDict(ctx kern.ExprContext, opTerm *term) (v any, err error) { - dict, _ := opTerm.value().(map[any]*term) +func evalDict(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { + dict, _ := opTerm.Value().(map[any]*scan.Term) items := make(kern.DictType, len(dict)) for key, tree := range dict { var param any diff --git a/operand-expr.go b/operand-expr.go index 781078c..2a60578 100644 --- a/operand-expr.go +++ b/operand-expr.go @@ -8,27 +8,28 @@ import ( "fmt" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) // -------- expr term -func newExprTerm(root *term) *term { - tk := NewValueToken(root.tk.row, root.tk.col, SymExpression, root.Source(), root) - return &term{ - tk: *tk, - parent: nil, - children: nil, - position: posLeaf, - priority: priValue, - evalFunc: evalExpr, +func newExprTerm(root *scan.Term) *scan.Term { + tk := scan.NewValueToken(root.Tk.Row(), root.Tk.Col(), scan.SymExpression, root.Source(), root) + return &scan.Term{ + Tk: *tk, + Parent: nil, + Children: nil, + Position: scan.PosLeaf, + Priority: scan.PriValue, + EvalFunc: evalExpr, } } // -------- eval expr -func evalExpr(ctx kern.ExprContext, opTerm *term) (v any, err error) { - if ast, ok := opTerm.value().(*term); ok { +func evalExpr(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { + if ast, ok := opTerm.Value().(*scan.Term); ok { v, err = ast.Compute(ctx) } else { - err = fmt.Errorf("expression expected, got %T", opTerm.value()) + err = fmt.Errorf("expression expected, got %T", opTerm.Value()) } return } diff --git a/operand-func.go b/operand-func.go index f16eb39..000a1ec 100644 --- a/operand-func.go +++ b/operand-func.go @@ -8,31 +8,32 @@ import ( "errors" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) // -------- function call term -func newFuncCallTerm(tk *Token, args []*term) *term { - var pos termPosition = posLeaf +func newFuncCallTerm(tk *scan.Token, args []*scan.Term) *scan.Term { + var pos scan.TermPosition = scan.PosLeaf if len(args) > 0 { - pos = posMultifix + pos = scan.PosMultifix } - return &term{ - tk: *tk, - parent: nil, - children: args, - position: pos, - priority: priValue, - evalFunc: evalFuncCall, + return &scan.Term{ + Tk: *tk, + Parent: nil, + Children: args, + Position: pos, + Priority: scan.PriValue, + EvalFunc: evalFuncCall, } } // -------- eval func call // func _evalFuncCall(ctx ExprContext, opTerm *term) (v any, err error) { -// name, _ := opTerm.tk.Value.(string) -// params := make([]any, len(opTerm.children), len(opTerm.children)+5) -// for i, tree := range opTerm.children { +// name, _ := opTerm.Tk.Value.(string) +// params := make([]any, len(opTerm.Children), len(opTerm.Children)+5) +// for i, tree := range opTerm.Children { // var param any -// if param, err = tree.compute(ctx); err != nil { +// if param, err = tree.Compute(ctx); err != nil { // break // } // params[i] = param @@ -44,35 +45,35 @@ func newFuncCallTerm(tk *Token, args []*term) *term { // return // } -func evalFuncCall(ctx kern.ExprContext, opTerm *term) (v any, err error) { - name, _ := opTerm.tk.Value.(string) +func evalFuncCall(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { + name, _ := opTerm.Tk.Value.(string) v, err = kern.CallFunctionByTerm(ctx, name, opTerm) return } // -------- function definition term -func newFuncDefTerm(tk *Token, args []*term) *term { - return &term{ - tk: *tk, // value is the expression body - parent: nil, - children: args, // function params - position: posLeaf, - priority: priValue, - evalFunc: evalFuncDef, +func newFuncDefTerm(tk *scan.Token, args []*scan.Term) *scan.Term { + return &scan.Term{ + Tk: *tk, // value is the expression body + Parent: nil, + Children: args, // function params + Position: scan.PosLeaf, + Priority: scan.PriValue, + EvalFunc: evalFuncDef, } } // -------- eval func def -func evalFuncDef(ctx kern.ExprContext, opTerm *term) (v any, err error) { - bodySpec := opTerm.value() - if ast, ok := bodySpec.(*ast); ok { - paramList := make([]kern.ExprFuncParam, 0, len(opTerm.children)) - for _, param := range opTerm.children { +func evalFuncDef(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { + bodySpec := opTerm.Value() + if ast, ok := bodySpec.(*scan.Ast); ok { + paramList := make([]kern.ExprFuncParam, 0, len(opTerm.Children)) + for _, param := range opTerm.Children { var defValue any flags := paramFlags(0) - if len(param.children) > 0 { + if len(param.Children) > 0 { flags |= PfDefault - if defValue, err = param.children[0].Compute(ctx); err != nil { + if defValue, err = param.Children[0].Compute(ctx); err != nil { return } } diff --git a/operand-iterator.go b/operand-iterator.go index beaebab..17a5913 100644 --- a/operand-iterator.go +++ b/operand-iterator.go @@ -9,25 +9,26 @@ import ( "strings" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) // -------- iterator term -func newIteratorTerm(tk *Token, args []*term) *term { - tk.Sym = SymIterator - return &term{ - tk: *tk, - parent: nil, - children: args, - position: posLeaf, - priority: priValue, - evalFunc: evalIterator, +func newIteratorTerm(tk *scan.Token, args []*scan.Term) *scan.Term { + tk.Sym = scan.SymIterator + return &scan.Term{ + Tk: *tk, + Parent: nil, + Children: args, + Position: scan.PosLeaf, + Priority: scan.PriValue, + EvalFunc: evalIterator, } } // -------- eval iterator -func evalTermArray(ctx kern.ExprContext, terms []*term) (values []any, err error) { +func evalTermArray(ctx kern.ExprContext, terms []*scan.Term) (values []any, err error) { values = make([]any, len(terms)) for i, t := range terms { var value any @@ -40,17 +41,17 @@ func evalTermArray(ctx kern.ExprContext, terms []*term) (values []any, err error return } -func evalFirstChild(ctx kern.ExprContext, iteratorTerm *term) (value any, err error) { - if len(iteratorTerm.children) < 1 || iteratorTerm.children[0] == nil { +func evalFirstChild(ctx kern.ExprContext, iteratorTerm *scan.Term) (value any, err error) { + if len(iteratorTerm.Children) < 1 || iteratorTerm.Children[0] == nil { err = iteratorTerm.Errorf("missing the data-source parameter") return } - value, err = iteratorTerm.children[0].Compute(ctx) + value, err = iteratorTerm.Children[0].Compute(ctx) return } -func getDataSourceDict(iteratorTerm *term, firstChildValue any) (ds map[string]kern.Functor, err error) { +func getDataSourceDict(iteratorTerm *scan.Term, firstChildValue any) (ds map[string]kern.Functor, err error) { if dictAny, ok := firstChildValue.(*kern.DictType); ok { requiredFields := []string{kern.NextName} fieldsMask := 0b1 @@ -74,13 +75,13 @@ func getDataSourceDict(iteratorTerm *term, firstChildValue any) (ds map[string]k missingFields = append(missingFields, field) } } - err = iteratorTerm.children[0].Errorf("the data-source must provide a non-nil %q operator(s)", strings.Join(missingFields, ", ")) + err = iteratorTerm.Children[0].Errorf("the data-source must provide a non-nil %q operator(s)", strings.Join(missingFields, ", ")) } } return } -func evalIterator(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalIterator(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var firstChildValue any var ds map[string]kern.Functor @@ -100,8 +101,8 @@ func evalIterator(ctx kern.ExprContext, opTerm *term) (v any, err error) { if initFunc, exists := ds[kern.InitName]; exists && initFunc != nil { var args []any var resource any - if len(opTerm.children) > 1 { - if args, err = evalTermArray(ctx, opTerm.children[1:]); err != nil { + if len(opTerm.Children) > 1 { + if args, err = evalTermArray(ctx, opTerm.Children[1:]); err != nil { return } } else { @@ -124,33 +125,33 @@ func evalIterator(ctx kern.ExprContext, opTerm *term) (v any, err error) { } else { if dictIt, ok := firstChildValue.(*kern.DictType); ok { var args []any - if args, err = evalSibling(ctx, opTerm.children, nil); err == nil { + if args, err = evalSibling(ctx, opTerm.Children, nil); err == nil { v, err = NewDictIterator(dictIt, args) } } else { - err = opTerm.children[0].Errorf("the data-source must be a dictionary") + err = opTerm.Children[0].Errorf("the data-source must be a dictionary") } } } else if list, ok := firstChildValue.(*kern.ListType); ok { var args []any - if args, err = evalSibling(ctx, opTerm.children, nil); err == nil { + if args, err = evalSibling(ctx, opTerm.Children, nil); err == nil { v = NewListIterator(list, args) } } else if intVal, ok := firstChildValue.(int64); ok { var args []any - if args, err = evalSibling(ctx, opTerm.children, intVal); err == nil { + if args, err = evalSibling(ctx, opTerm.Children, intVal); err == nil { v, err = NewIntIterator(args) } } else { var list []any - if list, err = evalSibling(ctx, opTerm.children, firstChildValue); err == nil { + if list, err = evalSibling(ctx, opTerm.Children, firstChildValue); err == nil { v = NewArrayIterator(list) } } return } -func evalSibling(ctx kern.ExprContext, terms []*term, firstChildValue any) (list []any, err error) { +func evalSibling(ctx kern.ExprContext, terms []*scan.Term, firstChildValue any) (list []any, err error) { items := make([]any, 0, len(terms)) for i, tree := range terms { var param any diff --git a/operand-list.go b/operand-list.go index 173b800..f7a9d50 100644 --- a/operand-list.go +++ b/operand-list.go @@ -6,27 +6,28 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) // -------- list term -func newListTermA(args ...*term) *term { +func newListTermA(args ...*scan.Term) *scan.Term { return newListTerm(0, 0, args) } -func newListTerm(row, col int, args []*term) *term { - return &term{ - tk: *NewValueToken(row, col, SymList, "[]", args), - parent: nil, - children: nil, - position: posLeaf, - priority: priValue, - evalFunc: evalList, +func newListTerm(row, col int, args []*scan.Term) *scan.Term { + return &scan.Term{ + Tk: *scan.NewValueToken(row, col, scan.SymList, "[]", args), + Parent: nil, + Children: nil, + Position: scan.PosLeaf, + Priority: scan.PriValue, + EvalFunc: evalList, } } // -------- list func -func evalList(ctx kern.ExprContext, opTerm *term) (v any, err error) { - list, _ := opTerm.value().([]*term) +func evalList(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { + list, _ := opTerm.Value().([]*scan.Term) items := make(kern.ListType, len(list)) for i, tree := range list { var param any diff --git a/operand-literal.go b/operand-literal.go index b11cfa4..73833d0 100644 --- a/operand-literal.go +++ b/operand-literal.go @@ -6,32 +6,33 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) // -------- literal term -func newLiteralTerm(tk *Token) *term { - return &term{ - tk: *tk, - parent: nil, - children: nil, - position: posLeaf, - priority: priValue, - evalFunc: evalLiteral, +func newLiteralTerm(tk *scan.Token) *scan.Term { + return &scan.Term{ + Tk: *tk, + Parent: nil, + Children: nil, + Position: scan.PosLeaf, + Priority: scan.PriValue, + EvalFunc: evalLiteral, } } // -------- eval func -func evalLiteral(ctx kern.ExprContext, opTerm *term) (v any, err error) { - v = opTerm.tk.Value +func evalLiteral(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { + v = opTerm.Tk.Value return } // init func init() { - registerTermConstructor(SymString, newLiteralTerm) - registerTermConstructor(SymInteger, newLiteralTerm) - registerTermConstructor(SymFloat, newLiteralTerm) - registerTermConstructor(SymFraction, newLiteralTerm) - registerTermConstructor(SymBool, newLiteralTerm) - registerTermConstructor(SymKwNil, newLiteralTerm) + scan.RegisterTermConstructor(scan.SymString, newLiteralTerm) + scan.RegisterTermConstructor(scan.SymInteger, newLiteralTerm) + scan.RegisterTermConstructor(scan.SymFloat, newLiteralTerm) + scan.RegisterTermConstructor(scan.SymFraction, newLiteralTerm) + scan.RegisterTermConstructor(scan.SymBool, newLiteralTerm) + scan.RegisterTermConstructor(scan.SymKwNil, newLiteralTerm) } diff --git a/operand-selector-case.go b/operand-selector-case.go index af61dad..9985a3d 100644 --- a/operand-selector-case.go +++ b/operand-selector-case.go @@ -9,19 +9,20 @@ import ( "strings" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) // -------- selector case term type selectorCase struct { - filterList *term - caseExpr Expr + filterList *scan.Term + caseExpr kern.Expr } func (sc *selectorCase) String() string { var sb strings.Builder if sc.filterList != nil { - sc.filterList.toString(&sb) + sc.filterList.ToString(&sb) sb.WriteByte(' ') } sb.WriteByte('{') @@ -30,23 +31,23 @@ func (sc *selectorCase) String() string { return sb.String() } -func newSelectorCaseTerm(row, col int, filterList *term, caseExpr Expr) *term { - tk := NewValueToken(row, col, SymSelectorCase, "", &selectorCase{filterList: filterList, caseExpr: caseExpr}) - return &term{ - tk: *tk, - parent: nil, - children: nil, - position: posLeaf, - priority: priValue, - evalFunc: evalSelectorCase, +func newSelectorCaseTerm(row, col int, filterList *scan.Term, caseExpr kern.Expr) *scan.Term { + tk := scan.NewValueToken(row, col, scan.SymSelectorCase, "", &selectorCase{filterList: filterList, caseExpr: caseExpr}) + return &scan.Term{ + Tk: *tk, + Parent: nil, + Children: nil, + Position: scan.PosLeaf, + Priority: scan.PriValue, + EvalFunc: evalSelectorCase, } } // -------- eval selector case -func evalSelectorCase(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalSelectorCase(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var ok bool - if v, ok = opTerm.value().(*selectorCase); !ok { - err = fmt.Errorf("selector-case expected, got %T", opTerm.value()) + if v, ok = opTerm.Value().(*selectorCase); !ok { + err = fmt.Errorf("selector-case expected, got %T", opTerm.Value()) } return } diff --git a/operand-var.go b/operand-var.go index d66d94c..d0b2c0d 100644 --- a/operand-var.go +++ b/operand-var.go @@ -8,24 +8,25 @@ import ( "fmt" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) // -------- variable term -func newVarTerm(tk *Token) *term { - t := &term{ - tk: *tk, - parent: nil, - children: nil, - position: posLeaf, - priority: priValue, - evalFunc: evalVar, +func newVarTerm(tk *scan.Token) *scan.Term { + t := &scan.Term{ + Tk: *tk, + Parent: nil, + Children: nil, + Position: scan.PosLeaf, + Priority: scan.PriValue, + EvalFunc: evalVar, } - t.tk.Sym = SymVariable + t.Tk.Sym = scan.SymVariable return t } // -------- eval func -func evalVar(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalVar(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var exists bool name := opTerm.Source() if v, exists = ctx.GetVar(name); !exists { @@ -40,5 +41,5 @@ func evalVar(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymIdentifier, newVarTerm) + scan.RegisterTermConstructor(scan.SymIdentifier, newVarTerm) } diff --git a/operator-assign.go b/operator-assign.go index 445eb02..62197dd 100644 --- a/operator-assign.go +++ b/operator-assign.go @@ -6,22 +6,23 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/util" ) //-------- assign term -func newAssignTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priAssign, - evalFunc: evalAssign, +func newAssignTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriAssign, + EvalFunc: evalAssign, } } -func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *term, value any) (err error) { +func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *scan.Term, value any) (err error) { var collectionValue, keyListValue, keyValue any var keyList *kern.ListType var ok bool @@ -56,32 +57,32 @@ func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *ter return } -func assignValue(ctx kern.ExprContext, leftTerm *term, v any) (err error) { - if leftTerm.symbol() == SymIndex { - err = assignCollectionItem(ctx, leftTerm.children[0], leftTerm.children[1], v) +func assignValue(ctx kern.ExprContext, leftTerm *scan.Term, v any) (err error) { + if leftTerm.Symbol() == scan.SymIndex { + err = assignCollectionItem(ctx, leftTerm.Children[0], leftTerm.Children[1], v) } else { ctx.UnsafeSetVar(leftTerm.Source(), v) } return } -func evalAssign(ctx kern.ExprContext, opTerm *term) (v any, err error) { - if err = opTerm.checkOperands(); err != nil { +func evalAssign(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { + if err = opTerm.CheckOperands(); err != nil { return } - leftTerm := opTerm.children[0] - leftSym := leftTerm.symbol() - if leftSym != SymVariable && leftSym != SymIndex { - err = leftTerm.tk.Errorf("left operand of %q must be a variable or a collection's item", opTerm.tk.source) + leftTerm := opTerm.Children[0] + leftSym := leftTerm.Symbol() + if leftSym != scan.SymVariable && leftSym != scan.SymIndex { + err = leftTerm.Tk.Errorf("left operand of %q must be a variable or a collection's item", opTerm.Tk.Source()) return } - rightChild := opTerm.children[1] + rightChild := opTerm.Children[1] if v, err = rightChild.Compute(ctx); err == nil { if functor, ok := v.(kern.Functor); ok { - if leftSym == SymVariable { + if leftSym == scan.SymVariable { if info := functor.GetFunc(); info != nil { ctx.RegisterFunc(leftTerm.Source(), info.Functor(), info.ReturnType(), info.Params()) } else if funcDef, ok := functor.(*exprFunctor); ok { @@ -106,17 +107,17 @@ func evalAssign(ctx kern.ExprContext, opTerm *term) (v any, err error) { //-------- assign term -func newOpAssignTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priAssign, - evalFunc: evalOpAssign, +func newOpAssignTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriAssign, + EvalFunc: evalOpAssign, } } -func getCollectionItemValue(ctx kern.ExprContext, collectionTerm, keyListTerm *term) (value any, err error) { +func getCollectionItemValue(ctx kern.ExprContext, collectionTerm, keyListTerm *scan.Term) (value any, err error) { var collectionValue, keyListValue, keyValue any var keyList *kern.ListType var ok bool @@ -151,52 +152,52 @@ func getCollectionItemValue(ctx kern.ExprContext, collectionTerm, keyListTerm *t return } -func getAssignValue(ctx kern.ExprContext, leftTerm *term) (value any, err error) { - if leftTerm.symbol() == SymIndex { - value, err = getCollectionItemValue(ctx, leftTerm.children[0], leftTerm.children[1]) +func getAssignValue(ctx kern.ExprContext, leftTerm *scan.Term) (value any, err error) { + if leftTerm.Symbol() == scan.SymIndex { + value, err = getCollectionItemValue(ctx, leftTerm.Children[0], leftTerm.Children[1]) } else { value, _ = ctx.GetVar(leftTerm.Source()) } return } -func evalOpAssign(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalOpAssign(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var rightValue, leftValue any - if err = opTerm.checkOperands(); err != nil { + if err = opTerm.CheckOperands(); err != nil { return } - leftTerm := opTerm.children[0] - leftSym := leftTerm.symbol() - if leftSym != SymVariable && leftSym != SymIndex { - err = leftTerm.tk.Errorf("left operand of %q must be a variable or a collection's item", opTerm.tk.source) + leftTerm := opTerm.Children[0] + leftSym := leftTerm.Symbol() + if leftSym != scan.SymVariable && leftSym != scan.SymIndex { + err = leftTerm.Tk.Errorf("left operand of %q must be a variable or a collection's item", opTerm.Tk.Source()) return } - rightChild := opTerm.children[1] + rightChild := opTerm.Children[1] if rightValue, err = rightChild.Compute(ctx); err == nil { if leftValue, err = getAssignValue(ctx, leftTerm); err == nil { - switch opTerm.symbol() { - case SymPlusEqual: + switch opTerm.Symbol() { + case scan.SymPlusEqual: v, err = sumValues(opTerm, leftValue, rightValue) - case SymMinusEqual: + case scan.SymMinusEqual: v, err = diffValues(opTerm, leftValue, rightValue) - case SymStarEqual: + case scan.SymStarEqual: v, err = mulValues(opTerm, leftValue, rightValue) - case SymSlashEqual: + case scan.SymSlashEqual: v, err = divValues(opTerm, leftValue, rightValue) - case SymPercEqual: + case scan.SymPercEqual: v, err = remainderValues(opTerm, leftValue, rightValue) - case SymAmpersandEqual: + case scan.SymAmpersandEqual: v, err = bitwiseAnd(opTerm, leftValue, rightValue) - case SymVertBarEqual: + case scan.SymVertBarEqual: v, err = bitwiseOr(opTerm, leftValue, rightValue) - case SymCaretEqual: + case scan.SymCaretEqual: v, err = bitwiseXor(opTerm, leftValue, rightValue) - case SymDoubleLessEqual: + case scan.SymDoubleLessEqual: v, err = bitLeftShift(opTerm, leftValue, rightValue) - case SymDoubleGreaterEqual: + case scan.SymDoubleGreaterEqual: v, err = bitRightShift(opTerm, leftValue, rightValue) default: err = opTerm.Errorf("unsupported assign operator %q", opTerm.Source()) @@ -211,15 +212,15 @@ func evalOpAssign(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymEqual, newAssignTerm) - registerTermConstructor(SymPlusEqual, newOpAssignTerm) - registerTermConstructor(SymMinusEqual, newOpAssignTerm) - registerTermConstructor(SymStarEqual, newOpAssignTerm) - registerTermConstructor(SymSlashEqual, newOpAssignTerm) - registerTermConstructor(SymPercEqual, newOpAssignTerm) - registerTermConstructor(SymDoubleLessEqual, newOpAssignTerm) - registerTermConstructor(SymDoubleGreaterEqual, newOpAssignTerm) - registerTermConstructor(SymAmpersandEqual, newOpAssignTerm) - registerTermConstructor(SymVertBarEqual, newOpAssignTerm) - registerTermConstructor(SymCaretEqual, newOpAssignTerm) + scan.RegisterTermConstructor(scan.SymEqual, newAssignTerm) + scan.RegisterTermConstructor(scan.SymPlusEqual, newOpAssignTerm) + scan.RegisterTermConstructor(scan.SymMinusEqual, newOpAssignTerm) + scan.RegisterTermConstructor(scan.SymStarEqual, newOpAssignTerm) + scan.RegisterTermConstructor(scan.SymSlashEqual, newOpAssignTerm) + scan.RegisterTermConstructor(scan.SymPercEqual, newOpAssignTerm) + scan.RegisterTermConstructor(scan.SymDoubleLessEqual, newOpAssignTerm) + scan.RegisterTermConstructor(scan.SymDoubleGreaterEqual, newOpAssignTerm) + scan.RegisterTermConstructor(scan.SymAmpersandEqual, newOpAssignTerm) + scan.RegisterTermConstructor(scan.SymVertBarEqual, newOpAssignTerm) + scan.RegisterTermConstructor(scan.SymCaretEqual, newOpAssignTerm) } diff --git a/operator-bitwise.go b/operator-bitwise.go index a6bf828..71d08eb 100644 --- a/operator-bitwise.go +++ b/operator-bitwise.go @@ -6,24 +6,25 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- Bitwise NOT term -func newBitwiseNotTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 1), - position: posPrefix, - priority: priBitwiseNot, - evalFunc: evalBitwiseNot, +func newBitwiseNotTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPrefix, + Priority: scan.PriBitwiseNot, + EvalFunc: evalBitwiseNot, } } -func evalBitwiseNot(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalBitwiseNot(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var value any - if value, err = opTerm.evalPrefix(ctx); err != nil { + if value, err = opTerm.EvalPrefix(ctx); err != nil { return } @@ -31,24 +32,24 @@ func evalBitwiseNot(ctx kern.ExprContext, opTerm *term) (v any, err error) { i, _ := value.(int64) v = ^i } else { - err = opTerm.errIncompatiblePrefixPostfixType(value) + err = opTerm.ErrIncompatiblePrefixPostfixType(value) } return } //-------- Bitwise AND term -func newBitwiseAndTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priBitwiseAnd, - evalFunc: evalBitwiseAnd, +func newBitwiseAndTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriBitwiseAnd, + EvalFunc: evalBitwiseAnd, } } -func bitwiseAnd(opTerm *term, leftValue, rightValue any) (v any, err error) { +func bitwiseAnd(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) { var leftInt, rightInt int64 var lok, rok bool @@ -58,15 +59,15 @@ func bitwiseAnd(opTerm *term, leftValue, rightValue any) (v any, err error) { if lok && rok { v = leftInt & rightInt } else { - err = opTerm.errIncompatibleTypes(leftValue, rightValue) + err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } return } -func evalBitwiseAnd(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalBitwiseAnd(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } v, err = bitwiseAnd(opTerm, leftValue, rightValue) @@ -75,17 +76,17 @@ func evalBitwiseAnd(ctx kern.ExprContext, opTerm *term) (v any, err error) { //-------- Bitwise OR term -func newBitwiseOrTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priBitwiseOr, - evalFunc: evalBitwiseOr, +func newBitwiseOrTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriBitwiseOr, + EvalFunc: evalBitwiseOr, } } -func bitwiseOr(opTerm *term, leftValue, rightValue any) (v any, err error) { +func bitwiseOr(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) { var leftInt, rightInt int64 var lok, rok bool @@ -95,15 +96,15 @@ func bitwiseOr(opTerm *term, leftValue, rightValue any) (v any, err error) { if lok && rok { v = leftInt | rightInt } else { - err = opTerm.errIncompatibleTypes(leftValue, rightValue) + err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } return } -func evalBitwiseOr(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalBitwiseOr(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } @@ -113,17 +114,17 @@ func evalBitwiseOr(ctx kern.ExprContext, opTerm *term) (v any, err error) { //-------- Bitwise XOR term -func newBitwiseXorTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priBitwiseOr, - evalFunc: evalBitwiseXor, +func newBitwiseXorTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriBitwiseXor, + EvalFunc: evalBitwiseXor, } } -func bitwiseXor(opTerm *term, leftValue, rightValue any) (v any, err error) { +func bitwiseXor(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) { var leftInt, rightInt int64 var lok, rok bool @@ -133,15 +134,15 @@ func bitwiseXor(opTerm *term, leftValue, rightValue any) (v any, err error) { if lok && rok { v = leftInt ^ rightInt } else { - err = opTerm.errIncompatibleTypes(leftValue, rightValue) + err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } return } -func evalBitwiseXor(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalBitwiseXor(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } @@ -151,8 +152,8 @@ func evalBitwiseXor(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymTilde, newBitwiseNotTerm) - registerTermConstructor(SymAmpersand, newBitwiseAndTerm) - registerTermConstructor(SymVertBar, newBitwiseOrTerm) - registerTermConstructor(SymCaret, newBitwiseXorTerm) + scan.RegisterTermConstructor(scan.SymTilde, newBitwiseNotTerm) + scan.RegisterTermConstructor(scan.SymAmpersand, newBitwiseAndTerm) + scan.RegisterTermConstructor(scan.SymVertBar, newBitwiseOrTerm) + scan.RegisterTermConstructor(scan.SymCaret, newBitwiseXorTerm) } diff --git a/operator-bool.go b/operator-bool.go index 7a116bc..e4fd9b2 100644 --- a/operator-bool.go +++ b/operator-bool.go @@ -8,48 +8,49 @@ import ( "fmt" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- NOT term -func newNotTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 1), - position: posPrefix, - priority: priNot, - evalFunc: evalNot, +func newNotTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPrefix, + Priority: scan.PriNot, + EvalFunc: evalNot, } } -func evalNot(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalNot(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var rightValue any - if rightValue, err = opTerm.evalPrefix(ctx); err != nil { + if rightValue, err = opTerm.EvalPrefix(ctx); err != nil { return } if b, ok := kern.ToBool(rightValue); ok { v = !b } else { - err = opTerm.errIncompatiblePrefixPostfixType(rightValue) + err = opTerm.ErrIncompatiblePrefixPostfixType(rightValue) } return } //-------- AND term -func newAndTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priAnd, - evalFunc: evalAnd, +func newAndTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriAnd, + EvalFunc: evalAnd, } } -func evalAnd(ctx kern.ExprContext, self *term) (v any, err error) { +func evalAnd(ctx kern.ExprContext, self *scan.Term) (v any, err error) { if kern.CtrlIsEnabled(ctx, kern.ControlBoolShortcut) { v, err = evalAndWithShortcut(ctx, self) } else { @@ -58,12 +59,12 @@ func evalAnd(ctx kern.ExprContext, self *term) (v any, err error) { return } -func evalAndWithoutShortcut(ctx kern.ExprContext, self *term) (v any, err error) { +func evalAndWithoutShortcut(ctx kern.ExprContext, self *scan.Term) (v any, err error) { var leftValue, rightValue any var leftBool, rightBool bool var lok, rok bool - if leftValue, rightValue, err = self.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = self.EvalInfix(ctx); err != nil { return } @@ -73,33 +74,33 @@ func evalAndWithoutShortcut(ctx kern.ExprContext, self *term) (v any, err error) if lok && rok { v = leftBool && rightBool } else { - err = self.errIncompatibleTypes(leftValue, rightValue) + err = self.ErrIncompatibleTypes(leftValue, rightValue) } return } -func evalAndWithShortcut(ctx kern.ExprContext, self *term) (v any, err error) { +func evalAndWithShortcut(ctx kern.ExprContext, self *scan.Term) (v any, err error) { var leftValue, rightValue any - if err = self.checkOperands(); err != nil { + if err = self.CheckOperands(); err != nil { return } - if leftValue, err = self.children[0].Compute(ctx); err != nil { + if leftValue, err = self.Children[0].Compute(ctx); err != nil { return } if leftBool, lok := kern.ToBool(leftValue); !lok { // err = fmt.Errorf("got %s as left operand type of 'AND' operator, it must be bool", expr.TypeName(leftValue)) // return - err = self.errIncompatibleType(leftValue, "left") + err = self.ErrIncompatibleType(leftValue, "left") } else if !leftBool { v = false - } else if rightValue, err = self.children[1].Compute(ctx); err == nil { + } else if rightValue, err = self.Children[1].Compute(ctx); err == nil { if rightBool, rok := kern.ToBool(rightValue); rok { v = rightBool } else { - err = self.errIncompatibleTypes(leftValue, rightValue) + err = self.ErrIncompatibleTypes(leftValue, rightValue) } } return @@ -107,17 +108,17 @@ func evalAndWithShortcut(ctx kern.ExprContext, self *term) (v any, err error) { //-------- OR term -func newOrTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priOr, - evalFunc: evalOr, +func newOrTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriOr, + EvalFunc: evalOr, } } -func evalOr(ctx kern.ExprContext, self *term) (v any, err error) { +func evalOr(ctx kern.ExprContext, self *scan.Term) (v any, err error) { if kern.CtrlIsEnabled(ctx, kern.ControlBoolShortcut) { v, err = evalOrWithShortcut(ctx, self) } else { @@ -126,12 +127,12 @@ func evalOr(ctx kern.ExprContext, self *term) (v any, err error) { return } -func evalOrWithoutShortcut(ctx kern.ExprContext, self *term) (v any, err error) { +func evalOrWithoutShortcut(ctx kern.ExprContext, self *scan.Term) (v any, err error) { var leftValue, rightValue any var leftBool, rightBool bool var lok, rok bool - if leftValue, rightValue, err = self.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = self.EvalInfix(ctx); err != nil { return } @@ -141,19 +142,19 @@ func evalOrWithoutShortcut(ctx kern.ExprContext, self *term) (v any, err error) if lok && rok { v = leftBool || rightBool } else { - err = self.errIncompatibleTypes(leftValue, rightValue) + err = self.ErrIncompatibleTypes(leftValue, rightValue) } return } -func evalOrWithShortcut(ctx kern.ExprContext, self *term) (v any, err error) { +func evalOrWithShortcut(ctx kern.ExprContext, self *scan.Term) (v any, err error) { var leftValue, rightValue any - if err = self.checkOperands(); err != nil { + if err = self.CheckOperands(); err != nil { return } - if leftValue, err = self.children[0].Compute(ctx); err != nil { + if leftValue, err = self.Children[0].Compute(ctx); err != nil { return } @@ -162,11 +163,11 @@ func evalOrWithShortcut(ctx kern.ExprContext, self *term) (v any, err error) { return } else if leftBool { v = true - } else if rightValue, err = self.children[1].Compute(ctx); err == nil { + } else if rightValue, err = self.Children[1].Compute(ctx); err == nil { if rightBool, rok := kern.ToBool(rightValue); rok { v = rightBool } else { - err = self.errIncompatibleTypes(leftValue, rightValue) + err = self.ErrIncompatibleTypes(leftValue, rightValue) } } return @@ -174,7 +175,7 @@ func evalOrWithShortcut(ctx kern.ExprContext, self *term) (v any, err error) { // init func init() { - registerTermConstructor(SymNot, newNotTerm) - registerTermConstructor(SymAnd, newAndTerm) - registerTermConstructor(SymOr, newOrTerm) + scan.RegisterTermConstructor(scan.SymNot, newNotTerm) + scan.RegisterTermConstructor(scan.SymAnd, newAndTerm) + scan.RegisterTermConstructor(scan.SymOr, newOrTerm) } diff --git a/operator-builtin.go b/operator-builtin.go index 44631c8..2dc6057 100644 --- a/operator-builtin.go +++ b/operator-builtin.go @@ -8,24 +8,25 @@ import ( "io" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- builtin term -func newBuiltinTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 1), - position: posPrefix, - priority: priSign, - evalFunc: evalBuiltin, +func newBuiltinTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPrefix, + Priority: scan.PriSign, + EvalFunc: evalBuiltin, } } -func evalBuiltin(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalBuiltin(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var childValue any - if childValue, err = opTerm.evalPrefix(ctx); err != nil { + if childValue, err = opTerm.EvalPrefix(ctx); err != nil { return } @@ -64,5 +65,5 @@ func evalBuiltin(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymKwBuiltin, newBuiltinTerm) + scan.RegisterTermConstructor(scan.SymKwBuiltin, newBuiltinTerm) } diff --git a/operator-but.go b/operator-but.go index 92daf86..2997fc3 100644 --- a/operator-but.go +++ b/operator-but.go @@ -6,26 +6,27 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- but term -func newButTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priBut, - evalFunc: evalBut, +func newButTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriBut, + EvalFunc: evalBut, } } -func evalBut(ctx kern.ExprContext, opTerm *term) (v any, err error) { - _, v, err = opTerm.evalInfix(ctx) +func evalBut(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { + _, v, err = opTerm.EvalInfix(ctx) return } // init func init() { - registerTermConstructor(SymKwBut, newButTerm) + scan.RegisterTermConstructor(scan.SymKwBut, newButTerm) } diff --git a/operator-context.go b/operator-context.go index c4d5df8..120eeb1 100644 --- a/operator-context.go +++ b/operator-context.go @@ -6,29 +6,30 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- context term -func newContextTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 1), - position: posPrefix, - priority: priIncDec, - evalFunc: evalContextValue, +func newContextTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPrefix, + Priority: scan.PriIncDec, + EvalFunc: evalContextValue, } } -func evalContextValue(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalContextValue(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var childValue any var sourceCtx kern.ExprContext - if len(opTerm.children) == 0 { + if len(opTerm.Children) == 0 { sourceCtx = ctx - } else if opTerm.children[0].symbol() == SymVariable && opTerm.children[0].Source() == "global" { + } else if opTerm.Children[0].Symbol() == scan.SymVariable && opTerm.Children[0].Source() == "global" { sourceCtx = ctx.GetGlobal() - } else if childValue, err = opTerm.evalPrefix(ctx); err == nil { + } else if childValue, err = opTerm.EvalPrefix(ctx); err == nil { if dc, ok := childValue.(*dataCursor); ok { sourceCtx = dc.ctx } @@ -53,12 +54,12 @@ func evalContextValue(ctx kern.ExprContext, opTerm *term) (v any, err error) { v = d } } else { - err = opTerm.errIncompatiblePrefixPostfixType(childValue) + err = opTerm.ErrIncompatiblePrefixPostfixType(childValue) } return } // init func init() { - registerTermConstructor(SymDoubleDollar, newContextTerm) + scan.RegisterTermConstructor(scan.SymDoubleDollar, newContextTerm) } diff --git a/operator-ctrl.go b/operator-ctrl.go index 04ce944..e25e74e 100644 --- a/operator-ctrl.go +++ b/operator-ctrl.go @@ -6,26 +6,27 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- export all term -func newExportAllTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: nil, - position: posLeaf, - priority: priValue, - evalFunc: evalExportAll, +func newExportAllTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: nil, + Position: scan.PosLeaf, + Priority: scan.PriValue, + EvalFunc: evalExportAll, } } -func evalExportAll(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalExportAll(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { CtrlEnable(ctx, kern.ControlExportAll) return } // init func init() { - registerTermConstructor(SymDoubleAt, newExportAllTerm) + scan.RegisterTermConstructor(scan.SymDoubleAt, newExportAllTerm) } diff --git a/operator-default.go b/operator-default.go index 730a4fa..e6a7cc3 100644 --- a/operator-default.go +++ b/operator-default.go @@ -6,29 +6,30 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- default term -func newDefaultTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priDefault, - evalFunc: evalDefault, +func newDefaultTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriDefault, + EvalFunc: evalDefault, } } -func evalDefault(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalDefault(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var rightValue any - if err = opTerm.checkOperands(); err != nil { + if err = opTerm.CheckOperands(); err != nil { return } - leftTerm := opTerm.children[0] - if leftTerm.tk.Sym != SymVariable { + leftTerm := opTerm.Children[0] + if leftTerm.Tk.Sym != scan.SymVariable { // err = leftTerm.Errorf("left operand of %q must be a variable", self.tk.source) err = kern.ErrLeftOperandMustBeVariable(leftTerm, opTerm) return @@ -36,7 +37,7 @@ func evalDefault(ctx kern.ExprContext, opTerm *term) (v any, err error) { if leftValue, exists := ctx.GetVar(leftTerm.Source()); exists { v = leftValue - } else if rightValue, err = opTerm.children[1].Compute(ctx); err == nil { + } else if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil { v = rightValue } return @@ -44,32 +45,32 @@ func evalDefault(ctx kern.ExprContext, opTerm *term) (v any, err error) { //-------- alternate term -func newAlternateTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priDefault, - evalFunc: evalAlternate, +func newAlternateTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriDefault, + EvalFunc: evalAlternate, } } -func evalAlternate(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalAlternate(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var rightValue any - if err = opTerm.checkOperands(); err != nil { + if err = opTerm.CheckOperands(); err != nil { return } - leftTerm := opTerm.children[0] - if leftTerm.tk.Sym != SymVariable { + leftTerm := opTerm.Children[0] + if leftTerm.Tk.Sym != scan.SymVariable { // err = leftTerm.Errorf("left operand of %q must be a variable", self.tk.source) err = kern.ErrLeftOperandMustBeVariable(leftTerm, opTerm) return } if leftValue, exists := ctx.GetVar(leftTerm.Source()); exists && leftValue != nil { - if rightValue, err = opTerm.children[1].Compute(ctx); err == nil { + if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil { v = rightValue } } else { @@ -80,25 +81,25 @@ func evalAlternate(ctx kern.ExprContext, opTerm *term) (v any, err error) { //-------- default assign term -func newDefaultAssignTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priDefault, - evalFunc: evalAssignDefault, +func newDefaultAssignTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriDefault, + EvalFunc: evalAssignDefault, } } -func evalAssignDefault(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalAssignDefault(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var rightValue any - if err = opTerm.checkOperands(); err != nil { + if err = opTerm.CheckOperands(); err != nil { return } - leftTerm := opTerm.children[0] - if leftTerm.tk.Sym != SymVariable { + leftTerm := opTerm.Children[0] + if leftTerm.Tk.Sym != scan.SymVariable { // err = leftTerm.Errorf("left operand of %q must be a variable", self.tk.source) err = kern.ErrLeftOperandMustBeVariable(leftTerm, opTerm) return @@ -106,7 +107,7 @@ func evalAssignDefault(ctx kern.ExprContext, opTerm *term) (v any, err error) { if leftValue, exists := ctx.GetVar(leftTerm.Source()); exists { v = leftValue - } else if rightValue, err = opTerm.children[1].Compute(ctx); err == nil { + } else if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil { if functor, ok := rightValue.(kern.Functor); ok { //ctx.RegisterFunc(leftTerm.source(), functor, 0, -1) ctx.RegisterFunc(leftTerm.Source(), functor, kern.TypeAny, []kern.ExprFuncParam{ @@ -122,7 +123,7 @@ func evalAssignDefault(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymDoubleQuestion, newDefaultTerm) - registerTermConstructor(SymQuestionEqual, newDefaultAssignTerm) - registerTermConstructor(SymQuestionExclam, newAlternateTerm) + scan.RegisterTermConstructor(scan.SymDoubleQuestion, newDefaultTerm) + scan.RegisterTermConstructor(scan.SymQuestionEqual, newDefaultAssignTerm) + scan.RegisterTermConstructor(scan.SymQuestionExclam, newAlternateTerm) } diff --git a/operator-digest.go b/operator-digest.go index 5ac9e88..402853c 100644 --- a/operator-digest.go +++ b/operator-digest.go @@ -9,30 +9,31 @@ import ( "io" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- digest term -func newDigestTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priIterOp, - evalFunc: evalDigest, +func newDigestTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriIterOp, + EvalFunc: evalDigest, } } -func evalDigest(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalDigest(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any var it kern.Iterator var item, lastValue any - if err = opTerm.checkOperands(); err != nil { + if err = opTerm.CheckOperands(); err != nil { return } - if leftValue, err = opTerm.children[0].Compute(ctx); err != nil { + if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil { return } @@ -45,7 +46,7 @@ func evalDigest(ctx kern.ExprContext, opTerm *term) (v any, err error) { ctx.SetVar("_", item) ctx.SetVar("__", it.Index()) ctx.SetVar("_#", it.Count()) - if rightValue, err = opTerm.children[1].Compute(ctx); err == nil { + if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil { if rightValue == nil { break } else { @@ -68,5 +69,5 @@ func evalDigest(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymKwDigest, newDigestTerm) + scan.RegisterTermConstructor(scan.SymKwDigest, newDigestTerm) } diff --git a/operator-dot.go b/operator-dot.go index b87d6ad..c64cb13 100644 --- a/operator-dot.go +++ b/operator-dot.go @@ -6,34 +6,35 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) // -------- dot term -func newDotTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priDot, - evalFunc: evalDot, +func newDotTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriDot, + EvalFunc: evalDot, } } -func evalDot(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalDot(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if err = opTerm.checkOperands(); err != nil { + if err = opTerm.CheckOperands(); err != nil { return } - if leftValue, err = opTerm.children[0].Compute(ctx); err != nil { + if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil { return } - indexTerm := opTerm.children[1] + indexTerm := opTerm.Children[1] switch unboxedValue := leftValue.(type) { case kern.ExtIterator: - if indexTerm.symbol() == SymVariable /*|| indexTerm.symbol() == SymString */ { + if indexTerm.Tk.Sym == scan.SymVariable /*|| indexTerm.Tk.Sym == scan.SymString */ { opName := indexTerm.Source() if unboxedValue.HasOperation(opName) { v, err = unboxedValue.CallOperation(opName, map[string]any{}) @@ -42,27 +43,27 @@ func evalDot(ctx kern.ExprContext, opTerm *term) (v any, err error) { v = false } } else { - err = indexTerm.tk.ErrorExpectedGot("identifier") + err = indexTerm.Tk.ErrorExpectedGot("identifier") } case *kern.DictType: var ok bool - s := opTerm.children[1].symbol() - if s == SymVariable || s == SymString { - src := opTerm.children[1].Source() + s := opTerm.Children[1].Tk.Sym + if s == scan.SymVariable || s == scan.SymString { + src := opTerm.Children[1].Source() if len(src) > 1 && src[0] == '"' && src[len(src)-1] == '"' { src = src[1 : len(src)-1] } if v, ok = unboxedValue.GetItem(src); !ok { - err = opTerm.errKeyNotFound(src) + err = opTerm.Errorf("key %q not found", src) } - } else if rightValue, err = opTerm.children[1].Compute(ctx); err == nil { + } else if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil { if v, ok = unboxedValue.GetItem(rightValue); !ok { - err = opTerm.errKeyNotFound(rightValue) + err = opTerm.Errorf("key %q not found", rightValue) } } default: - if rightValue, err = opTerm.children[1].Compute(ctx); err == nil { - err = opTerm.errIncompatibleTypes(leftValue, rightValue) + if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil { + err = opTerm.Errorf("incompatible types: %s and %s", kern.TypeName(leftValue), kern.TypeName(rightValue)) } } return @@ -70,5 +71,5 @@ func evalDot(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymDot, newDotTerm) + scan.RegisterTermConstructor(scan.SymDot, newDotTerm) } diff --git a/operator-fact.go b/operator-fact.go index 1d37603..19c716a 100644 --- a/operator-fact.go +++ b/operator-fact.go @@ -8,24 +8,25 @@ import ( "fmt" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- fact term -func newFactTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 1), - position: posPostfix, - priority: priFact, - evalFunc: evalFact, +func newFactTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPostfix, + Priority: scan.PriFact, + EvalFunc: evalFact, } } -func evalFact(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalFact(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue any - if leftValue, err = opTerm.evalPrefix(ctx); err != nil { + if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil { return } @@ -40,12 +41,12 @@ func evalFact(ctx kern.ExprContext, opTerm *term) (v any, err error) { err = fmt.Errorf("factorial of a negative integer (%d) is not allowed", i) } } else { - err = opTerm.errIncompatiblePrefixPostfixType(leftValue) + err = opTerm.Errorf("incompatible type for factorial: %s", kern.TypeName(leftValue)) } return } // init func init() { - registerTermConstructor(SymExclamation, newFactTerm) + scan.RegisterTermConstructor(scan.SymExclamation, newFactTerm) } diff --git a/operator-filter.go b/operator-filter.go index 875aaa9..cd6daec 100644 --- a/operator-filter.go +++ b/operator-filter.go @@ -9,30 +9,31 @@ import ( "io" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- map term -func newFilterTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priIterOp, - evalFunc: evalFilter, +func newFilterTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriIterOp, + EvalFunc: evalFilter, } } -func evalFilter(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalFilter(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any var it kern.Iterator var item any - if err = opTerm.checkOperands(); err != nil { + if err = opTerm.CheckOperands(); err != nil { return } - if leftValue, err = opTerm.children[0].Compute(ctx); err != nil { + if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil { return } @@ -45,7 +46,7 @@ func evalFilter(ctx kern.ExprContext, opTerm *term) (v any, err error) { ctx.SetVar("_", item) ctx.SetVar("__", it.Index()) ctx.SetVar("_#", it.Count()) - if rightValue, err = opTerm.children[1].Compute(ctx); err == nil { + if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil { if success, valid := kern.ToBool(rightValue); valid { if success { values.AppendItem(item) @@ -70,5 +71,5 @@ func evalFilter(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymKwFilter, newFilterTerm) + scan.RegisterTermConstructor(scan.SymKwFilter, newFilterTerm) } diff --git a/operator-fraction.go b/operator-fraction.go index 9fc3e09..dc8a5ee 100644 --- a/operator-fraction.go +++ b/operator-fraction.go @@ -10,27 +10,27 @@ import ( "fmt" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) // -------- fraction term -func newFractionTerm(tk *Token) *term { - return &term{ - tk: *tk, - parent: nil, - children: make([]*term, 0, 2), - position: posInfix, - priority: priFraction, - evalFunc: evalFraction, +func newFractionTerm(tk *scan.Token) *scan.Term { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriFraction, + EvalFunc: evalFraction, } } // -------- eval func -func evalFraction(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalFraction(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var numValue, denValue any var num, den int64 var ok bool - if numValue, denValue, err = opTerm.evalInfix(ctx); err != nil { + if numValue, denValue, err = opTerm.EvalInfix(ctx); err != nil { return } if num, ok = numValue.(int64); !ok { @@ -42,7 +42,7 @@ func evalFraction(ctx kern.ExprContext, opTerm *term) (v any, err error) { return } if den == 0 { - err = opTerm.errDivisionByZero() + err = opTerm.Errorf("division by zero") return } @@ -71,5 +71,5 @@ func evalFraction(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { // registerTermConstructor(SymVertBar, newFractionTerm) - registerTermConstructor(SymColon, newFractionTerm) + scan.RegisterTermConstructor(scan.SymColon, newFractionTerm) } diff --git a/operator-groupby.go b/operator-groupby.go index 3537b05..9323b87 100644 --- a/operator-groupby.go +++ b/operator-groupby.go @@ -10,32 +10,33 @@ import ( "strconv" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- group by term -func newGroupByTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priIterOp, - evalFunc: evalGroupBy, +func newGroupByTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriIterOp, + EvalFunc: evalGroupBy, } } -func evalGroupBy(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalGroupBy(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any var it kern.Iterator var item any var sKey string var keyByIndex bool - if err = opTerm.checkOperands(); err != nil { + if err = opTerm.CheckOperands(); err != nil { return } - if leftValue, err = opTerm.children[0].Compute(ctx); err != nil { + if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil { return } @@ -43,10 +44,10 @@ func evalGroupBy(ctx kern.ExprContext, opTerm *term) (v any, err error) { return nil, fmt.Errorf("left operand of MAP must be an iterable data-source; got %s", kern.TypeName(leftValue)) } - rightTk := opTerm.children[1].tk - if rightTk.IsSymbol(SymVariable) && rightTk.source == "__" { + rightTk := opTerm.Children[1].Tk + if rightTk.IsSymbol(scan.SymVariable) && rightTk.Source() == "__" { keyByIndex = true - } else if rightValue, err = opTerm.children[1].Compute(ctx); err != nil { + } else if rightValue, err = opTerm.Children[1].Compute(ctx); err != nil { return } else if kern.IsString(rightValue) { sKey = rightValue.(string) @@ -101,5 +102,5 @@ func evalGroupBy(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymKwGroupBy, newGroupByTerm) + scan.RegisterTermConstructor(scan.SymKwGroupBy, newGroupByTerm) } diff --git a/operator-in.go b/operator-in.go index cfb2cff..06f7919 100644 --- a/operator-in.go +++ b/operator-in.go @@ -6,17 +6,18 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- in term -func newInTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priRelational, - evalFunc: evalIn, +func newInTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriRelational, + EvalFunc: evalIn, } } @@ -25,10 +26,10 @@ func newInTerm(tk *Token) (inst *term) { // return // } -func evalIn(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalIn(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } @@ -39,12 +40,12 @@ func evalIn(ctx kern.ExprContext, opTerm *term) (v any, err error) { dict, _ := rightValue.(*kern.DictType) v = dict.HasKey(leftValue) } else { - err = opTerm.errIncompatibleTypes(leftValue, rightValue) + err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } return } // init func init() { - registerTermConstructor(SymKwIn, newInTerm) + scan.RegisterTermConstructor(scan.SymKwIn, newInTerm) } diff --git a/operator-include.go b/operator-include.go index 6a4f174..d9ded2b 100644 --- a/operator-include.go +++ b/operator-include.go @@ -6,24 +6,25 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- include term -func newIncludeTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 1), - position: posPrefix, - priority: priSign, - evalFunc: evalInclude, +func newIncludeTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPrefix, + Priority: scan.PriSign, + EvalFunc: evalInclude, } } -func evalInclude(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalInclude(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var childValue any - if childValue, err = opTerm.evalPrefix(ctx); err != nil { + if childValue, err = opTerm.EvalPrefix(ctx); err != nil { return } @@ -49,7 +50,7 @@ func evalInclude(ctx kern.ExprContext, opTerm *term) (v any, err error) { count++ } } else { - err = opTerm.errIncompatiblePrefixPostfixType(childValue) + err = opTerm.ErrIncompatiblePrefixPostfixType(childValue) } if err != nil { //v = count @@ -60,5 +61,5 @@ func evalInclude(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymKwInclude, newIncludeTerm) + scan.RegisterTermConstructor(scan.SymKwInclude, newIncludeTerm) } diff --git a/operator-index.go b/operator-index.go index e3d853f..eb007ac 100644 --- a/operator-index.go +++ b/operator-index.go @@ -6,16 +6,17 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) // -------- index term -func newIndexTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priDot, - evalFunc: evalIndex, +func newIndexTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriDot, + EvalFunc: evalIndex, } } @@ -24,7 +25,7 @@ func verifyKey(indexList *kern.ListType) (index any, err error) { return } -func verifyIndex(indexTerm *term, indexList *kern.ListType, maxValue int) (index int, err error) { +func verifyIndex(indexTerm *scan.Term, indexList *kern.ListType, maxValue int) (index int, err error) { var v int if v, err = kern.ToGoInt((*indexList)[0], "index expression"); err == nil { @@ -40,7 +41,7 @@ func verifyIndex(indexTerm *term, indexList *kern.ListType, maxValue int) (index return } -func verifyRange(indexTerm *term, indexList *kern.ListType, maxValue int) (startIndex, endIndex int, err error) { +func verifyRange(indexTerm *scan.Term, indexList *kern.ListType, maxValue int) (startIndex, endIndex int, err error) { v, _ := ((*indexList)[0]).(*intPair) startIndex = v.a endIndex = v.b @@ -63,16 +64,16 @@ func verifyRange(indexTerm *term, indexList *kern.ListType, maxValue int) (start return } -func evalIndex(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any var indexList *kern.ListType var ok bool - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } - indexTerm := opTerm.children[1] + indexTerm := opTerm.Children[1] if indexList, ok = rightValue.(*kern.ListType); !ok { err = opTerm.Errorf("invalid index expression") return @@ -96,7 +97,7 @@ func evalIndex(ctx kern.ExprContext, opTerm *term) (v any, err error) { case *kern.DictType: v, err = getDictItem(unboxedValue, indexTerm, indexList, rightValue) default: - err = opTerm.errIncompatibleTypes(leftValue, rightValue) + err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } } else if isIntPair((*indexList)[0]) { switch unboxedValue := leftValue.(type) { @@ -112,19 +113,19 @@ func evalIndex(ctx kern.ExprContext, opTerm *term) (v any, err error) { v = unboxedValue[start:end] } default: - err = opTerm.errIncompatibleTypes(leftValue, rightValue) + err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } } else if kern.IsDict(leftValue) { d := leftValue.(*kern.DictType) v, err = getDictItem(d, indexTerm, indexList, rightValue) } else { - rightChild := opTerm.children[1] + rightChild := opTerm.Children[1] err = rightChild.Errorf("invalid index type: %v", (*indexList)[0]) } return } -func getDictItem(d *kern.DictType, indexTerm *term, indexList *kern.ListType, rightValue any) (v any, err error) { +func getDictItem(d *kern.DictType, indexTerm *scan.Term, indexList *kern.ListType, rightValue any) (v any, err error) { var ok bool var indexValue any @@ -138,5 +139,5 @@ func getDictItem(d *kern.DictType, indexTerm *term, indexList *kern.ListType, ri // init func init() { - registerTermConstructor(SymIndex, newIndexTerm) + scan.RegisterTermConstructor(scan.SymIndex, newIndexTerm) } diff --git a/operator-insert.go b/operator-insert.go index 7ae3b2e..16db494 100644 --- a/operator-insert.go +++ b/operator-insert.go @@ -6,34 +6,35 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- prepend term -func newPrependTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priInsert, - evalFunc: evalPrepend, +func newPrependTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriInsert, + EvalFunc: evalPrepend, } } -func newAppendTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priInsert, - evalFunc: evalAppend, +func newAppendTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriInsert, + EvalFunc: evalAppend, } } -func evalPrepend(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalPrepend(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } @@ -41,19 +42,19 @@ func evalPrepend(ctx kern.ExprContext, opTerm *term) (v any, err error) { list, _ := rightValue.(*kern.ListType) newList := append(kern.ListType{leftValue}, *list...) v = &newList - if opTerm.children[1].symbol() == SymVariable { - ctx.UnsafeSetVar(opTerm.children[1].Source(), v) + if opTerm.Children[1].Symbol() == scan.SymVariable { + ctx.UnsafeSetVar(opTerm.Children[1].Source(), v) } } else { - err = opTerm.errIncompatibleTypes(leftValue, rightValue) + err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } return } -func evalAppend(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalAppend(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } @@ -61,11 +62,11 @@ func evalAppend(ctx kern.ExprContext, opTerm *term) (v any, err error) { list, _ := leftValue.(*kern.ListType) newList := append(*list, rightValue) v = &newList - if opTerm.children[0].symbol() == SymVariable { - ctx.UnsafeSetVar(opTerm.children[0].Source(), v) + if opTerm.Children[0].Symbol() == scan.SymVariable { + ctx.UnsafeSetVar(opTerm.Children[0].Source(), v) } } else { - err = opTerm.errIncompatibleTypes(leftValue, rightValue) + err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } return } @@ -90,6 +91,6 @@ func evalAppend(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymPlusGreater, newPrependTerm) - registerTermConstructor(SymLessPlus, newAppendTerm) + scan.RegisterTermConstructor(scan.SymPlusGreater, newPrependTerm) + scan.RegisterTermConstructor(scan.SymLessPlus, newAppendTerm) } diff --git a/operator-iter-value.go b/operator-iter-value.go index efda21c..1b42608 100644 --- a/operator-iter-value.go +++ b/operator-iter-value.go @@ -6,31 +6,32 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- iter value term -func newIterValueTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 1), - position: posPrefix, - priority: priDereference, - evalFunc: evalIterValue, +func newIterValueTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPrefix, + Priority: scan.PriDereference, + EvalFunc: evalIterValue, } } -func evalIterValue(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalIterValue(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var childValue any - if childValue, err = opTerm.evalPrefix(ctx); err != nil { + if childValue, err = opTerm.EvalPrefix(ctx); err != nil { return } if it, ok := childValue.(kern.Iterator); ok { v, err = it.Current() } else { - err = opTerm.errIncompatiblePrefixPostfixType(childValue) + err = opTerm.ErrIncompatiblePrefixPostfixType(childValue) } return } @@ -38,5 +39,5 @@ func evalIterValue(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { // registerTermConstructor(SymOpenClosedRound, newIterValueTerm) - registerTermConstructor(SymDereference, newIterValueTerm) + scan.RegisterTermConstructor(scan.SymDereference, newIterValueTerm) } diff --git a/operator-join.go b/operator-join.go index 33df15c..c7af63f 100644 --- a/operator-join.go +++ b/operator-join.go @@ -9,34 +9,35 @@ import ( "io" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- join term -func newJoinTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priIterOp, - evalFunc: evalJoin, +func newJoinTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriIterOp, + EvalFunc: evalJoin, } } -func evalJoin(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalJoin(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any var itLeft, itRight kern.Iterator var item any - if err = opTerm.checkOperands(); err != nil { + if err = opTerm.CheckOperands(); err != nil { return } - if leftValue, err = opTerm.children[0].Compute(ctx); err != nil { + if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil { return } - if rightValue, err = opTerm.children[1].Compute(ctx); err != nil { + if rightValue, err = opTerm.Children[1].Compute(ctx); err != nil { return } @@ -63,5 +64,5 @@ func evalJoin(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymKwJoin, newJoinTerm) + scan.RegisterTermConstructor(scan.SymKwJoin, newJoinTerm) } diff --git a/operator-length.go b/operator-length.go index 79a5321..cc6914c 100644 --- a/operator-length.go +++ b/operator-length.go @@ -6,24 +6,25 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- length term -func newLengthTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 1), - position: posPrefix, - priority: priSign, - evalFunc: evalLength, +func newLengthTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPrefix, + Priority: scan.PriSign, + EvalFunc: evalLength, } } -func evalLength(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalLength(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var childValue any - if childValue, err = opTerm.evalPrefix(ctx); err != nil { + if childValue, err = opTerm.EvalPrefix(ctx); err != nil { return } @@ -45,12 +46,12 @@ func evalLength(ctx kern.ExprContext, opTerm *term) (v any, err error) { // v = int64(it.Index() + 1) // } } else { - err = opTerm.errIncompatiblePrefixPostfixType(childValue) + err = opTerm.ErrIncompatiblePrefixPostfixType(childValue) } return } // init func init() { - registerTermConstructor(SymHash, newLengthTerm) + scan.RegisterTermConstructor(scan.SymHash, newLengthTerm) } diff --git a/operator-map.go b/operator-map.go index 7f38cd7..65ef742 100644 --- a/operator-map.go +++ b/operator-map.go @@ -9,30 +9,31 @@ import ( "io" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- map term -func newMapTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priIterOp, - evalFunc: evalMap, +func newMapTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriIterOp, + EvalFunc: evalMap, } } -func evalMap(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalMap(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any var it kern.Iterator var item any - if err = opTerm.checkOperands(); err != nil { + if err = opTerm.CheckOperands(); err != nil { return } - if leftValue, err = opTerm.children[0].Compute(ctx); err != nil { + if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil { return } @@ -45,7 +46,7 @@ func evalMap(ctx kern.ExprContext, opTerm *term) (v any, err error) { ctx.SetVar("_", item) ctx.SetVar("__", it.Index()) ctx.SetVar("_#", it.Count()) - if rightValue, err = opTerm.children[1].Compute(ctx); err == nil { + if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil { values.AppendItem(rightValue) } ctx.DeleteVar("_#") @@ -66,5 +67,5 @@ func evalMap(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymKwMap, newMapTerm) + scan.RegisterTermConstructor(scan.SymKwMap, newMapTerm) } diff --git a/operator-plugin.go b/operator-plugin.go index af4049e..aff3df9 100644 --- a/operator-plugin.go +++ b/operator-plugin.go @@ -6,25 +6,26 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- plugin term -func newPluginTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 1), - position: posPrefix, - priority: priSign, - evalFunc: evalPlugin, +func newPluginTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPrefix, + Priority: scan.PriSign, + EvalFunc: evalPlugin, } } -func evalPlugin(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalPlugin(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var childValue any var count int - if childValue, err = opTerm.evalPrefix(ctx); err != nil { + if childValue, err = opTerm.EvalPrefix(ctx); err != nil { return } @@ -36,5 +37,5 @@ func evalPlugin(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymKwPlugin, newPluginTerm) + scan.RegisterTermConstructor(scan.SymKwPlugin, newPluginTerm) } diff --git a/operator-post-inc-dec.go b/operator-post-inc-dec.go index 0768b37..a50dbd5 100644 --- a/operator-post-inc-dec.go +++ b/operator-post-inc-dec.go @@ -6,24 +6,24 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) // -------- post increment term -func newPostIncTerm(tk *Token) *term { - return &term{ - tk: *tk, - parent: nil, - children: make([]*term, 0, 1), - position: posPostfix, - priority: priIncDec, - evalFunc: evalPostInc, +func newPostIncTerm(tk *scan.Token) *scan.Term { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPostfix, + Priority: scan.PriIncDec, + EvalFunc: evalPostInc, } } -func evalPostInc(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalPostInc(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var childValue any - if childValue, err = opTerm.evalPrefix(ctx); err != nil { + if childValue, err = opTerm.EvalPrefix(ctx); err != nil { return } @@ -31,8 +31,8 @@ func evalPostInc(ctx kern.ExprContext, opTerm *term) (v any, err error) { var namePrefix string v, err = it.Next() - if opTerm.children[0].symbol() == SymVariable { - namePrefix = opTerm.children[0].Source() + if opTerm.Children[0].Symbol() == scan.SymVariable { + namePrefix = opTerm.Children[0].Source() } ctx.UnsafeSetVar(namePrefix+"_index", it.Index()) if c, err1 := it.Current(); err1 == nil { @@ -49,49 +49,48 @@ func evalPostInc(ctx kern.ExprContext, opTerm *term) (v any, err error) { ctx.UnsafeSetVar(namePrefix+"_value", v1) } } - } else if kern.IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable { + } else if kern.IsInteger(childValue) && opTerm.Children[0].Symbol() == scan.SymVariable { v = childValue i, _ := childValue.(int64) - ctx.SetVar(opTerm.children[0].Source(), i+1) + ctx.SetVar(opTerm.Children[0].Source(), i+1) } else { - err = opTerm.errIncompatiblePrefixPostfixType(childValue) + err = opTerm.ErrIncompatiblePrefixPostfixType(childValue) } return } // -------- post decrement term -func newPostDecTerm(tk *Token) *term { - return &term{ - tk: *tk, - parent: nil, - children: make([]*term, 0, 1), - position: posPostfix, - priority: priIncDec, - evalFunc: evalPostDec, +func newPostDecTerm(tk *scan.Token) *scan.Term { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPostfix, + Priority: scan.PriIncDec, + EvalFunc: evalPostDec, } } -func evalPostDec(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalPostDec(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var childValue any - if childValue, err = opTerm.evalPrefix(ctx); err != nil { + if childValue, err = opTerm.EvalPrefix(ctx); err != nil { return } /* if it, ok := childValue.(Iterator); ok { v, err = it.Next() - } else */if kern.IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable { + } else */if kern.IsInteger(childValue) && opTerm.Children[0].Symbol() == scan.SymVariable { v = childValue i, _ := childValue.(int64) - ctx.SetVar(opTerm.children[0].Source(), i-1) + ctx.SetVar(opTerm.Children[0].Source(), i-1) } else { - err = opTerm.errIncompatiblePrefixPostfixType(childValue) + err = opTerm.ErrIncompatiblePrefixPostfixType(childValue) } return } // init func init() { - registerTermConstructor(SymDoublePlus, newPostIncTerm) - registerTermConstructor(SymDoubleMinus, newPostDecTerm) + scan.RegisterTermConstructor(scan.SymDoublePlus, newPostIncTerm) + scan.RegisterTermConstructor(scan.SymDoubleMinus, newPostDecTerm) } diff --git a/operator-pre-inc-dec.go b/operator-pre-inc-dec.go index 241c53e..b9776bf 100644 --- a/operator-pre-inc-dec.go +++ b/operator-pre-inc-dec.go @@ -6,68 +6,68 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) // -------- pre increment term -func newPreIncTerm(tk *Token) *term { - return &term{ - tk: *tk, - parent: nil, - children: make([]*term, 0, 1), - position: posPrefix, - priority: priIncDec, - evalFunc: evalPreInc, +func newPreIncTerm(tk *scan.Token) *scan.Term { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPrefix, + Priority: scan.PriIncDec, + EvalFunc: evalPreInc, } } -func evalPreInc(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalPreInc(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var childValue any - if childValue, err = opTerm.evalPrefix(ctx); err != nil { + if childValue, err = opTerm.EvalPrefix(ctx); err != nil { return } - if kern.IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable { + if kern.IsInteger(childValue) && opTerm.Children[0].Symbol() == scan.SymVariable { i := childValue.(int64) + 1 - ctx.SetVar(opTerm.children[0].Source(), i) + ctx.SetVar(opTerm.Children[0].Source(), i) v = i } else { - err = opTerm.errIncompatiblePrefixPostfixType(childValue) + err = opTerm.ErrIncompatiblePrefixPostfixType(childValue) } return } // -------- pre decrement term -func newPreDecTerm(tk *Token) *term { - return &term{ - tk: *tk, - parent: nil, - children: make([]*term, 0, 1), - position: posPrefix, - priority: priIncDec, - evalFunc: evalPreDec, +func newPreDecTerm(tk *scan.Token) *scan.Term { + return &scan.Term{ + Tk: *tk, + Parent: nil, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPrefix, + Priority: scan.PriIncDec, + EvalFunc: evalPreDec, } } -func evalPreDec(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalPreDec(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var childValue any - if childValue, err = opTerm.evalPrefix(ctx); err != nil { + if childValue, err = opTerm.EvalPrefix(ctx); err != nil { return } - if kern.IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable { + if kern.IsInteger(childValue) && opTerm.Children[0].Symbol() == scan.SymVariable { i := childValue.(int64) - 1 - ctx.SetVar(opTerm.children[0].Source(), i) + ctx.SetVar(opTerm.Children[0].Source(), i) v = i } else { - err = opTerm.errIncompatiblePrefixPostfixType(childValue) + err = opTerm.ErrIncompatiblePrefixPostfixType(childValue) } return } // init func init() { - registerTermConstructor(SymPreInc, newPreIncTerm) - registerTermConstructor(SymPreDec, newPreDecTerm) + scan.RegisterTermConstructor(scan.SymPreInc, newPreIncTerm) + scan.RegisterTermConstructor(scan.SymPreDec, newPreDecTerm) } diff --git a/operator-prod.go b/operator-prod.go index af652c6..40e8af6 100644 --- a/operator-prod.go +++ b/operator-prod.go @@ -8,21 +8,22 @@ import ( "strings" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- multiply term -func newMultiplyTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priProduct, - evalFunc: evalMultiply, +func newMultiplyTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriProduct, + EvalFunc: evalMultiply, } } -func mulValues(opTerm *term, leftValue, rightValue any) (v any, err error) { +func mulValues(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) { if kern.IsString(leftValue) && kern.IsInteger(rightValue) { s, _ := leftValue.(string) n, _ := rightValue.(int64) @@ -38,15 +39,15 @@ func mulValues(opTerm *term, leftValue, rightValue any) (v any, err error) { v = leftInt * rightInt } } else { - err = opTerm.errIncompatibleTypes(leftValue, rightValue) + err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } return } -func evalMultiply(ctx kern.ExprContext, prodTerm *term) (v any, err error) { +func evalMultiply(ctx kern.ExprContext, prodTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = prodTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = prodTerm.EvalInfix(ctx); err != nil { return } @@ -55,22 +56,22 @@ func evalMultiply(ctx kern.ExprContext, prodTerm *term) (v any, err error) { //-------- divide term -func newDivideTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priProduct, - evalFunc: evalDivide, +func newDivideTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriProduct, + EvalFunc: evalDivide, } } -func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) { +func divValues(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) { if kern.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) { if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) { d := kern.NumAsFloat(rightValue) if d == 0.0 { - err = opTerm.errDivisionByZero() + err = opTerm.ErrDivisionByZero() } else { v = kern.NumAsFloat(leftValue) / d } @@ -79,7 +80,7 @@ func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) { } else { leftInt, _ := leftValue.(int64) if rightInt, _ := rightValue.(int64); rightInt == 0 { - err = opTerm.errDivisionByZero() + err = opTerm.ErrDivisionByZero() } else { v = leftInt / rightInt } @@ -92,7 +93,7 @@ func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) { source := leftValue.(string) partSize := int(rightValue.(int64)) if partSize == 0 { - err = opTerm.errDivisionByZero() + err = opTerm.ErrDivisionByZero() } else { partCount := len(source) / partSize remainder := len(source) % partSize @@ -110,15 +111,15 @@ func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) { v = kern.NewList(parts) } } else { - err = opTerm.errIncompatibleTypes(leftValue, rightValue) + err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } return } -func evalDivide(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalDivide(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } @@ -127,66 +128,66 @@ func evalDivide(ctx kern.ExprContext, opTerm *term) (v any, err error) { //-------- divide as float term -func newDivideAsFloatTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priProduct, - evalFunc: evalDivideAsFloat, +func newDivideAsFloatTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriProduct, + EvalFunc: evalDivideAsFloat, } } -func evalDivideAsFloat(ctx kern.ExprContext, floatDivTerm *term) (v any, err error) { +func evalDivideAsFloat(ctx kern.ExprContext, floatDivTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = floatDivTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = floatDivTerm.EvalInfix(ctx); err != nil { return } if kern.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) { d := kern.NumAsFloat(rightValue) if d == 0.0 { - err = floatDivTerm.errDivisionByZero() + err = floatDivTerm.ErrDivisionByZero() } else { v = kern.NumAsFloat(leftValue) / d } } else { - err = floatDivTerm.errIncompatibleTypes(leftValue, rightValue) + err = floatDivTerm.ErrIncompatibleTypes(leftValue, rightValue) } return } //-------- reminder term -func newRemainderTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priProduct, - evalFunc: evalRemainder, +func newRemainderTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriProduct, + EvalFunc: evalRemainder, } } -func remainderValues(opTerm *term, leftValue, rightValue any) (v any, err error) { +func remainderValues(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) { if kern.IsInteger(leftValue) && kern.IsInteger(rightValue) { rightInt, _ := rightValue.(int64) if rightInt == 0 { - err = opTerm.errDivisionByZero() + err = opTerm.ErrDivisionByZero() } else { leftInt, _ := leftValue.(int64) v = leftInt % rightInt } } else { - err = opTerm.errIncompatibleTypes(leftValue, rightValue) + err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } return } -func evalRemainder(ctx kern.ExprContext, remainderTerm *term) (v any, err error) { +func evalRemainder(ctx kern.ExprContext, remainderTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = remainderTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = remainderTerm.EvalInfix(ctx); err != nil { return } @@ -195,8 +196,8 @@ func evalRemainder(ctx kern.ExprContext, remainderTerm *term) (v any, err error) // init func init() { - registerTermConstructor(SymStar, newMultiplyTerm) - registerTermConstructor(SymSlash, newDivideTerm) - registerTermConstructor(SymDotSlash, newDivideAsFloatTerm) - registerTermConstructor(SymPercent, newRemainderTerm) + scan.RegisterTermConstructor(scan.SymStar, newMultiplyTerm) + scan.RegisterTermConstructor(scan.SymSlash, newDivideTerm) + scan.RegisterTermConstructor(scan.SymDotSlash, newDivideAsFloatTerm) + scan.RegisterTermConstructor(scan.SymPercent, newRemainderTerm) } diff --git a/operator-range.go b/operator-range.go index beb1760..c2ce6c4 100644 --- a/operator-range.go +++ b/operator-range.go @@ -8,6 +8,7 @@ import ( "fmt" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) // -------- range term @@ -28,35 +29,35 @@ func isIntPair(v any) bool { return ok } -func newRangeTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priRange, - evalFunc: evalRange, +func newRangeTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriRange, + EvalFunc: evalRange, } } -func changeColonToRange(t *term) { - if t.tk.IsSymbol(SymColon) { - t.tk.Sym = SymRange - t.evalFunc = evalRange +func changeColonToRange(t *scan.Term) { + if t.Tk.IsSymbol(scan.SymColon) { + t.Tk.Sym = scan.SymRange + t.EvalFunc = evalRange } } -func evalRange(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalRange(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if len(opTerm.children) == 0 { + if len(opTerm.Children) == 0 { leftValue = int64(0) rightValue = int64(-1) - } else if len(opTerm.children) == 1 { - if leftValue, err = opTerm.children[0].Compute(ctx); err != nil { + } else if len(opTerm.Children) == 1 { + if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil { return } rightValue = int64(kern.ConstLastIndex) - } else if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + } else if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } if !(kern.IsInteger(leftValue) && kern.IsInteger(rightValue)) { @@ -72,15 +73,15 @@ func evalRange(ctx kern.ExprContext, opTerm *term) (v any, err error) { return } -func errRangeInvalidSpecification(t *term) error { +func errRangeInvalidSpecification(t *scan.Term) error { return t.Errorf("invalid range specification") } -func errRangeUnexpectedExpression(t *term) error { +func errRangeUnexpectedExpression(t *scan.Term) error { return t.Errorf("unexpected range expression") } // init func init() { - registerTermConstructor(SymRange, newRangeTerm) + scan.RegisterTermConstructor(scan.SymRange, newRangeTerm) } diff --git a/operator-rel.go b/operator-rel.go index 4a2410a..0ab4be1 100644 --- a/operator-rel.go +++ b/operator-rel.go @@ -8,17 +8,18 @@ import ( "reflect" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- equal term -func newEqualTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priRelational, - evalFunc: evalEqual, +func newEqualTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriRelational, + EvalFunc: evalEqual, } } @@ -49,10 +50,10 @@ func equals(a, b any, deepCmp kern.DeepFuncTemplate) (eq bool, err error) { return } -func evalEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalEqual(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } @@ -62,17 +63,17 @@ func evalEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) { //-------- not equal term -func newNotEqualTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priRelational, - evalFunc: evalNotEqual, +func newNotEqualTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriRelational, + EvalFunc: evalNotEqual, } } -func evalNotEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalNotEqual(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { if v, err = evalEqual(ctx, opTerm); err == nil { b, _ := kern.ToBool(v) v = !b @@ -82,17 +83,17 @@ func evalNotEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) { //-------- less term -func newLessTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priRelational, - evalFunc: evalLess, +func newLessTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriRelational, + EvalFunc: evalLess, } } -func lessThan(self *term, a, b any) (isLess bool, err error) { +func lessThan(self *scan.Term, a, b any) (isLess bool, err error) { if kern.IsNumOrFract(a) && kern.IsNumOrFract(b) { if kern.IsNumber(a) && kern.IsNumber(b) { if kern.IsInteger(a) && kern.IsInteger(b) { @@ -118,15 +119,15 @@ func lessThan(self *term, a, b any) (isLess bool, err error) { bList, _ := b.(*kern.ListType) isLess = len(*aList) < len(*bList) && bList.Contains(aList) } else { - err = self.errIncompatibleTypes(a, b) + err = self.ErrIncompatibleTypes(a, b) } return } -func evalLess(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalLess(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } v, err = lessThan(opTerm, leftValue, rightValue) @@ -135,17 +136,17 @@ func evalLess(ctx kern.ExprContext, opTerm *term) (v any, err error) { //-------- less or equal term -func newLessEqualTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priRelational, - evalFunc: evalLessEqual, +func newLessEqualTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriRelational, + EvalFunc: evalLessEqual, } } -func lessThanOrEqual(self *term, a, b any) (isLessEq bool, err error) { +func lessThanOrEqual(self *scan.Term, a, b any) (isLessEq bool, err error) { if isLessEq, err = lessThan(self, a, b); err == nil { if !isLessEq { if kern.IsList(a) && kern.IsList(b) { @@ -158,10 +159,10 @@ func lessThanOrEqual(self *term, a, b any) (isLessEq bool, err error) { return } -func evalLessEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalLessEqual(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } @@ -172,20 +173,20 @@ func evalLessEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) { //-------- greater term -func newGreaterTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priRelational, - evalFunc: evalGreater, +func newGreaterTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriRelational, + EvalFunc: evalGreater, } } -func evalGreater(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalGreater(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } @@ -195,20 +196,20 @@ func evalGreater(ctx kern.ExprContext, opTerm *term) (v any, err error) { //-------- greater or equal term -func newGreaterEqualTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priRelational, - evalFunc: evalGreaterEqual, +func newGreaterEqualTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriRelational, + EvalFunc: evalGreaterEqual, } } -func evalGreaterEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalGreaterEqual(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } @@ -218,10 +219,10 @@ func evalGreaterEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymDoubleEqual, newEqualTerm) - registerTermConstructor(SymNotEqual, newNotEqualTerm) - registerTermConstructor(SymLess, newLessTerm) - registerTermConstructor(SymLessOrEqual, newLessEqualTerm) - registerTermConstructor(SymGreater, newGreaterTerm) - registerTermConstructor(SymGreaterOrEqual, newGreaterEqualTerm) + scan.RegisterTermConstructor(scan.SymDoubleEqual, newEqualTerm) + scan.RegisterTermConstructor(scan.SymNotEqual, newNotEqualTerm) + scan.RegisterTermConstructor(scan.SymLess, newLessTerm) + scan.RegisterTermConstructor(scan.SymLessOrEqual, newLessEqualTerm) + scan.RegisterTermConstructor(scan.SymGreater, newGreaterTerm) + scan.RegisterTermConstructor(scan.SymGreaterOrEqual, newGreaterEqualTerm) } diff --git a/operator-selector.go b/operator-selector.go index ad7fede..bb840b9 100644 --- a/operator-selector.go +++ b/operator-selector.go @@ -6,17 +6,18 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- selector term -func newSelectorTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 3), - position: posInfix, - priority: priSelector, - evalFunc: evalSelector, +func newSelectorTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 3), + Position: scan.PosInfix, + Priority: scan.PriSelector, + EvalFunc: evalSelector, } } @@ -25,7 +26,7 @@ func trySelectorCase(ctx kern.ExprContext, exprValue, caseSel any, caseIndex int if caseData.filterList == nil { selectedValue, err = caseData.caseExpr.Eval(ctx) match = true - } else if filterList, ok := caseData.filterList.value().([]*term); ok { + } else if filterList, ok := caseData.filterList.Value().([]*scan.Term); ok { if len(filterList) == 0 { var valueAsInt = int64(0) if b, ok := exprValue.(bool); ok { @@ -53,33 +54,33 @@ func trySelectorCase(ctx kern.ExprContext, exprValue, caseSel any, caseIndex int return } -func evalSelector(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalSelector(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var exprValue any var match bool - if err = opTerm.checkOperands(); err != nil { + if err = opTerm.CheckOperands(); err != nil { return } - exprTerm := opTerm.children[0] + exprTerm := opTerm.Children[0] if exprValue, err = exprTerm.Compute(ctx); err != nil { return } - caseListTerm := opTerm.children[1] - caseList, _ := caseListTerm.value().([]*term) + caseListTerm := opTerm.Children[1] + caseList, _ := caseListTerm.Value().([]*scan.Term) for i, caseTerm := range caseList { - caseSel := caseTerm.value() + caseSel := caseTerm.Value() if match, v, err = trySelectorCase(ctx, exprValue, caseSel, i); err != nil || match { break } } if err == nil && !match { - err = exprTerm.tk.Errorf("no case catches the value (%v) of the selection expression", exprValue) + err = exprTerm.Tk.Errorf("no case catches the value (%v) of the selection expression", exprValue) } return } // init func init() { - registerTermConstructor(SymSelector, newSelectorTerm) + scan.RegisterTermConstructor(scan.SymSelector, newSelectorTerm) } diff --git a/operator-shift.go b/operator-shift.go index 540d48e..c08b8b4 100644 --- a/operator-shift.go +++ b/operator-shift.go @@ -6,35 +6,36 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- bit right shift term -func newRightShiftTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priBinShift, - evalFunc: evalRightShift, +func newRightShiftTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriBinShift, + EvalFunc: evalRightShift, } } -func bitRightShift(opTerm *term, leftValue, rightValue any) (v any, err error) { +func bitRightShift(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) { if kern.IsInteger(leftValue) && kern.IsInteger(rightValue) { leftInt := leftValue.(int64) rightInt := rightValue.(int64) v = leftInt >> rightInt } else { - err = opTerm.errIncompatibleTypes(leftValue, rightValue) + err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } return } -func evalRightShift(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalRightShift(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } @@ -42,31 +43,31 @@ func evalRightShift(ctx kern.ExprContext, opTerm *term) (v any, err error) { return } -func newLeftShiftTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priBinShift, - evalFunc: evalLeftShift, +func newLeftShiftTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriBinShift, + EvalFunc: evalLeftShift, } } -func bitLeftShift(opTerm *term, leftValue, rightValue any) (v any, err error) { +func bitLeftShift(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) { if kern.IsInteger(leftValue) && kern.IsInteger(rightValue) { leftInt := leftValue.(int64) rightInt := rightValue.(int64) v = leftInt << rightInt } else { - err = opTerm.errIncompatibleTypes(leftValue, rightValue) + err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } return } -func evalLeftShift(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalLeftShift(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } @@ -76,6 +77,6 @@ func evalLeftShift(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymDoubleGreater, newRightShiftTerm) - registerTermConstructor(SymDoubleLess, newLeftShiftTerm) + scan.RegisterTermConstructor(scan.SymDoubleGreater, newRightShiftTerm) + scan.RegisterTermConstructor(scan.SymDoubleLess, newLeftShiftTerm) } diff --git a/operator-sign.go b/operator-sign.go index 4c4b6cf..019e33e 100644 --- a/operator-sign.go +++ b/operator-sign.go @@ -6,61 +6,60 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- plus sign term -func newPlusSignTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - // class: classOperator, - // kind: kindUnknown, - children: make([]*term, 0, 1), - position: posPrefix, - priority: priSign, - evalFunc: evalSign, +func newPlusSignTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPrefix, + Priority: scan.PriSign, + EvalFunc: evalSign, } } -func newMinusSignTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 1), - position: posPrefix, - priority: priSign, - evalFunc: evalSign, +func newMinusSignTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPrefix, + Priority: scan.PriSign, + EvalFunc: evalSign, } } -func evalSign(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalSign(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var rightValue any - if rightValue, err = opTerm.evalPrefix(ctx); err != nil { + if rightValue, err = opTerm.EvalPrefix(ctx); err != nil { return } if kern.IsFloat(rightValue) { - if opTerm.tk.Sym == SymChangeSign { + if opTerm.Tk.Sym == scan.SymChangeSign { f, _ := rightValue.(float64) v = -f } else { v = rightValue } } else if kern.IsInteger(rightValue) { - if opTerm.tk.Sym == SymChangeSign { + if opTerm.Tk.Sym == scan.SymChangeSign { i, _ := rightValue.(int64) v = -i } else { v = rightValue } } else { - err = opTerm.errIncompatiblePrefixPostfixType(rightValue) + err = opTerm.ErrIncompatiblePrefixPostfixType(rightValue) } return } // init func init() { - registerTermConstructor(SymUnchangeSign, newPlusSignTerm) - registerTermConstructor(SymChangeSign, newMinusSignTerm) + scan.RegisterTermConstructor(scan.SymUnchangeSign, newPlusSignTerm) + scan.RegisterTermConstructor(scan.SymChangeSign, newMinusSignTerm) } diff --git a/operator-sum.go b/operator-sum.go index ce5ff8f..9fb7352 100644 --- a/operator-sum.go +++ b/operator-sum.go @@ -9,21 +9,22 @@ import ( "slices" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- plus term -func newPlusTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priSum, - evalFunc: evalPlus, +func newPlusTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriSum, + EvalFunc: evalPlus, } } -func sumValues(plusTerm *term, leftValue, rightValue any) (v any, err error) { +func sumValues(plusTerm *scan.Term, leftValue, rightValue any) (v any, err error) { if (kern.IsString(leftValue) && kern.IsNumberString(rightValue)) || (kern.IsString(rightValue) && kern.IsNumberString(leftValue)) { v = fmt.Sprintf("%v%v", leftValue, rightValue) } else if kern.IsNumber(leftValue) && kern.IsNumber(rightValue) { @@ -58,15 +59,15 @@ func sumValues(plusTerm *term, leftValue, rightValue any) (v any, err error) { } else if kern.IsFraction(leftValue) && kern.IsFraction(rightValue) { v, err = kern.SumAnyFract(leftValue, rightValue) } else { - err = plusTerm.errIncompatibleTypes(leftValue, rightValue) + err = plusTerm.ErrIncompatibleTypes(leftValue, rightValue) } return v, err } -func evalPlus(ctx kern.ExprContext, plusTerm *term) (v any, err error) { +func evalPlus(ctx kern.ExprContext, plusTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = plusTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = plusTerm.EvalInfix(ctx); err != nil { return } @@ -75,17 +76,17 @@ func evalPlus(ctx kern.ExprContext, plusTerm *term) (v any, err error) { //-------- minus term -func newMinusTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 2), - position: posInfix, - priority: priSum, - evalFunc: evalMinus, +func newMinusTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 2), + Position: scan.PosInfix, + Priority: scan.PriSum, + EvalFunc: evalMinus, } } -func diffValues(minusTerm *term, leftValue, rightValue any) (v any, err error) { +func diffValues(minusTerm *scan.Term, leftValue, rightValue any) (v any, err error) { if kern.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) { if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) { v = kern.NumAsFloat(leftValue) - kern.NumAsFloat(rightValue) @@ -107,15 +108,15 @@ func diffValues(minusTerm *term, leftValue, rightValue any) (v any, err error) { } v = &diffList } else { - err = minusTerm.errIncompatibleTypes(leftValue, rightValue) + err = minusTerm.ErrIncompatibleTypes(leftValue, rightValue) } return } -func evalMinus(ctx kern.ExprContext, minusTerm *term) (v any, err error) { +func evalMinus(ctx kern.ExprContext, minusTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - if leftValue, rightValue, err = minusTerm.evalInfix(ctx); err != nil { + if leftValue, rightValue, err = minusTerm.EvalInfix(ctx); err != nil { return } @@ -124,6 +125,6 @@ func evalMinus(ctx kern.ExprContext, minusTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymPlus, newPlusTerm) - registerTermConstructor(SymMinus, newMinusTerm) + scan.RegisterTermConstructor(scan.SymPlus, newPlusTerm) + scan.RegisterTermConstructor(scan.SymMinus, newMinusTerm) } diff --git a/operator-unset.go b/operator-unset.go index 66f4b01..a914798 100644 --- a/operator-unset.go +++ b/operator-unset.go @@ -8,21 +8,22 @@ import ( "strings" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) //-------- unset term -func newUnsetTerm(tk *Token) (inst *term) { - return &term{ - tk: *tk, - children: make([]*term, 0, 1), - position: posPrefix, - priority: priSign, - evalFunc: evalUnset, +func newUnsetTerm(tk *scan.Token) (inst *scan.Term) { + return &scan.Term{ + Tk: *tk, + Children: make([]*scan.Term, 0, 1), + Position: scan.PosPrefix, + Priority: scan.PriSign, + EvalFunc: evalUnset, } } -func deleteContextItem(ctx kern.ExprContext, opTerm *term, item any) (deleted bool, err error) { +func deleteContextItem(ctx kern.ExprContext, opTerm *scan.Term, item any) (deleted bool, err error) { if name, ok := item.(string); ok { var size int if strings.HasSuffix(name, "()") { @@ -35,16 +36,16 @@ func deleteContextItem(ctx kern.ExprContext, opTerm *term, item any) (deleted bo deleted = ctx.VarCount() < size } } else { - err = opTerm.errIncompatiblePrefixPostfixType(item) + err = opTerm.ErrIncompatiblePrefixPostfixType(item) } return } -func evalUnset(ctx kern.ExprContext, opTerm *term) (v any, err error) { +func evalUnset(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var childValue any var deleted bool - if childValue, err = opTerm.evalPrefix(ctx); err != nil { + if childValue, err = opTerm.EvalPrefix(ctx); err != nil { return } @@ -69,5 +70,5 @@ func evalUnset(ctx kern.ExprContext, opTerm *term) (v any, err error) { // init func init() { - registerTermConstructor(SymKwUnset, newUnsetTerm) + scan.RegisterTermConstructor(scan.SymKwUnset, newUnsetTerm) } diff --git a/parser.go b/parser.go index 69d30d6..d8c662c 100644 --- a/parser.go +++ b/parser.go @@ -7,6 +7,7 @@ package expr import ( "errors" + "git.portale-stac.it/go-pkg/expr/scan" "golang.org/x/exp/constraints" ) @@ -54,34 +55,34 @@ func NewParser() (p *parser) { return p } -func (parser *parser) Next(scanner *scanner) (tk *Token) { - for tk = scanner.Next(); tk.IsSymbol(SymComment); tk = scanner.Next() { +func (parser *parser) Next(scanner *scan.Scanner) (tk *scan.Token) { + for tk = scanner.Next(); tk.IsSymbol(scan.SymComment); tk = scanner.Next() { } return } -func (parser *parser) parseFuncCall(scanner *scanner, ctx parserContext, tk *Token) (tree *term, err error) { - args := make([]*term, 0, 10) +func (parser *parser) parseFuncCall(scanner *scan.Scanner, ctx parserContext, tk *scan.Token) (tree *scan.Term, err error) { + args := make([]*scan.Term, 0, 10) itemExpected := false - lastSym := SymUnknown - for lastSym != SymClosedRound && lastSym != SymEos { - var subTree *ast - if subTree, err = parser.parseItem(scanner, ctx, SymComma, SymClosedRound); err != nil { + lastSym := scan.SymUnknown + for lastSym != scan.SymClosedRound && lastSym != scan.SymEos { + var subTree *scan.Ast + if subTree, err = parser.parseItem(scanner, ctx, scan.SymComma, scan.SymClosedRound); err != nil { break } prev := scanner.Previous() - if subTree.root != nil { - args = append(args, subTree.root) + if subTree.Root() != nil { + args = append(args, subTree.Root()) } else if itemExpected { err = prev.ErrorExpectedGot("function-param-value") break } - itemExpected = prev.Sym == SymComma + itemExpected = prev.Sym == scan.SymComma lastSym = scanner.Previous().Sym } if err == nil { - if lastSym != SymClosedRound { + if lastSym != scan.SymClosedRound { err = errors.New("unterminated arguments list") } else { tree = newFuncCallTerm(tk, args) @@ -90,18 +91,18 @@ func (parser *parser) parseFuncCall(scanner *scanner, ctx parserContext, tk *Tok return } -func (parser *parser) parseFuncDef(scanner *scanner) (tree *term, err error) { +func (parser *parser) parseFuncDef(scanner *scan.Scanner) (tree *scan.Term, err error) { // Example: "add = func(x,y) {x+y} - var body *ast - args := make([]*term, 0) - lastSym := SymUnknown + var body *scan.Ast + args := make([]*scan.Term, 0) + lastSym := scan.SymUnknown defaultParamsStarted := false itemExpected := false tk := scanner.Previous() - for lastSym != SymClosedRound && lastSym != SymEos { + for lastSym != scan.SymClosedRound && lastSym != scan.SymEos { tk = parser.Next(scanner) - if tk.IsSymbol(SymIdentifier) { - param := newTerm(tk) + if tk.IsSymbol(scan.SymIdentifier) { + param := scan.NewTerm(tk) if len(args) > 0 { if pos := paramAlreadyDefined(args, param); pos > 0 { err = tk.Errorf("parameter %q at position %d already defined at position %d", param.Source(), len(args)+1, pos) @@ -110,13 +111,13 @@ func (parser *parser) parseFuncDef(scanner *scanner) (tree *term, err error) { } args = append(args, param) tk = parser.Next(scanner) - if tk.Sym == SymEqual { - var paramExpr *ast + if tk.Sym == scan.SymEqual { + var paramExpr *scan.Ast defaultParamsStarted = true - if paramExpr, err = parser.parseItem(scanner, parserNoFlags, SymComma, SymClosedRound); err != nil { + if paramExpr, err = parser.parseItem(scanner, parserNoFlags, scan.SymComma, scan.SymClosedRound); err != nil { break } - param.forceChild(paramExpr.root) + param.ForceChild(paramExpr.Root()) } else if defaultParamsStarted { err = tk.Errorf("can't mix default and non-default parameters") break @@ -127,32 +128,32 @@ func (parser *parser) parseFuncDef(scanner *scanner) (tree *term, err error) { break } lastSym = scanner.Previous().Sym - itemExpected = lastSym == SymComma + itemExpected = lastSym == scan.SymComma } - if err == nil && lastSym != SymClosedRound { + if err == nil && lastSym != scan.SymClosedRound { err = tk.ErrorExpectedGot(")") } if err == nil { tk = parser.Next(scanner) - if tk.IsSymbol(SymOpenBrace) { - body, err = parser.parseGeneral(scanner, allowMultiExpr|allowVarRef, SymClosedBrace) + if tk.IsSymbol(scan.SymOpenBrace) { + body, err = parser.parseGeneral(scanner, allowMultiExpr|allowVarRef, scan.SymClosedBrace) } else { err = tk.ErrorExpectedGot("{") } } if err == nil { - if scanner.Previous().Sym != SymClosedBrace { + if scanner.Previous().Sym != scan.SymClosedBrace { err = scanner.Previous().ErrorExpectedGot("}") } else { - tk = scanner.makeValueToken(SymExpression, "", body) + tk = scanner.MakeValueToken(scan.SymExpression, "", body) tree = newFuncDefTerm(tk, args) } } return } -func paramAlreadyDefined(args []*term, param *term) (position int) { +func paramAlreadyDefined(args []*scan.Term, param *scan.Term) (position int) { position = 0 for i, arg := range args { if arg.Source() == param.Source() { @@ -162,39 +163,39 @@ func paramAlreadyDefined(args []*term, param *term) (position int) { return } -func (parser *parser) parseList(scanner *scanner, ctx parserContext) (listTerm *term, err error) { - r, c := scanner.lastPos() - args := make([]*term, 0) - lastSym := SymUnknown +func (parser *parser) parseList(scanner *scan.Scanner, ctx parserContext) (listTerm *scan.Term, err error) { + r, c := scanner.LastPos() + args := make([]*scan.Term, 0) + lastSym := scan.SymUnknown itemExpected := false itemCtx := remFlags(ctx, allowIndex) - for lastSym != SymClosedSquare && lastSym != SymEos { - zeroRequired := scanner.current.Sym == SymColon - var itemTree *ast - if itemTree, err = parser.parseItem(scanner, itemCtx, SymComma, SymClosedSquare); err == nil { - root := itemTree.root + for lastSym != scan.SymClosedSquare && lastSym != scan.SymEos { + zeroRequired := scanner.Current().Sym == scan.SymColon + var itemTree *scan.Ast + if itemTree, err = parser.parseItem(scanner, itemCtx, scan.SymComma, scan.SymClosedSquare); err == nil { + root := itemTree.Root() if root != nil { - if hasFlag(ctx, allowIndex) && root.symbol() == SymColon { + if hasFlag(ctx, allowIndex) && root.Symbol() == scan.SymColon { changeColonToRange(root) } - if !hasFlag(ctx, allowIndex) && root.symbol() == SymRange { + if !hasFlag(ctx, allowIndex) && root.Symbol() == scan.SymRange { // err = root.Errorf("unexpected range expression") err = errRangeUnexpectedExpression(root) break } args = append(args, root) - if hasFlag(ctx, allowIndex) && root.symbol() == SymRange && zeroRequired { //len(root.children) == 0 { - if len(root.children) == 1 { - root.children = append(root.children, root.children[0]) - } else if len(root.children) > 1 { + if hasFlag(ctx, allowIndex) && root.Symbol() == scan.SymRange && zeroRequired { //len(root.children) == 0 { + if len(root.Children) == 1 { + root.Children = append(root.Children, root.Children[0]) + } else if len(root.Children) > 1 { // err = root.Errorf("invalid range specification") err = errRangeInvalidSpecification(root) break } - zeroTk := NewValueToken(root.tk.row, root.tk.col, SymInteger, "0", int64(0)) - zeroTerm := newTerm(zeroTk) - zeroTerm.setParent(root) - root.children[0] = zeroTerm + zeroTk := scan.NewValueToken(root.Tk.Row(), root.Tk.Col(), scan.SymInteger, "0", int64(0)) + zeroTerm := scan.NewTerm(zeroTk) + zeroTerm.SetParent(root) + root.Children[0] = zeroTerm } } else if itemExpected { prev := scanner.Previous() @@ -205,12 +206,12 @@ func (parser *parser) parseList(scanner *scanner, ctx parserContext) (listTerm * break } lastSym = scanner.Previous().Sym - if itemExpected = lastSym == SymComma; itemExpected { + if itemExpected = lastSym == scan.SymComma; itemExpected { remFlags(ctx, allowIndex) } } if err == nil { - if lastSym != SymClosedSquare { + if lastSym != scan.SymClosedSquare { err = scanner.Previous().ErrorExpectedGot("]") } else { listTerm = newListTerm(r, c, args) @@ -219,16 +220,16 @@ func (parser *parser) parseList(scanner *scanner, ctx parserContext) (listTerm * return } -func (parser *parser) parseIterDef(scanner *scanner, ctx parserContext) (subtree *term, err error) { +func (parser *parser) parseIterDef(scanner *scan.Scanner, ctx parserContext) (subtree *scan.Term, err error) { tk := scanner.Previous() - args := make([]*term, 0) - lastSym := SymUnknown + args := make([]*scan.Term, 0) + lastSym := scan.SymUnknown itemExpected := false - for lastSym != SymClosedRound && lastSym != SymEos { - var subTree *ast - if subTree, err = parser.parseItem(scanner, ctx, SymComma, SymClosedRound); err == nil { - if subTree.root != nil { - args = append(args, subTree.root) + for lastSym != scan.SymClosedRound && lastSym != scan.SymEos { + var subTree *scan.Ast + if subTree, err = parser.parseItem(scanner, ctx, scan.SymComma, scan.SymClosedRound); err == nil { + if subTree.Root() != nil { + args = append(args, subTree.Root()) } else if itemExpected { prev := scanner.Previous() err = prev.ErrorExpectedGot("iterator-param") @@ -238,10 +239,10 @@ func (parser *parser) parseIterDef(scanner *scanner, ctx parserContext) (subtree break } lastSym = scanner.Previous().Sym - itemExpected = lastSym == SymComma + itemExpected = lastSym == scan.SymComma } if err == nil { - if lastSym != SymClosedRound { + if lastSym != scan.SymClosedRound { err = scanner.Previous().ErrorExpectedGot(")") } else { subtree = newIteratorTerm(tk, args) @@ -250,18 +251,18 @@ func (parser *parser) parseIterDef(scanner *scanner, ctx parserContext) (subtree return } -func (parser *parser) parseDictKey(scanner *scanner) (key any, err error) { +func (parser *parser) parseDictKey(scanner *scan.Scanner) (key any, err error) { tk := parser.Next(scanner) - if tk.Sym == SymError { + if tk.Sym == scan.SymError { err = tk.Error() return } - if tk.Sym == SymClosedBrace || tk.Sym == SymEos { + if tk.Sym == scan.SymClosedBrace || tk.Sym == scan.SymEos { return } - if tk.Sym == SymInteger || tk.Sym == SymString { + if tk.Sym == scan.SymInteger || tk.Sym == scan.SymString { tkSep := parser.Next(scanner) - if tkSep.Sym != SymColon { + if tkSep.Sym != scan.SymColon { err = tkSep.ErrorExpectedGot(":") } else { key = tk.Value @@ -272,12 +273,12 @@ func (parser *parser) parseDictKey(scanner *scanner) (key any, err error) { return } -func (parser *parser) parseDictionary(scanner *scanner, ctx parserContext) (subtree *term, err error) { - args := make(map[any]*term, 0) - lastSym := SymUnknown +func (parser *parser) parseDictionary(scanner *scan.Scanner, ctx parserContext) (subtree *scan.Term, err error) { + args := make(map[any]*scan.Term, 0) + lastSym := scan.SymUnknown itemExpected := false - for lastSym != SymClosedBrace && lastSym != SymEos { - var subTree *ast + for lastSym != scan.SymClosedBrace && lastSym != scan.SymEos { + var subTree *scan.Ast var key any if key, err = parser.parseDictKey(scanner); err != nil { break @@ -289,9 +290,9 @@ func (parser *parser) parseDictionary(scanner *scanner, ctx parserContext) (subt } break } - if subTree, err = parser.parseItem(scanner, ctx, SymComma, SymClosedBrace); err == nil { - if subTree.root != nil { - args[key] = subTree.root + if subTree, err = parser.parseItem(scanner, ctx, scan.SymComma, scan.SymClosedBrace); err == nil { + if subTree.Root() != nil { + args[key] = subTree.Root() } else /*if key != nil*/ { prev := scanner.Previous() err = prev.ErrorExpectedGot("dictionary-value") @@ -301,10 +302,10 @@ func (parser *parser) parseDictionary(scanner *scanner, ctx parserContext) (subt break } lastSym = scanner.Previous().Sym - itemExpected = lastSym == SymComma + itemExpected = lastSym == scan.SymComma } if err == nil { - if lastSym != SymClosedBrace { + if lastSym != scan.SymClosedBrace { err = scanner.Previous().ErrorExpectedGot("}") } else { subtree = newDictTerm(args) @@ -313,14 +314,14 @@ func (parser *parser) parseDictionary(scanner *scanner, ctx parserContext) (subt return } -func (parser *parser) parseSelectorCase(scanner *scanner, ctx parserContext, defaultCase bool) (caseTerm *term, err error) { - var filterList *term - var caseExpr *ast +func (parser *parser) parseSelectorCase(scanner *scan.Scanner, ctx parserContext, defaultCase bool) (caseTerm *scan.Term, err error) { + var filterList *scan.Term + var caseExpr *scan.Ast ctx = remFlags(ctx, allowIndex) tk := parser.Next(scanner) - startRow := tk.row - startCol := tk.col - if tk.Sym == SymOpenSquare { + startRow := tk.Row() + startCol := tk.Col() + if tk.Sym == scan.SymOpenSquare { if defaultCase { err = tk.Errorf("case list in default clause") return @@ -329,14 +330,14 @@ func (parser *parser) parseSelectorCase(scanner *scanner, ctx parserContext, def return } tk = parser.Next(scanner) - startRow = tk.row - startCol = tk.col + startRow = tk.Row() + startCol = tk.Col() } else if !defaultCase { - filterList = newListTerm(startRow, startCol, make([]*term, 0)) + filterList = newListTerm(startRow, startCol, make([]*scan.Term, 0)) } - if tk.Sym == SymOpenBrace { - if caseExpr, err = parser.parseGeneral(scanner, ctx|allowMultiExpr, SymClosedBrace); err != nil { + if tk.Sym == scan.SymOpenBrace { + if caseExpr, err = parser.parseGeneral(scanner, ctx|allowMultiExpr, scan.SymClosedBrace); err != nil { return } } else { @@ -349,25 +350,25 @@ func (parser *parser) parseSelectorCase(scanner *scanner, ctx parserContext, def return } -func addSelectorCase(selectorTerm, caseTerm *term) { - if len(selectorTerm.children) < 2 { +func addSelectorCase(selectorTerm, caseTerm *scan.Term) { + if len(selectorTerm.Children) < 2 { caseListTerm := newListTermA(caseTerm) - selectorTerm.children = append(selectorTerm.children, caseListTerm) + selectorTerm.Children = append(selectorTerm.Children, caseListTerm) } else { - caseListTerm := selectorTerm.children[1] - caseList, _ := caseListTerm.value().([]*term) + caseListTerm := selectorTerm.Children[1] + caseList, _ := caseListTerm.Value().([]*scan.Term) caseList = append(caseList, caseTerm) - caseListTerm.tk.Value = caseList + caseListTerm.Tk.Value = caseList } - caseTerm.parent = selectorTerm + caseTerm.Parent = selectorTerm } -func (parser *parser) parseSelector(scanner *scanner, tree *ast, ctx parserContext) (selectorTerm *term, err error) { - var caseTerm *term +func (parser *parser) parseSelector(scanner *scan.Scanner, tree *scan.Ast, ctx parserContext) (selectorTerm *scan.Term, err error) { + var caseTerm *scan.Term ctx = remFlags(ctx, allowIndex) - tk := scanner.makeToken(SymSelector, '?') - if selectorTerm, err = tree.addToken(tk); err != nil { + tk := scanner.MakeToken(scan.SymSelector, '?') + if selectorTerm, err = tree.AddToken(tk); err != nil { return } @@ -377,11 +378,11 @@ func (parser *parser) parseSelector(scanner *scanner, tree *ast, ctx parserConte return } -func (parser *parser) parseItem(scanner *scanner, ctx parserContext, termSymbols ...Symbol) (tree *ast, err error) { +func (parser *parser) parseItem(scanner *scan.Scanner, ctx parserContext, termSymbols ...scan.Symbol) (tree *scan.Ast, err error) { return parser.parseGeneral(scanner, ctx|allowVarRef, termSymbols...) } -func (parser *parser) Parse(scanner *scanner, termSymbols ...Symbol) (tree *ast, err error) { +func (parser *parser) Parse(scanner *scan.Scanner, termSymbols ...scan.Symbol) (tree *scan.Ast, err error) { defer func() { if r := recover(); r != nil { if errVal, ok := r.(error); ok { @@ -391,56 +392,56 @@ func (parser *parser) Parse(scanner *scanner, termSymbols ...Symbol) (tree *ast, } } }() - termSymbols = append(termSymbols, SymEos) + termSymbols = append(termSymbols, scan.SymEos) return parser.parseGeneral(scanner, allowMultiExpr, termSymbols...) } -func couldBeACollection(t *term) bool { - var sym = SymUnknown +func couldBeACollection(t *scan.Term) bool { + var sym = scan.SymUnknown if t != nil { - sym = t.symbol() + sym = t.Symbol() } - return sym == SymList || sym == SymString || sym == SymDict || sym == SymExpression || sym == SymVariable + return sym == scan.SymList || sym == scan.SymString || sym == scan.SymDict || sym == scan.SymExpression || sym == scan.SymVariable } -func listSubTree(tree *ast, listTerm *term, allowIndeces bool) (root *term, err error) { - var tk *Token +func listSubTree(tree *scan.Ast, listTerm *scan.Term, allowIndeces bool) (root *scan.Term, err error) { + var tk *scan.Token if allowIndeces { - tk = NewToken(listTerm.tk.row, listTerm.tk.col, SymIndex, listTerm.Source()) - root = newTerm(tk) - if err = tree.addTerm(root); err == nil { - err = tree.addTerm(listTerm) + tk = scan.NewToken(listTerm.Tk.Row(), listTerm.Tk.Col(), scan.SymIndex, listTerm.Source()) + root = scan.NewTerm(tk) + if err = tree.AddTerm(root); err == nil { + err = tree.AddTerm(listTerm) } } else { root = listTerm - err = tree.addTerm(listTerm) + err = tree.AddTerm(listTerm) } return } -func changePrefix(tk *Token) { +func changePrefix(tk *scan.Token) { switch tk.Sym { - case SymMinus: - tk.SetSymbol(SymChangeSign) - case SymPlus: - tk.SetSymbol(SymUnchangeSign) - case SymStar: - tk.SetSymbol(SymDereference) - case SymExclamation: - tk.SetSymbol(SymNot) - case SymDoublePlus: - tk.SetSymbol(SymPreInc) - case SymDoubleMinus: - tk.SetSymbol(SymPreDec) + case scan.SymMinus: + tk.SetSymbol(scan.SymChangeSign) + case scan.SymPlus: + tk.SetSymbol(scan.SymUnchangeSign) + case scan.SymStar: + tk.SetSymbol(scan.SymDereference) + case scan.SymExclamation: + tk.SetSymbol(scan.SymNot) + case scan.SymDoublePlus: + tk.SetSymbol(scan.SymPreInc) + case scan.SymDoubleMinus: + tk.SetSymbol(scan.SymPreDec) } } -func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymbols ...Symbol) (tree *ast, err error) { - var selectorTerm *term = nil - var currentTerm *term = nil - var tk *Token +func (parser *parser) parseGeneral(scanner *scan.Scanner, ctx parserContext, termSymbols ...scan.Symbol) (tree *scan.Ast, err error) { + var selectorTerm *scan.Term = nil + var currentTerm *scan.Term = nil + var tk *scan.Token - tree = NewAst() + tree = scan.NewAst() firstToken := true // lastSym := SymUnknown for tk = parser.Next(scanner); err == nil && tk != nil && !tk.IsTerm(termSymbols); /*&& !areSymbolsOutOfCtx(tk, selectorTerm, SymColon, SymDoubleColon)*/ tk = parser.Next(scanner) { @@ -448,7 +449,7 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb // continue // } - if tk.Sym == SymSemiColon { + if tk.Sym == scan.SymSemiColon { if hasFlag(ctx, allowMultiExpr) { tree.ToForest() firstToken = true @@ -456,7 +457,7 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb selectorTerm = nil continue } else { - err = tk.Errorf(`unexpected token %q, expected ",", "]", or ")"`, tk.source) + err = tk.Errorf(`unexpected token %q, expected ",", "]", or ")"`, tk.Source()) break } } @@ -468,87 +469,87 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb } switch tk.Sym { - case SymOpenRound: - var subTree *ast - if subTree, err = parser.parseGeneral(scanner, ctx, SymClosedRound); err == nil { - if subTree.root == nil { + case scan.SymOpenRound: + var subTree *scan.Ast + if subTree, err = parser.parseGeneral(scanner, ctx, scan.SymClosedRound); err == nil { + if subTree.Root() == nil { err = tk.ErrorExpectedGotString("expression", "()") } else { - exprTerm := newExprTerm(subTree.root) - err = tree.addTerm(exprTerm) + exprTerm := newExprTerm(subTree.Root()) + err = tree.AddTerm(exprTerm) currentTerm = exprTerm } } - case SymFuncCall: - var funcCallTerm *term + case scan.SymFuncCall: + var funcCallTerm *scan.Term if funcCallTerm, err = parser.parseFuncCall(scanner, ctx, tk); err == nil { - err = tree.addTerm(funcCallTerm) + err = tree.AddTerm(funcCallTerm) currentTerm = funcCallTerm } - case SymOpenSquare: - var listTerm *term + case scan.SymOpenSquare: + var listTerm *scan.Term newCtx := addFlagsCond(addFlags(ctx, squareContext), allowIndex, couldBeACollection(currentTerm)) if listTerm, err = parser.parseList(scanner, newCtx); err == nil { currentTerm, err = listSubTree(tree, listTerm, hasFlag(newCtx, allowIndex)) } - case SymOpenBrace: - if currentTerm != nil && currentTerm.symbol() == SymColon { + case scan.SymOpenBrace: + if currentTerm != nil && currentTerm.Symbol() == scan.SymColon { err = currentTerm.Errorf(`selector-case outside of a selector context`) } else { - var mapTerm *term + var mapTerm *scan.Term if mapTerm, err = parser.parseDictionary(scanner, ctx); err == nil { - err = tree.addTerm(mapTerm) + err = tree.AddTerm(mapTerm) currentTerm = mapTerm } } - case SymEqual, SymPlusEqual, SymMinusEqual, SymStarEqual, SymSlashEqual, SymPercEqual, SymAmpersandEqual, SymVertBarEqual, SymDoubleLessEqual, SymDoubleGreaterEqual, SymCaretEqual: - currentTerm, err = tree.addToken(tk) + case scan.SymEqual, scan.SymPlusEqual, scan.SymMinusEqual, scan.SymStarEqual, scan.SymSlashEqual, scan.SymPercEqual, scan.SymAmpersandEqual, scan.SymVertBarEqual, scan.SymDoubleLessEqual, scan.SymDoubleGreaterEqual, scan.SymCaretEqual: + currentTerm, err = tree.AddToken(tk) firstToken = true - case SymFuncDef: - var funcDefTerm *term + case scan.SymFuncDef: + var funcDefTerm *scan.Term if funcDefTerm, err = parser.parseFuncDef(scanner); err == nil { - err = tree.addTerm(funcDefTerm) + err = tree.AddTerm(funcDefTerm) currentTerm = funcDefTerm } - case SymDollarRound: - var iterDefTerm *term + case scan.SymDollarRound: + var iterDefTerm *scan.Term if iterDefTerm, err = parser.parseIterDef(scanner, ctx); err == nil { - err = tree.addTerm(iterDefTerm) + err = tree.AddTerm(iterDefTerm) currentTerm = iterDefTerm } - case SymIdentifier: - if tk.source[0] == '@' && !hasFlag(ctx, allowVarRef) { - err = tk.Errorf("variable references are not allowed in top level expressions: %q", tk.source) + case scan.SymIdentifier: + if tk.Source()[0] == '@' && !hasFlag(ctx, allowVarRef) { + err = tk.Errorf("variable references are not allowed in top level expressions: %q", tk.Source()) } else { - currentTerm, err = tree.addToken(tk) + currentTerm, err = tree.AddToken(tk) } - case SymQuestion: + case scan.SymQuestion: if selectorTerm, err = parser.parseSelector(scanner, tree, ctx); err == nil { currentTerm = selectorTerm addFlags(ctx, selectorContext) } - case SymColon, SymDoubleColon: - var caseTerm *term + case scan.SymColon, scan.SymDoubleColon: + var caseTerm *scan.Term if selectorTerm != nil { - if caseTerm, err = parser.parseSelectorCase(scanner, ctx, tk.Sym == SymDoubleColon); err == nil { + if caseTerm, err = parser.parseSelectorCase(scanner, ctx, tk.Sym == scan.SymDoubleColon); err == nil { addSelectorCase(selectorTerm, caseTerm) currentTerm = caseTerm - if tk.Sym == SymDoubleColon { + if tk.Sym == scan.SymDoubleColon { selectorTerm = nil } } } else { - currentTerm, err = tree.addToken(tk) - if tk.IsOneOfA(SymColon, SymRange) { + currentTerm, err = tree.AddToken(tk) + if tk.IsOneOfA(scan.SymColon, scan.SymRange) { // Colon outside a selector term acts like a separator firstToken = true } } default: - currentTerm, err = tree.addToken(tk) + currentTerm, err = tree.AddToken(tk) } - if currentTerm != nil && currentTerm.tk.Sym != SymSelector && currentTerm.parent != nil && currentTerm.parent.tk.Sym != SymSelector { + if currentTerm != nil && currentTerm.Tk.Sym != scan.SymSelector && currentTerm.Parent != nil && currentTerm.Parent.Tk.Sym != scan.SymSelector { selectorTerm = nil remFlags(ctx, selectorContext) } @@ -558,12 +559,12 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb if err == nil { if !tk.IsOneOf(termSymbols) { var symDesc string - if tk.IsSymbol(SymError) { + if tk.IsSymbol(scan.SymError) { symDesc = tk.ErrorText() } else { - symDesc = SymToString(tk.Sym) + symDesc = scan.SymToString(tk.Sym) } - err = tk.ErrorExpectedGotStringWithPrefix("expected one of", SymListToString(termSymbols, true), symDesc) + err = tk.ErrorExpectedGotStringWithPrefix("expected one of", scan.SymListToString(termSymbols, true), symDesc) } else { err = tk.Error() } diff --git a/ast.go b/scan/ast.go similarity index 71% rename from ast.go rename to scan/ast.go index bc1f187..b126bb0 100644 --- a/ast.go +++ b/scan/ast.go @@ -2,7 +2,7 @@ // All rights reserved. // ast.go -package expr +package scan import ( "errors" @@ -13,42 +13,46 @@ import ( //-------- ast -type ast struct { - forest []*term - root *term +type Ast struct { + forest []*Term + root *Term } -func NewAst() *ast { - return &ast{} +func NewAst() *Ast { + return &Ast{} } -func (ast *ast) TypeName() string { +func (ast *Ast) TypeName() string { return "Expression" } -func (ast *ast) ToForest() { +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 = make([]*Term, 0) } ast.forest = append(ast.forest, ast.root) ast.root = nil } } -func (ast *ast) String() string { +func (ast *Ast) String() string { var sb strings.Builder if ast.root == nil { sb.WriteString("(nil)") } else { - ast.root.toString(&sb) + ast.root.ToString(&sb) } return sb.String() } -func (ast *ast) addTokens(tokens ...*Token) (err error) { +func (ast *Ast) AddTokens(tokens ...*Token) (err error) { for _, tk := range tokens { - if _, err = ast.addToken(tk); err != nil { + if _, err = ast.AddToken(tk); err != nil { break } } @@ -60,16 +64,16 @@ func (ast *ast) addTokens(tokens ...*Token) (err error) { // return // } -func (ast *ast) addToken(tk *Token) (t *term, err error) { - if t = newTerm(tk); t != nil { - err = ast.addTerm(t) +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) { +func (ast *Ast) AddTerm(node *Term) (err error) { if ast.root == nil { ast.root = node } else { @@ -78,35 +82,35 @@ func (ast *ast) addTerm(node *term) (err error) { return } -func (ast *ast) insert(tree, node *term) (root *term, err error) { +func (ast *Ast) insert(tree, node *Term) (root *Term, err error) { if tree.getPriority() < node.getPriority() { root = tree if tree.isComplete() { - var subRoot *term + var subRoot *Term last := tree.removeLastChild() if subRoot, err = ast.insert(last, node); err == nil { - subRoot.setParent(tree) + subRoot.SetParent(tree) } } else { - node.setParent(tree) + node.SetParent(tree) } } else if !node.isLeaf() { root = node - tree.setParent(node) + tree.SetParent(node) } else { err = node.Errorf("two adjacent operators: %q and %q", tree, node) } return } -func (ast *ast) Finish() { +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) { +func (ast *Ast) Eval(ctx kern.ExprContext) (result any, err error) { defer func() { if r := recover(); r != nil { if errVal, ok := r.(error); ok { diff --git a/scanner.go b/scan/scanner.go similarity index 81% rename from scanner.go rename to scan/scanner.go index 1b51180..c856746 100644 --- a/scanner.go +++ b/scan/scanner.go @@ -2,7 +2,7 @@ // All rights reserved. // expr project scanner.go -package expr +package scan import ( "bufio" @@ -13,9 +13,10 @@ import ( "strings" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/util" ) -type scanner struct { +type Scanner struct { current *Token prev *Token stage *Token @@ -25,8 +26,8 @@ type scanner struct { translations map[Symbol]Symbol } -func NewScanner(s io.Reader, translations map[Symbol]Symbol) (inst *scanner) { - inst = &scanner{ +func NewScanner(s io.Reader, translations map[Symbol]Symbol) (inst *Scanner) { + inst = &Scanner{ stream: bufio.NewReader(s), row: 1, column: 1, @@ -52,7 +53,11 @@ func DefaultTranslations() map[Symbol]Symbol { // return self.current // } -func (scanner *scanner) readChar() (ch byte, err error) { +func (scanner *Scanner) Current() *Token { + return scanner.current +} + +func (scanner *Scanner) readChar() (ch byte, err error) { if ch, err = scanner.stream.ReadByte(); err == nil { if ch == '\n' { scanner.row++ @@ -64,7 +69,7 @@ func (scanner *scanner) readChar() (ch byte, err error) { return } -func (scanner *scanner) unreadChar() (err error) { +func (scanner *Scanner) unreadChar() (err error) { if err = scanner.stream.UnreadByte(); err == nil { if scanner.column--; scanner.column == 0 { if scanner.row--; scanner.row == 0 { @@ -77,7 +82,7 @@ func (scanner *scanner) unreadChar() (err error) { return } -func (scanner *scanner) UnreadToken() (err error) { +func (scanner *Scanner) UnreadToken() (err error) { if scanner.stage == nil { scanner.stage = scanner.current scanner.current = scanner.prev @@ -87,7 +92,7 @@ func (scanner *scanner) UnreadToken() (err error) { return } -func (scanner *scanner) lastPos() (r, c int) { +func (scanner *Scanner) LastPos() (r, c int) { if scanner.prev != nil { r = scanner.prev.row c = scanner.prev.col @@ -95,11 +100,11 @@ func (scanner *scanner) lastPos() (r, c int) { return } -func (scanner *scanner) Previous() *Token { +func (scanner *Scanner) Previous() *Token { return scanner.prev } -func (scanner *scanner) Next() (tk *Token) { +func (scanner *Scanner) Next() (tk *Token) { scanner.prev = scanner.current tk = scanner.current if scanner.stage != nil { @@ -111,7 +116,7 @@ func (scanner *scanner) Next() (tk *Token) { return tk } -func (scanner *scanner) fetchNextToken() (tk *Token) { +func (scanner *Scanner) fetchNextToken() (tk *Token) { var ch byte if err := scanner.skipBlanks(); err != nil { return scanner.makeErrorToken(err) @@ -129,7 +134,7 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { } else if next == '>' { tk = scanner.moveOn(SymPlusGreater, ch, next) } else { - tk = scanner.makeToken(SymPlus, ch) + tk = scanner.MakeToken(SymPlus, ch) } case '-': if next, _ := scanner.peek(); next == '-' { @@ -137,7 +142,7 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { } else if next == '=' { tk = scanner.moveOn(SymMinusEqual, ch, next) } else { - tk = scanner.makeToken(SymMinus, ch) + tk = scanner.MakeToken(SymMinus, ch) } case '*': if next, _ := scanner.peek(); next == '*' { @@ -147,7 +152,7 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { } else if next, _ = scanner.peek(); next == '=' { tk = scanner.moveOn(SymStarEqual, ch, next) } else { - tk = scanner.makeToken(SymStar, ch) + tk = scanner.MakeToken(SymStar, ch) } case '/': if next, _ := scanner.peek(); next == '*' { @@ -159,11 +164,11 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { scanner.readChar() tk = scanner.fetchOnLineComment() } else { - tk = scanner.makeToken(SymSlash, ch) + tk = scanner.MakeToken(SymSlash, ch) } case '\\': if escape { - tk = scanner.makeToken(SymBackSlash, ch) + tk = scanner.MakeToken(SymBackSlash, ch) escape = false } else { escape = true @@ -174,24 +179,24 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { } else if next, _ = scanner.peek(); next == '=' { tk = scanner.moveOn(SymVertBarEqual, ch, next) } else { - tk = scanner.makeToken(SymVertBar, ch) + tk = scanner.MakeToken(SymVertBar, ch) } case ',': - tk = scanner.makeToken(SymComma, ch) + tk = scanner.MakeToken(SymComma, ch) case '^': if next, _ := scanner.peek(); next == '=' { tk = scanner.moveOn(SymCaretEqual, ch, next) } else { - tk = scanner.makeToken(SymCaret, ch) + tk = scanner.MakeToken(SymCaret, ch) } case ':': if next, _ := scanner.peek(); next == ':' { tk = scanner.moveOn(SymDoubleColon, ch, next) } else { - tk = scanner.makeToken(SymColon, ch) + tk = scanner.MakeToken(SymColon, ch) } case ';': - tk = scanner.makeToken(SymSemiColon, ch) + tk = scanner.MakeToken(SymSemiColon, ch) case '.': //if next, _ := self.peek(); next >= '0' && next <= '9' { // tk = self.parseNumber(ch) @@ -205,29 +210,29 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { tk = scanner.moveOn(SymDoubleDot, ch, next) } } else { - tk = scanner.makeToken(SymDot, ch) + tk = scanner.MakeToken(SymDot, ch) } case '\'': if escape { - tk = scanner.makeToken(SymQuote, ch) + tk = scanner.MakeToken(SymQuote, ch) escape = false } else { tk = scanner.fetchString(ch, true) } case '"': if escape { - tk = scanner.makeToken(SymDoubleQuote, ch) + tk = scanner.MakeToken(SymDoubleQuote, ch) escape = false } else { tk = scanner.fetchString(ch, true) } case '`': - tk = scanner.makeToken(SymBackTick, ch) + tk = scanner.MakeToken(SymBackTick, ch) case '!': if next, _ := scanner.peek(); next == '=' { tk = scanner.moveOn(SymNotEqual, ch, next) } else { - tk = scanner.makeToken(SymExclamation, ch) + tk = scanner.MakeToken(SymExclamation, ch) } case '?': if next, _ := scanner.peek(); next == '?' { @@ -237,7 +242,7 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { } else if next == '!' { tk = scanner.moveOn(SymQuestionExclam, ch, next) } else { - tk = scanner.makeToken(SymQuestion, ch) + tk = scanner.MakeToken(SymQuestion, ch) } case '&': if next, _ := scanner.peek(); next == '&' { @@ -245,16 +250,16 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { } else if next, _ = scanner.peek(); next == '=' { tk = scanner.moveOn(SymAmpersandEqual, ch, next) } else { - tk = scanner.makeToken(SymAmpersand, ch) + tk = scanner.MakeToken(SymAmpersand, ch) } case '%': if next, _ := scanner.peek(); next == '=' { tk = scanner.moveOn(SymPercEqual, ch, next) } else { - tk = scanner.makeToken(SymPercent, ch) + tk = scanner.MakeToken(SymPercent, ch) } case '#': - tk = scanner.makeToken(SymHash, ch) + tk = scanner.MakeToken(SymHash, ch) case '@': if next, _ := scanner.peek(); (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z') { scanner.readChar() @@ -267,15 +272,15 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { } else if next == '@' { tk = scanner.moveOn(SymDoubleAt, ch, next) } else { - tk = scanner.makeToken(SymAt, ch) + tk = scanner.MakeToken(SymAt, ch) } case '_': - tk = scanner.makeToken(SymUndescore, ch) + tk = scanner.MakeToken(SymUndescore, ch) case '=': if next, _ := scanner.peek(); next == '=' { tk = scanner.moveOn(SymDoubleEqual, ch, next) } else { - tk = scanner.makeToken(SymEqual, ch) + tk = scanner.MakeToken(SymEqual, ch) } case '<': if next, _ := scanner.peek(); next == '=' { @@ -294,7 +299,7 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { } else if next == '+' { tk = scanner.moveOn(SymLessPlus, ch, next) } else { - tk = scanner.makeToken(SymLess, ch) + tk = scanner.MakeToken(SymLess, ch) } case '>': if next, _ := scanner.peek(); next == '=' { @@ -309,7 +314,7 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { tk = scanner.accept(SymDoubleGreater, ch, next) } } else { - tk = scanner.makeToken(SymGreater, ch) + tk = scanner.MakeToken(SymGreater, ch) } case '$': if next, _ := scanner.peek(); next == '(' { @@ -326,26 +331,26 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { scanner.readChar() tk = scanner.fetchIdentifier(next) } else { - tk = scanner.makeToken(SymDollar, ch) + tk = scanner.MakeToken(SymDollar, ch) } case '(': // if next, _ := scanner.peek(); next == ')' { // tk = scanner.moveOn(SymOpenClosedRound, ch, next) // } else { - tk = scanner.makeToken(SymOpenRound, ch) + tk = scanner.MakeToken(SymOpenRound, ch) // } case ')': - tk = scanner.makeToken(SymClosedRound, ch) + tk = scanner.MakeToken(SymClosedRound, ch) case '[': - tk = scanner.makeToken(SymOpenSquare, ch) + tk = scanner.MakeToken(SymOpenSquare, ch) case ']': - tk = scanner.makeToken(SymClosedSquare, ch) + tk = scanner.MakeToken(SymClosedSquare, ch) case '{': - tk = scanner.makeToken(SymOpenBrace, ch) + tk = scanner.MakeToken(SymOpenBrace, ch) case '}': - tk = scanner.makeToken(SymClosedBrace, ch) + tk = scanner.MakeToken(SymClosedBrace, ch) case '~': - tk = scanner.makeToken(SymTilde, ch) + tk = scanner.MakeToken(SymTilde, ch) case 0: if escape { tk = scanner.makeErrorToken(errors.New("incomplete escape sequence")) @@ -372,7 +377,7 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { return } -func (scanner *scanner) sync(err error) error { +func (scanner *Scanner) sync(err error) error { if err == nil { err = scanner.unreadChar() } @@ -395,7 +400,7 @@ func isHexDigit(ch byte) bool { return (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') } -func (scanner *scanner) initBase(currentFirstCh byte) (firstCh byte, numBase int, digitFunc func(byte) bool, err error) { +func (scanner *Scanner) initBase(currentFirstCh byte) (firstCh byte, numBase int, digitFunc func(byte) bool, err error) { var ch byte var digitType string firstCh = currentFirstCh @@ -434,7 +439,7 @@ func (scanner *scanner) initBase(currentFirstCh byte) (firstCh byte, numBase int return } -func (scanner *scanner) parseNumber(firstCh byte) (tk *Token) { +func (scanner *Scanner) parseNumber(firstCh byte) (tk *Token) { var err error var ch byte var sym Symbol = SymInteger @@ -510,7 +515,7 @@ func (scanner *scanner) parseNumber(firstCh byte) (tk *Token) { value, err = strconv.ParseInt(txt, numBase, 64) } if err == nil { - tk = scanner.makeValueToken(sym, txt, value) + tk = scanner.MakeValueToken(sym, txt, value) } else { tk = scanner.makeErrorToken(err) } @@ -518,7 +523,7 @@ func (scanner *scanner) parseNumber(firstCh byte) (tk *Token) { return } -func (scanner *scanner) fetchIdentifier(firstCh byte) (tk *Token) { +func (scanner *Scanner) fetchIdentifier(firstCh byte) (tk *Token) { var err error var sb strings.Builder for ch := firstCh; err == nil && (ch == '_' || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')); ch, err = scanner.readChar() { @@ -535,14 +540,14 @@ func (scanner *scanner) fetchIdentifier(firstCh byte) (tk *Token) { if sym, ok := keywords[uptxt]; ok { tk = scanner.makeKeywordToken(sym, uptxt) } else if uptxt == `TRUE` { - tk = scanner.makeValueToken(SymBool, txt, true) + tk = scanner.MakeValueToken(SymBool, txt, true) } else if uptxt == `FALSE` { - tk = scanner.makeValueToken(SymBool, txt, false) + tk = scanner.MakeValueToken(SymBool, txt, false) } else if ch, _ := scanner.peek(); ch == '(' { scanner.readChar() - tk = scanner.makeValueToken(SymFuncCall, txt+"(", txt) + tk = scanner.MakeValueToken(SymFuncCall, txt+"(", txt) } else { - tk = scanner.makeValueToken(SymIdentifier, txt, txt) + tk = scanner.MakeValueToken(SymIdentifier, txt, txt) } } @@ -562,20 +567,20 @@ func (scanner *scanner) fetchIdentifier(firstCh byte) (tk *Token) { return } -func (scanner *scanner) fetchBlockComment() *Token { +func (scanner *Scanner) fetchBlockComment() *Token { return scanner.fetchUntil(SymComment, false, '*', '/') } -func (scanner *scanner) fetchOnLineComment() *Token { +func (scanner *Scanner) fetchOnLineComment() *Token { return scanner.fetchUntil(SymComment, true, '\n') } -func (scanner *scanner) fetchUntil(sym Symbol, allowEos bool, endings ...byte) (tk *Token) { +func (scanner *Scanner) fetchUntil(sym Symbol, allowEos bool, endings ...byte) (tk *Token) { var err error var ch byte var sb strings.Builder var value string - ring := NewByteSlider(len(endings)) + ring := util.NewByteSlider(len(endings)) endReached := false for ch, err = scanner.readChar(); err == nil && !endReached; { sb.WriteByte(ch) @@ -593,14 +598,14 @@ func (scanner *scanner) fetchUntil(sym Symbol, allowEos bool, endings ...byte) ( } if endReached { - tk = scanner.makeValueToken(sym, "", value) + tk = scanner.MakeValueToken(sym, "", value) } else { tk = scanner.makeErrorToken(err) } return } -func (scanner *scanner) fetchString(termCh byte, addQuote bool) (tk *Token) { +func (scanner *Scanner) fetchString(termCh byte, addQuote bool) (tk *Token) { var err error var ch, prev byte var sb strings.Builder @@ -639,15 +644,15 @@ func (scanner *scanner) fetchString(termCh byte, addQuote bool) (tk *Token) { } else { txt := sb.String() if addQuote { - tk = scanner.makeValueToken(SymString, `"`+txt+`"`, txt) + tk = scanner.MakeValueToken(SymString, `"`+txt+`"`, txt) } else { - tk = scanner.makeValueToken(SymString, txt, txt) + tk = scanner.MakeValueToken(SymString, txt, txt) } } return } -func (scanner *scanner) peek() (next byte, err error) { +func (scanner *Scanner) peek() (next byte, err error) { var one []byte if one, err = scanner.stream.Peek(1); err == nil { next = one[0] @@ -655,7 +660,7 @@ func (scanner *scanner) peek() (next byte, err error) { return } -func (scanner *scanner) skipBlanks() (err error) { +func (scanner *Scanner) skipBlanks() (err error) { var one []byte for one, err = scanner.stream.Peek(1); err == nil && one[0] <= 32; one, err = scanner.stream.Peek(1) { scanner.readChar() @@ -663,7 +668,7 @@ func (scanner *scanner) skipBlanks() (err error) { return } -func (scanner *scanner) translate(sym Symbol) Symbol { +func (scanner *Scanner) translate(sym Symbol) Symbol { if scanner.translations != nil { if translatedSym, ok := scanner.translations[sym]; ok { return translatedSym @@ -672,7 +677,7 @@ func (scanner *scanner) translate(sym Symbol) Symbol { return sym } -func (scanner *scanner) moveOn(sym Symbol, chars ...byte) (tk *Token) { +func (scanner *Scanner) moveOn(sym Symbol, chars ...byte) (tk *Token) { tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), string(chars)) // for i := 1; i < len(chars); i++ { if len(chars) > 1 { @@ -682,26 +687,26 @@ func (scanner *scanner) moveOn(sym Symbol, chars ...byte) (tk *Token) { return } -func (scanner *scanner) accept(sym Symbol, chars ...byte) (tk *Token) { +func (scanner *Scanner) accept(sym Symbol, chars ...byte) (tk *Token) { tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), string(chars)) return } -func (scanner *scanner) makeToken(sym Symbol, chars ...byte) (tk *Token) { +func (scanner *Scanner) MakeToken(sym Symbol, chars ...byte) (tk *Token) { tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), string(chars)) return } -func (scanner *scanner) makeKeywordToken(sym Symbol, upperCaseKeyword string) (tk *Token) { +func (scanner *Scanner) makeKeywordToken(sym Symbol, upperCaseKeyword string) (tk *Token) { tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), upperCaseKeyword) return } -func (scanner *scanner) makeValueToken(sym Symbol, source string, value any) (tk *Token) { +func (scanner *Scanner) MakeValueToken(sym Symbol, source string, value any) (tk *Token) { tk = NewValueToken(scanner.row, scanner.column, scanner.translate(sym), source, value) return } -func (scanner *scanner) makeErrorToken(err error) *Token { +func (scanner *Scanner) makeErrorToken(err error) *Token { return NewErrorToken(scanner.row, scanner.column, err) } diff --git a/scan/symbol-map.go b/scan/symbol-map.go new file mode 100644 index 0000000..ab3772c --- /dev/null +++ b/scan/symbol-map.go @@ -0,0 +1,231 @@ +// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). +// All rights reserved. + +// Symbol.go +package scan + +import ( + "strings" +) + +var symbolMap map[Symbol]symbolSpec + +type SymbolClass int16 + +const ( + SymClassOperator SymbolClass = iota + SymClassCommand + SymClassIdentifier + SymClassDelimiter + SymClassParenthesis + SymClassDeclaration + SymClassValue + SymClassOther +) + +type symbolSpec struct { + repr string + kind SymbolClass + opType TermPosition +} + +func init() { + + symbolMap = map[Symbol]symbolSpec{ + SymUnknown: {"", SymClassOther, PosLeaf}, // -1: Unknown symbol + SymNone: {"", SymClassOther, PosLeaf}, // 0: Null value for variable of type symbol + SymError: {"", SymClassOther, PosLeaf}, // 1: Error reading from stream + SymEos: {"", SymClassOther, PosLeaf}, // 2: End of stream + SymMinus: {"-", SymClassOperator, PosInfix}, // 3: '-' + SymMinusEqual: {"-=", SymClassOperator, PosInfix}, // 4: '-=' + SymDoubleMinus: {"--", SymClassOperator, PosPostfix}, // 5: '--' + SymPlus: {"+", SymClassOperator, PosInfix}, // 6: '+' + SymPlusEqual: {"+=", SymClassOperator, PosInfix}, // 7: '+=' + SymDoublePlus: {"++", SymClassOperator, PosPostfix}, // 8: '++' + SymStar: {"*", SymClassOperator, PosInfix}, // 9: '*' + SymDoubleStar: {"**", SymClassOperator, PosInfix}, // 10: '**' + SymSlash: {"/", SymClassOperator, PosInfix}, // 11: '/' + SymBackSlash: {"\\", SymClassOperator, PosLeaf}, // 12: '\' + SymVertBar: {"|", SymClassOperator, PosInfix}, // 13: '|' + SymDoubleVertBar: {"||", SymClassOperator, PosInfix}, // 14: '||' + SymComma: {",", SymClassOperator, PosInfix}, // 15: ',' + SymColon: {":", SymClassOperator, PosInfix}, // 16: ':' + SymSemiColon: {";", SymClassOperator, PosInfix}, // 17: ';' + SymDot: {".", SymClassOperator, PosInfix}, // 18: '.' + SymDotSlash: {"./", SymClassOperator, PosInfix}, // 19: './' + SymQuote: {"'", SymClassDelimiter, PosLeaf}, // 20: '\'' + SymDoubleQuote: {"\"", SymClassDelimiter, PosLeaf}, // 21: '"' + SymBackTick: {"`", SymClassDelimiter, PosLeaf}, // 22: '`' + SymExclamation: {"!", SymClassOperator, PosPostfix}, // 23: '!' + SymQuestion: {"?", SymClassOperator, PosInfix}, // 24: '?' + SymAmpersand: {"&", SymClassOperator, PosInfix}, // 25: '&' + SymDoubleAmpersand: {"&&", SymClassOperator, PosInfix}, // 26: '&&' + SymPercent: {"%", SymClassOperator, PosInfix}, // 27: '%' + SymAt: {"@", SymClassOperator, PosPrefix}, // 28: '@' + SymUndescore: {"_", SymClassIdentifier, PosLeaf}, // 29: '_' + SymEqual: {"=", SymClassOperator, PosInfix}, // 30: '=' + SymDoubleEqual: {"==", SymClassOperator, PosInfix}, // 31: '==' + SymLess: {"<", SymClassOperator, PosInfix}, // 32: '<' + SymLessOrEqual: {"<=", SymClassOperator, PosInfix}, // 33: '<=' + SymGreater: {">", SymClassOperator, PosInfix}, // 34: '>' + SymGreaterOrEqual: {">=", SymClassOperator, PosInfix}, // 35: '>=' + SymLessGreater: {"<>", SymClassOperator, PosInfix}, // 36: '<>' + SymNotEqual: {"!=", SymClassOperator, PosInfix}, // 37: '!=' + SymDollar: {"$", SymClassOperator, PosPrefix}, // 38: '$' + SymHash: {"#", SymClassOperator, PosPrefix}, // 39: '#' + SymOpenRound: {"(", SymClassParenthesis, PosPrefix}, // 40: '(' + SymClosedRound: {")", SymClassParenthesis, PosPostfix}, // 41: ')' + SymOpenSquare: {"[", SymClassParenthesis, PosPrefix}, // 42: '[' + SymClosedSquare: {"]", SymClassParenthesis, PosPostfix}, // 43: ']' + SymOpenBrace: {"{", SymClassParenthesis, PosPrefix}, // 44: '{' + SymClosedBrace: {"}", SymClassParenthesis, PosPostfix}, // 45: '}' + SymTilde: {"~", SymClassOperator, PosPrefix}, // 46: '~' + SymDoubleQuestion: {"??", SymClassOperator, PosInfix}, // 47: '??' + SymQuestionEqual: {"?=", SymClassOperator, PosInfix}, // 48: '?=' + SymQuestionExclam: {"?!", SymClassOperator, PosInfix}, // 49: '?!' + SymDoubleAt: {"@@", SymClassCommand, PosLeaf}, // 50: '@@' + SymDoubleColon: {"::", SymClassOperator, PosInfix}, // 51: '::' + SymDoubleGreater: {">>", SymClassOperator, PosInfix}, // 52: '>>' + SymDoubleLess: {"<<", SymClassOperator, PosInfix}, // 53: '<<' + SymCaret: {"^", SymClassOperator, PosInfix}, // 54: '^' + SymDollarRound: {"$(", SymClassOperator, PosPrefix}, // 55: '$(' + SymOpenClosedRound: {"()", SymClassOperator, PosPostfix}, // 56: '()' + SymDoubleDollar: {"$$", SymClassCommand, PosLeaf}, // 57: '$$' + SymDoubleDot: {"..", SymClassOperator, PosInfix}, // 58: '..' + SymTripleDot: {"...", SymClassOperator, PosPostfix}, // 59: '...' + SymStarEqual: {"*=", SymClassOperator, PosInfix}, // 60: '*=' + SymSlashEqual: {"/=", SymClassOperator, PosInfix}, // 61: '/=' + SymPercEqual: {"%=", SymClassOperator, PosInfix}, // 62: '%=' + SymDoubleLessEqual: {"<<=", SymClassOperator, PosInfix}, // 63: '<<=' + SymDoubleGreaterEqual: {">>=", SymClassOperator, PosInfix}, // 64: '>>=' + SymAmpersandEqual: {"&=", SymClassOperator, PosInfix}, // 65: '&=' + SymVertBarEqual: {"|=", SymClassOperator, PosInfix}, // 65: '|=' + SymCaretEqual: {"^=", SymClassOperator, PosInfix}, // 66: '^=' + SymPlusGreater: {"+>", SymClassOperator, PosInfix}, // 67: '+>' + SymLessPlus: {"<+", SymClassOperator, PosInfix}, // 68: '<+' + SymPreInc: {"++", SymClassOperator, PosPrefix}, // : '++' + SymPreDec: {"--", SymClassOperator, PosPrefix}, // : '--' + // SymChangeSign + // SymUnchangeSign + // SymIdentifier + // SymBool + // SymInteger + // SymVariable + // SymFloat + // SymFraction + // SymString + // SymIterator + // SymOr: "or", + // SymAnd: "and", + // SymNot: "not", + // SymComment + // SymFuncCall + // SymFuncDef + // SymList + // SymDict + // SymIndex + // SymExpression + // SymSelector // ::= "?" {":" } ["::" ] + // SymSelectorCase // ::= [] "{" "}" + // // SymOpenComment // 0: '/*' + // // SymClosedComment // 0: '*/' + // // SymOneLineComment // 0: '//' + // keywordBase + SymKwAnd: {"and", SymClassOperator, PosInfix}, + SymKwNot: {"not", SymClassOperator, PosInfix}, + SymKwOr: {"or", SymClassOperator, PosInfix}, + SymKwBut: {"but", SymClassOperator, PosInfix}, + SymKwMap: {"map", SymClassOperator, PosInfix}, + SymKwFilter: {"filter", SymClassOperator, PosInfix}, + SymKwDigest: {"digest", SymClassOperator, PosInfix}, + SymKwJoin: {"join", SymClassOperator, PosInfix}, + SymKwGroupBy: {"groupby", SymClassOperator, PosInfix}, + SymKwFunc: {"func(", SymClassDeclaration, PosPrefix}, + SymKwBuiltin: {"builtin", SymClassOperator, PosPrefix}, + SymKwPlugin: {"plugin", SymClassOperator, PosPrefix}, + SymKwIn: {"in", SymClassOperator, PosInfix}, + SymKwInclude: {"include", SymClassOperator, PosPrefix}, + SymKwNil: {"nil", SymClassValue, PosLeaf}, + SymKwUnset: {"unset", SymClassOperator, PosPrefix}, + } +} + +func SymToString(sym Symbol) string { + if s, ok := symbolMap[sym]; ok { + return s.repr + } + return "" +} + +func SymListToString(symList []Symbol, quote bool) string { + var sb strings.Builder + if len(symList) == 0 { + sb.WriteString("") + } else { + for _, sym := range symList { + if sb.Len() > 0 { + sb.WriteByte(',') + sb.WriteByte(' ') + } + if quote { + sb.WriteByte('`') + } + sb.WriteString(SymToString(sym)) + if quote { + sb.WriteByte('`') + } + } + } + return sb.String() +} + +func StringEndsWithOperator(s string) bool { + return endingOperator(s) != SymNone +} + +// func endingOperator(s string) (sym Symbol) { +// var matchLength = 0 +// sym = SymNone +// lower := strings.TrimRight(strings.ToLower(s), " \t") +// for symbol, spec := range symbolMap { +// if strings.HasSuffix(lower, spec.repr) { +// if len(spec.repr) > matchLength { +// matchLength = len(spec.repr) +// if spec.kind == symClassOperator && (spec.opType == PosInfix || spec.opType == PosPrefix) { +// sym = symbol +// } else { +// sym = SymNone +// } +// } +// } +// } +// return +// } + +func endingOperator(s string) (sym Symbol) { + var matchLength = 0 + var repr string + sym = SymNone + lower := strings.TrimRight(strings.ToLower(s), " \t") + for symbol, spec := range symbolMap { + if len(spec.repr) > matchLength || repr == spec.repr { + if strings.HasSuffix(lower, spec.repr) { + if isNotEndingSymbol(spec) && repr != spec.repr { + repr = spec.repr + matchLength = len(spec.repr) + sym = symbol + } else { + sym = SymNone + break + // matchLength = 0 + } + } + } + } + return +} + +func isNotEndingSymbol(spec symbolSpec) bool { + return (spec.kind == SymClassOperator && (spec.opType == PosInfix || spec.opType == PosPrefix)) || + (spec.kind == SymClassParenthesis && spec.opType == PosPrefix) +} diff --git a/symbol.go b/scan/symbol.go similarity index 99% rename from symbol.go rename to scan/symbol.go index 5f5ab99..ca33324 100644 --- a/symbol.go +++ b/scan/symbol.go @@ -2,7 +2,7 @@ // All rights reserved. // Symbol.go -package expr +package scan type Symbol int16 diff --git a/t_scanner_test.go b/scan/t_scanner_test.go similarity index 99% rename from t_scanner_test.go rename to scan/t_scanner_test.go index 748b944..83a44a5 100644 --- a/t_scanner_test.go +++ b/scan/t_scanner_test.go @@ -2,7 +2,7 @@ // All rights reserved. // t_scanner_test.go -package expr +package scan import ( "errors" diff --git a/term-constuctor-registry.go b/scan/term-constructor-registry.go similarity index 72% rename from term-constuctor-registry.go rename to scan/term-constructor-registry.go index 9479b79..8c40fa3 100644 --- a/term-constuctor-registry.go +++ b/scan/term-constructor-registry.go @@ -1,23 +1,23 @@ // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. -// op-registry.go -package expr +// term-constructor-registry.go +package scan const initialRegistryCapacity = 10 -type termContructor func(tk *Token) *term +type termContructor func(tk *Token) *Term var constructorRegistry map[Symbol]termContructor = nil -func registerTermConstructor(sym Symbol, constructor termContructor) { +func RegisterTermConstructor(sym Symbol, constructor termContructor) { if constructorRegistry == nil { constructorRegistry = make(map[Symbol]termContructor, initialRegistryCapacity) } constructorRegistry[sym] = constructor } -func newTerm(tk *Token) (inst *term) { +func NewTerm(tk *Token) (inst *Term) { if constructorRegistry != nil { if construct, exists := constructorRegistry[tk.Sym]; exists { inst = construct(tk) diff --git a/scan/term.go b/scan/term.go new file mode 100644 index 0000000..f180c9a --- /dev/null +++ b/scan/term.go @@ -0,0 +1,301 @@ +// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). +// All rights reserved. + +// term.go +package scan + +import ( + "strings" + + "git.portale-stac.it/go-pkg/expr/kern" +) + +type TermPriority uint32 + +const ( + PriNone TermPriority = iota + PriRange + PriIterOp // map, filter, digest, etc + PriBut + PriAssign + PriInsert + PriOr + PriAnd + PriNot + PriRelational + PriBitwiseOr + PriBitwiseAnd + PriBitwiseNot + PriSum + PriProduct + PriFraction + PriSelector + PriBinShift + PriSign + PriFact + PriIterValue + PriDefault + PriIncDec + PriDot + PriDereference + PriValue + PriBitwiseXor = PriBitwiseOr +) + +type TermPosition uint8 + +const ( + PosLeaf TermPosition = iota + PosInfix + PosPrefix + PosPostfix + PosMultifix +) + +type EvalFuncType func(ctx kern.ExprContext, self *Term) (v any, err error) + +type Term struct { + Tk Token + Parent *Term + Children []*Term + Position TermPosition // operator position: leaf, infix, prefix, postfix, multifix + Priority TermPriority // operator priority: higher value means higher priority + EvalFunc EvalFuncType +} + +func (t *Term) Clone() (d *Term) { + var children []*Term + if t.Children != nil { + children = make([]*Term, len(t.Children)) + for i, c := range t.Children { + children[i] = c.Clone() + } + } + d = &Term{ + Tk: *t.Tk.Clone(), + Parent: t.Parent, + Children: children, + Position: t.Position, + Priority: t.Priority, + EvalFunc: t.EvalFunc, + } + return +} + +func (t *Term) String() string { + var sb strings.Builder + t.ToString(&sb) + return sb.String() +} + +func (t *Term) ToString(sb *strings.Builder) { + if t.Position == PosLeaf { + sb.WriteString(t.Tk.String()) + } else { + sb.WriteByte('[') + sb.WriteString(t.Tk.String()) + if t.Children != nil { + sb.WriteByte('(') + for i, c := range t.Children { + if i > 0 { + sb.WriteByte(' ') + } + c.ToString(sb) + } + sb.WriteByte(')') + } + sb.WriteByte(']') + } +} + +func (t *Term) GetChildCount() (count int) { + if t.Position == PosLeaf || t.Children == nil { + count = 0 + } else { + count = len(t.Children) + } + return +} + +func (t *Term) GetRoom() (room int) { + switch t.Position { + case PosLeaf: + room = 0 + case PosInfix: + room = 2 + case PosPostfix, PosPrefix: + room = 1 + default: + panic("Invalid node position") + } + return +} + +func (t *Term) isComplete() bool { + return t.GetChildCount() == t.GetRoom() +} + +func (t *Term) removeLastChild() (child *Term) { + if t.Children != nil { + child = t.Children[len(t.Children)-1] + t.Children = t.Children[0 : len(t.Children)-1] + } else { + panic("Can't get last child") + } + return +} + +func (t *Term) isLeaf() bool { + return t.Position == PosLeaf +} + +func (t *Term) getPriority() TermPriority { + return t.Priority +} + +func (t *Term) SetParent(parent *Term) { + t.Parent = parent + if parent != nil && len(parent.Children) < cap(parent.Children) { + parent.Children = append(parent.Children, t) + } +} + +func (t *Term) Symbol() Symbol { + return t.Tk.Sym +} + +func (t *Term) Source() string { + return t.Tk.source +} + +func (t *Term) Value() any { + return t.Tk.Value +} + +func (t *Term) GetChild(index int) (c kern.Term) { + if index >= 0 && index < len(t.Children) { + c = t.Children[index] + } + return +} + +func (t *Term) GetChildSource(index int) (s string) { + if index >= 0 && index < len(t.Children) { + s = t.Children[index].Tk.source + } + return +} + +func (t *Term) IsAssign() bool { + return t.Symbol() == SymEqual +} + +func (t *Term) Compute(ctx kern.ExprContext) (v any, err error) { + if t.EvalFunc == nil { + err = t.Errorf("undefined eval-func for %q term", t.Source()) + } else { + v, err = t.EvalFunc(ctx, t) + } + return +} + +// func (term *term) toInt(computedValue any, valueDescription string) (i int, err error) { +// if index64, ok := computedValue.(int64); ok { +// i = int(index64) +// } else { +// err = term.Errorf("%s, got %s (%v)", valueDescription, TypeName(computedValue), computedValue) +// } +// return +// } + +func (t *Term) ErrIncompatibleTypes(leftValue, rightValue any) error { + leftType := kern.TypeName(leftValue) + leftText := kern.GetFormatted(leftValue, kern.Truncate) + rightType := kern.TypeName(rightValue) + rightText := kern.GetFormatted(rightValue, kern.Truncate) + return t.Tk.Errorf( + "left operand '%s' [%s] and right operand '%s' [%s] are not compatible with operator %q", + leftText, leftType, + rightText, rightType, + t.Source()) +} + +func (t *Term) ErrIncompatibleType(value any, side string) error { + return t.Tk.Errorf( + "operator %q does not support operand '%v' [%s] on its %s side", + t.Source(), value, kern.TypeName(value), side) +} + +func (t *Term) ErrIncompatiblePrefixPostfixType(value any) error { + return t.Tk.Errorf( + "prefix/postfix operator %q does not support operand '%v' [%s]", + t.Source(), value, kern.TypeName(value)) +} + +func (t *Term) ErrDivisionByZero() error { + return t.Tk.Errorf("division by zero") +} + +func (t *Term) ErrKeyNotFound(key any) error { + return t.Tk.Errorf("key '%v' not found", key) +} + +func (t *Term) Errorf(template string, args ...any) (err error) { + err = t.Tk.Errorf(template, args...) + return +} + +func (t *Term) CheckOperands() (err error) { + switch t.Position { + case PosInfix: + if t.Children == nil || len(t.Children) != 2 || t.anyChildrenNil() { + err = t.Tk.Errorf("infix operator %q requires two non-nil operands, got %d", t.Source(), t.GetChildCount()) + } + case PosPrefix: + if t.Children == nil || len(t.Children) != 1 || t.Children[0] == nil { + err = t.Tk.Errorf("prefix operator %q requires one non-nil operand", t.Tk.String()) + } + case PosPostfix: + if t.Children == nil || len(t.Children) != 1 || t.anyChildrenNil() { + err = t.Tk.Errorf("postfix operator %q requires one non-nil operand", t.Tk.String()) + } + case PosMultifix: + if len(t.Children) < 3 || t.anyChildrenNil() { + err = t.Tk.Errorf("infix operator %q requires at least three not operands, got %d", t.Source(), t.GetChildCount()) + } + } + return +} + +func (t *Term) anyChildrenNil() bool { + for _, child := range t.Children { + if child == nil { + return true + } + } + return false +} +func (t *Term) EvalInfix(ctx kern.ExprContext) (leftValue, rightValue any, err error) { + if err = t.CheckOperands(); err == nil { + if leftValue, err = t.Children[0].Compute(ctx); err == nil { + rightValue, err = t.Children[1].Compute(ctx) + } + } + return +} + +func (t *Term) EvalPrefix(ctx kern.ExprContext) (childValue any, err error) { + if err = t.CheckOperands(); err == nil { + childValue, err = t.Children[0].Compute(ctx) + } + return +} + +// NOTE Temporary solution to support function parameters with default value + +func (t *Term) ForceChild(c *Term) { + if t.Children == nil { + t.Children = make([]*Term, 0, 1) + } + t.Children = append(t.Children, c) +} diff --git a/token.go b/scan/token.go similarity index 94% rename from token.go rename to scan/token.go index e779619..293e13f 100644 --- a/token.go +++ b/scan/token.go @@ -2,7 +2,7 @@ // All rights reserved. // token.go -package expr +package scan import ( "fmt" @@ -51,6 +51,18 @@ func NewErrorToken(row, col int, err error) *Token { return NewValueToken(row, col, SymError, fmt.Sprintf("[%d:%d]", row, col), err) } +func (tk *Token) Source() string { + return tk.source +} + +func (tk *Token) Row() int { + return tk.row +} + +func (tk *Token) Col() int { + return tk.col +} + func (tk *Token) Clone() (c *Token) { return NewValueToken(tk.row, tk.col, tk.Sym, tk.source, tk.Value) } diff --git a/symbol-map.go b/symbol-map.go deleted file mode 100644 index bb95e67..0000000 --- a/symbol-map.go +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). -// All rights reserved. - -// Symbol.go -package expr - -import ( - "strings" -) - -var symbolMap map[Symbol]symbolSpec - -type symbolClass int16 - -const ( - symClassOperator symbolClass = iota - symClassCommand - symClassIdentifier - symClassDelimiter - symClassParenthesis - symClassDeclaration - symClassValue - symClassOther -) - -type symbolSpec struct { - repr string - kind symbolClass - opType termPosition -} - -func init() { - - symbolMap = map[Symbol]symbolSpec{ - SymUnknown: {"", symClassOther, posLeaf}, // -1: Unknown symbol - SymNone: {"", symClassOther, posLeaf}, // 0: Null value for variable of type symbol - SymError: {"", symClassOther, posLeaf}, // 1: Error reading from stream - SymEos: {"", symClassOther, posLeaf}, // 2: End of stream - SymMinus: {"-", symClassOperator, posInfix}, // 3: '-' - SymMinusEqual: {"-=", symClassOperator, posInfix}, // 4: '-=' - SymDoubleMinus: {"--", symClassOperator, posPostfix}, // 5: '--' - SymPlus: {"+", symClassOperator, posInfix}, // 6: '+' - SymPlusEqual: {"+=", symClassOperator, posInfix}, // 7: '+=' - SymDoublePlus: {"++", symClassOperator, posPostfix}, // 8: '++' - SymStar: {"*", symClassOperator, posInfix}, // 9: '*' - SymDoubleStar: {"**", symClassOperator, posInfix}, // 10: '**' - SymSlash: {"/", symClassOperator, posInfix}, // 11: '/' - SymBackSlash: {"\\", symClassOperator, posLeaf}, // 12: '\' - SymVertBar: {"|", symClassOperator, posInfix}, // 13: '|' - SymDoubleVertBar: {"||", symClassOperator, posInfix}, // 14: '||' - SymComma: {",", symClassOperator, posInfix}, // 15: ',' - SymColon: {":", symClassOperator, posInfix}, // 16: ':' - SymSemiColon: {";", symClassOperator, posInfix}, // 17: ';' - SymDot: {".", symClassOperator, posInfix}, // 18: '.' - SymDotSlash: {"./", symClassOperator, posInfix}, // 19: './' - SymQuote: {"'", symClassDelimiter, posLeaf}, // 20: '\'' - SymDoubleQuote: {"\"", symClassDelimiter, posLeaf}, // 21: '"' - SymBackTick: {"`", symClassDelimiter, posLeaf}, // 22: '`' - SymExclamation: {"!", symClassOperator, posPostfix}, // 23: '!' - SymQuestion: {"?", symClassOperator, posInfix}, // 24: '?' - SymAmpersand: {"&", symClassOperator, posInfix}, // 25: '&' - SymDoubleAmpersand: {"&&", symClassOperator, posInfix}, // 26: '&&' - SymPercent: {"%", symClassOperator, posInfix}, // 27: '%' - SymAt: {"@", symClassOperator, posPrefix}, // 28: '@' - SymUndescore: {"_", symClassIdentifier, posLeaf}, // 29: '_' - SymEqual: {"=", symClassOperator, posInfix}, // 30: '=' - SymDoubleEqual: {"==", symClassOperator, posInfix}, // 31: '==' - SymLess: {"<", symClassOperator, posInfix}, // 32: '<' - SymLessOrEqual: {"<=", symClassOperator, posInfix}, // 33: '<=' - SymGreater: {">", symClassOperator, posInfix}, // 34: '>' - SymGreaterOrEqual: {">=", symClassOperator, posInfix}, // 35: '>=' - SymLessGreater: {"<>", symClassOperator, posInfix}, // 36: '<>' - SymNotEqual: {"!=", symClassOperator, posInfix}, // 37: '!=' - SymDollar: {"$", symClassOperator, posPrefix}, // 38: '$' - SymHash: {"#", symClassOperator, posPrefix}, // 39: '#' - SymOpenRound: {"(", symClassParenthesis, posPrefix}, // 40: '(' - SymClosedRound: {")", symClassParenthesis, posPostfix}, // 41: ')' - SymOpenSquare: {"[", symClassParenthesis, posPrefix}, // 42: '[' - SymClosedSquare: {"]", symClassParenthesis, posPostfix}, // 43: ']' - SymOpenBrace: {"{", symClassParenthesis, posPrefix}, // 44: '{' - SymClosedBrace: {"}", symClassParenthesis, posPostfix}, // 45: '}' - SymTilde: {"~", symClassOperator, posPrefix}, // 46: '~' - SymDoubleQuestion: {"??", symClassOperator, posInfix}, // 47: '??' - SymQuestionEqual: {"?=", symClassOperator, posInfix}, // 48: '?=' - SymQuestionExclam: {"?!", symClassOperator, posInfix}, // 49: '?!' - SymDoubleAt: {"@@", symClassCommand, posLeaf}, // 50: '@@' - SymDoubleColon: {"::", symClassOperator, posInfix}, // 51: '::' - SymDoubleGreater: {">>", symClassOperator, posInfix}, // 52: '>>' - SymDoubleLess: {"<<", symClassOperator, posInfix}, // 53: '<<' - SymCaret: {"^", symClassOperator, posInfix}, // 54: '^' - SymDollarRound: {"$(", symClassOperator, posPrefix}, // 55: '$(' - SymOpenClosedRound: {"()", symClassOperator, posPostfix}, // 56: '()' - SymDoubleDollar: {"$$", symClassCommand, posLeaf}, // 57: '$$' - SymDoubleDot: {"..", symClassOperator, posInfix}, // 58: '..' - SymTripleDot: {"...", symClassOperator, posPostfix}, // 59: '...' - SymStarEqual: {"*=", symClassOperator, posInfix}, // 60: '*=' - SymSlashEqual: {"/=", symClassOperator, posInfix}, // 61: '/=' - SymPercEqual: {"%=", symClassOperator, posInfix}, // 62: '%=' - SymDoubleLessEqual: {"<<=", symClassOperator, posInfix}, // 63: '<<=' - SymDoubleGreaterEqual: {">>=", symClassOperator, posInfix}, // 64: '>>=' - SymAmpersandEqual: {"&=", symClassOperator, posInfix}, // 65: '&=' - SymVertBarEqual: {"|=", symClassOperator, posInfix}, // 65: '|=' - SymCaretEqual: {"^=", symClassOperator, posInfix}, // 66: '^=' - SymPlusGreater: {"+>", symClassOperator, posInfix}, // 67: '+>' - SymLessPlus: {"<+", symClassOperator, posInfix}, // 68: '<+' - SymPreInc: {"++", symClassOperator, posPrefix}, // : '++' - SymPreDec: {"--", symClassOperator, posPrefix}, // : '--' - // SymChangeSign - // SymUnchangeSign - // SymIdentifier - // SymBool - // SymInteger - // SymVariable - // SymFloat - // SymFraction - // SymString - // SymIterator - // SymOr: "or", - // SymAnd: "and", - // SymNot: "not", - // SymComment - // SymFuncCall - // SymFuncDef - // SymList - // SymDict - // SymIndex - // SymExpression - // SymSelector // ::= "?" {":" } ["::" ] - // SymSelectorCase // ::= [] "{" "}" - // // SymOpenComment // 0: '/*' - // // SymClosedComment // 0: '*/' - // // SymOneLineComment // 0: '//' - // keywordBase - SymKwAnd: {"and", symClassOperator, posInfix}, - SymKwNot: {"not", symClassOperator, posInfix}, - SymKwOr: {"or", symClassOperator, posInfix}, - SymKwBut: {"but", symClassOperator, posInfix}, - SymKwMap: {"map", symClassOperator, posInfix}, - SymKwFilter: {"filter", symClassOperator, posInfix}, - SymKwDigest: {"digest", symClassOperator, posInfix}, - SymKwJoin: {"join", symClassOperator, posInfix}, - SymKwGroupBy: {"groupby", symClassOperator, posInfix}, - SymKwFunc: {"func(", symClassDeclaration, posPrefix}, - SymKwBuiltin: {"builtin", symClassOperator, posPrefix}, - SymKwPlugin: {"plugin", symClassOperator, posPrefix}, - SymKwIn: {"in", symClassOperator, posInfix}, - SymKwInclude: {"include", symClassOperator, posPrefix}, - SymKwNil: {"nil", symClassValue, posLeaf}, - SymKwUnset: {"unset", symClassOperator, posPrefix}, - } -} - -func SymToString(sym Symbol) string { - if s, ok := symbolMap[sym]; ok { - return s.repr - } - return "" -} - -func SymListToString(symList []Symbol, quote bool) string { - var sb strings.Builder - if len(symList) == 0 { - sb.WriteString("") - } else { - for _, sym := range symList { - if sb.Len() > 0 { - sb.WriteByte(',') - sb.WriteByte(' ') - } - if quote { - sb.WriteByte('`') - } - sb.WriteString(SymToString(sym)) - if quote { - sb.WriteByte('`') - } - } - } - return sb.String() -} - -func StringEndsWithOperator(s string) bool { - return endingOperator(s) != SymNone -} - -// func endingOperator(s string) (sym Symbol) { -// var matchLength = 0 -// sym = SymNone -// lower := strings.TrimRight(strings.ToLower(s), " \t") -// for symbol, spec := range symbolMap { -// if strings.HasSuffix(lower, spec.repr) { -// if len(spec.repr) > matchLength { -// matchLength = len(spec.repr) -// if spec.kind == symClassOperator && (spec.opType == posInfix || spec.opType == posPrefix) { -// sym = symbol -// } else { -// sym = SymNone -// } -// } -// } -// } -// return -// } - -func endingOperator(s string) (sym Symbol) { - var matchLength = 0 - var repr string - sym = SymNone - lower := strings.TrimRight(strings.ToLower(s), " \t") - for symbol, spec := range symbolMap { - if len(spec.repr) > matchLength || repr == spec.repr { - if strings.HasSuffix(lower, spec.repr) { - if isNotEndingSymbol(spec) && repr != spec.repr { - repr = spec.repr - matchLength = len(spec.repr) - sym = symbol - } else { - sym = SymNone - break - // matchLength = 0 - } - } - } - } - return -} - -func isNotEndingSymbol(spec symbolSpec) bool { - return (spec.kind == symClassOperator && (spec.opType == posInfix || spec.opType == posPrefix)) || - (spec.kind == symClassParenthesis && spec.opType == posPrefix) -} diff --git a/t_ast_test.go b/t_ast_test.go index 45ed9a6..add1bfe 100644 --- a/t_ast_test.go +++ b/t_ast_test.go @@ -7,47 +7,49 @@ package expr import ( "errors" "testing" + + "git.portale-stac.it/go-pkg/expr/scan" ) func TestAstString(t *testing.T) { - tree := NewAst() + tree := scan.NewAst() if gotResult := tree.String(); gotResult != "(nil)" { t.Errorf(`result: got %q, want "(nil)"`, gotResult) } } func TestAddTokensGood(t *testing.T) { - tk1 := NewValueToken(0, 0, SymInteger, "100", 100) - tk2 := NewToken(0, 0, SymPlus, "+") - tk3 := NewValueToken(0, 0, SymInteger, "50", 500) + tk1 := scan.NewValueToken(0, 0, scan.SymInteger, "100", 100) + tk2 := scan.NewToken(0, 0, scan.SymPlus, "+") + tk3 := scan.NewValueToken(0, 0, scan.SymInteger, "50", 500) - tree := NewAst() - if gotErr := tree.addTokens(tk1, tk2, tk3); gotErr != nil { + tree := scan.NewAst() + if gotErr := tree.AddTokens(tk1, tk2, tk3); gotErr != nil { t.Errorf("err: got <%v>, want ", gotErr) } } func TestAddTokensBad(t *testing.T) { - tk0 := NewValueToken(0, 0, SymInteger, "200", 200) - tk1 := NewValueToken(0, 0, SymInteger, "100", 100) - tk2 := NewToken(0, 0, SymPlus, "+") - tk3 := NewValueToken(0, 0, SymInteger, "50", 500) + tk0 := scan.NewValueToken(0, 0, scan.SymInteger, "200", 200) + tk1 := scan.NewValueToken(0, 0, scan.SymInteger, "100", 100) + tk2 := scan.NewToken(0, 0, scan.SymPlus, "+") + tk3 := scan.NewValueToken(0, 0, scan.SymInteger, "50", 500) wantErr := errors.New(`[0:0] two adjacent operators: "200" and "100"`) - tree := NewAst() - if gotErr := tree.addTokens(tk0, tk1, tk2, tk3); gotErr != nil && gotErr.Error() != wantErr.Error() { + tree := scan.NewAst() + if gotErr := tree.AddTokens(tk0, tk1, tk2, tk3); gotErr != nil && gotErr.Error() != wantErr.Error() { t.Errorf("err: got <%v>, want ", gotErr) } } func TestAddUnknownTokens(t *testing.T) { - tk0 := NewToken(0, 0, SymPercent, "%") + tk0 := scan.NewToken(0, 0, scan.SymPercent, "%") wantErr := errors.New(`unexpected token "%"`) - tree := NewAst() - if _, gotErr := tree.addToken(tk0); gotErr != nil && gotErr.Error() != wantErr.Error() { + tree := scan.NewAst() + if _, gotErr := tree.AddToken(tk0); gotErr != nil && gotErr.Error() != wantErr.Error() { t.Errorf("err: got <%v>, want <%v>", gotErr, wantErr) } } diff --git a/t_common_test.go b/t_common_test.go index bd5668d..9d9166b 100644 --- a/t_common_test.go +++ b/t_common_test.go @@ -10,6 +10,7 @@ import ( "testing" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) type inputType struct { @@ -70,7 +71,7 @@ func getWantedError(input *inputType) error { } func doTest(t *testing.T, ctx kern.ExprContext, section string, input *inputType, count int) (good bool) { - var ast Expr + var ast kern.Expr var gotResult any var gotErr error @@ -84,7 +85,7 @@ func doTest(t *testing.T, ctx kern.ExprContext, section string, input *inputType logTest(t, count, section, input.source, input.wantResult, wantErr) r := strings.NewReader(input.source) - scanner := NewScanner(r, DefaultTranslations()) + scanner := scan.NewScanner(r, scan.DefaultTranslations()) good = true if ast, gotErr = parser.Parse(scanner); gotErr == nil { diff --git a/t_dict_test.go b/t_dict_test.go index ce764de..45842df 100644 --- a/t_dict_test.go +++ b/t_dict_test.go @@ -11,6 +11,7 @@ import ( "testing" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) func TestDictParser(t *testing.T) { @@ -52,7 +53,7 @@ func TestDictParser(t *testing.T) { // } for i, input := range inputs { - var expr *ast + var expr *scan.Ast var gotResult any var gotErr error @@ -65,7 +66,7 @@ func TestDictParser(t *testing.T) { logTest(t, i+1, "Dict", input.source, input.wantResult, input.wantErr) r := strings.NewReader(input.source) - scanner := NewScanner(r, DefaultTranslations()) + scanner := scan.NewScanner(r, scan.DefaultTranslations()) good := true if expr, gotErr = parser.Parse(scanner); gotErr == nil { @@ -124,7 +125,7 @@ func TestDictToStringMultiLine(t *testing.T) { "first": 1 }` args := map[any]any{ - "first": newLiteralTerm(NewValueToken(0, 0, SymInteger, "1", 1)), + "first": newLiteralTerm(scan.NewValueToken(0, 0, scan.SymInteger, "1", 1)), } dict := kern.NewDict(args) got := dict.ToString(kern.MultiLine) @@ -146,7 +147,7 @@ func TestDictToString(t *testing.T) { section := "dict-ToString-SL" want := `{"first": 1}` args := map[any]any{ - "first": newLiteralTerm(NewValueToken(0, 0, SymInteger, "1", 1)), + "first": newLiteralTerm(scan.NewValueToken(0, 0, scan.SymInteger, "1", 1)), } dict := kern.NewDict(args) got := dict.ToString(0) diff --git a/t_symbol_test.go b/t_symbol_test.go index 4a75d96..824c0b8 100644 --- a/t_symbol_test.go +++ b/t_symbol_test.go @@ -8,6 +8,7 @@ import ( "testing" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) func TestOperatorEnding(t *testing.T) { @@ -28,7 +29,7 @@ func TestOperatorEnding(t *testing.T) { } func testStringEndingWithOperator(source string) bool { - return StringEndsWithOperator(source) + return scan.StringEndsWithOperator(source) } func testStringArrayEndingWithOperatorSpec(t *testing.T, section string, inputs []inputType, spec ...int) { diff --git a/t_term_test.go b/t_term_test.go index 0c22a85..4ae9b37 100644 --- a/t_term_test.go +++ b/t_term_test.go @@ -6,15 +6,17 @@ package expr import ( "testing" + + "git.portale-stac.it/go-pkg/expr/scan" ) func TestString(t *testing.T) { - tk1 := NewValueToken(0, 0, SymInteger, "100", 100) - tk2 := NewToken(0, 0, SymPlus, "+") - tk3 := NewValueToken(0, 0, SymInteger, "50", 500) + tk1 := scan.NewValueToken(0, 0, scan.SymInteger, "100", 100) + tk2 := scan.NewToken(0, 0, scan.SymPlus, "+") + tk3 := scan.NewValueToken(0, 0, scan.SymInteger, "50", 500) - tree := NewAst() - if gotErr := tree.addTokens(tk1, tk2, tk3); gotErr == nil { + tree := scan.NewAst() + if gotErr := tree.AddTokens(tk1, tk2, tk3); gotErr == nil { t.Log("Tree:", tree) } else { t.Errorf("err: got <%v>, want ", gotErr) @@ -22,22 +24,22 @@ func TestString(t *testing.T) { } func TestGetRoom(t *testing.T) { - tk1 := NewValueToken(0, 0, SymInteger, "100", 100) + tk1 := scan.NewValueToken(0, 0, scan.SymInteger, "100", 100) - tree := NewAst() - if gotErr := tree.addTokens(tk1); gotErr == nil { - t.Log("Tree-root room:", tree.root.getRoom()) + tree := scan.NewAst() + if gotErr := tree.AddTokens(tk1); gotErr == nil { + t.Log("Tree-root room:", tree.Root().GetRoom()) } else { t.Errorf("err: got <%v>, want ", gotErr) } } func TestGetChildrenCount(t *testing.T) { - tk1 := NewValueToken(0, 0, SymInteger, "100", 100) + tk1 := scan.NewValueToken(0, 0, scan.SymInteger, "100", 100) - tree := NewAst() - if gotErr := tree.addTokens(tk1); gotErr == nil { - t.Log("Tree-root children count:", tree.root.GetChildCount()) + tree := scan.NewAst() + if gotErr := tree.AddTokens(tk1); gotErr == nil { + t.Log("Tree-root children count:", tree.Root().GetChildCount()) } else { t.Errorf("err: got <%v>, want ", gotErr) } diff --git a/t_token_test.go b/t_token_test.go index aef7a65..e913570 100644 --- a/t_token_test.go +++ b/t_token_test.go @@ -7,27 +7,29 @@ package expr import ( "fmt" "testing" + + "git.portale-stac.it/go-pkg/expr/scan" ) func TestDevString(t *testing.T) { type inputType struct { source string - sym Symbol + sym scan.Symbol value any wantResult string } inputs := []inputType{ - /* 1 */ {"100", SymInteger, 100, fmt.Sprintf(`[%d]"100"{100}`, SymInteger)}, - /* 2 */ {"+", SymPlus, nil, fmt.Sprintf(`[%d]"+"{}`, SymPlus)}, + /* 1 */ {"100", scan.SymInteger, 100, fmt.Sprintf(`[%d]"100"{100}`, scan.SymInteger)}, + /* 2 */ {"+", scan.SymPlus, nil, fmt.Sprintf(`[%d]"+"{}`, scan.SymPlus)}, } for i, input := range inputs { - var tk *Token + var tk *scan.Token if input.value == nil { - tk = NewToken(0, 0, input.sym, input.source) + tk = scan.NewToken(0, 0, input.sym, input.source) } else { - tk = NewValueToken(0, 0, input.sym, input.source, input.value) + tk = scan.NewValueToken(0, 0, input.sym, input.source, input.value) } t.Logf("Test nr %2d: %q --> %q", i+1, input.source, input.wantResult) diff --git a/term.go b/term.go deleted file mode 100644 index 94860d5..0000000 --- a/term.go +++ /dev/null @@ -1,300 +0,0 @@ -// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). -// All rights reserved. - -// term.go -package expr - -import ( - "strings" - - "git.portale-stac.it/go-pkg/expr/kern" -) - -type termPriority uint32 - -const ( - priNone termPriority = iota - priRange - priIterOp // map, filter, digest, etc - priBut - priAssign - priInsert - priOr - priAnd - priNot - priRelational - priBitwiseOr - priBitwiseAnd - priBitwiseNot - priSum - priProduct - priFraction - priSelector - priBinShift - priSign - priFact - priIterValue - priDefault - priIncDec - priDot - priDereference - priValue -) - -type termPosition uint8 - -const ( - posLeaf termPosition = iota - posInfix - posPrefix - posPostfix - posMultifix -) - -type evalFuncType func(ctx kern.ExprContext, self *term) (v any, err error) - -type term struct { - tk Token - parent *term - children []*term - position termPosition // operator position: leaf, infix, prefix, postfix, multifix - priority termPriority // operator priority: higher value means higher priority - evalFunc evalFuncType -} - -func (t *term) Clone() (d *term) { - var children []*term - if t.children != nil { - children = make([]*term, len(t.children)) - for i, c := range t.children { - children[i] = c.Clone() - } - } - d = &term{ - tk: *t.tk.Clone(), - parent: t.parent, - children: children, - position: t.position, - priority: t.priority, - evalFunc: t.evalFunc, - } - return -} - -func (t *term) String() string { - var sb strings.Builder - t.toString(&sb) - return sb.String() -} - -func (t *term) toString(sb *strings.Builder) { - if t.position == posLeaf { - sb.WriteString(t.tk.String()) - } else { - sb.WriteByte('[') - sb.WriteString(t.tk.String()) - if t.children != nil { - sb.WriteByte('(') - for i, c := range t.children { - if i > 0 { - sb.WriteByte(' ') - } - c.toString(sb) - } - sb.WriteByte(')') - } - sb.WriteByte(']') - } -} - -func (t *term) GetChildCount() (count int) { - if t.position == posLeaf || t.children == nil { - count = 0 - } else { - count = len(t.children) - } - return -} - -func (t *term) getRoom() (room int) { - switch t.position { - case posLeaf: - room = 0 - case posInfix: - room = 2 - case posPostfix, posPrefix: - room = 1 - default: - panic("Invalid node position") - } - return -} - -func (t *term) isComplete() bool { - return t.GetChildCount() == t.getRoom() -} - -func (t *term) removeLastChild() (child *term) { - if t.children != nil { - child = t.children[len(t.children)-1] - t.children = t.children[0 : len(t.children)-1] - } else { - panic("Can't get last child") - } - return -} - -func (t *term) isLeaf() bool { - return t.position == posLeaf -} - -func (t *term) getPriority() termPriority { - return t.priority -} - -func (t *term) setParent(parent *term) { - t.parent = parent - if parent != nil && len(parent.children) < cap(parent.children) { - parent.children = append(parent.children, t) - } -} - -func (t *term) symbol() Symbol { - return t.tk.Sym -} - -func (t *term) Source() string { - return t.tk.source -} - -func (t *term) value() any { - return t.tk.Value -} - -func (t *term) GetChild(index int) (c kern.Term) { - if index >= 0 && index < len(t.children) { - c = t.children[index] - } - return -} - -func (t *term) GetChildSource(index int) (s string) { - if index >= 0 && index < len(t.children) { - s = t.children[index].tk.source - } - return -} - -func (t *term) IsAssign() bool { - return t.symbol() == SymEqual -} - -func (t *term) Compute(ctx kern.ExprContext) (v any, err error) { - if t.evalFunc == nil { - err = t.Errorf("undefined eval-func for %q term", t.Source()) - } else { - v, err = t.evalFunc(ctx, t) - } - return -} - -// func (term *term) toInt(computedValue any, valueDescription string) (i int, err error) { -// if index64, ok := computedValue.(int64); ok { -// i = int(index64) -// } else { -// err = term.Errorf("%s, got %s (%v)", valueDescription, TypeName(computedValue), computedValue) -// } -// return -// } - -func (t *term) errIncompatibleTypes(leftValue, rightValue any) error { - leftType := kern.TypeName(leftValue) - leftText := kern.GetFormatted(leftValue, kern.Truncate) - rightType := kern.TypeName(rightValue) - rightText := kern.GetFormatted(rightValue, kern.Truncate) - return t.tk.Errorf( - "left operand '%s' [%s] and right operand '%s' [%s] are not compatible with operator %q", - leftText, leftType, - rightText, rightType, - t.Source()) -} - -func (t *term) errIncompatibleType(value any, side string) error { - return t.tk.Errorf( - "operator %q does not support operand '%v' [%s] on its %s side", - t.Source(), value, kern.TypeName(value), side) -} - -func (t *term) errIncompatiblePrefixPostfixType(value any) error { - return t.tk.Errorf( - "prefix/postfix operator %q does not support operand '%v' [%s]", - t.Source(), value, kern.TypeName(value)) -} - -func (t *term) errDivisionByZero() error { - return t.tk.Errorf("division by zero") -} - -func (t *term) errKeyNotFound(key any) error { - return t.tk.Errorf("key '%v' not found", key) -} - -func (t *term) Errorf(template string, args ...any) (err error) { - err = t.tk.Errorf(template, args...) - return -} - -func (t *term) checkOperands() (err error) { - switch t.position { - case posInfix: - if t.children == nil || len(t.children) != 2 || t.anyChildrenNil() { - err = t.tk.Errorf("infix operator %q requires two non-nil operands, got %d", t.Source(), t.GetChildCount()) - } - case posPrefix: - if t.children == nil || len(t.children) != 1 || t.children[0] == nil { - err = t.tk.Errorf("prefix operator %q requires one non-nil operand", t.tk.String()) - } - case posPostfix: - if t.children == nil || len(t.children) != 1 || t.anyChildrenNil() { - err = t.tk.Errorf("postfix operator %q requires one non-nil operand", t.tk.String()) - } - case posMultifix: - if t.children == nil || len(t.children) < 3 || t.anyChildrenNil() { - err = t.tk.Errorf("infix operator %q requires at least three not operands, got %d", t.Source(), t.GetChildCount()) - } - } - return -} - -func (t *term) anyChildrenNil() bool { - for _, child := range t.children { - if child == nil { - return true - } - } - return false -} -func (t *term) evalInfix(ctx kern.ExprContext) (leftValue, rightValue any, err error) { - if err = t.checkOperands(); err == nil { - if leftValue, err = t.children[0].Compute(ctx); err == nil { - rightValue, err = t.children[1].Compute(ctx) - } - } - return -} - -func (t *term) evalPrefix(ctx kern.ExprContext) (childValue any, err error) { - if err = t.checkOperands(); err == nil { - childValue, err = t.children[0].Compute(ctx) - } - return -} - -// NOTE Temporary solution to support function parameters with default value - -func (t *term) forceChild(c *term) { - if t.children == nil { - t.children = make([]*term, 0, 1) - } - t.children = append(t.children, c) -} diff --git a/byte-slider.go b/util/byte-slider.go similarity index 98% rename from byte-slider.go rename to util/byte-slider.go index 5fb8d3d..ada2b36 100644 --- a/byte-slider.go +++ b/util/byte-slider.go @@ -2,7 +2,7 @@ // All rights reserved. // byte-slider.go -package expr +package util import "bytes" diff --git a/util/utils-unix.go b/util/utils-unix.go index d1b3728..6b5543f 100644 --- a/util/utils-unix.go +++ b/util/utils-unix.go @@ -1,8 +1,8 @@ -//go:build unix - // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. +//go:build unix + // utils-unix.go package util