moved scanner sources to package 'scan'
This commit is contained in:
@@ -12,7 +12,7 @@ import (
|
|||||||
type exprFunctor struct {
|
type exprFunctor struct {
|
||||||
kern.BaseFunctor
|
kern.BaseFunctor
|
||||||
params []kern.ExprFuncParam
|
params []kern.ExprFuncParam
|
||||||
expr Expr
|
expr kern.Expr
|
||||||
defCtx kern.ExprContext
|
defCtx kern.ExprContext
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ func (functor *exprFunctor) GetParams() (params []kern.ExprFuncParam) {
|
|||||||
return functor.params
|
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
|
var defCtx kern.ExprContext
|
||||||
if ctx != nil {
|
if ctx != nil {
|
||||||
defCtx = ctx
|
defCtx = ctx
|
||||||
|
|||||||
+3
-2
@@ -11,6 +11,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
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) {
|
func evalFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||||
if source, ok := args[kern.ParamSource].(string); ok {
|
if source, ok := args[kern.ParamSource].(string); ok {
|
||||||
var ast Expr
|
var ast kern.Expr
|
||||||
|
|
||||||
parser := NewParser()
|
parser := NewParser()
|
||||||
if ctx == nil {
|
if ctx == nil {
|
||||||
@@ -207,7 +208,7 @@ func evalFunc(ctx kern.ExprContext, name string, args map[string]any) (result an
|
|||||||
}
|
}
|
||||||
|
|
||||||
r := strings.NewReader(source)
|
r := strings.NewReader(source)
|
||||||
scanner := NewScanner(r, DefaultTranslations())
|
scanner := scan.NewScanner(r, scan.DefaultTranslations())
|
||||||
|
|
||||||
if ast, err = parser.Parse(scanner); err == nil {
|
if ast, err = parser.Parse(scanner); err == nil {
|
||||||
CtrlEnable(ctx, kern.ControlExportAll)
|
CtrlEnable(ctx, kern.ControlExportAll)
|
||||||
|
|||||||
+4
-3
@@ -9,6 +9,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"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) {
|
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
|
var file *os.File
|
||||||
if file, err = os.Open(sourceFilepath); err == nil {
|
if file, err = os.Open(sourceFilepath); err == nil {
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
var expr *ast
|
var expr *scan.Ast
|
||||||
scanner := NewScanner(file, DefaultTranslations())
|
scanner := scan.NewScanner(file, scan.DefaultTranslations())
|
||||||
parser := NewParser()
|
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)
|
result, err = expr.Eval(ctx)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
+5
-4
@@ -9,6 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ---- Function template
|
// ---- Function template
|
||||||
@@ -223,7 +224,7 @@ func (info *funcInfo) ParamSpec(paramName string) kern.ExprFuncParam {
|
|||||||
return nil
|
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 varArgs []any
|
||||||
var varName string
|
var varName string
|
||||||
|
|
||||||
@@ -235,7 +236,7 @@ func initActualParams(ctx kern.ExprContext, info kern.ExprFunc, callTerm *term)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tree := range callTerm.children {
|
for i, tree := range callTerm.Children {
|
||||||
var paramValue any
|
var paramValue any
|
||||||
paramCtx := ctx.Clone()
|
paramCtx := ctx.Clone()
|
||||||
if paramValue, err = tree.Compute(paramCtx); err != nil {
|
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) {
|
} else if i < len(formalParams) {
|
||||||
spec := formalParams[i]
|
spec := formalParams[i]
|
||||||
if spec.IsRepeat() {
|
if spec.IsRepeat() {
|
||||||
varArgs = make([]any, 0, len(callTerm.children)-i)
|
varArgs = make([]any, 0, len(callTerm.Children)-i)
|
||||||
varArgs = append(varArgs, paramValue)
|
varArgs = append(varArgs, paramValue)
|
||||||
varName = spec.Name()
|
varName = spec.Name()
|
||||||
} else {
|
} else {
|
||||||
actualParams[spec.Name()] = paramValue
|
actualParams[spec.Name()] = paramValue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = kern.ErrTooManyParams(info.Name(), len(formalParams), len(callTerm.children))
|
err = kern.ErrTooManyParams(info.Name(), len(formalParams), len(callTerm.Children))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+5
-4
@@ -11,14 +11,15 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
"git.portale-stac.it/go-pkg/expr/util"
|
"git.portale-stac.it/go-pkg/expr/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func EvalString(ctx kern.ExprContext, source string) (result any, err error) {
|
func EvalString(ctx kern.ExprContext, source string) (result any, err error) {
|
||||||
var tree *ast
|
var tree *scan.Ast
|
||||||
|
|
||||||
r := strings.NewReader(source)
|
r := strings.NewReader(source)
|
||||||
scanner := NewScanner(r, DefaultTranslations())
|
scanner := scan.NewScanner(r, scan.DefaultTranslations())
|
||||||
parser := NewParser()
|
parser := NewParser()
|
||||||
|
|
||||||
if tree, err = parser.Parse(scanner); err == nil {
|
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) {
|
func EvalStream(ctx kern.ExprContext, r io.Reader) (result any, err error) {
|
||||||
var tree *ast
|
var tree *scan.Ast
|
||||||
scanner := NewScanner(r, DefaultTranslations())
|
scanner := scan.NewScanner(r, scan.DefaultTranslations())
|
||||||
parser := NewParser()
|
parser := NewParser()
|
||||||
|
|
||||||
if tree, err = parser.Parse(scanner); err == nil {
|
if tree, err = parser.Parse(scanner); err == nil {
|
||||||
|
|||||||
@@ -2,15 +2,11 @@
|
|||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
|
|
||||||
// expr.go
|
// expr.go
|
||||||
package expr
|
package kern
|
||||||
|
|
||||||
import (
|
|
||||||
kern "git.portale-stac.it/go-pkg/expr/kern"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ----Expression interface
|
// ----Expression interface
|
||||||
type Expr interface {
|
type Expr interface {
|
||||||
kern.Typer
|
Typer
|
||||||
Eval(ctx kern.ExprContext) (result any, err error)
|
Eval(ctx ExprContext) (result any, err error)
|
||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
+11
-10
@@ -6,23 +6,24 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------- dict term
|
// -------- dict term
|
||||||
func newDictTerm(args map[any]*term) *term {
|
func newDictTerm(args map[any]*scan.Term) *scan.Term {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *NewValueToken(0, 0, SymDict, "{}", args),
|
Tk: *scan.NewValueToken(0, 0, scan.SymDict, "{}", args),
|
||||||
parent: nil,
|
Parent: nil,
|
||||||
children: nil,
|
Children: nil,
|
||||||
position: posLeaf,
|
Position: scan.PosLeaf,
|
||||||
priority: priValue,
|
Priority: scan.PriValue,
|
||||||
evalFunc: evalDict,
|
EvalFunc: evalDict,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- dict func
|
// -------- dict func
|
||||||
func evalDict(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
func evalDict(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||||
dict, _ := opTerm.value().(map[any]*term)
|
dict, _ := opTerm.Value().(map[any]*scan.Term)
|
||||||
items := make(kern.DictType, len(dict))
|
items := make(kern.DictType, len(dict))
|
||||||
for key, tree := range dict {
|
for key, tree := range dict {
|
||||||
var param any
|
var param any
|
||||||
|
|||||||
+13
-12
@@ -8,27 +8,28 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------- expr term
|
// -------- expr term
|
||||||
func newExprTerm(root *term) *term {
|
func newExprTerm(root *scan.Term) *scan.Term {
|
||||||
tk := NewValueToken(root.tk.row, root.tk.col, SymExpression, root.Source(), root)
|
tk := scan.NewValueToken(root.Tk.Row(), root.Tk.Col(), scan.SymExpression, root.Source(), root)
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
parent: nil,
|
Parent: nil,
|
||||||
children: nil,
|
Children: nil,
|
||||||
position: posLeaf,
|
Position: scan.PosLeaf,
|
||||||
priority: priValue,
|
Priority: scan.PriValue,
|
||||||
evalFunc: evalExpr,
|
EvalFunc: evalExpr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- eval expr
|
// -------- eval expr
|
||||||
func evalExpr(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
func evalExpr(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||||
if ast, ok := opTerm.value().(*term); ok {
|
if ast, ok := opTerm.Value().(*scan.Term); ok {
|
||||||
v, err = ast.Compute(ctx)
|
v, err = ast.Compute(ctx)
|
||||||
} else {
|
} else {
|
||||||
err = fmt.Errorf("expression expected, got %T", opTerm.value())
|
err = fmt.Errorf("expression expected, got %T", opTerm.Value())
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-31
@@ -8,31 +8,32 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------- function call term
|
// -------- function call term
|
||||||
func newFuncCallTerm(tk *Token, args []*term) *term {
|
func newFuncCallTerm(tk *scan.Token, args []*scan.Term) *scan.Term {
|
||||||
var pos termPosition = posLeaf
|
var pos scan.TermPosition = scan.PosLeaf
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
pos = posMultifix
|
pos = scan.PosMultifix
|
||||||
}
|
}
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
parent: nil,
|
Parent: nil,
|
||||||
children: args,
|
Children: args,
|
||||||
position: pos,
|
Position: pos,
|
||||||
priority: priValue,
|
Priority: scan.PriValue,
|
||||||
evalFunc: evalFuncCall,
|
EvalFunc: evalFuncCall,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- eval func call
|
// -------- eval func call
|
||||||
// func _evalFuncCall(ctx ExprContext, opTerm *term) (v any, err error) {
|
// func _evalFuncCall(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||||
// name, _ := opTerm.tk.Value.(string)
|
// name, _ := opTerm.Tk.Value.(string)
|
||||||
// params := make([]any, len(opTerm.children), len(opTerm.children)+5)
|
// params := make([]any, len(opTerm.Children), len(opTerm.Children)+5)
|
||||||
// for i, tree := range opTerm.children {
|
// for i, tree := range opTerm.Children {
|
||||||
// var param any
|
// var param any
|
||||||
// if param, err = tree.compute(ctx); err != nil {
|
// if param, err = tree.Compute(ctx); err != nil {
|
||||||
// break
|
// break
|
||||||
// }
|
// }
|
||||||
// params[i] = param
|
// params[i] = param
|
||||||
@@ -44,35 +45,35 @@ func newFuncCallTerm(tk *Token, args []*term) *term {
|
|||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func evalFuncCall(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
func evalFuncCall(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||||
name, _ := opTerm.tk.Value.(string)
|
name, _ := opTerm.Tk.Value.(string)
|
||||||
v, err = kern.CallFunctionByTerm(ctx, name, opTerm)
|
v, err = kern.CallFunctionByTerm(ctx, name, opTerm)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- function definition term
|
// -------- function definition term
|
||||||
func newFuncDefTerm(tk *Token, args []*term) *term {
|
func newFuncDefTerm(tk *scan.Token, args []*scan.Term) *scan.Term {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk, // value is the expression body
|
Tk: *tk, // value is the expression body
|
||||||
parent: nil,
|
Parent: nil,
|
||||||
children: args, // function params
|
Children: args, // function params
|
||||||
position: posLeaf,
|
Position: scan.PosLeaf,
|
||||||
priority: priValue,
|
Priority: scan.PriValue,
|
||||||
evalFunc: evalFuncDef,
|
EvalFunc: evalFuncDef,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- eval func def
|
// -------- eval func def
|
||||||
func evalFuncDef(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
func evalFuncDef(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||||
bodySpec := opTerm.value()
|
bodySpec := opTerm.Value()
|
||||||
if ast, ok := bodySpec.(*ast); ok {
|
if ast, ok := bodySpec.(*scan.Ast); ok {
|
||||||
paramList := make([]kern.ExprFuncParam, 0, len(opTerm.children))
|
paramList := make([]kern.ExprFuncParam, 0, len(opTerm.Children))
|
||||||
for _, param := range opTerm.children {
|
for _, param := range opTerm.Children {
|
||||||
var defValue any
|
var defValue any
|
||||||
flags := paramFlags(0)
|
flags := paramFlags(0)
|
||||||
if len(param.children) > 0 {
|
if len(param.Children) > 0 {
|
||||||
flags |= PfDefault
|
flags |= PfDefault
|
||||||
if defValue, err = param.children[0].Compute(ctx); err != nil {
|
if defValue, err = param.Children[0].Compute(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-24
@@ -9,25 +9,26 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------- iterator term
|
// -------- iterator term
|
||||||
|
|
||||||
func newIteratorTerm(tk *Token, args []*term) *term {
|
func newIteratorTerm(tk *scan.Token, args []*scan.Term) *scan.Term {
|
||||||
tk.Sym = SymIterator
|
tk.Sym = scan.SymIterator
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
parent: nil,
|
Parent: nil,
|
||||||
children: args,
|
Children: args,
|
||||||
position: posLeaf,
|
Position: scan.PosLeaf,
|
||||||
priority: priValue,
|
Priority: scan.PriValue,
|
||||||
evalFunc: evalIterator,
|
EvalFunc: evalIterator,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- eval iterator
|
// -------- 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))
|
values = make([]any, len(terms))
|
||||||
for i, t := range terms {
|
for i, t := range terms {
|
||||||
var value any
|
var value any
|
||||||
@@ -40,17 +41,17 @@ func evalTermArray(ctx kern.ExprContext, terms []*term) (values []any, err error
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func evalFirstChild(ctx kern.ExprContext, iteratorTerm *term) (value any, err error) {
|
func evalFirstChild(ctx kern.ExprContext, iteratorTerm *scan.Term) (value any, err error) {
|
||||||
if len(iteratorTerm.children) < 1 || iteratorTerm.children[0] == nil {
|
if len(iteratorTerm.Children) < 1 || iteratorTerm.Children[0] == nil {
|
||||||
err = iteratorTerm.Errorf("missing the data-source parameter")
|
err = iteratorTerm.Errorf("missing the data-source parameter")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
value, err = iteratorTerm.children[0].Compute(ctx)
|
value, err = iteratorTerm.Children[0].Compute(ctx)
|
||||||
return
|
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 {
|
if dictAny, ok := firstChildValue.(*kern.DictType); ok {
|
||||||
requiredFields := []string{kern.NextName}
|
requiredFields := []string{kern.NextName}
|
||||||
fieldsMask := 0b1
|
fieldsMask := 0b1
|
||||||
@@ -74,13 +75,13 @@ func getDataSourceDict(iteratorTerm *term, firstChildValue any) (ds map[string]k
|
|||||||
missingFields = append(missingFields, field)
|
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
|
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 firstChildValue any
|
||||||
var ds map[string]kern.Functor
|
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 {
|
if initFunc, exists := ds[kern.InitName]; exists && initFunc != nil {
|
||||||
var args []any
|
var args []any
|
||||||
var resource any
|
var resource any
|
||||||
if len(opTerm.children) > 1 {
|
if len(opTerm.Children) > 1 {
|
||||||
if args, err = evalTermArray(ctx, opTerm.children[1:]); err != nil {
|
if args, err = evalTermArray(ctx, opTerm.Children[1:]); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -124,33 +125,33 @@ func evalIterator(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
} else {
|
} else {
|
||||||
if dictIt, ok := firstChildValue.(*kern.DictType); ok {
|
if dictIt, ok := firstChildValue.(*kern.DictType); ok {
|
||||||
var args []any
|
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)
|
v, err = NewDictIterator(dictIt, args)
|
||||||
}
|
}
|
||||||
} else {
|
} 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 {
|
} else if list, ok := firstChildValue.(*kern.ListType); ok {
|
||||||
var args []any
|
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)
|
v = NewListIterator(list, args)
|
||||||
}
|
}
|
||||||
} else if intVal, ok := firstChildValue.(int64); ok {
|
} else if intVal, ok := firstChildValue.(int64); ok {
|
||||||
var args []any
|
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)
|
v, err = NewIntIterator(args)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var list []any
|
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)
|
v = NewArrayIterator(list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
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))
|
items := make([]any, 0, len(terms))
|
||||||
for i, tree := range terms {
|
for i, tree := range terms {
|
||||||
var param any
|
var param any
|
||||||
|
|||||||
+12
-11
@@ -6,27 +6,28 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------- list term
|
// -------- list term
|
||||||
func newListTermA(args ...*term) *term {
|
func newListTermA(args ...*scan.Term) *scan.Term {
|
||||||
return newListTerm(0, 0, args)
|
return newListTerm(0, 0, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newListTerm(row, col int, args []*term) *term {
|
func newListTerm(row, col int, args []*scan.Term) *scan.Term {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *NewValueToken(row, col, SymList, "[]", args),
|
Tk: *scan.NewValueToken(row, col, scan.SymList, "[]", args),
|
||||||
parent: nil,
|
Parent: nil,
|
||||||
children: nil,
|
Children: nil,
|
||||||
position: posLeaf,
|
Position: scan.PosLeaf,
|
||||||
priority: priValue,
|
Priority: scan.PriValue,
|
||||||
evalFunc: evalList,
|
EvalFunc: evalList,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- list func
|
// -------- list func
|
||||||
func evalList(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
func evalList(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||||
list, _ := opTerm.value().([]*term)
|
list, _ := opTerm.Value().([]*scan.Term)
|
||||||
items := make(kern.ListType, len(list))
|
items := make(kern.ListType, len(list))
|
||||||
for i, tree := range list {
|
for i, tree := range list {
|
||||||
var param any
|
var param any
|
||||||
|
|||||||
+17
-16
@@ -6,32 +6,33 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------- literal term
|
// -------- literal term
|
||||||
func newLiteralTerm(tk *Token) *term {
|
func newLiteralTerm(tk *scan.Token) *scan.Term {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
parent: nil,
|
Parent: nil,
|
||||||
children: nil,
|
Children: nil,
|
||||||
position: posLeaf,
|
Position: scan.PosLeaf,
|
||||||
priority: priValue,
|
Priority: scan.PriValue,
|
||||||
evalFunc: evalLiteral,
|
EvalFunc: evalLiteral,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- eval func
|
// -------- eval func
|
||||||
func evalLiteral(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
func evalLiteral(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||||
v = opTerm.tk.Value
|
v = opTerm.Tk.Value
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymString, newLiteralTerm)
|
scan.RegisterTermConstructor(scan.SymString, newLiteralTerm)
|
||||||
registerTermConstructor(SymInteger, newLiteralTerm)
|
scan.RegisterTermConstructor(scan.SymInteger, newLiteralTerm)
|
||||||
registerTermConstructor(SymFloat, newLiteralTerm)
|
scan.RegisterTermConstructor(scan.SymFloat, newLiteralTerm)
|
||||||
registerTermConstructor(SymFraction, newLiteralTerm)
|
scan.RegisterTermConstructor(scan.SymFraction, newLiteralTerm)
|
||||||
registerTermConstructor(SymBool, newLiteralTerm)
|
scan.RegisterTermConstructor(scan.SymBool, newLiteralTerm)
|
||||||
registerTermConstructor(SymKwNil, newLiteralTerm)
|
scan.RegisterTermConstructor(scan.SymKwNil, newLiteralTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-15
@@ -9,19 +9,20 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------- selector case term
|
// -------- selector case term
|
||||||
|
|
||||||
type selectorCase struct {
|
type selectorCase struct {
|
||||||
filterList *term
|
filterList *scan.Term
|
||||||
caseExpr Expr
|
caseExpr kern.Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *selectorCase) String() string {
|
func (sc *selectorCase) String() string {
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
if sc.filterList != nil {
|
if sc.filterList != nil {
|
||||||
sc.filterList.toString(&sb)
|
sc.filterList.ToString(&sb)
|
||||||
sb.WriteByte(' ')
|
sb.WriteByte(' ')
|
||||||
}
|
}
|
||||||
sb.WriteByte('{')
|
sb.WriteByte('{')
|
||||||
@@ -30,23 +31,23 @@ func (sc *selectorCase) String() string {
|
|||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSelectorCaseTerm(row, col int, filterList *term, caseExpr Expr) *term {
|
func newSelectorCaseTerm(row, col int, filterList *scan.Term, caseExpr kern.Expr) *scan.Term {
|
||||||
tk := NewValueToken(row, col, SymSelectorCase, "", &selectorCase{filterList: filterList, caseExpr: caseExpr})
|
tk := scan.NewValueToken(row, col, scan.SymSelectorCase, "", &selectorCase{filterList: filterList, caseExpr: caseExpr})
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
parent: nil,
|
Parent: nil,
|
||||||
children: nil,
|
Children: nil,
|
||||||
position: posLeaf,
|
Position: scan.PosLeaf,
|
||||||
priority: priValue,
|
Priority: scan.PriValue,
|
||||||
evalFunc: evalSelectorCase,
|
EvalFunc: evalSelectorCase,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- eval selector case
|
// -------- 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
|
var ok bool
|
||||||
if v, ok = opTerm.value().(*selectorCase); !ok {
|
if v, ok = opTerm.Value().(*selectorCase); !ok {
|
||||||
err = fmt.Errorf("selector-case expected, got %T", opTerm.value())
|
err = fmt.Errorf("selector-case expected, got %T", opTerm.Value())
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-11
@@ -8,24 +8,25 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------- variable term
|
// -------- variable term
|
||||||
func newVarTerm(tk *Token) *term {
|
func newVarTerm(tk *scan.Token) *scan.Term {
|
||||||
t := &term{
|
t := &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
parent: nil,
|
Parent: nil,
|
||||||
children: nil,
|
Children: nil,
|
||||||
position: posLeaf,
|
Position: scan.PosLeaf,
|
||||||
priority: priValue,
|
Priority: scan.PriValue,
|
||||||
evalFunc: evalVar,
|
EvalFunc: evalVar,
|
||||||
}
|
}
|
||||||
t.tk.Sym = SymVariable
|
t.Tk.Sym = scan.SymVariable
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- eval func
|
// -------- 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
|
var exists bool
|
||||||
name := opTerm.Source()
|
name := opTerm.Source()
|
||||||
if v, exists = ctx.GetVar(name); !exists {
|
if v, exists = ctx.GetVar(name); !exists {
|
||||||
@@ -40,5 +41,5 @@ func evalVar(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymIdentifier, newVarTerm)
|
scan.RegisterTermConstructor(scan.SymIdentifier, newVarTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+60
-59
@@ -6,22 +6,23 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
"git.portale-stac.it/go-pkg/expr/util"
|
"git.portale-stac.it/go-pkg/expr/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- assign term
|
//-------- assign term
|
||||||
|
|
||||||
func newAssignTerm(tk *Token) (inst *term) {
|
func newAssignTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priAssign,
|
Priority: scan.PriAssign,
|
||||||
evalFunc: evalAssign,
|
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 collectionValue, keyListValue, keyValue any
|
||||||
var keyList *kern.ListType
|
var keyList *kern.ListType
|
||||||
var ok bool
|
var ok bool
|
||||||
@@ -56,32 +57,32 @@ func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *ter
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func assignValue(ctx kern.ExprContext, leftTerm *term, v any) (err error) {
|
func assignValue(ctx kern.ExprContext, leftTerm *scan.Term, v any) (err error) {
|
||||||
if leftTerm.symbol() == SymIndex {
|
if leftTerm.Symbol() == scan.SymIndex {
|
||||||
err = assignCollectionItem(ctx, leftTerm.children[0], leftTerm.children[1], v)
|
err = assignCollectionItem(ctx, leftTerm.Children[0], leftTerm.Children[1], v)
|
||||||
} else {
|
} else {
|
||||||
ctx.UnsafeSetVar(leftTerm.Source(), v)
|
ctx.UnsafeSetVar(leftTerm.Source(), v)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func evalAssign(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
func evalAssign(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||||
if err = opTerm.checkOperands(); err != nil {
|
if err = opTerm.CheckOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
leftTerm := opTerm.children[0]
|
leftTerm := opTerm.Children[0]
|
||||||
leftSym := leftTerm.symbol()
|
leftSym := leftTerm.Symbol()
|
||||||
if leftSym != SymVariable && leftSym != SymIndex {
|
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)
|
err = leftTerm.Tk.Errorf("left operand of %q must be a variable or a collection's item", opTerm.Tk.Source())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rightChild := opTerm.children[1]
|
rightChild := opTerm.Children[1]
|
||||||
|
|
||||||
if v, err = rightChild.Compute(ctx); err == nil {
|
if v, err = rightChild.Compute(ctx); err == nil {
|
||||||
if functor, ok := v.(kern.Functor); ok {
|
if functor, ok := v.(kern.Functor); ok {
|
||||||
if leftSym == SymVariable {
|
if leftSym == scan.SymVariable {
|
||||||
if info := functor.GetFunc(); info != nil {
|
if info := functor.GetFunc(); info != nil {
|
||||||
ctx.RegisterFunc(leftTerm.Source(), info.Functor(), info.ReturnType(), info.Params())
|
ctx.RegisterFunc(leftTerm.Source(), info.Functor(), info.ReturnType(), info.Params())
|
||||||
} else if funcDef, ok := functor.(*exprFunctor); ok {
|
} else if funcDef, ok := functor.(*exprFunctor); ok {
|
||||||
@@ -106,17 +107,17 @@ func evalAssign(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
//-------- assign term
|
//-------- assign term
|
||||||
|
|
||||||
func newOpAssignTerm(tk *Token) (inst *term) {
|
func newOpAssignTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priAssign,
|
Priority: scan.PriAssign,
|
||||||
evalFunc: evalOpAssign,
|
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 collectionValue, keyListValue, keyValue any
|
||||||
var keyList *kern.ListType
|
var keyList *kern.ListType
|
||||||
var ok bool
|
var ok bool
|
||||||
@@ -151,52 +152,52 @@ func getCollectionItemValue(ctx kern.ExprContext, collectionTerm, keyListTerm *t
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAssignValue(ctx kern.ExprContext, leftTerm *term) (value any, err error) {
|
func getAssignValue(ctx kern.ExprContext, leftTerm *scan.Term) (value any, err error) {
|
||||||
if leftTerm.symbol() == SymIndex {
|
if leftTerm.Symbol() == scan.SymIndex {
|
||||||
value, err = getCollectionItemValue(ctx, leftTerm.children[0], leftTerm.children[1])
|
value, err = getCollectionItemValue(ctx, leftTerm.Children[0], leftTerm.Children[1])
|
||||||
} else {
|
} else {
|
||||||
value, _ = ctx.GetVar(leftTerm.Source())
|
value, _ = ctx.GetVar(leftTerm.Source())
|
||||||
}
|
}
|
||||||
return
|
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
|
var rightValue, leftValue any
|
||||||
if err = opTerm.checkOperands(); err != nil {
|
if err = opTerm.CheckOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
leftTerm := opTerm.children[0]
|
leftTerm := opTerm.Children[0]
|
||||||
leftSym := leftTerm.symbol()
|
leftSym := leftTerm.Symbol()
|
||||||
if leftSym != SymVariable && leftSym != SymIndex {
|
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)
|
err = leftTerm.Tk.Errorf("left operand of %q must be a variable or a collection's item", opTerm.Tk.Source())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rightChild := opTerm.children[1]
|
rightChild := opTerm.Children[1]
|
||||||
|
|
||||||
if rightValue, err = rightChild.Compute(ctx); err == nil {
|
if rightValue, err = rightChild.Compute(ctx); err == nil {
|
||||||
if leftValue, err = getAssignValue(ctx, leftTerm); err == nil {
|
if leftValue, err = getAssignValue(ctx, leftTerm); err == nil {
|
||||||
switch opTerm.symbol() {
|
switch opTerm.Symbol() {
|
||||||
case SymPlusEqual:
|
case scan.SymPlusEqual:
|
||||||
v, err = sumValues(opTerm, leftValue, rightValue)
|
v, err = sumValues(opTerm, leftValue, rightValue)
|
||||||
case SymMinusEqual:
|
case scan.SymMinusEqual:
|
||||||
v, err = diffValues(opTerm, leftValue, rightValue)
|
v, err = diffValues(opTerm, leftValue, rightValue)
|
||||||
case SymStarEqual:
|
case scan.SymStarEqual:
|
||||||
v, err = mulValues(opTerm, leftValue, rightValue)
|
v, err = mulValues(opTerm, leftValue, rightValue)
|
||||||
case SymSlashEqual:
|
case scan.SymSlashEqual:
|
||||||
v, err = divValues(opTerm, leftValue, rightValue)
|
v, err = divValues(opTerm, leftValue, rightValue)
|
||||||
case SymPercEqual:
|
case scan.SymPercEqual:
|
||||||
v, err = remainderValues(opTerm, leftValue, rightValue)
|
v, err = remainderValues(opTerm, leftValue, rightValue)
|
||||||
case SymAmpersandEqual:
|
case scan.SymAmpersandEqual:
|
||||||
v, err = bitwiseAnd(opTerm, leftValue, rightValue)
|
v, err = bitwiseAnd(opTerm, leftValue, rightValue)
|
||||||
case SymVertBarEqual:
|
case scan.SymVertBarEqual:
|
||||||
v, err = bitwiseOr(opTerm, leftValue, rightValue)
|
v, err = bitwiseOr(opTerm, leftValue, rightValue)
|
||||||
case SymCaretEqual:
|
case scan.SymCaretEqual:
|
||||||
v, err = bitwiseXor(opTerm, leftValue, rightValue)
|
v, err = bitwiseXor(opTerm, leftValue, rightValue)
|
||||||
case SymDoubleLessEqual:
|
case scan.SymDoubleLessEqual:
|
||||||
v, err = bitLeftShift(opTerm, leftValue, rightValue)
|
v, err = bitLeftShift(opTerm, leftValue, rightValue)
|
||||||
case SymDoubleGreaterEqual:
|
case scan.SymDoubleGreaterEqual:
|
||||||
v, err = bitRightShift(opTerm, leftValue, rightValue)
|
v, err = bitRightShift(opTerm, leftValue, rightValue)
|
||||||
default:
|
default:
|
||||||
err = opTerm.Errorf("unsupported assign operator %q", opTerm.Source())
|
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
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymEqual, newAssignTerm)
|
scan.RegisterTermConstructor(scan.SymEqual, newAssignTerm)
|
||||||
registerTermConstructor(SymPlusEqual, newOpAssignTerm)
|
scan.RegisterTermConstructor(scan.SymPlusEqual, newOpAssignTerm)
|
||||||
registerTermConstructor(SymMinusEqual, newOpAssignTerm)
|
scan.RegisterTermConstructor(scan.SymMinusEqual, newOpAssignTerm)
|
||||||
registerTermConstructor(SymStarEqual, newOpAssignTerm)
|
scan.RegisterTermConstructor(scan.SymStarEqual, newOpAssignTerm)
|
||||||
registerTermConstructor(SymSlashEqual, newOpAssignTerm)
|
scan.RegisterTermConstructor(scan.SymSlashEqual, newOpAssignTerm)
|
||||||
registerTermConstructor(SymPercEqual, newOpAssignTerm)
|
scan.RegisterTermConstructor(scan.SymPercEqual, newOpAssignTerm)
|
||||||
registerTermConstructor(SymDoubleLessEqual, newOpAssignTerm)
|
scan.RegisterTermConstructor(scan.SymDoubleLessEqual, newOpAssignTerm)
|
||||||
registerTermConstructor(SymDoubleGreaterEqual, newOpAssignTerm)
|
scan.RegisterTermConstructor(scan.SymDoubleGreaterEqual, newOpAssignTerm)
|
||||||
registerTermConstructor(SymAmpersandEqual, newOpAssignTerm)
|
scan.RegisterTermConstructor(scan.SymAmpersandEqual, newOpAssignTerm)
|
||||||
registerTermConstructor(SymVertBarEqual, newOpAssignTerm)
|
scan.RegisterTermConstructor(scan.SymVertBarEqual, newOpAssignTerm)
|
||||||
registerTermConstructor(SymCaretEqual, newOpAssignTerm)
|
scan.RegisterTermConstructor(scan.SymCaretEqual, newOpAssignTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+48
-47
@@ -6,24 +6,25 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- Bitwise NOT term
|
//-------- Bitwise NOT term
|
||||||
|
|
||||||
func newBitwiseNotTerm(tk *Token) (inst *term) {
|
func newBitwiseNotTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 1),
|
Children: make([]*scan.Term, 0, 1),
|
||||||
position: posPrefix,
|
Position: scan.PosPrefix,
|
||||||
priority: priBitwiseNot,
|
Priority: scan.PriBitwiseNot,
|
||||||
evalFunc: evalBitwiseNot,
|
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
|
var value any
|
||||||
|
|
||||||
if value, err = opTerm.evalPrefix(ctx); err != nil {
|
if value, err = opTerm.EvalPrefix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,24 +32,24 @@ func evalBitwiseNot(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
i, _ := value.(int64)
|
i, _ := value.(int64)
|
||||||
v = ^i
|
v = ^i
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatiblePrefixPostfixType(value)
|
err = opTerm.ErrIncompatiblePrefixPostfixType(value)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------- Bitwise AND term
|
//-------- Bitwise AND term
|
||||||
|
|
||||||
func newBitwiseAndTerm(tk *Token) (inst *term) {
|
func newBitwiseAndTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priBitwiseAnd,
|
Priority: scan.PriBitwiseAnd,
|
||||||
evalFunc: evalBitwiseAnd,
|
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 leftInt, rightInt int64
|
||||||
var lok, rok bool
|
var lok, rok bool
|
||||||
|
|
||||||
@@ -58,15 +59,15 @@ func bitwiseAnd(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
|||||||
if lok && rok {
|
if lok && rok {
|
||||||
v = leftInt & rightInt
|
v = leftInt & rightInt
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
v, err = bitwiseAnd(opTerm, leftValue, rightValue)
|
v, err = bitwiseAnd(opTerm, leftValue, rightValue)
|
||||||
@@ -75,17 +76,17 @@ func evalBitwiseAnd(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
//-------- Bitwise OR term
|
//-------- Bitwise OR term
|
||||||
|
|
||||||
func newBitwiseOrTerm(tk *Token) (inst *term) {
|
func newBitwiseOrTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priBitwiseOr,
|
Priority: scan.PriBitwiseOr,
|
||||||
evalFunc: evalBitwiseOr,
|
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 leftInt, rightInt int64
|
||||||
var lok, rok bool
|
var lok, rok bool
|
||||||
|
|
||||||
@@ -95,15 +96,15 @@ func bitwiseOr(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
|||||||
if lok && rok {
|
if lok && rok {
|
||||||
v = leftInt | rightInt
|
v = leftInt | rightInt
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,17 +114,17 @@ func evalBitwiseOr(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
//-------- Bitwise XOR term
|
//-------- Bitwise XOR term
|
||||||
|
|
||||||
func newBitwiseXorTerm(tk *Token) (inst *term) {
|
func newBitwiseXorTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priBitwiseOr,
|
Priority: scan.PriBitwiseXor,
|
||||||
evalFunc: evalBitwiseXor,
|
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 leftInt, rightInt int64
|
||||||
var lok, rok bool
|
var lok, rok bool
|
||||||
|
|
||||||
@@ -133,15 +134,15 @@ func bitwiseXor(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
|||||||
if lok && rok {
|
if lok && rok {
|
||||||
v = leftInt ^ rightInt
|
v = leftInt ^ rightInt
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,8 +152,8 @@ func evalBitwiseXor(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymTilde, newBitwiseNotTerm)
|
scan.RegisterTermConstructor(scan.SymTilde, newBitwiseNotTerm)
|
||||||
registerTermConstructor(SymAmpersand, newBitwiseAndTerm)
|
scan.RegisterTermConstructor(scan.SymAmpersand, newBitwiseAndTerm)
|
||||||
registerTermConstructor(SymVertBar, newBitwiseOrTerm)
|
scan.RegisterTermConstructor(scan.SymVertBar, newBitwiseOrTerm)
|
||||||
registerTermConstructor(SymCaret, newBitwiseXorTerm)
|
scan.RegisterTermConstructor(scan.SymCaret, newBitwiseXorTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-46
@@ -8,48 +8,49 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- NOT term
|
//-------- NOT term
|
||||||
|
|
||||||
func newNotTerm(tk *Token) (inst *term) {
|
func newNotTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 1),
|
Children: make([]*scan.Term, 0, 1),
|
||||||
position: posPrefix,
|
Position: scan.PosPrefix,
|
||||||
priority: priNot,
|
Priority: scan.PriNot,
|
||||||
evalFunc: evalNot,
|
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
|
var rightValue any
|
||||||
|
|
||||||
if rightValue, err = opTerm.evalPrefix(ctx); err != nil {
|
if rightValue, err = opTerm.EvalPrefix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if b, ok := kern.ToBool(rightValue); ok {
|
if b, ok := kern.ToBool(rightValue); ok {
|
||||||
v = !b
|
v = !b
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatiblePrefixPostfixType(rightValue)
|
err = opTerm.ErrIncompatiblePrefixPostfixType(rightValue)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------- AND term
|
//-------- AND term
|
||||||
|
|
||||||
func newAndTerm(tk *Token) (inst *term) {
|
func newAndTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priAnd,
|
Priority: scan.PriAnd,
|
||||||
evalFunc: evalAnd,
|
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) {
|
if kern.CtrlIsEnabled(ctx, kern.ControlBoolShortcut) {
|
||||||
v, err = evalAndWithShortcut(ctx, self)
|
v, err = evalAndWithShortcut(ctx, self)
|
||||||
} else {
|
} else {
|
||||||
@@ -58,12 +59,12 @@ func evalAnd(ctx kern.ExprContext, self *term) (v any, err error) {
|
|||||||
return
|
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 leftValue, rightValue any
|
||||||
var leftBool, rightBool bool
|
var leftBool, rightBool bool
|
||||||
var lok, rok bool
|
var lok, rok bool
|
||||||
|
|
||||||
if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = self.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,33 +74,33 @@ func evalAndWithoutShortcut(ctx kern.ExprContext, self *term) (v any, err error)
|
|||||||
if lok && rok {
|
if lok && rok {
|
||||||
v = leftBool && rightBool
|
v = leftBool && rightBool
|
||||||
} else {
|
} else {
|
||||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
err = self.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if err = self.checkOperands(); err != nil {
|
if err = self.CheckOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if leftValue, err = self.children[0].Compute(ctx); err != nil {
|
if leftValue, err = self.Children[0].Compute(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if leftBool, lok := kern.ToBool(leftValue); !lok {
|
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))
|
// err = fmt.Errorf("got %s as left operand type of 'AND' operator, it must be bool", expr.TypeName(leftValue))
|
||||||
// return
|
// return
|
||||||
err = self.errIncompatibleType(leftValue, "left")
|
err = self.ErrIncompatibleType(leftValue, "left")
|
||||||
} else if !leftBool {
|
} else if !leftBool {
|
||||||
v = false
|
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 {
|
if rightBool, rok := kern.ToBool(rightValue); rok {
|
||||||
v = rightBool
|
v = rightBool
|
||||||
} else {
|
} else {
|
||||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
err = self.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -107,17 +108,17 @@ func evalAndWithShortcut(ctx kern.ExprContext, self *term) (v any, err error) {
|
|||||||
|
|
||||||
//-------- OR term
|
//-------- OR term
|
||||||
|
|
||||||
func newOrTerm(tk *Token) (inst *term) {
|
func newOrTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priOr,
|
Priority: scan.PriOr,
|
||||||
evalFunc: evalOr,
|
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) {
|
if kern.CtrlIsEnabled(ctx, kern.ControlBoolShortcut) {
|
||||||
v, err = evalOrWithShortcut(ctx, self)
|
v, err = evalOrWithShortcut(ctx, self)
|
||||||
} else {
|
} else {
|
||||||
@@ -126,12 +127,12 @@ func evalOr(ctx kern.ExprContext, self *term) (v any, err error) {
|
|||||||
return
|
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 leftValue, rightValue any
|
||||||
var leftBool, rightBool bool
|
var leftBool, rightBool bool
|
||||||
var lok, rok bool
|
var lok, rok bool
|
||||||
|
|
||||||
if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = self.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,19 +142,19 @@ func evalOrWithoutShortcut(ctx kern.ExprContext, self *term) (v any, err error)
|
|||||||
if lok && rok {
|
if lok && rok {
|
||||||
v = leftBool || rightBool
|
v = leftBool || rightBool
|
||||||
} else {
|
} else {
|
||||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
err = self.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if err = self.checkOperands(); err != nil {
|
if err = self.CheckOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if leftValue, err = self.children[0].Compute(ctx); err != nil {
|
if leftValue, err = self.Children[0].Compute(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,11 +163,11 @@ func evalOrWithShortcut(ctx kern.ExprContext, self *term) (v any, err error) {
|
|||||||
return
|
return
|
||||||
} else if leftBool {
|
} else if leftBool {
|
||||||
v = true
|
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 {
|
if rightBool, rok := kern.ToBool(rightValue); rok {
|
||||||
v = rightBool
|
v = rightBool
|
||||||
} else {
|
} else {
|
||||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
err = self.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -174,7 +175,7 @@ func evalOrWithShortcut(ctx kern.ExprContext, self *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymNot, newNotTerm)
|
scan.RegisterTermConstructor(scan.SymNot, newNotTerm)
|
||||||
registerTermConstructor(SymAnd, newAndTerm)
|
scan.RegisterTermConstructor(scan.SymAnd, newAndTerm)
|
||||||
registerTermConstructor(SymOr, newOrTerm)
|
scan.RegisterTermConstructor(scan.SymOr, newOrTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-10
@@ -8,24 +8,25 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- builtin term
|
//-------- builtin term
|
||||||
|
|
||||||
func newBuiltinTerm(tk *Token) (inst *term) {
|
func newBuiltinTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 1),
|
Children: make([]*scan.Term, 0, 1),
|
||||||
position: posPrefix,
|
Position: scan.PosPrefix,
|
||||||
priority: priSign,
|
Priority: scan.PriSign,
|
||||||
evalFunc: evalBuiltin,
|
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
|
var childValue any
|
||||||
|
|
||||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
if childValue, err = opTerm.EvalPrefix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,5 +65,5 @@ func evalBuiltin(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymKwBuiltin, newBuiltinTerm)
|
scan.RegisterTermConstructor(scan.SymKwBuiltin, newBuiltinTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-10
@@ -6,26 +6,27 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- but term
|
//-------- but term
|
||||||
|
|
||||||
func newButTerm(tk *Token) (inst *term) {
|
func newButTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priBut,
|
Priority: scan.PriBut,
|
||||||
evalFunc: evalBut,
|
EvalFunc: evalBut,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func evalBut(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
func evalBut(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||||
_, v, err = opTerm.evalInfix(ctx)
|
_, v, err = opTerm.EvalInfix(ctx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymKwBut, newButTerm)
|
scan.RegisterTermConstructor(scan.SymKwBut, newButTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-13
@@ -6,29 +6,30 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- context term
|
//-------- context term
|
||||||
|
|
||||||
func newContextTerm(tk *Token) (inst *term) {
|
func newContextTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 1),
|
Children: make([]*scan.Term, 0, 1),
|
||||||
position: posPrefix,
|
Position: scan.PosPrefix,
|
||||||
priority: priIncDec,
|
Priority: scan.PriIncDec,
|
||||||
evalFunc: evalContextValue,
|
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 childValue any
|
||||||
|
|
||||||
var sourceCtx kern.ExprContext
|
var sourceCtx kern.ExprContext
|
||||||
if len(opTerm.children) == 0 {
|
if len(opTerm.Children) == 0 {
|
||||||
sourceCtx = ctx
|
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()
|
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 {
|
if dc, ok := childValue.(*dataCursor); ok {
|
||||||
sourceCtx = dc.ctx
|
sourceCtx = dc.ctx
|
||||||
}
|
}
|
||||||
@@ -53,12 +54,12 @@ func evalContextValue(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
v = d
|
v = d
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
err = opTerm.ErrIncompatiblePrefixPostfixType(childValue)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymDoubleDollar, newContextTerm)
|
scan.RegisterTermConstructor(scan.SymDoubleDollar, newContextTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-9
@@ -6,26 +6,27 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- export all term
|
//-------- export all term
|
||||||
|
|
||||||
func newExportAllTerm(tk *Token) (inst *term) {
|
func newExportAllTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: nil,
|
Children: nil,
|
||||||
position: posLeaf,
|
Position: scan.PosLeaf,
|
||||||
priority: priValue,
|
Priority: scan.PriValue,
|
||||||
evalFunc: evalExportAll,
|
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)
|
CtrlEnable(ctx, kern.ControlExportAll)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymDoubleAt, newExportAllTerm)
|
scan.RegisterTermConstructor(scan.SymDoubleAt, newExportAllTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-39
@@ -6,29 +6,30 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- default term
|
//-------- default term
|
||||||
|
|
||||||
func newDefaultTerm(tk *Token) (inst *term) {
|
func newDefaultTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priDefault,
|
Priority: scan.PriDefault,
|
||||||
evalFunc: evalDefault,
|
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
|
var rightValue any
|
||||||
|
|
||||||
if err = opTerm.checkOperands(); err != nil {
|
if err = opTerm.CheckOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
leftTerm := opTerm.children[0]
|
leftTerm := opTerm.Children[0]
|
||||||
if leftTerm.tk.Sym != SymVariable {
|
if leftTerm.Tk.Sym != scan.SymVariable {
|
||||||
// err = leftTerm.Errorf("left operand of %q must be a variable", self.tk.source)
|
// err = leftTerm.Errorf("left operand of %q must be a variable", self.tk.source)
|
||||||
err = kern.ErrLeftOperandMustBeVariable(leftTerm, opTerm)
|
err = kern.ErrLeftOperandMustBeVariable(leftTerm, opTerm)
|
||||||
return
|
return
|
||||||
@@ -36,7 +37,7 @@ func evalDefault(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
if leftValue, exists := ctx.GetVar(leftTerm.Source()); exists {
|
if leftValue, exists := ctx.GetVar(leftTerm.Source()); exists {
|
||||||
v = leftValue
|
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
|
v = rightValue
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -44,32 +45,32 @@ func evalDefault(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
//-------- alternate term
|
//-------- alternate term
|
||||||
|
|
||||||
func newAlternateTerm(tk *Token) (inst *term) {
|
func newAlternateTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priDefault,
|
Priority: scan.PriDefault,
|
||||||
evalFunc: evalAlternate,
|
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
|
var rightValue any
|
||||||
|
|
||||||
if err = opTerm.checkOperands(); err != nil {
|
if err = opTerm.CheckOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
leftTerm := opTerm.children[0]
|
leftTerm := opTerm.Children[0]
|
||||||
if leftTerm.tk.Sym != SymVariable {
|
if leftTerm.Tk.Sym != scan.SymVariable {
|
||||||
// err = leftTerm.Errorf("left operand of %q must be a variable", self.tk.source)
|
// err = leftTerm.Errorf("left operand of %q must be a variable", self.tk.source)
|
||||||
err = kern.ErrLeftOperandMustBeVariable(leftTerm, opTerm)
|
err = kern.ErrLeftOperandMustBeVariable(leftTerm, opTerm)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if leftValue, exists := ctx.GetVar(leftTerm.Source()); exists && leftValue != nil {
|
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
|
v = rightValue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -80,25 +81,25 @@ func evalAlternate(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
//-------- default assign term
|
//-------- default assign term
|
||||||
|
|
||||||
func newDefaultAssignTerm(tk *Token) (inst *term) {
|
func newDefaultAssignTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priDefault,
|
Priority: scan.PriDefault,
|
||||||
evalFunc: evalAssignDefault,
|
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
|
var rightValue any
|
||||||
|
|
||||||
if err = opTerm.checkOperands(); err != nil {
|
if err = opTerm.CheckOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
leftTerm := opTerm.children[0]
|
leftTerm := opTerm.Children[0]
|
||||||
if leftTerm.tk.Sym != SymVariable {
|
if leftTerm.Tk.Sym != scan.SymVariable {
|
||||||
// err = leftTerm.Errorf("left operand of %q must be a variable", self.tk.source)
|
// err = leftTerm.Errorf("left operand of %q must be a variable", self.tk.source)
|
||||||
err = kern.ErrLeftOperandMustBeVariable(leftTerm, opTerm)
|
err = kern.ErrLeftOperandMustBeVariable(leftTerm, opTerm)
|
||||||
return
|
return
|
||||||
@@ -106,7 +107,7 @@ func evalAssignDefault(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
if leftValue, exists := ctx.GetVar(leftTerm.Source()); exists {
|
if leftValue, exists := ctx.GetVar(leftTerm.Source()); exists {
|
||||||
v = leftValue
|
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 {
|
if functor, ok := rightValue.(kern.Functor); ok {
|
||||||
//ctx.RegisterFunc(leftTerm.source(), functor, 0, -1)
|
//ctx.RegisterFunc(leftTerm.source(), functor, 0, -1)
|
||||||
ctx.RegisterFunc(leftTerm.Source(), functor, kern.TypeAny, []kern.ExprFuncParam{
|
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
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymDoubleQuestion, newDefaultTerm)
|
scan.RegisterTermConstructor(scan.SymDoubleQuestion, newDefaultTerm)
|
||||||
registerTermConstructor(SymQuestionEqual, newDefaultAssignTerm)
|
scan.RegisterTermConstructor(scan.SymQuestionEqual, newDefaultAssignTerm)
|
||||||
registerTermConstructor(SymQuestionExclam, newAlternateTerm)
|
scan.RegisterTermConstructor(scan.SymQuestionExclam, newAlternateTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-12
@@ -9,30 +9,31 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- digest term
|
//-------- digest term
|
||||||
|
|
||||||
func newDigestTerm(tk *Token) (inst *term) {
|
func newDigestTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priIterOp,
|
Priority: scan.PriIterOp,
|
||||||
evalFunc: evalDigest,
|
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 leftValue, rightValue any
|
||||||
var it kern.Iterator
|
var it kern.Iterator
|
||||||
var item, lastValue any
|
var item, lastValue any
|
||||||
|
|
||||||
if err = opTerm.checkOperands(); err != nil {
|
if err = opTerm.CheckOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if leftValue, err = opTerm.children[0].Compute(ctx); err != nil {
|
if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +46,7 @@ func evalDigest(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
ctx.SetVar("_", item)
|
ctx.SetVar("_", item)
|
||||||
ctx.SetVar("__", it.Index())
|
ctx.SetVar("__", it.Index())
|
||||||
ctx.SetVar("_#", it.Count())
|
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 {
|
if rightValue == nil {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
@@ -68,5 +69,5 @@ func evalDigest(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymKwDigest, newDigestTerm)
|
scan.RegisterTermConstructor(scan.SymKwDigest, newDigestTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-22
@@ -6,34 +6,35 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------- dot term
|
// -------- dot term
|
||||||
func newDotTerm(tk *Token) (inst *term) {
|
func newDotTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priDot,
|
Priority: scan.PriDot,
|
||||||
evalFunc: evalDot,
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if err = opTerm.checkOperands(); err != nil {
|
if err = opTerm.CheckOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if leftValue, err = opTerm.children[0].Compute(ctx); err != nil {
|
if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
indexTerm := opTerm.children[1]
|
indexTerm := opTerm.Children[1]
|
||||||
|
|
||||||
switch unboxedValue := leftValue.(type) {
|
switch unboxedValue := leftValue.(type) {
|
||||||
case kern.ExtIterator:
|
case kern.ExtIterator:
|
||||||
if indexTerm.symbol() == SymVariable /*|| indexTerm.symbol() == SymString */ {
|
if indexTerm.Tk.Sym == scan.SymVariable /*|| indexTerm.Tk.Sym == scan.SymString */ {
|
||||||
opName := indexTerm.Source()
|
opName := indexTerm.Source()
|
||||||
if unboxedValue.HasOperation(opName) {
|
if unboxedValue.HasOperation(opName) {
|
||||||
v, err = unboxedValue.CallOperation(opName, map[string]any{})
|
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
|
v = false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = indexTerm.tk.ErrorExpectedGot("identifier")
|
err = indexTerm.Tk.ErrorExpectedGot("identifier")
|
||||||
}
|
}
|
||||||
case *kern.DictType:
|
case *kern.DictType:
|
||||||
var ok bool
|
var ok bool
|
||||||
s := opTerm.children[1].symbol()
|
s := opTerm.Children[1].Tk.Sym
|
||||||
if s == SymVariable || s == SymString {
|
if s == scan.SymVariable || s == scan.SymString {
|
||||||
src := opTerm.children[1].Source()
|
src := opTerm.Children[1].Source()
|
||||||
if len(src) > 1 && src[0] == '"' && src[len(src)-1] == '"' {
|
if len(src) > 1 && src[0] == '"' && src[len(src)-1] == '"' {
|
||||||
src = src[1 : len(src)-1]
|
src = src[1 : len(src)-1]
|
||||||
}
|
}
|
||||||
if v, ok = unboxedValue.GetItem(src); !ok {
|
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 {
|
if v, ok = unboxedValue.GetItem(rightValue); !ok {
|
||||||
err = opTerm.errKeyNotFound(rightValue)
|
err = opTerm.Errorf("key %q not found", rightValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if rightValue, err = opTerm.children[1].Compute(ctx); err == nil {
|
if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil {
|
||||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.Errorf("incompatible types: %s and %s", kern.TypeName(leftValue), kern.TypeName(rightValue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -70,5 +71,5 @@ func evalDot(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymDot, newDotTerm)
|
scan.RegisterTermConstructor(scan.SymDot, newDotTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-11
@@ -8,24 +8,25 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- fact term
|
//-------- fact term
|
||||||
|
|
||||||
func newFactTerm(tk *Token) (inst *term) {
|
func newFactTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 1),
|
Children: make([]*scan.Term, 0, 1),
|
||||||
position: posPostfix,
|
Position: scan.PosPostfix,
|
||||||
priority: priFact,
|
Priority: scan.PriFact,
|
||||||
evalFunc: evalFact,
|
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
|
var leftValue any
|
||||||
|
|
||||||
if leftValue, err = opTerm.evalPrefix(ctx); err != nil {
|
if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil {
|
||||||
return
|
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)
|
err = fmt.Errorf("factorial of a negative integer (%d) is not allowed", i)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatiblePrefixPostfixType(leftValue)
|
err = opTerm.Errorf("incompatible type for factorial: %s", kern.TypeName(leftValue))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymExclamation, newFactTerm)
|
scan.RegisterTermConstructor(scan.SymExclamation, newFactTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-12
@@ -9,30 +9,31 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- map term
|
//-------- map term
|
||||||
|
|
||||||
func newFilterTerm(tk *Token) (inst *term) {
|
func newFilterTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priIterOp,
|
Priority: scan.PriIterOp,
|
||||||
evalFunc: evalFilter,
|
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 leftValue, rightValue any
|
||||||
var it kern.Iterator
|
var it kern.Iterator
|
||||||
var item any
|
var item any
|
||||||
|
|
||||||
if err = opTerm.checkOperands(); err != nil {
|
if err = opTerm.CheckOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if leftValue, err = opTerm.children[0].Compute(ctx); err != nil {
|
if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +46,7 @@ func evalFilter(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
ctx.SetVar("_", item)
|
ctx.SetVar("_", item)
|
||||||
ctx.SetVar("__", it.Index())
|
ctx.SetVar("__", it.Index())
|
||||||
ctx.SetVar("_#", it.Count())
|
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, valid := kern.ToBool(rightValue); valid {
|
||||||
if success {
|
if success {
|
||||||
values.AppendItem(item)
|
values.AppendItem(item)
|
||||||
@@ -70,5 +71,5 @@ func evalFilter(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymKwFilter, newFilterTerm)
|
scan.RegisterTermConstructor(scan.SymKwFilter, newFilterTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-12
@@ -10,27 +10,27 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------- fraction term
|
// -------- fraction term
|
||||||
func newFractionTerm(tk *Token) *term {
|
func newFractionTerm(tk *scan.Token) *scan.Term {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
parent: nil,
|
Children: make([]*scan.Term, 0, 2),
|
||||||
children: make([]*term, 0, 2),
|
Position: scan.PosInfix,
|
||||||
position: posInfix,
|
Priority: scan.PriFraction,
|
||||||
priority: priFraction,
|
EvalFunc: evalFraction,
|
||||||
evalFunc: evalFraction,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- eval func
|
// -------- 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 numValue, denValue any
|
||||||
var num, den int64
|
var num, den int64
|
||||||
var ok bool
|
var ok bool
|
||||||
|
|
||||||
if numValue, denValue, err = opTerm.evalInfix(ctx); err != nil {
|
if numValue, denValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if num, ok = numValue.(int64); !ok {
|
if num, ok = numValue.(int64); !ok {
|
||||||
@@ -42,7 +42,7 @@ func evalFraction(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if den == 0 {
|
if den == 0 {
|
||||||
err = opTerm.errDivisionByZero()
|
err = opTerm.Errorf("division by zero")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,5 +71,5 @@ func evalFraction(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
// registerTermConstructor(SymVertBar, newFractionTerm)
|
// registerTermConstructor(SymVertBar, newFractionTerm)
|
||||||
registerTermConstructor(SymColon, newFractionTerm)
|
scan.RegisterTermConstructor(scan.SymColon, newFractionTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-14
@@ -10,32 +10,33 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- group by term
|
//-------- group by term
|
||||||
|
|
||||||
func newGroupByTerm(tk *Token) (inst *term) {
|
func newGroupByTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priIterOp,
|
Priority: scan.PriIterOp,
|
||||||
evalFunc: evalGroupBy,
|
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 leftValue, rightValue any
|
||||||
var it kern.Iterator
|
var it kern.Iterator
|
||||||
var item any
|
var item any
|
||||||
var sKey string
|
var sKey string
|
||||||
var keyByIndex bool
|
var keyByIndex bool
|
||||||
|
|
||||||
if err = opTerm.checkOperands(); err != nil {
|
if err = opTerm.CheckOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if leftValue, err = opTerm.children[0].Compute(ctx); err != nil {
|
if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil {
|
||||||
return
|
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))
|
return nil, fmt.Errorf("left operand of MAP must be an iterable data-source; got %s", kern.TypeName(leftValue))
|
||||||
}
|
}
|
||||||
|
|
||||||
rightTk := opTerm.children[1].tk
|
rightTk := opTerm.Children[1].Tk
|
||||||
if rightTk.IsSymbol(SymVariable) && rightTk.source == "__" {
|
if rightTk.IsSymbol(scan.SymVariable) && rightTk.Source() == "__" {
|
||||||
keyByIndex = true
|
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
|
return
|
||||||
} else if kern.IsString(rightValue) {
|
} else if kern.IsString(rightValue) {
|
||||||
sKey = rightValue.(string)
|
sKey = rightValue.(string)
|
||||||
@@ -101,5 +102,5 @@ func evalGroupBy(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymKwGroupBy, newGroupByTerm)
|
scan.RegisterTermConstructor(scan.SymKwGroupBy, newGroupByTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-11
@@ -6,17 +6,18 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- in term
|
//-------- in term
|
||||||
|
|
||||||
func newInTerm(tk *Token) (inst *term) {
|
func newInTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priRelational,
|
Priority: scan.PriRelational,
|
||||||
evalFunc: evalIn,
|
EvalFunc: evalIn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,10 +26,10 @@ func newInTerm(tk *Token) (inst *term) {
|
|||||||
// return
|
// 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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,12 +40,12 @@ func evalIn(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
dict, _ := rightValue.(*kern.DictType)
|
dict, _ := rightValue.(*kern.DictType)
|
||||||
v = dict.HasKey(leftValue)
|
v = dict.HasKey(leftValue)
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymKwIn, newInTerm)
|
scan.RegisterTermConstructor(scan.SymKwIn, newInTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-11
@@ -6,24 +6,25 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- include term
|
//-------- include term
|
||||||
|
|
||||||
func newIncludeTerm(tk *Token) (inst *term) {
|
func newIncludeTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 1),
|
Children: make([]*scan.Term, 0, 1),
|
||||||
position: posPrefix,
|
Position: scan.PosPrefix,
|
||||||
priority: priSign,
|
Priority: scan.PriSign,
|
||||||
evalFunc: evalInclude,
|
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
|
var childValue any
|
||||||
|
|
||||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
if childValue, err = opTerm.EvalPrefix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +50,7 @@ func evalInclude(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
err = opTerm.ErrIncompatiblePrefixPostfixType(childValue)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//v = count
|
//v = count
|
||||||
@@ -60,5 +61,5 @@ func evalInclude(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymKwInclude, newIncludeTerm)
|
scan.RegisterTermConstructor(scan.SymKwInclude, newIncludeTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-17
@@ -6,16 +6,17 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------- index term
|
// -------- index term
|
||||||
func newIndexTerm(tk *Token) (inst *term) {
|
func newIndexTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priDot,
|
Priority: scan.PriDot,
|
||||||
evalFunc: evalIndex,
|
EvalFunc: evalIndex,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ func verifyKey(indexList *kern.ListType) (index any, err error) {
|
|||||||
return
|
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
|
var v int
|
||||||
|
|
||||||
if v, err = kern.ToGoInt((*indexList)[0], "index expression"); err == nil {
|
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
|
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)
|
v, _ := ((*indexList)[0]).(*intPair)
|
||||||
startIndex = v.a
|
startIndex = v.a
|
||||||
endIndex = v.b
|
endIndex = v.b
|
||||||
@@ -63,16 +64,16 @@ func verifyRange(indexTerm *term, indexList *kern.ListType, maxValue int) (start
|
|||||||
return
|
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 leftValue, rightValue any
|
||||||
var indexList *kern.ListType
|
var indexList *kern.ListType
|
||||||
var ok bool
|
var ok bool
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
indexTerm := opTerm.children[1]
|
indexTerm := opTerm.Children[1]
|
||||||
if indexList, ok = rightValue.(*kern.ListType); !ok {
|
if indexList, ok = rightValue.(*kern.ListType); !ok {
|
||||||
err = opTerm.Errorf("invalid index expression")
|
err = opTerm.Errorf("invalid index expression")
|
||||||
return
|
return
|
||||||
@@ -96,7 +97,7 @@ func evalIndex(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
case *kern.DictType:
|
case *kern.DictType:
|
||||||
v, err = getDictItem(unboxedValue, indexTerm, indexList, rightValue)
|
v, err = getDictItem(unboxedValue, indexTerm, indexList, rightValue)
|
||||||
default:
|
default:
|
||||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
} else if isIntPair((*indexList)[0]) {
|
} else if isIntPair((*indexList)[0]) {
|
||||||
switch unboxedValue := leftValue.(type) {
|
switch unboxedValue := leftValue.(type) {
|
||||||
@@ -112,19 +113,19 @@ func evalIndex(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
v = unboxedValue[start:end]
|
v = unboxedValue[start:end]
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
} else if kern.IsDict(leftValue) {
|
} else if kern.IsDict(leftValue) {
|
||||||
d := leftValue.(*kern.DictType)
|
d := leftValue.(*kern.DictType)
|
||||||
v, err = getDictItem(d, indexTerm, indexList, rightValue)
|
v, err = getDictItem(d, indexTerm, indexList, rightValue)
|
||||||
} else {
|
} else {
|
||||||
rightChild := opTerm.children[1]
|
rightChild := opTerm.Children[1]
|
||||||
err = rightChild.Errorf("invalid index type: %v", (*indexList)[0])
|
err = rightChild.Errorf("invalid index type: %v", (*indexList)[0])
|
||||||
}
|
}
|
||||||
return
|
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 ok bool
|
||||||
var indexValue any
|
var indexValue any
|
||||||
|
|
||||||
@@ -138,5 +139,5 @@ func getDictItem(d *kern.DictType, indexTerm *term, indexList *kern.ListType, ri
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymIndex, newIndexTerm)
|
scan.RegisterTermConstructor(scan.SymIndex, newIndexTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-26
@@ -6,34 +6,35 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- prepend term
|
//-------- prepend term
|
||||||
|
|
||||||
func newPrependTerm(tk *Token) (inst *term) {
|
func newPrependTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priInsert,
|
Priority: scan.PriInsert,
|
||||||
evalFunc: evalPrepend,
|
EvalFunc: evalPrepend,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAppendTerm(tk *Token) (inst *term) {
|
func newAppendTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priInsert,
|
Priority: scan.PriInsert,
|
||||||
evalFunc: evalAppend,
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,19 +42,19 @@ func evalPrepend(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
list, _ := rightValue.(*kern.ListType)
|
list, _ := rightValue.(*kern.ListType)
|
||||||
newList := append(kern.ListType{leftValue}, *list...)
|
newList := append(kern.ListType{leftValue}, *list...)
|
||||||
v = &newList
|
v = &newList
|
||||||
if opTerm.children[1].symbol() == SymVariable {
|
if opTerm.Children[1].Symbol() == scan.SymVariable {
|
||||||
ctx.UnsafeSetVar(opTerm.children[1].Source(), v)
|
ctx.UnsafeSetVar(opTerm.Children[1].Source(), v)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,11 +62,11 @@ func evalAppend(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
list, _ := leftValue.(*kern.ListType)
|
list, _ := leftValue.(*kern.ListType)
|
||||||
newList := append(*list, rightValue)
|
newList := append(*list, rightValue)
|
||||||
v = &newList
|
v = &newList
|
||||||
if opTerm.children[0].symbol() == SymVariable {
|
if opTerm.Children[0].Symbol() == scan.SymVariable {
|
||||||
ctx.UnsafeSetVar(opTerm.children[0].Source(), v)
|
ctx.UnsafeSetVar(opTerm.Children[0].Source(), v)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -90,6 +91,6 @@ func evalAppend(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymPlusGreater, newPrependTerm)
|
scan.RegisterTermConstructor(scan.SymPlusGreater, newPrependTerm)
|
||||||
registerTermConstructor(SymLessPlus, newAppendTerm)
|
scan.RegisterTermConstructor(scan.SymLessPlus, newAppendTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-11
@@ -6,31 +6,32 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- iter value term
|
//-------- iter value term
|
||||||
|
|
||||||
func newIterValueTerm(tk *Token) (inst *term) {
|
func newIterValueTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 1),
|
Children: make([]*scan.Term, 0, 1),
|
||||||
position: posPrefix,
|
Position: scan.PosPrefix,
|
||||||
priority: priDereference,
|
Priority: scan.PriDereference,
|
||||||
evalFunc: evalIterValue,
|
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
|
var childValue any
|
||||||
|
|
||||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
if childValue, err = opTerm.EvalPrefix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if it, ok := childValue.(kern.Iterator); ok {
|
if it, ok := childValue.(kern.Iterator); ok {
|
||||||
v, err = it.Current()
|
v, err = it.Current()
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
err = opTerm.ErrIncompatiblePrefixPostfixType(childValue)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -38,5 +39,5 @@ func evalIterValue(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
// registerTermConstructor(SymOpenClosedRound, newIterValueTerm)
|
// registerTermConstructor(SymOpenClosedRound, newIterValueTerm)
|
||||||
registerTermConstructor(SymDereference, newIterValueTerm)
|
scan.RegisterTermConstructor(scan.SymDereference, newIterValueTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-12
@@ -9,34 +9,35 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- join term
|
//-------- join term
|
||||||
|
|
||||||
func newJoinTerm(tk *Token) (inst *term) {
|
func newJoinTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priIterOp,
|
Priority: scan.PriIterOp,
|
||||||
evalFunc: evalJoin,
|
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 leftValue, rightValue any
|
||||||
var itLeft, itRight kern.Iterator
|
var itLeft, itRight kern.Iterator
|
||||||
var item any
|
var item any
|
||||||
|
|
||||||
if err = opTerm.checkOperands(); err != nil {
|
if err = opTerm.CheckOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if leftValue, err = opTerm.children[0].Compute(ctx); err != nil {
|
if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if rightValue, err = opTerm.children[1].Compute(ctx); err != nil {
|
if rightValue, err = opTerm.Children[1].Compute(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,5 +64,5 @@ func evalJoin(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymKwJoin, newJoinTerm)
|
scan.RegisterTermConstructor(scan.SymKwJoin, newJoinTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-11
@@ -6,24 +6,25 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- length term
|
//-------- length term
|
||||||
|
|
||||||
func newLengthTerm(tk *Token) (inst *term) {
|
func newLengthTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 1),
|
Children: make([]*scan.Term, 0, 1),
|
||||||
position: posPrefix,
|
Position: scan.PosPrefix,
|
||||||
priority: priSign,
|
Priority: scan.PriSign,
|
||||||
evalFunc: evalLength,
|
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
|
var childValue any
|
||||||
|
|
||||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
if childValue, err = opTerm.EvalPrefix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,12 +46,12 @@ func evalLength(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
// v = int64(it.Index() + 1)
|
// v = int64(it.Index() + 1)
|
||||||
// }
|
// }
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
err = opTerm.ErrIncompatiblePrefixPostfixType(childValue)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymHash, newLengthTerm)
|
scan.RegisterTermConstructor(scan.SymHash, newLengthTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-12
@@ -9,30 +9,31 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- map term
|
//-------- map term
|
||||||
|
|
||||||
func newMapTerm(tk *Token) (inst *term) {
|
func newMapTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priIterOp,
|
Priority: scan.PriIterOp,
|
||||||
evalFunc: evalMap,
|
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 leftValue, rightValue any
|
||||||
var it kern.Iterator
|
var it kern.Iterator
|
||||||
var item any
|
var item any
|
||||||
|
|
||||||
if err = opTerm.checkOperands(); err != nil {
|
if err = opTerm.CheckOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if leftValue, err = opTerm.children[0].Compute(ctx); err != nil {
|
if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +46,7 @@ func evalMap(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
ctx.SetVar("_", item)
|
ctx.SetVar("_", item)
|
||||||
ctx.SetVar("__", it.Index())
|
ctx.SetVar("__", it.Index())
|
||||||
ctx.SetVar("_#", it.Count())
|
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)
|
values.AppendItem(rightValue)
|
||||||
}
|
}
|
||||||
ctx.DeleteVar("_#")
|
ctx.DeleteVar("_#")
|
||||||
@@ -66,5 +67,5 @@ func evalMap(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymKwMap, newMapTerm)
|
scan.RegisterTermConstructor(scan.SymKwMap, newMapTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-10
@@ -6,25 +6,26 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- plugin term
|
//-------- plugin term
|
||||||
|
|
||||||
func newPluginTerm(tk *Token) (inst *term) {
|
func newPluginTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 1),
|
Children: make([]*scan.Term, 0, 1),
|
||||||
position: posPrefix,
|
Position: scan.PosPrefix,
|
||||||
priority: priSign,
|
Priority: scan.PriSign,
|
||||||
evalFunc: evalPlugin,
|
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 childValue any
|
||||||
var count int
|
var count int
|
||||||
|
|
||||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
if childValue, err = opTerm.EvalPrefix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,5 +37,5 @@ func evalPlugin(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymKwPlugin, newPluginTerm)
|
scan.RegisterTermConstructor(scan.SymKwPlugin, newPluginTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-30
@@ -6,24 +6,24 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------- post increment term
|
// -------- post increment term
|
||||||
|
|
||||||
func newPostIncTerm(tk *Token) *term {
|
func newPostIncTerm(tk *scan.Token) *scan.Term {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
parent: nil,
|
Children: make([]*scan.Term, 0, 1),
|
||||||
children: make([]*term, 0, 1),
|
Position: scan.PosPostfix,
|
||||||
position: posPostfix,
|
Priority: scan.PriIncDec,
|
||||||
priority: priIncDec,
|
EvalFunc: evalPostInc,
|
||||||
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
|
var childValue any
|
||||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
if childValue, err = opTerm.EvalPrefix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,8 +31,8 @@ func evalPostInc(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
var namePrefix string
|
var namePrefix string
|
||||||
v, err = it.Next()
|
v, err = it.Next()
|
||||||
|
|
||||||
if opTerm.children[0].symbol() == SymVariable {
|
if opTerm.Children[0].Symbol() == scan.SymVariable {
|
||||||
namePrefix = opTerm.children[0].Source()
|
namePrefix = opTerm.Children[0].Source()
|
||||||
}
|
}
|
||||||
ctx.UnsafeSetVar(namePrefix+"_index", it.Index())
|
ctx.UnsafeSetVar(namePrefix+"_index", it.Index())
|
||||||
if c, err1 := it.Current(); err1 == nil {
|
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)
|
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
|
v = childValue
|
||||||
i, _ := childValue.(int64)
|
i, _ := childValue.(int64)
|
||||||
ctx.SetVar(opTerm.children[0].Source(), i+1)
|
ctx.SetVar(opTerm.Children[0].Source(), i+1)
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
err = opTerm.ErrIncompatiblePrefixPostfixType(childValue)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- post decrement term
|
// -------- post decrement term
|
||||||
|
|
||||||
func newPostDecTerm(tk *Token) *term {
|
func newPostDecTerm(tk *scan.Token) *scan.Term {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
parent: nil,
|
Children: make([]*scan.Term, 0, 1),
|
||||||
children: make([]*term, 0, 1),
|
Position: scan.PosPostfix,
|
||||||
position: posPostfix,
|
Priority: scan.PriIncDec,
|
||||||
priority: priIncDec,
|
EvalFunc: evalPostDec,
|
||||||
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
|
var childValue any
|
||||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
if childValue, err = opTerm.EvalPrefix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if it, ok := childValue.(Iterator); ok {
|
/* if it, ok := childValue.(Iterator); ok {
|
||||||
v, err = it.Next()
|
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
|
v = childValue
|
||||||
i, _ := childValue.(int64)
|
i, _ := childValue.(int64)
|
||||||
ctx.SetVar(opTerm.children[0].Source(), i-1)
|
ctx.SetVar(opTerm.Children[0].Source(), i-1)
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
err = opTerm.ErrIncompatiblePrefixPostfixType(childValue)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymDoublePlus, newPostIncTerm)
|
scan.RegisterTermConstructor(scan.SymDoublePlus, newPostIncTerm)
|
||||||
registerTermConstructor(SymDoubleMinus, newPostDecTerm)
|
scan.RegisterTermConstructor(scan.SymDoubleMinus, newPostDecTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-28
@@ -6,68 +6,68 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------- pre increment term
|
// -------- pre increment term
|
||||||
|
|
||||||
func newPreIncTerm(tk *Token) *term {
|
func newPreIncTerm(tk *scan.Token) *scan.Term {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
parent: nil,
|
Children: make([]*scan.Term, 0, 1),
|
||||||
children: make([]*term, 0, 1),
|
Position: scan.PosPrefix,
|
||||||
position: posPrefix,
|
Priority: scan.PriIncDec,
|
||||||
priority: priIncDec,
|
EvalFunc: evalPreInc,
|
||||||
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
|
var childValue any
|
||||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
if childValue, err = opTerm.EvalPrefix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if kern.IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable {
|
if kern.IsInteger(childValue) && opTerm.Children[0].Symbol() == scan.SymVariable {
|
||||||
i := childValue.(int64) + 1
|
i := childValue.(int64) + 1
|
||||||
ctx.SetVar(opTerm.children[0].Source(), i)
|
ctx.SetVar(opTerm.Children[0].Source(), i)
|
||||||
v = i
|
v = i
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
err = opTerm.ErrIncompatiblePrefixPostfixType(childValue)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- pre decrement term
|
// -------- pre decrement term
|
||||||
|
|
||||||
func newPreDecTerm(tk *Token) *term {
|
func newPreDecTerm(tk *scan.Token) *scan.Term {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
parent: nil,
|
Parent: nil,
|
||||||
children: make([]*term, 0, 1),
|
Children: make([]*scan.Term, 0, 1),
|
||||||
position: posPrefix,
|
Position: scan.PosPrefix,
|
||||||
priority: priIncDec,
|
Priority: scan.PriIncDec,
|
||||||
evalFunc: evalPreDec,
|
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
|
var childValue any
|
||||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
if childValue, err = opTerm.EvalPrefix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if kern.IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable {
|
if kern.IsInteger(childValue) && opTerm.Children[0].Symbol() == scan.SymVariable {
|
||||||
i := childValue.(int64) - 1
|
i := childValue.(int64) - 1
|
||||||
ctx.SetVar(opTerm.children[0].Source(), i)
|
ctx.SetVar(opTerm.Children[0].Source(), i)
|
||||||
v = i
|
v = i
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
err = opTerm.ErrIncompatiblePrefixPostfixType(childValue)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymPreInc, newPreIncTerm)
|
scan.RegisterTermConstructor(scan.SymPreInc, newPreIncTerm)
|
||||||
registerTermConstructor(SymPreDec, newPreDecTerm)
|
scan.RegisterTermConstructor(scan.SymPreDec, newPreDecTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+53
-52
@@ -8,21 +8,22 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- multiply term
|
//-------- multiply term
|
||||||
|
|
||||||
func newMultiplyTerm(tk *Token) (inst *term) {
|
func newMultiplyTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priProduct,
|
Priority: scan.PriProduct,
|
||||||
evalFunc: evalMultiply,
|
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) {
|
if kern.IsString(leftValue) && kern.IsInteger(rightValue) {
|
||||||
s, _ := leftValue.(string)
|
s, _ := leftValue.(string)
|
||||||
n, _ := rightValue.(int64)
|
n, _ := rightValue.(int64)
|
||||||
@@ -38,15 +39,15 @@ func mulValues(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
|||||||
v = leftInt * rightInt
|
v = leftInt * rightInt
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = prodTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = prodTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,22 +56,22 @@ func evalMultiply(ctx kern.ExprContext, prodTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
//-------- divide term
|
//-------- divide term
|
||||||
|
|
||||||
func newDivideTerm(tk *Token) (inst *term) {
|
func newDivideTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priProduct,
|
Priority: scan.PriProduct,
|
||||||
evalFunc: evalDivide,
|
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.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) {
|
||||||
if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) {
|
if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) {
|
||||||
d := kern.NumAsFloat(rightValue)
|
d := kern.NumAsFloat(rightValue)
|
||||||
if d == 0.0 {
|
if d == 0.0 {
|
||||||
err = opTerm.errDivisionByZero()
|
err = opTerm.ErrDivisionByZero()
|
||||||
} else {
|
} else {
|
||||||
v = kern.NumAsFloat(leftValue) / d
|
v = kern.NumAsFloat(leftValue) / d
|
||||||
}
|
}
|
||||||
@@ -79,7 +80,7 @@ func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
|||||||
} else {
|
} else {
|
||||||
leftInt, _ := leftValue.(int64)
|
leftInt, _ := leftValue.(int64)
|
||||||
if rightInt, _ := rightValue.(int64); rightInt == 0 {
|
if rightInt, _ := rightValue.(int64); rightInt == 0 {
|
||||||
err = opTerm.errDivisionByZero()
|
err = opTerm.ErrDivisionByZero()
|
||||||
} else {
|
} else {
|
||||||
v = leftInt / rightInt
|
v = leftInt / rightInt
|
||||||
}
|
}
|
||||||
@@ -92,7 +93,7 @@ func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
|||||||
source := leftValue.(string)
|
source := leftValue.(string)
|
||||||
partSize := int(rightValue.(int64))
|
partSize := int(rightValue.(int64))
|
||||||
if partSize == 0 {
|
if partSize == 0 {
|
||||||
err = opTerm.errDivisionByZero()
|
err = opTerm.ErrDivisionByZero()
|
||||||
} else {
|
} else {
|
||||||
partCount := len(source) / partSize
|
partCount := len(source) / partSize
|
||||||
remainder := 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)
|
v = kern.NewList(parts)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,66 +128,66 @@ func evalDivide(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
//-------- divide as float term
|
//-------- divide as float term
|
||||||
|
|
||||||
func newDivideAsFloatTerm(tk *Token) (inst *term) {
|
func newDivideAsFloatTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priProduct,
|
Priority: scan.PriProduct,
|
||||||
evalFunc: evalDivideAsFloat,
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = floatDivTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = floatDivTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if kern.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) {
|
if kern.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) {
|
||||||
d := kern.NumAsFloat(rightValue)
|
d := kern.NumAsFloat(rightValue)
|
||||||
if d == 0.0 {
|
if d == 0.0 {
|
||||||
err = floatDivTerm.errDivisionByZero()
|
err = floatDivTerm.ErrDivisionByZero()
|
||||||
} else {
|
} else {
|
||||||
v = kern.NumAsFloat(leftValue) / d
|
v = kern.NumAsFloat(leftValue) / d
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = floatDivTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = floatDivTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------- reminder term
|
//-------- reminder term
|
||||||
|
|
||||||
func newRemainderTerm(tk *Token) (inst *term) {
|
func newRemainderTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priProduct,
|
Priority: scan.PriProduct,
|
||||||
evalFunc: evalRemainder,
|
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) {
|
if kern.IsInteger(leftValue) && kern.IsInteger(rightValue) {
|
||||||
rightInt, _ := rightValue.(int64)
|
rightInt, _ := rightValue.(int64)
|
||||||
if rightInt == 0 {
|
if rightInt == 0 {
|
||||||
err = opTerm.errDivisionByZero()
|
err = opTerm.ErrDivisionByZero()
|
||||||
} else {
|
} else {
|
||||||
leftInt, _ := leftValue.(int64)
|
leftInt, _ := leftValue.(int64)
|
||||||
v = leftInt % rightInt
|
v = leftInt % rightInt
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = remainderTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = remainderTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,8 +196,8 @@ func evalRemainder(ctx kern.ExprContext, remainderTerm *term) (v any, err error)
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymStar, newMultiplyTerm)
|
scan.RegisterTermConstructor(scan.SymStar, newMultiplyTerm)
|
||||||
registerTermConstructor(SymSlash, newDivideTerm)
|
scan.RegisterTermConstructor(scan.SymSlash, newDivideTerm)
|
||||||
registerTermConstructor(SymDotSlash, newDivideAsFloatTerm)
|
scan.RegisterTermConstructor(scan.SymDotSlash, newDivideAsFloatTerm)
|
||||||
registerTermConstructor(SymPercent, newRemainderTerm)
|
scan.RegisterTermConstructor(scan.SymPercent, newRemainderTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-19
@@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------- range term
|
// -------- range term
|
||||||
@@ -28,35 +29,35 @@ func isIntPair(v any) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRangeTerm(tk *Token) (inst *term) {
|
func newRangeTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priRange,
|
Priority: scan.PriRange,
|
||||||
evalFunc: evalRange,
|
EvalFunc: evalRange,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func changeColonToRange(t *term) {
|
func changeColonToRange(t *scan.Term) {
|
||||||
if t.tk.IsSymbol(SymColon) {
|
if t.Tk.IsSymbol(scan.SymColon) {
|
||||||
t.tk.Sym = SymRange
|
t.Tk.Sym = scan.SymRange
|
||||||
t.evalFunc = evalRange
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if len(opTerm.children) == 0 {
|
if len(opTerm.Children) == 0 {
|
||||||
leftValue = int64(0)
|
leftValue = int64(0)
|
||||||
rightValue = int64(-1)
|
rightValue = int64(-1)
|
||||||
} else if len(opTerm.children) == 1 {
|
} else if len(opTerm.Children) == 1 {
|
||||||
if leftValue, err = opTerm.children[0].Compute(ctx); err != nil {
|
if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rightValue = int64(kern.ConstLastIndex)
|
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
|
return
|
||||||
}
|
}
|
||||||
if !(kern.IsInteger(leftValue) && kern.IsInteger(rightValue)) {
|
if !(kern.IsInteger(leftValue) && kern.IsInteger(rightValue)) {
|
||||||
@@ -72,15 +73,15 @@ func evalRange(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func errRangeInvalidSpecification(t *term) error {
|
func errRangeInvalidSpecification(t *scan.Term) error {
|
||||||
return t.Errorf("invalid range specification")
|
return t.Errorf("invalid range specification")
|
||||||
}
|
}
|
||||||
|
|
||||||
func errRangeUnexpectedExpression(t *term) error {
|
func errRangeUnexpectedExpression(t *scan.Term) error {
|
||||||
return t.Errorf("unexpected range expression")
|
return t.Errorf("unexpected range expression")
|
||||||
}
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymRange, newRangeTerm)
|
scan.RegisterTermConstructor(scan.SymRange, newRangeTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+63
-62
@@ -8,17 +8,18 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- equal term
|
//-------- equal term
|
||||||
|
|
||||||
func newEqualTerm(tk *Token) (inst *term) {
|
func newEqualTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priRelational,
|
Priority: scan.PriRelational,
|
||||||
evalFunc: evalEqual,
|
EvalFunc: evalEqual,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,10 +50,10 @@ func equals(a, b any, deepCmp kern.DeepFuncTemplate) (eq bool, err error) {
|
|||||||
return
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,17 +63,17 @@ func evalEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
//-------- not equal term
|
//-------- not equal term
|
||||||
|
|
||||||
func newNotEqualTerm(tk *Token) (inst *term) {
|
func newNotEqualTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priRelational,
|
Priority: scan.PriRelational,
|
||||||
evalFunc: evalNotEqual,
|
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 {
|
if v, err = evalEqual(ctx, opTerm); err == nil {
|
||||||
b, _ := kern.ToBool(v)
|
b, _ := kern.ToBool(v)
|
||||||
v = !b
|
v = !b
|
||||||
@@ -82,17 +83,17 @@ func evalNotEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
//-------- less term
|
//-------- less term
|
||||||
|
|
||||||
func newLessTerm(tk *Token) (inst *term) {
|
func newLessTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priRelational,
|
Priority: scan.PriRelational,
|
||||||
evalFunc: evalLess,
|
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.IsNumOrFract(a) && kern.IsNumOrFract(b) {
|
||||||
if kern.IsNumber(a) && kern.IsNumber(b) {
|
if kern.IsNumber(a) && kern.IsNumber(b) {
|
||||||
if kern.IsInteger(a) && kern.IsInteger(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)
|
bList, _ := b.(*kern.ListType)
|
||||||
isLess = len(*aList) < len(*bList) && bList.Contains(aList)
|
isLess = len(*aList) < len(*bList) && bList.Contains(aList)
|
||||||
} else {
|
} else {
|
||||||
err = self.errIncompatibleTypes(a, b)
|
err = self.ErrIncompatibleTypes(a, b)
|
||||||
}
|
}
|
||||||
return
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
v, err = lessThan(opTerm, leftValue, rightValue)
|
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
|
//-------- less or equal term
|
||||||
|
|
||||||
func newLessEqualTerm(tk *Token) (inst *term) {
|
func newLessEqualTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priRelational,
|
Priority: scan.PriRelational,
|
||||||
evalFunc: evalLessEqual,
|
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, err = lessThan(self, a, b); err == nil {
|
||||||
if !isLessEq {
|
if !isLessEq {
|
||||||
if kern.IsList(a) && kern.IsList(b) {
|
if kern.IsList(a) && kern.IsList(b) {
|
||||||
@@ -158,10 +159,10 @@ func lessThanOrEqual(self *term, a, b any) (isLessEq bool, err error) {
|
|||||||
return
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,20 +173,20 @@ func evalLessEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
//-------- greater term
|
//-------- greater term
|
||||||
|
|
||||||
func newGreaterTerm(tk *Token) (inst *term) {
|
func newGreaterTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priRelational,
|
Priority: scan.PriRelational,
|
||||||
evalFunc: evalGreater,
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,20 +196,20 @@ func evalGreater(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
//-------- greater or equal term
|
//-------- greater or equal term
|
||||||
|
|
||||||
func newGreaterEqualTerm(tk *Token) (inst *term) {
|
func newGreaterEqualTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priRelational,
|
Priority: scan.PriRelational,
|
||||||
evalFunc: evalGreaterEqual,
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,10 +219,10 @@ func evalGreaterEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymDoubleEqual, newEqualTerm)
|
scan.RegisterTermConstructor(scan.SymDoubleEqual, newEqualTerm)
|
||||||
registerTermConstructor(SymNotEqual, newNotEqualTerm)
|
scan.RegisterTermConstructor(scan.SymNotEqual, newNotEqualTerm)
|
||||||
registerTermConstructor(SymLess, newLessTerm)
|
scan.RegisterTermConstructor(scan.SymLess, newLessTerm)
|
||||||
registerTermConstructor(SymLessOrEqual, newLessEqualTerm)
|
scan.RegisterTermConstructor(scan.SymLessOrEqual, newLessEqualTerm)
|
||||||
registerTermConstructor(SymGreater, newGreaterTerm)
|
scan.RegisterTermConstructor(scan.SymGreater, newGreaterTerm)
|
||||||
registerTermConstructor(SymGreaterOrEqual, newGreaterEqualTerm)
|
scan.RegisterTermConstructor(scan.SymGreaterOrEqual, newGreaterEqualTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-16
@@ -6,17 +6,18 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- selector term
|
//-------- selector term
|
||||||
|
|
||||||
func newSelectorTerm(tk *Token) (inst *term) {
|
func newSelectorTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 3),
|
Children: make([]*scan.Term, 0, 3),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priSelector,
|
Priority: scan.PriSelector,
|
||||||
evalFunc: evalSelector,
|
EvalFunc: evalSelector,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ func trySelectorCase(ctx kern.ExprContext, exprValue, caseSel any, caseIndex int
|
|||||||
if caseData.filterList == nil {
|
if caseData.filterList == nil {
|
||||||
selectedValue, err = caseData.caseExpr.Eval(ctx)
|
selectedValue, err = caseData.caseExpr.Eval(ctx)
|
||||||
match = true
|
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 {
|
if len(filterList) == 0 {
|
||||||
var valueAsInt = int64(0)
|
var valueAsInt = int64(0)
|
||||||
if b, ok := exprValue.(bool); ok {
|
if b, ok := exprValue.(bool); ok {
|
||||||
@@ -53,33 +54,33 @@ func trySelectorCase(ctx kern.ExprContext, exprValue, caseSel any, caseIndex int
|
|||||||
return
|
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 exprValue any
|
||||||
var match bool
|
var match bool
|
||||||
|
|
||||||
if err = opTerm.checkOperands(); err != nil {
|
if err = opTerm.CheckOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
exprTerm := opTerm.children[0]
|
exprTerm := opTerm.Children[0]
|
||||||
if exprValue, err = exprTerm.Compute(ctx); err != nil {
|
if exprValue, err = exprTerm.Compute(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
caseListTerm := opTerm.children[1]
|
caseListTerm := opTerm.Children[1]
|
||||||
caseList, _ := caseListTerm.value().([]*term)
|
caseList, _ := caseListTerm.Value().([]*scan.Term)
|
||||||
for i, caseTerm := range caseList {
|
for i, caseTerm := range caseList {
|
||||||
caseSel := caseTerm.value()
|
caseSel := caseTerm.Value()
|
||||||
if match, v, err = trySelectorCase(ctx, exprValue, caseSel, i); err != nil || match {
|
if match, v, err = trySelectorCase(ctx, exprValue, caseSel, i); err != nil || match {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err == nil && !match {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymSelector, newSelectorTerm)
|
scan.RegisterTermConstructor(scan.SymSelector, newSelectorTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-24
@@ -6,35 +6,36 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- bit right shift term
|
//-------- bit right shift term
|
||||||
|
|
||||||
func newRightShiftTerm(tk *Token) (inst *term) {
|
func newRightShiftTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priBinShift,
|
Priority: scan.PriBinShift,
|
||||||
evalFunc: evalRightShift,
|
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) {
|
if kern.IsInteger(leftValue) && kern.IsInteger(rightValue) {
|
||||||
leftInt := leftValue.(int64)
|
leftInt := leftValue.(int64)
|
||||||
rightInt := rightValue.(int64)
|
rightInt := rightValue.(int64)
|
||||||
v = leftInt >> rightInt
|
v = leftInt >> rightInt
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,31 +43,31 @@ func evalRightShift(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLeftShiftTerm(tk *Token) (inst *term) {
|
func newLeftShiftTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priBinShift,
|
Priority: scan.PriBinShift,
|
||||||
evalFunc: evalLeftShift,
|
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) {
|
if kern.IsInteger(leftValue) && kern.IsInteger(rightValue) {
|
||||||
leftInt := leftValue.(int64)
|
leftInt := leftValue.(int64)
|
||||||
rightInt := rightValue.(int64)
|
rightInt := rightValue.(int64)
|
||||||
v = leftInt << rightInt
|
v = leftInt << rightInt
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +77,6 @@ func evalLeftShift(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymDoubleGreater, newRightShiftTerm)
|
scan.RegisterTermConstructor(scan.SymDoubleGreater, newRightShiftTerm)
|
||||||
registerTermConstructor(SymDoubleLess, newLeftShiftTerm)
|
scan.RegisterTermConstructor(scan.SymDoubleLess, newLeftShiftTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-23
@@ -6,61 +6,60 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- plus sign term
|
//-------- plus sign term
|
||||||
|
|
||||||
func newPlusSignTerm(tk *Token) (inst *term) {
|
func newPlusSignTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
// class: classOperator,
|
Children: make([]*scan.Term, 0, 1),
|
||||||
// kind: kindUnknown,
|
Position: scan.PosPrefix,
|
||||||
children: make([]*term, 0, 1),
|
Priority: scan.PriSign,
|
||||||
position: posPrefix,
|
EvalFunc: evalSign,
|
||||||
priority: priSign,
|
|
||||||
evalFunc: evalSign,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMinusSignTerm(tk *Token) (inst *term) {
|
func newMinusSignTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 1),
|
Children: make([]*scan.Term, 0, 1),
|
||||||
position: posPrefix,
|
Position: scan.PosPrefix,
|
||||||
priority: priSign,
|
Priority: scan.PriSign,
|
||||||
evalFunc: evalSign,
|
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
|
var rightValue any
|
||||||
|
|
||||||
if rightValue, err = opTerm.evalPrefix(ctx); err != nil {
|
if rightValue, err = opTerm.EvalPrefix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if kern.IsFloat(rightValue) {
|
if kern.IsFloat(rightValue) {
|
||||||
if opTerm.tk.Sym == SymChangeSign {
|
if opTerm.Tk.Sym == scan.SymChangeSign {
|
||||||
f, _ := rightValue.(float64)
|
f, _ := rightValue.(float64)
|
||||||
v = -f
|
v = -f
|
||||||
} else {
|
} else {
|
||||||
v = rightValue
|
v = rightValue
|
||||||
}
|
}
|
||||||
} else if kern.IsInteger(rightValue) {
|
} else if kern.IsInteger(rightValue) {
|
||||||
if opTerm.tk.Sym == SymChangeSign {
|
if opTerm.Tk.Sym == scan.SymChangeSign {
|
||||||
i, _ := rightValue.(int64)
|
i, _ := rightValue.(int64)
|
||||||
v = -i
|
v = -i
|
||||||
} else {
|
} else {
|
||||||
v = rightValue
|
v = rightValue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatiblePrefixPostfixType(rightValue)
|
err = opTerm.ErrIncompatiblePrefixPostfixType(rightValue)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymUnchangeSign, newPlusSignTerm)
|
scan.RegisterTermConstructor(scan.SymUnchangeSign, newPlusSignTerm)
|
||||||
registerTermConstructor(SymChangeSign, newMinusSignTerm)
|
scan.RegisterTermConstructor(scan.SymChangeSign, newMinusSignTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-24
@@ -9,21 +9,22 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- plus term
|
//-------- plus term
|
||||||
|
|
||||||
func newPlusTerm(tk *Token) (inst *term) {
|
func newPlusTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priSum,
|
Priority: scan.PriSum,
|
||||||
evalFunc: evalPlus,
|
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)) {
|
if (kern.IsString(leftValue) && kern.IsNumberString(rightValue)) || (kern.IsString(rightValue) && kern.IsNumberString(leftValue)) {
|
||||||
v = fmt.Sprintf("%v%v", leftValue, rightValue)
|
v = fmt.Sprintf("%v%v", leftValue, rightValue)
|
||||||
} else if kern.IsNumber(leftValue) && kern.IsNumber(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) {
|
} else if kern.IsFraction(leftValue) && kern.IsFraction(rightValue) {
|
||||||
v, err = kern.SumAnyFract(leftValue, rightValue)
|
v, err = kern.SumAnyFract(leftValue, rightValue)
|
||||||
} else {
|
} else {
|
||||||
err = plusTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = plusTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return v, err
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = plusTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = plusTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,17 +76,17 @@ func evalPlus(ctx kern.ExprContext, plusTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
//-------- minus term
|
//-------- minus term
|
||||||
|
|
||||||
func newMinusTerm(tk *Token) (inst *term) {
|
func newMinusTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 2),
|
Children: make([]*scan.Term, 0, 2),
|
||||||
position: posInfix,
|
Position: scan.PosInfix,
|
||||||
priority: priSum,
|
Priority: scan.PriSum,
|
||||||
evalFunc: evalMinus,
|
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.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) {
|
||||||
if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) {
|
if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) {
|
||||||
v = kern.NumAsFloat(leftValue) - kern.NumAsFloat(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
|
v = &diffList
|
||||||
} else {
|
} else {
|
||||||
err = minusTerm.errIncompatibleTypes(leftValue, rightValue)
|
err = minusTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
return
|
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
|
var leftValue, rightValue any
|
||||||
|
|
||||||
if leftValue, rightValue, err = minusTerm.evalInfix(ctx); err != nil {
|
if leftValue, rightValue, err = minusTerm.EvalInfix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,6 +125,6 @@ func evalMinus(ctx kern.ExprContext, minusTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymPlus, newPlusTerm)
|
scan.RegisterTermConstructor(scan.SymPlus, newPlusTerm)
|
||||||
registerTermConstructor(SymMinus, newMinusTerm)
|
scan.RegisterTermConstructor(scan.SymMinus, newMinusTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-12
@@ -8,21 +8,22 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- unset term
|
//-------- unset term
|
||||||
|
|
||||||
func newUnsetTerm(tk *Token) (inst *term) {
|
func newUnsetTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
return &term{
|
return &scan.Term{
|
||||||
tk: *tk,
|
Tk: *tk,
|
||||||
children: make([]*term, 0, 1),
|
Children: make([]*scan.Term, 0, 1),
|
||||||
position: posPrefix,
|
Position: scan.PosPrefix,
|
||||||
priority: priSign,
|
Priority: scan.PriSign,
|
||||||
evalFunc: evalUnset,
|
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 {
|
if name, ok := item.(string); ok {
|
||||||
var size int
|
var size int
|
||||||
if strings.HasSuffix(name, "()") {
|
if strings.HasSuffix(name, "()") {
|
||||||
@@ -35,16 +36,16 @@ func deleteContextItem(ctx kern.ExprContext, opTerm *term, item any) (deleted bo
|
|||||||
deleted = ctx.VarCount() < size
|
deleted = ctx.VarCount() < size
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.errIncompatiblePrefixPostfixType(item)
|
err = opTerm.ErrIncompatiblePrefixPostfixType(item)
|
||||||
}
|
}
|
||||||
return
|
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 childValue any
|
||||||
var deleted bool
|
var deleted bool
|
||||||
|
|
||||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
if childValue, err = opTerm.EvalPrefix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,5 +70,5 @@ func evalUnset(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymKwUnset, newUnsetTerm)
|
scan.RegisterTermConstructor(scan.SymKwUnset, newUnsetTerm)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package expr
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
"golang.org/x/exp/constraints"
|
"golang.org/x/exp/constraints"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -54,34 +55,34 @@ func NewParser() (p *parser) {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (parser *parser) Next(scanner *scanner) (tk *Token) {
|
func (parser *parser) Next(scanner *scan.Scanner) (tk *scan.Token) {
|
||||||
for tk = scanner.Next(); tk.IsSymbol(SymComment); tk = scanner.Next() {
|
for tk = scanner.Next(); tk.IsSymbol(scan.SymComment); tk = scanner.Next() {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (parser *parser) parseFuncCall(scanner *scanner, ctx parserContext, tk *Token) (tree *term, err error) {
|
func (parser *parser) parseFuncCall(scanner *scan.Scanner, ctx parserContext, tk *scan.Token) (tree *scan.Term, err error) {
|
||||||
args := make([]*term, 0, 10)
|
args := make([]*scan.Term, 0, 10)
|
||||||
itemExpected := false
|
itemExpected := false
|
||||||
lastSym := SymUnknown
|
lastSym := scan.SymUnknown
|
||||||
for lastSym != SymClosedRound && lastSym != SymEos {
|
for lastSym != scan.SymClosedRound && lastSym != scan.SymEos {
|
||||||
var subTree *ast
|
var subTree *scan.Ast
|
||||||
if subTree, err = parser.parseItem(scanner, ctx, SymComma, SymClosedRound); err != nil {
|
if subTree, err = parser.parseItem(scanner, ctx, scan.SymComma, scan.SymClosedRound); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
prev := scanner.Previous()
|
prev := scanner.Previous()
|
||||||
if subTree.root != nil {
|
if subTree.Root() != nil {
|
||||||
args = append(args, subTree.root)
|
args = append(args, subTree.Root())
|
||||||
} else if itemExpected {
|
} else if itemExpected {
|
||||||
err = prev.ErrorExpectedGot("function-param-value")
|
err = prev.ErrorExpectedGot("function-param-value")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
itemExpected = prev.Sym == SymComma
|
itemExpected = prev.Sym == scan.SymComma
|
||||||
lastSym = scanner.Previous().Sym
|
lastSym = scanner.Previous().Sym
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if lastSym != SymClosedRound {
|
if lastSym != scan.SymClosedRound {
|
||||||
err = errors.New("unterminated arguments list")
|
err = errors.New("unterminated arguments list")
|
||||||
} else {
|
} else {
|
||||||
tree = newFuncCallTerm(tk, args)
|
tree = newFuncCallTerm(tk, args)
|
||||||
@@ -90,18 +91,18 @@ func (parser *parser) parseFuncCall(scanner *scanner, ctx parserContext, tk *Tok
|
|||||||
return
|
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}
|
// Example: "add = func(x,y) {x+y}
|
||||||
var body *ast
|
var body *scan.Ast
|
||||||
args := make([]*term, 0)
|
args := make([]*scan.Term, 0)
|
||||||
lastSym := SymUnknown
|
lastSym := scan.SymUnknown
|
||||||
defaultParamsStarted := false
|
defaultParamsStarted := false
|
||||||
itemExpected := false
|
itemExpected := false
|
||||||
tk := scanner.Previous()
|
tk := scanner.Previous()
|
||||||
for lastSym != SymClosedRound && lastSym != SymEos {
|
for lastSym != scan.SymClosedRound && lastSym != scan.SymEos {
|
||||||
tk = parser.Next(scanner)
|
tk = parser.Next(scanner)
|
||||||
if tk.IsSymbol(SymIdentifier) {
|
if tk.IsSymbol(scan.SymIdentifier) {
|
||||||
param := newTerm(tk)
|
param := scan.NewTerm(tk)
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
if pos := paramAlreadyDefined(args, param); pos > 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)
|
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)
|
args = append(args, param)
|
||||||
tk = parser.Next(scanner)
|
tk = parser.Next(scanner)
|
||||||
if tk.Sym == SymEqual {
|
if tk.Sym == scan.SymEqual {
|
||||||
var paramExpr *ast
|
var paramExpr *scan.Ast
|
||||||
defaultParamsStarted = true
|
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
|
break
|
||||||
}
|
}
|
||||||
param.forceChild(paramExpr.root)
|
param.ForceChild(paramExpr.Root())
|
||||||
} else if defaultParamsStarted {
|
} else if defaultParamsStarted {
|
||||||
err = tk.Errorf("can't mix default and non-default parameters")
|
err = tk.Errorf("can't mix default and non-default parameters")
|
||||||
break
|
break
|
||||||
@@ -127,32 +128,32 @@ func (parser *parser) parseFuncDef(scanner *scanner) (tree *term, err error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
lastSym = scanner.Previous().Sym
|
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(")")
|
err = tk.ErrorExpectedGot(")")
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
tk = parser.Next(scanner)
|
tk = parser.Next(scanner)
|
||||||
if tk.IsSymbol(SymOpenBrace) {
|
if tk.IsSymbol(scan.SymOpenBrace) {
|
||||||
body, err = parser.parseGeneral(scanner, allowMultiExpr|allowVarRef, SymClosedBrace)
|
body, err = parser.parseGeneral(scanner, allowMultiExpr|allowVarRef, scan.SymClosedBrace)
|
||||||
} else {
|
} else {
|
||||||
err = tk.ErrorExpectedGot("{")
|
err = tk.ErrorExpectedGot("{")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if scanner.Previous().Sym != SymClosedBrace {
|
if scanner.Previous().Sym != scan.SymClosedBrace {
|
||||||
err = scanner.Previous().ErrorExpectedGot("}")
|
err = scanner.Previous().ErrorExpectedGot("}")
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeValueToken(SymExpression, "", body)
|
tk = scanner.MakeValueToken(scan.SymExpression, "", body)
|
||||||
tree = newFuncDefTerm(tk, args)
|
tree = newFuncDefTerm(tk, args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func paramAlreadyDefined(args []*term, param *term) (position int) {
|
func paramAlreadyDefined(args []*scan.Term, param *scan.Term) (position int) {
|
||||||
position = 0
|
position = 0
|
||||||
for i, arg := range args {
|
for i, arg := range args {
|
||||||
if arg.Source() == param.Source() {
|
if arg.Source() == param.Source() {
|
||||||
@@ -162,39 +163,39 @@ func paramAlreadyDefined(args []*term, param *term) (position int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (parser *parser) parseList(scanner *scanner, ctx parserContext) (listTerm *term, err error) {
|
func (parser *parser) parseList(scanner *scan.Scanner, ctx parserContext) (listTerm *scan.Term, err error) {
|
||||||
r, c := scanner.lastPos()
|
r, c := scanner.LastPos()
|
||||||
args := make([]*term, 0)
|
args := make([]*scan.Term, 0)
|
||||||
lastSym := SymUnknown
|
lastSym := scan.SymUnknown
|
||||||
itemExpected := false
|
itemExpected := false
|
||||||
itemCtx := remFlags(ctx, allowIndex)
|
itemCtx := remFlags(ctx, allowIndex)
|
||||||
for lastSym != SymClosedSquare && lastSym != SymEos {
|
for lastSym != scan.SymClosedSquare && lastSym != scan.SymEos {
|
||||||
zeroRequired := scanner.current.Sym == SymColon
|
zeroRequired := scanner.Current().Sym == scan.SymColon
|
||||||
var itemTree *ast
|
var itemTree *scan.Ast
|
||||||
if itemTree, err = parser.parseItem(scanner, itemCtx, SymComma, SymClosedSquare); err == nil {
|
if itemTree, err = parser.parseItem(scanner, itemCtx, scan.SymComma, scan.SymClosedSquare); err == nil {
|
||||||
root := itemTree.root
|
root := itemTree.Root()
|
||||||
if root != nil {
|
if root != nil {
|
||||||
if hasFlag(ctx, allowIndex) && root.symbol() == SymColon {
|
if hasFlag(ctx, allowIndex) && root.Symbol() == scan.SymColon {
|
||||||
changeColonToRange(root)
|
changeColonToRange(root)
|
||||||
}
|
}
|
||||||
if !hasFlag(ctx, allowIndex) && root.symbol() == SymRange {
|
if !hasFlag(ctx, allowIndex) && root.Symbol() == scan.SymRange {
|
||||||
// err = root.Errorf("unexpected range expression")
|
// err = root.Errorf("unexpected range expression")
|
||||||
err = errRangeUnexpectedExpression(root)
|
err = errRangeUnexpectedExpression(root)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
args = append(args, root)
|
args = append(args, root)
|
||||||
if hasFlag(ctx, allowIndex) && root.symbol() == SymRange && zeroRequired { //len(root.children) == 0 {
|
if hasFlag(ctx, allowIndex) && root.Symbol() == scan.SymRange && zeroRequired { //len(root.children) == 0 {
|
||||||
if len(root.children) == 1 {
|
if len(root.Children) == 1 {
|
||||||
root.children = append(root.children, root.children[0])
|
root.Children = append(root.Children, root.Children[0])
|
||||||
} else if len(root.children) > 1 {
|
} else if len(root.Children) > 1 {
|
||||||
// err = root.Errorf("invalid range specification")
|
// err = root.Errorf("invalid range specification")
|
||||||
err = errRangeInvalidSpecification(root)
|
err = errRangeInvalidSpecification(root)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
zeroTk := NewValueToken(root.tk.row, root.tk.col, SymInteger, "0", int64(0))
|
zeroTk := scan.NewValueToken(root.Tk.Row(), root.Tk.Col(), scan.SymInteger, "0", int64(0))
|
||||||
zeroTerm := newTerm(zeroTk)
|
zeroTerm := scan.NewTerm(zeroTk)
|
||||||
zeroTerm.setParent(root)
|
zeroTerm.SetParent(root)
|
||||||
root.children[0] = zeroTerm
|
root.Children[0] = zeroTerm
|
||||||
}
|
}
|
||||||
} else if itemExpected {
|
} else if itemExpected {
|
||||||
prev := scanner.Previous()
|
prev := scanner.Previous()
|
||||||
@@ -205,12 +206,12 @@ func (parser *parser) parseList(scanner *scanner, ctx parserContext) (listTerm *
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
lastSym = scanner.Previous().Sym
|
lastSym = scanner.Previous().Sym
|
||||||
if itemExpected = lastSym == SymComma; itemExpected {
|
if itemExpected = lastSym == scan.SymComma; itemExpected {
|
||||||
remFlags(ctx, allowIndex)
|
remFlags(ctx, allowIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if lastSym != SymClosedSquare {
|
if lastSym != scan.SymClosedSquare {
|
||||||
err = scanner.Previous().ErrorExpectedGot("]")
|
err = scanner.Previous().ErrorExpectedGot("]")
|
||||||
} else {
|
} else {
|
||||||
listTerm = newListTerm(r, c, args)
|
listTerm = newListTerm(r, c, args)
|
||||||
@@ -219,16 +220,16 @@ func (parser *parser) parseList(scanner *scanner, ctx parserContext) (listTerm *
|
|||||||
return
|
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()
|
tk := scanner.Previous()
|
||||||
args := make([]*term, 0)
|
args := make([]*scan.Term, 0)
|
||||||
lastSym := SymUnknown
|
lastSym := scan.SymUnknown
|
||||||
itemExpected := false
|
itemExpected := false
|
||||||
for lastSym != SymClosedRound && lastSym != SymEos {
|
for lastSym != scan.SymClosedRound && lastSym != scan.SymEos {
|
||||||
var subTree *ast
|
var subTree *scan.Ast
|
||||||
if subTree, err = parser.parseItem(scanner, ctx, SymComma, SymClosedRound); err == nil {
|
if subTree, err = parser.parseItem(scanner, ctx, scan.SymComma, scan.SymClosedRound); err == nil {
|
||||||
if subTree.root != nil {
|
if subTree.Root() != nil {
|
||||||
args = append(args, subTree.root)
|
args = append(args, subTree.Root())
|
||||||
} else if itemExpected {
|
} else if itemExpected {
|
||||||
prev := scanner.Previous()
|
prev := scanner.Previous()
|
||||||
err = prev.ErrorExpectedGot("iterator-param")
|
err = prev.ErrorExpectedGot("iterator-param")
|
||||||
@@ -238,10 +239,10 @@ func (parser *parser) parseIterDef(scanner *scanner, ctx parserContext) (subtree
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
lastSym = scanner.Previous().Sym
|
lastSym = scanner.Previous().Sym
|
||||||
itemExpected = lastSym == SymComma
|
itemExpected = lastSym == scan.SymComma
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if lastSym != SymClosedRound {
|
if lastSym != scan.SymClosedRound {
|
||||||
err = scanner.Previous().ErrorExpectedGot(")")
|
err = scanner.Previous().ErrorExpectedGot(")")
|
||||||
} else {
|
} else {
|
||||||
subtree = newIteratorTerm(tk, args)
|
subtree = newIteratorTerm(tk, args)
|
||||||
@@ -250,18 +251,18 @@ func (parser *parser) parseIterDef(scanner *scanner, ctx parserContext) (subtree
|
|||||||
return
|
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)
|
tk := parser.Next(scanner)
|
||||||
if tk.Sym == SymError {
|
if tk.Sym == scan.SymError {
|
||||||
err = tk.Error()
|
err = tk.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if tk.Sym == SymClosedBrace || tk.Sym == SymEos {
|
if tk.Sym == scan.SymClosedBrace || tk.Sym == scan.SymEos {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if tk.Sym == SymInteger || tk.Sym == SymString {
|
if tk.Sym == scan.SymInteger || tk.Sym == scan.SymString {
|
||||||
tkSep := parser.Next(scanner)
|
tkSep := parser.Next(scanner)
|
||||||
if tkSep.Sym != SymColon {
|
if tkSep.Sym != scan.SymColon {
|
||||||
err = tkSep.ErrorExpectedGot(":")
|
err = tkSep.ErrorExpectedGot(":")
|
||||||
} else {
|
} else {
|
||||||
key = tk.Value
|
key = tk.Value
|
||||||
@@ -272,12 +273,12 @@ func (parser *parser) parseDictKey(scanner *scanner) (key any, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (parser *parser) parseDictionary(scanner *scanner, ctx parserContext) (subtree *term, err error) {
|
func (parser *parser) parseDictionary(scanner *scan.Scanner, ctx parserContext) (subtree *scan.Term, err error) {
|
||||||
args := make(map[any]*term, 0)
|
args := make(map[any]*scan.Term, 0)
|
||||||
lastSym := SymUnknown
|
lastSym := scan.SymUnknown
|
||||||
itemExpected := false
|
itemExpected := false
|
||||||
for lastSym != SymClosedBrace && lastSym != SymEos {
|
for lastSym != scan.SymClosedBrace && lastSym != scan.SymEos {
|
||||||
var subTree *ast
|
var subTree *scan.Ast
|
||||||
var key any
|
var key any
|
||||||
if key, err = parser.parseDictKey(scanner); err != nil {
|
if key, err = parser.parseDictKey(scanner); err != nil {
|
||||||
break
|
break
|
||||||
@@ -289,9 +290,9 @@ func (parser *parser) parseDictionary(scanner *scanner, ctx parserContext) (subt
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if subTree, err = parser.parseItem(scanner, ctx, SymComma, SymClosedBrace); err == nil {
|
if subTree, err = parser.parseItem(scanner, ctx, scan.SymComma, scan.SymClosedBrace); err == nil {
|
||||||
if subTree.root != nil {
|
if subTree.Root() != nil {
|
||||||
args[key] = subTree.root
|
args[key] = subTree.Root()
|
||||||
} else /*if key != nil*/ {
|
} else /*if key != nil*/ {
|
||||||
prev := scanner.Previous()
|
prev := scanner.Previous()
|
||||||
err = prev.ErrorExpectedGot("dictionary-value")
|
err = prev.ErrorExpectedGot("dictionary-value")
|
||||||
@@ -301,10 +302,10 @@ func (parser *parser) parseDictionary(scanner *scanner, ctx parserContext) (subt
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
lastSym = scanner.Previous().Sym
|
lastSym = scanner.Previous().Sym
|
||||||
itemExpected = lastSym == SymComma
|
itemExpected = lastSym == scan.SymComma
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if lastSym != SymClosedBrace {
|
if lastSym != scan.SymClosedBrace {
|
||||||
err = scanner.Previous().ErrorExpectedGot("}")
|
err = scanner.Previous().ErrorExpectedGot("}")
|
||||||
} else {
|
} else {
|
||||||
subtree = newDictTerm(args)
|
subtree = newDictTerm(args)
|
||||||
@@ -313,14 +314,14 @@ func (parser *parser) parseDictionary(scanner *scanner, ctx parserContext) (subt
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (parser *parser) parseSelectorCase(scanner *scanner, ctx parserContext, defaultCase bool) (caseTerm *term, err error) {
|
func (parser *parser) parseSelectorCase(scanner *scan.Scanner, ctx parserContext, defaultCase bool) (caseTerm *scan.Term, err error) {
|
||||||
var filterList *term
|
var filterList *scan.Term
|
||||||
var caseExpr *ast
|
var caseExpr *scan.Ast
|
||||||
ctx = remFlags(ctx, allowIndex)
|
ctx = remFlags(ctx, allowIndex)
|
||||||
tk := parser.Next(scanner)
|
tk := parser.Next(scanner)
|
||||||
startRow := tk.row
|
startRow := tk.Row()
|
||||||
startCol := tk.col
|
startCol := tk.Col()
|
||||||
if tk.Sym == SymOpenSquare {
|
if tk.Sym == scan.SymOpenSquare {
|
||||||
if defaultCase {
|
if defaultCase {
|
||||||
err = tk.Errorf("case list in default clause")
|
err = tk.Errorf("case list in default clause")
|
||||||
return
|
return
|
||||||
@@ -329,14 +330,14 @@ func (parser *parser) parseSelectorCase(scanner *scanner, ctx parserContext, def
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
tk = parser.Next(scanner)
|
tk = parser.Next(scanner)
|
||||||
startRow = tk.row
|
startRow = tk.Row()
|
||||||
startCol = tk.col
|
startCol = tk.Col()
|
||||||
} else if !defaultCase {
|
} else if !defaultCase {
|
||||||
filterList = newListTerm(startRow, startCol, make([]*term, 0))
|
filterList = newListTerm(startRow, startCol, make([]*scan.Term, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
if tk.Sym == SymOpenBrace {
|
if tk.Sym == scan.SymOpenBrace {
|
||||||
if caseExpr, err = parser.parseGeneral(scanner, ctx|allowMultiExpr, SymClosedBrace); err != nil {
|
if caseExpr, err = parser.parseGeneral(scanner, ctx|allowMultiExpr, scan.SymClosedBrace); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -349,25 +350,25 @@ func (parser *parser) parseSelectorCase(scanner *scanner, ctx parserContext, def
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func addSelectorCase(selectorTerm, caseTerm *term) {
|
func addSelectorCase(selectorTerm, caseTerm *scan.Term) {
|
||||||
if len(selectorTerm.children) < 2 {
|
if len(selectorTerm.Children) < 2 {
|
||||||
caseListTerm := newListTermA(caseTerm)
|
caseListTerm := newListTermA(caseTerm)
|
||||||
selectorTerm.children = append(selectorTerm.children, caseListTerm)
|
selectorTerm.Children = append(selectorTerm.Children, caseListTerm)
|
||||||
} else {
|
} else {
|
||||||
caseListTerm := selectorTerm.children[1]
|
caseListTerm := selectorTerm.Children[1]
|
||||||
caseList, _ := caseListTerm.value().([]*term)
|
caseList, _ := caseListTerm.Value().([]*scan.Term)
|
||||||
caseList = append(caseList, caseTerm)
|
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) {
|
func (parser *parser) parseSelector(scanner *scan.Scanner, tree *scan.Ast, ctx parserContext) (selectorTerm *scan.Term, err error) {
|
||||||
var caseTerm *term
|
var caseTerm *scan.Term
|
||||||
|
|
||||||
ctx = remFlags(ctx, allowIndex)
|
ctx = remFlags(ctx, allowIndex)
|
||||||
tk := scanner.makeToken(SymSelector, '?')
|
tk := scanner.MakeToken(scan.SymSelector, '?')
|
||||||
if selectorTerm, err = tree.addToken(tk); err != nil {
|
if selectorTerm, err = tree.AddToken(tk); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,11 +378,11 @@ func (parser *parser) parseSelector(scanner *scanner, tree *ast, ctx parserConte
|
|||||||
return
|
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...)
|
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() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
if errVal, ok := r.(error); ok {
|
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...)
|
return parser.parseGeneral(scanner, allowMultiExpr, termSymbols...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func couldBeACollection(t *term) bool {
|
func couldBeACollection(t *scan.Term) bool {
|
||||||
var sym = SymUnknown
|
var sym = scan.SymUnknown
|
||||||
if t != nil {
|
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) {
|
func listSubTree(tree *scan.Ast, listTerm *scan.Term, allowIndeces bool) (root *scan.Term, err error) {
|
||||||
var tk *Token
|
var tk *scan.Token
|
||||||
if allowIndeces {
|
if allowIndeces {
|
||||||
tk = NewToken(listTerm.tk.row, listTerm.tk.col, SymIndex, listTerm.Source())
|
tk = scan.NewToken(listTerm.Tk.Row(), listTerm.Tk.Col(), scan.SymIndex, listTerm.Source())
|
||||||
root = newTerm(tk)
|
root = scan.NewTerm(tk)
|
||||||
if err = tree.addTerm(root); err == nil {
|
if err = tree.AddTerm(root); err == nil {
|
||||||
err = tree.addTerm(listTerm)
|
err = tree.AddTerm(listTerm)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
root = listTerm
|
root = listTerm
|
||||||
err = tree.addTerm(listTerm)
|
err = tree.AddTerm(listTerm)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func changePrefix(tk *Token) {
|
func changePrefix(tk *scan.Token) {
|
||||||
switch tk.Sym {
|
switch tk.Sym {
|
||||||
case SymMinus:
|
case scan.SymMinus:
|
||||||
tk.SetSymbol(SymChangeSign)
|
tk.SetSymbol(scan.SymChangeSign)
|
||||||
case SymPlus:
|
case scan.SymPlus:
|
||||||
tk.SetSymbol(SymUnchangeSign)
|
tk.SetSymbol(scan.SymUnchangeSign)
|
||||||
case SymStar:
|
case scan.SymStar:
|
||||||
tk.SetSymbol(SymDereference)
|
tk.SetSymbol(scan.SymDereference)
|
||||||
case SymExclamation:
|
case scan.SymExclamation:
|
||||||
tk.SetSymbol(SymNot)
|
tk.SetSymbol(scan.SymNot)
|
||||||
case SymDoublePlus:
|
case scan.SymDoublePlus:
|
||||||
tk.SetSymbol(SymPreInc)
|
tk.SetSymbol(scan.SymPreInc)
|
||||||
case SymDoubleMinus:
|
case scan.SymDoubleMinus:
|
||||||
tk.SetSymbol(SymPreDec)
|
tk.SetSymbol(scan.SymPreDec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymbols ...Symbol) (tree *ast, err error) {
|
func (parser *parser) parseGeneral(scanner *scan.Scanner, ctx parserContext, termSymbols ...scan.Symbol) (tree *scan.Ast, err error) {
|
||||||
var selectorTerm *term = nil
|
var selectorTerm *scan.Term = nil
|
||||||
var currentTerm *term = nil
|
var currentTerm *scan.Term = nil
|
||||||
var tk *Token
|
var tk *scan.Token
|
||||||
|
|
||||||
tree = NewAst()
|
tree = scan.NewAst()
|
||||||
firstToken := true
|
firstToken := true
|
||||||
// lastSym := SymUnknown
|
// lastSym := SymUnknown
|
||||||
for tk = parser.Next(scanner); err == nil && tk != nil && !tk.IsTerm(termSymbols); /*&& !areSymbolsOutOfCtx(tk, selectorTerm, SymColon, SymDoubleColon)*/ tk = parser.Next(scanner) {
|
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
|
// continue
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if tk.Sym == SymSemiColon {
|
if tk.Sym == scan.SymSemiColon {
|
||||||
if hasFlag(ctx, allowMultiExpr) {
|
if hasFlag(ctx, allowMultiExpr) {
|
||||||
tree.ToForest()
|
tree.ToForest()
|
||||||
firstToken = true
|
firstToken = true
|
||||||
@@ -456,7 +457,7 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
|
|||||||
selectorTerm = nil
|
selectorTerm = nil
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
err = tk.Errorf(`unexpected token %q, expected ",", "]", or ")"`, tk.source)
|
err = tk.Errorf(`unexpected token %q, expected ",", "]", or ")"`, tk.Source())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -468,87 +469,87 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch tk.Sym {
|
switch tk.Sym {
|
||||||
case SymOpenRound:
|
case scan.SymOpenRound:
|
||||||
var subTree *ast
|
var subTree *scan.Ast
|
||||||
if subTree, err = parser.parseGeneral(scanner, ctx, SymClosedRound); err == nil {
|
if subTree, err = parser.parseGeneral(scanner, ctx, scan.SymClosedRound); err == nil {
|
||||||
if subTree.root == nil {
|
if subTree.Root() == nil {
|
||||||
err = tk.ErrorExpectedGotString("expression", "()")
|
err = tk.ErrorExpectedGotString("expression", "()")
|
||||||
} else {
|
} else {
|
||||||
exprTerm := newExprTerm(subTree.root)
|
exprTerm := newExprTerm(subTree.Root())
|
||||||
err = tree.addTerm(exprTerm)
|
err = tree.AddTerm(exprTerm)
|
||||||
currentTerm = exprTerm
|
currentTerm = exprTerm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case SymFuncCall:
|
case scan.SymFuncCall:
|
||||||
var funcCallTerm *term
|
var funcCallTerm *scan.Term
|
||||||
if funcCallTerm, err = parser.parseFuncCall(scanner, ctx, tk); err == nil {
|
if funcCallTerm, err = parser.parseFuncCall(scanner, ctx, tk); err == nil {
|
||||||
err = tree.addTerm(funcCallTerm)
|
err = tree.AddTerm(funcCallTerm)
|
||||||
currentTerm = funcCallTerm
|
currentTerm = funcCallTerm
|
||||||
}
|
}
|
||||||
case SymOpenSquare:
|
case scan.SymOpenSquare:
|
||||||
var listTerm *term
|
var listTerm *scan.Term
|
||||||
newCtx := addFlagsCond(addFlags(ctx, squareContext), allowIndex, couldBeACollection(currentTerm))
|
newCtx := addFlagsCond(addFlags(ctx, squareContext), allowIndex, couldBeACollection(currentTerm))
|
||||||
if listTerm, err = parser.parseList(scanner, newCtx); err == nil {
|
if listTerm, err = parser.parseList(scanner, newCtx); err == nil {
|
||||||
currentTerm, err = listSubTree(tree, listTerm, hasFlag(newCtx, allowIndex))
|
currentTerm, err = listSubTree(tree, listTerm, hasFlag(newCtx, allowIndex))
|
||||||
}
|
}
|
||||||
case SymOpenBrace:
|
case scan.SymOpenBrace:
|
||||||
if currentTerm != nil && currentTerm.symbol() == SymColon {
|
if currentTerm != nil && currentTerm.Symbol() == scan.SymColon {
|
||||||
err = currentTerm.Errorf(`selector-case outside of a selector context`)
|
err = currentTerm.Errorf(`selector-case outside of a selector context`)
|
||||||
} else {
|
} else {
|
||||||
var mapTerm *term
|
var mapTerm *scan.Term
|
||||||
if mapTerm, err = parser.parseDictionary(scanner, ctx); err == nil {
|
if mapTerm, err = parser.parseDictionary(scanner, ctx); err == nil {
|
||||||
err = tree.addTerm(mapTerm)
|
err = tree.AddTerm(mapTerm)
|
||||||
currentTerm = mapTerm
|
currentTerm = mapTerm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case SymEqual, SymPlusEqual, SymMinusEqual, SymStarEqual, SymSlashEqual, SymPercEqual, SymAmpersandEqual, SymVertBarEqual, SymDoubleLessEqual, SymDoubleGreaterEqual, SymCaretEqual:
|
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)
|
currentTerm, err = tree.AddToken(tk)
|
||||||
firstToken = true
|
firstToken = true
|
||||||
case SymFuncDef:
|
case scan.SymFuncDef:
|
||||||
var funcDefTerm *term
|
var funcDefTerm *scan.Term
|
||||||
if funcDefTerm, err = parser.parseFuncDef(scanner); err == nil {
|
if funcDefTerm, err = parser.parseFuncDef(scanner); err == nil {
|
||||||
err = tree.addTerm(funcDefTerm)
|
err = tree.AddTerm(funcDefTerm)
|
||||||
currentTerm = funcDefTerm
|
currentTerm = funcDefTerm
|
||||||
}
|
}
|
||||||
case SymDollarRound:
|
case scan.SymDollarRound:
|
||||||
var iterDefTerm *term
|
var iterDefTerm *scan.Term
|
||||||
if iterDefTerm, err = parser.parseIterDef(scanner, ctx); err == nil {
|
if iterDefTerm, err = parser.parseIterDef(scanner, ctx); err == nil {
|
||||||
err = tree.addTerm(iterDefTerm)
|
err = tree.AddTerm(iterDefTerm)
|
||||||
currentTerm = iterDefTerm
|
currentTerm = iterDefTerm
|
||||||
}
|
}
|
||||||
case SymIdentifier:
|
case scan.SymIdentifier:
|
||||||
if tk.source[0] == '@' && !hasFlag(ctx, allowVarRef) {
|
if tk.Source()[0] == '@' && !hasFlag(ctx, allowVarRef) {
|
||||||
err = tk.Errorf("variable references are not allowed in top level expressions: %q", tk.source)
|
err = tk.Errorf("variable references are not allowed in top level expressions: %q", tk.Source())
|
||||||
} else {
|
} 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 {
|
if selectorTerm, err = parser.parseSelector(scanner, tree, ctx); err == nil {
|
||||||
currentTerm = selectorTerm
|
currentTerm = selectorTerm
|
||||||
addFlags(ctx, selectorContext)
|
addFlags(ctx, selectorContext)
|
||||||
}
|
}
|
||||||
case SymColon, SymDoubleColon:
|
case scan.SymColon, scan.SymDoubleColon:
|
||||||
var caseTerm *term
|
var caseTerm *scan.Term
|
||||||
if selectorTerm != nil {
|
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)
|
addSelectorCase(selectorTerm, caseTerm)
|
||||||
currentTerm = caseTerm
|
currentTerm = caseTerm
|
||||||
if tk.Sym == SymDoubleColon {
|
if tk.Sym == scan.SymDoubleColon {
|
||||||
selectorTerm = nil
|
selectorTerm = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentTerm, err = tree.addToken(tk)
|
currentTerm, err = tree.AddToken(tk)
|
||||||
if tk.IsOneOfA(SymColon, SymRange) {
|
if tk.IsOneOfA(scan.SymColon, scan.SymRange) {
|
||||||
// Colon outside a selector term acts like a separator
|
// Colon outside a selector term acts like a separator
|
||||||
firstToken = true
|
firstToken = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
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
|
selectorTerm = nil
|
||||||
remFlags(ctx, selectorContext)
|
remFlags(ctx, selectorContext)
|
||||||
}
|
}
|
||||||
@@ -558,12 +559,12 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
if !tk.IsOneOf(termSymbols) {
|
if !tk.IsOneOf(termSymbols) {
|
||||||
var symDesc string
|
var symDesc string
|
||||||
if tk.IsSymbol(SymError) {
|
if tk.IsSymbol(scan.SymError) {
|
||||||
symDesc = tk.ErrorText()
|
symDesc = tk.ErrorText()
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
err = tk.Error()
|
err = tk.Error()
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-24
@@ -2,7 +2,7 @@
|
|||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
|
|
||||||
// ast.go
|
// ast.go
|
||||||
package expr
|
package scan
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@@ -13,42 +13,46 @@ import (
|
|||||||
|
|
||||||
//-------- ast
|
//-------- ast
|
||||||
|
|
||||||
type ast struct {
|
type Ast struct {
|
||||||
forest []*term
|
forest []*Term
|
||||||
root *term
|
root *Term
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAst() *ast {
|
func NewAst() *Ast {
|
||||||
return &ast{}
|
return &Ast{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ast *ast) TypeName() string {
|
func (ast *Ast) TypeName() string {
|
||||||
return "Expression"
|
return "Expression"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ast *ast) ToForest() {
|
func (ast *Ast) Root() *Term {
|
||||||
|
return ast.root
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ast *Ast) ToForest() {
|
||||||
if ast.root != nil {
|
if ast.root != nil {
|
||||||
if ast.forest == nil {
|
if ast.forest == nil {
|
||||||
ast.forest = make([]*term, 0)
|
ast.forest = make([]*Term, 0)
|
||||||
}
|
}
|
||||||
ast.forest = append(ast.forest, ast.root)
|
ast.forest = append(ast.forest, ast.root)
|
||||||
ast.root = nil
|
ast.root = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ast *ast) String() string {
|
func (ast *Ast) String() string {
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
if ast.root == nil {
|
if ast.root == nil {
|
||||||
sb.WriteString("(nil)")
|
sb.WriteString("(nil)")
|
||||||
} else {
|
} else {
|
||||||
ast.root.toString(&sb)
|
ast.root.ToString(&sb)
|
||||||
}
|
}
|
||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ast *ast) addTokens(tokens ...*Token) (err error) {
|
func (ast *Ast) AddTokens(tokens ...*Token) (err error) {
|
||||||
for _, tk := range tokens {
|
for _, tk := range tokens {
|
||||||
if _, err = ast.addToken(tk); err != nil {
|
if _, err = ast.AddToken(tk); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,16 +64,16 @@ func (ast *ast) addTokens(tokens ...*Token) (err error) {
|
|||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func (ast *ast) addToken(tk *Token) (t *term, err error) {
|
func (ast *Ast) AddToken(tk *Token) (t *Term, err error) {
|
||||||
if t = newTerm(tk); t != nil {
|
if t = NewTerm(tk); t != nil {
|
||||||
err = ast.addTerm(t)
|
err = ast.AddTerm(t)
|
||||||
} else {
|
} else {
|
||||||
err = tk.Errorf("unexpected token %q", tk.String())
|
err = tk.Errorf("unexpected token %q", tk.String())
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ast *ast) addTerm(node *term) (err error) {
|
func (ast *Ast) AddTerm(node *Term) (err error) {
|
||||||
if ast.root == nil {
|
if ast.root == nil {
|
||||||
ast.root = node
|
ast.root = node
|
||||||
} else {
|
} else {
|
||||||
@@ -78,35 +82,35 @@ func (ast *ast) addTerm(node *term) (err error) {
|
|||||||
return
|
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() {
|
if tree.getPriority() < node.getPriority() {
|
||||||
root = tree
|
root = tree
|
||||||
if tree.isComplete() {
|
if tree.isComplete() {
|
||||||
var subRoot *term
|
var subRoot *Term
|
||||||
last := tree.removeLastChild()
|
last := tree.removeLastChild()
|
||||||
if subRoot, err = ast.insert(last, node); err == nil {
|
if subRoot, err = ast.insert(last, node); err == nil {
|
||||||
subRoot.setParent(tree)
|
subRoot.SetParent(tree)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
node.setParent(tree)
|
node.SetParent(tree)
|
||||||
}
|
}
|
||||||
} else if !node.isLeaf() {
|
} else if !node.isLeaf() {
|
||||||
root = node
|
root = node
|
||||||
tree.setParent(node)
|
tree.SetParent(node)
|
||||||
} else {
|
} else {
|
||||||
err = node.Errorf("two adjacent operators: %q and %q", tree, node)
|
err = node.Errorf("two adjacent operators: %q and %q", tree, node)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ast *ast) Finish() {
|
func (ast *Ast) Finish() {
|
||||||
if ast.root == nil && ast.forest != nil && len(ast.forest) >= 1 {
|
if ast.root == nil && ast.forest != nil && len(ast.forest) >= 1 {
|
||||||
ast.root = ast.forest[len(ast.forest)-1]
|
ast.root = ast.forest[len(ast.forest)-1]
|
||||||
ast.forest = ast.forest[0 : 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() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
if errVal, ok := r.(error); ok {
|
if errVal, ok := r.(error); ok {
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
|
|
||||||
// expr project scanner.go
|
// expr project scanner.go
|
||||||
package expr
|
package scan
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
@@ -13,9 +13,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type scanner struct {
|
type Scanner struct {
|
||||||
current *Token
|
current *Token
|
||||||
prev *Token
|
prev *Token
|
||||||
stage *Token
|
stage *Token
|
||||||
@@ -25,8 +26,8 @@ type scanner struct {
|
|||||||
translations map[Symbol]Symbol
|
translations map[Symbol]Symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewScanner(s io.Reader, translations map[Symbol]Symbol) (inst *scanner) {
|
func NewScanner(s io.Reader, translations map[Symbol]Symbol) (inst *Scanner) {
|
||||||
inst = &scanner{
|
inst = &Scanner{
|
||||||
stream: bufio.NewReader(s),
|
stream: bufio.NewReader(s),
|
||||||
row: 1,
|
row: 1,
|
||||||
column: 1,
|
column: 1,
|
||||||
@@ -52,7 +53,11 @@ func DefaultTranslations() map[Symbol]Symbol {
|
|||||||
// return self.current
|
// 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, err = scanner.stream.ReadByte(); err == nil {
|
||||||
if ch == '\n' {
|
if ch == '\n' {
|
||||||
scanner.row++
|
scanner.row++
|
||||||
@@ -64,7 +69,7 @@ func (scanner *scanner) readChar() (ch byte, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner *scanner) unreadChar() (err error) {
|
func (scanner *Scanner) unreadChar() (err error) {
|
||||||
if err = scanner.stream.UnreadByte(); err == nil {
|
if err = scanner.stream.UnreadByte(); err == nil {
|
||||||
if scanner.column--; scanner.column == 0 {
|
if scanner.column--; scanner.column == 0 {
|
||||||
if scanner.row--; scanner.row == 0 {
|
if scanner.row--; scanner.row == 0 {
|
||||||
@@ -77,7 +82,7 @@ func (scanner *scanner) unreadChar() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner *scanner) UnreadToken() (err error) {
|
func (scanner *Scanner) UnreadToken() (err error) {
|
||||||
if scanner.stage == nil {
|
if scanner.stage == nil {
|
||||||
scanner.stage = scanner.current
|
scanner.stage = scanner.current
|
||||||
scanner.current = scanner.prev
|
scanner.current = scanner.prev
|
||||||
@@ -87,7 +92,7 @@ func (scanner *scanner) UnreadToken() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner *scanner) lastPos() (r, c int) {
|
func (scanner *Scanner) LastPos() (r, c int) {
|
||||||
if scanner.prev != nil {
|
if scanner.prev != nil {
|
||||||
r = scanner.prev.row
|
r = scanner.prev.row
|
||||||
c = scanner.prev.col
|
c = scanner.prev.col
|
||||||
@@ -95,11 +100,11 @@ func (scanner *scanner) lastPos() (r, c int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner *scanner) Previous() *Token {
|
func (scanner *Scanner) Previous() *Token {
|
||||||
return scanner.prev
|
return scanner.prev
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner *scanner) Next() (tk *Token) {
|
func (scanner *Scanner) Next() (tk *Token) {
|
||||||
scanner.prev = scanner.current
|
scanner.prev = scanner.current
|
||||||
tk = scanner.current
|
tk = scanner.current
|
||||||
if scanner.stage != nil {
|
if scanner.stage != nil {
|
||||||
@@ -111,7 +116,7 @@ func (scanner *scanner) Next() (tk *Token) {
|
|||||||
return tk
|
return tk
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner *scanner) fetchNextToken() (tk *Token) {
|
func (scanner *Scanner) fetchNextToken() (tk *Token) {
|
||||||
var ch byte
|
var ch byte
|
||||||
if err := scanner.skipBlanks(); err != nil {
|
if err := scanner.skipBlanks(); err != nil {
|
||||||
return scanner.makeErrorToken(err)
|
return scanner.makeErrorToken(err)
|
||||||
@@ -129,7 +134,7 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
} else if next == '>' {
|
} else if next == '>' {
|
||||||
tk = scanner.moveOn(SymPlusGreater, ch, next)
|
tk = scanner.moveOn(SymPlusGreater, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymPlus, ch)
|
tk = scanner.MakeToken(SymPlus, ch)
|
||||||
}
|
}
|
||||||
case '-':
|
case '-':
|
||||||
if next, _ := scanner.peek(); next == '-' {
|
if next, _ := scanner.peek(); next == '-' {
|
||||||
@@ -137,7 +142,7 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
} else if next == '=' {
|
} else if next == '=' {
|
||||||
tk = scanner.moveOn(SymMinusEqual, ch, next)
|
tk = scanner.moveOn(SymMinusEqual, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymMinus, ch)
|
tk = scanner.MakeToken(SymMinus, ch)
|
||||||
}
|
}
|
||||||
case '*':
|
case '*':
|
||||||
if next, _ := scanner.peek(); next == '*' {
|
if next, _ := scanner.peek(); next == '*' {
|
||||||
@@ -147,7 +152,7 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
} else if next, _ = scanner.peek(); next == '=' {
|
} else if next, _ = scanner.peek(); next == '=' {
|
||||||
tk = scanner.moveOn(SymStarEqual, ch, next)
|
tk = scanner.moveOn(SymStarEqual, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymStar, ch)
|
tk = scanner.MakeToken(SymStar, ch)
|
||||||
}
|
}
|
||||||
case '/':
|
case '/':
|
||||||
if next, _ := scanner.peek(); next == '*' {
|
if next, _ := scanner.peek(); next == '*' {
|
||||||
@@ -159,11 +164,11 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
scanner.readChar()
|
scanner.readChar()
|
||||||
tk = scanner.fetchOnLineComment()
|
tk = scanner.fetchOnLineComment()
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymSlash, ch)
|
tk = scanner.MakeToken(SymSlash, ch)
|
||||||
}
|
}
|
||||||
case '\\':
|
case '\\':
|
||||||
if escape {
|
if escape {
|
||||||
tk = scanner.makeToken(SymBackSlash, ch)
|
tk = scanner.MakeToken(SymBackSlash, ch)
|
||||||
escape = false
|
escape = false
|
||||||
} else {
|
} else {
|
||||||
escape = true
|
escape = true
|
||||||
@@ -174,24 +179,24 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
} else if next, _ = scanner.peek(); next == '=' {
|
} else if next, _ = scanner.peek(); next == '=' {
|
||||||
tk = scanner.moveOn(SymVertBarEqual, ch, next)
|
tk = scanner.moveOn(SymVertBarEqual, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymVertBar, ch)
|
tk = scanner.MakeToken(SymVertBar, ch)
|
||||||
}
|
}
|
||||||
case ',':
|
case ',':
|
||||||
tk = scanner.makeToken(SymComma, ch)
|
tk = scanner.MakeToken(SymComma, ch)
|
||||||
case '^':
|
case '^':
|
||||||
if next, _ := scanner.peek(); next == '=' {
|
if next, _ := scanner.peek(); next == '=' {
|
||||||
tk = scanner.moveOn(SymCaretEqual, ch, next)
|
tk = scanner.moveOn(SymCaretEqual, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymCaret, ch)
|
tk = scanner.MakeToken(SymCaret, ch)
|
||||||
}
|
}
|
||||||
case ':':
|
case ':':
|
||||||
if next, _ := scanner.peek(); next == ':' {
|
if next, _ := scanner.peek(); next == ':' {
|
||||||
tk = scanner.moveOn(SymDoubleColon, ch, next)
|
tk = scanner.moveOn(SymDoubleColon, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymColon, ch)
|
tk = scanner.MakeToken(SymColon, ch)
|
||||||
}
|
}
|
||||||
case ';':
|
case ';':
|
||||||
tk = scanner.makeToken(SymSemiColon, ch)
|
tk = scanner.MakeToken(SymSemiColon, ch)
|
||||||
case '.':
|
case '.':
|
||||||
//if next, _ := self.peek(); next >= '0' && next <= '9' {
|
//if next, _ := self.peek(); next >= '0' && next <= '9' {
|
||||||
// tk = self.parseNumber(ch)
|
// tk = self.parseNumber(ch)
|
||||||
@@ -205,29 +210,29 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
tk = scanner.moveOn(SymDoubleDot, ch, next)
|
tk = scanner.moveOn(SymDoubleDot, ch, next)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymDot, ch)
|
tk = scanner.MakeToken(SymDot, ch)
|
||||||
}
|
}
|
||||||
case '\'':
|
case '\'':
|
||||||
if escape {
|
if escape {
|
||||||
tk = scanner.makeToken(SymQuote, ch)
|
tk = scanner.MakeToken(SymQuote, ch)
|
||||||
escape = false
|
escape = false
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.fetchString(ch, true)
|
tk = scanner.fetchString(ch, true)
|
||||||
}
|
}
|
||||||
case '"':
|
case '"':
|
||||||
if escape {
|
if escape {
|
||||||
tk = scanner.makeToken(SymDoubleQuote, ch)
|
tk = scanner.MakeToken(SymDoubleQuote, ch)
|
||||||
escape = false
|
escape = false
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.fetchString(ch, true)
|
tk = scanner.fetchString(ch, true)
|
||||||
}
|
}
|
||||||
case '`':
|
case '`':
|
||||||
tk = scanner.makeToken(SymBackTick, ch)
|
tk = scanner.MakeToken(SymBackTick, ch)
|
||||||
case '!':
|
case '!':
|
||||||
if next, _ := scanner.peek(); next == '=' {
|
if next, _ := scanner.peek(); next == '=' {
|
||||||
tk = scanner.moveOn(SymNotEqual, ch, next)
|
tk = scanner.moveOn(SymNotEqual, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymExclamation, ch)
|
tk = scanner.MakeToken(SymExclamation, ch)
|
||||||
}
|
}
|
||||||
case '?':
|
case '?':
|
||||||
if next, _ := scanner.peek(); next == '?' {
|
if next, _ := scanner.peek(); next == '?' {
|
||||||
@@ -237,7 +242,7 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
} else if next == '!' {
|
} else if next == '!' {
|
||||||
tk = scanner.moveOn(SymQuestionExclam, ch, next)
|
tk = scanner.moveOn(SymQuestionExclam, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymQuestion, ch)
|
tk = scanner.MakeToken(SymQuestion, ch)
|
||||||
}
|
}
|
||||||
case '&':
|
case '&':
|
||||||
if next, _ := scanner.peek(); next == '&' {
|
if next, _ := scanner.peek(); next == '&' {
|
||||||
@@ -245,16 +250,16 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
} else if next, _ = scanner.peek(); next == '=' {
|
} else if next, _ = scanner.peek(); next == '=' {
|
||||||
tk = scanner.moveOn(SymAmpersandEqual, ch, next)
|
tk = scanner.moveOn(SymAmpersandEqual, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymAmpersand, ch)
|
tk = scanner.MakeToken(SymAmpersand, ch)
|
||||||
}
|
}
|
||||||
case '%':
|
case '%':
|
||||||
if next, _ := scanner.peek(); next == '=' {
|
if next, _ := scanner.peek(); next == '=' {
|
||||||
tk = scanner.moveOn(SymPercEqual, ch, next)
|
tk = scanner.moveOn(SymPercEqual, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymPercent, ch)
|
tk = scanner.MakeToken(SymPercent, ch)
|
||||||
}
|
}
|
||||||
case '#':
|
case '#':
|
||||||
tk = scanner.makeToken(SymHash, ch)
|
tk = scanner.MakeToken(SymHash, ch)
|
||||||
case '@':
|
case '@':
|
||||||
if next, _ := scanner.peek(); (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z') {
|
if next, _ := scanner.peek(); (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z') {
|
||||||
scanner.readChar()
|
scanner.readChar()
|
||||||
@@ -267,15 +272,15 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
} else if next == '@' {
|
} else if next == '@' {
|
||||||
tk = scanner.moveOn(SymDoubleAt, ch, next)
|
tk = scanner.moveOn(SymDoubleAt, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymAt, ch)
|
tk = scanner.MakeToken(SymAt, ch)
|
||||||
}
|
}
|
||||||
case '_':
|
case '_':
|
||||||
tk = scanner.makeToken(SymUndescore, ch)
|
tk = scanner.MakeToken(SymUndescore, ch)
|
||||||
case '=':
|
case '=':
|
||||||
if next, _ := scanner.peek(); next == '=' {
|
if next, _ := scanner.peek(); next == '=' {
|
||||||
tk = scanner.moveOn(SymDoubleEqual, ch, next)
|
tk = scanner.moveOn(SymDoubleEqual, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymEqual, ch)
|
tk = scanner.MakeToken(SymEqual, ch)
|
||||||
}
|
}
|
||||||
case '<':
|
case '<':
|
||||||
if next, _ := scanner.peek(); next == '=' {
|
if next, _ := scanner.peek(); next == '=' {
|
||||||
@@ -294,7 +299,7 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
} else if next == '+' {
|
} else if next == '+' {
|
||||||
tk = scanner.moveOn(SymLessPlus, ch, next)
|
tk = scanner.moveOn(SymLessPlus, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymLess, ch)
|
tk = scanner.MakeToken(SymLess, ch)
|
||||||
}
|
}
|
||||||
case '>':
|
case '>':
|
||||||
if next, _ := scanner.peek(); next == '=' {
|
if next, _ := scanner.peek(); next == '=' {
|
||||||
@@ -309,7 +314,7 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
tk = scanner.accept(SymDoubleGreater, ch, next)
|
tk = scanner.accept(SymDoubleGreater, ch, next)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymGreater, ch)
|
tk = scanner.MakeToken(SymGreater, ch)
|
||||||
}
|
}
|
||||||
case '$':
|
case '$':
|
||||||
if next, _ := scanner.peek(); next == '(' {
|
if next, _ := scanner.peek(); next == '(' {
|
||||||
@@ -326,26 +331,26 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
scanner.readChar()
|
scanner.readChar()
|
||||||
tk = scanner.fetchIdentifier(next)
|
tk = scanner.fetchIdentifier(next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeToken(SymDollar, ch)
|
tk = scanner.MakeToken(SymDollar, ch)
|
||||||
}
|
}
|
||||||
case '(':
|
case '(':
|
||||||
// if next, _ := scanner.peek(); next == ')' {
|
// if next, _ := scanner.peek(); next == ')' {
|
||||||
// tk = scanner.moveOn(SymOpenClosedRound, ch, next)
|
// tk = scanner.moveOn(SymOpenClosedRound, ch, next)
|
||||||
// } else {
|
// } else {
|
||||||
tk = scanner.makeToken(SymOpenRound, ch)
|
tk = scanner.MakeToken(SymOpenRound, ch)
|
||||||
// }
|
// }
|
||||||
case ')':
|
case ')':
|
||||||
tk = scanner.makeToken(SymClosedRound, ch)
|
tk = scanner.MakeToken(SymClosedRound, ch)
|
||||||
case '[':
|
case '[':
|
||||||
tk = scanner.makeToken(SymOpenSquare, ch)
|
tk = scanner.MakeToken(SymOpenSquare, ch)
|
||||||
case ']':
|
case ']':
|
||||||
tk = scanner.makeToken(SymClosedSquare, ch)
|
tk = scanner.MakeToken(SymClosedSquare, ch)
|
||||||
case '{':
|
case '{':
|
||||||
tk = scanner.makeToken(SymOpenBrace, ch)
|
tk = scanner.MakeToken(SymOpenBrace, ch)
|
||||||
case '}':
|
case '}':
|
||||||
tk = scanner.makeToken(SymClosedBrace, ch)
|
tk = scanner.MakeToken(SymClosedBrace, ch)
|
||||||
case '~':
|
case '~':
|
||||||
tk = scanner.makeToken(SymTilde, ch)
|
tk = scanner.MakeToken(SymTilde, ch)
|
||||||
case 0:
|
case 0:
|
||||||
if escape {
|
if escape {
|
||||||
tk = scanner.makeErrorToken(errors.New("incomplete escape sequence"))
|
tk = scanner.makeErrorToken(errors.New("incomplete escape sequence"))
|
||||||
@@ -372,7 +377,7 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner *scanner) sync(err error) error {
|
func (scanner *Scanner) sync(err error) error {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = scanner.unreadChar()
|
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')
|
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 ch byte
|
||||||
var digitType string
|
var digitType string
|
||||||
firstCh = currentFirstCh
|
firstCh = currentFirstCh
|
||||||
@@ -434,7 +439,7 @@ func (scanner *scanner) initBase(currentFirstCh byte) (firstCh byte, numBase int
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner *scanner) parseNumber(firstCh byte) (tk *Token) {
|
func (scanner *Scanner) parseNumber(firstCh byte) (tk *Token) {
|
||||||
var err error
|
var err error
|
||||||
var ch byte
|
var ch byte
|
||||||
var sym Symbol = SymInteger
|
var sym Symbol = SymInteger
|
||||||
@@ -510,7 +515,7 @@ func (scanner *scanner) parseNumber(firstCh byte) (tk *Token) {
|
|||||||
value, err = strconv.ParseInt(txt, numBase, 64)
|
value, err = strconv.ParseInt(txt, numBase, 64)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
tk = scanner.makeValueToken(sym, txt, value)
|
tk = scanner.MakeValueToken(sym, txt, value)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeErrorToken(err)
|
tk = scanner.makeErrorToken(err)
|
||||||
}
|
}
|
||||||
@@ -518,7 +523,7 @@ func (scanner *scanner) parseNumber(firstCh byte) (tk *Token) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner *scanner) fetchIdentifier(firstCh byte) (tk *Token) {
|
func (scanner *Scanner) fetchIdentifier(firstCh byte) (tk *Token) {
|
||||||
var err error
|
var err error
|
||||||
var sb strings.Builder
|
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() {
|
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 {
|
if sym, ok := keywords[uptxt]; ok {
|
||||||
tk = scanner.makeKeywordToken(sym, uptxt)
|
tk = scanner.makeKeywordToken(sym, uptxt)
|
||||||
} else if uptxt == `TRUE` {
|
} else if uptxt == `TRUE` {
|
||||||
tk = scanner.makeValueToken(SymBool, txt, true)
|
tk = scanner.MakeValueToken(SymBool, txt, true)
|
||||||
} else if uptxt == `FALSE` {
|
} else if uptxt == `FALSE` {
|
||||||
tk = scanner.makeValueToken(SymBool, txt, false)
|
tk = scanner.MakeValueToken(SymBool, txt, false)
|
||||||
} else if ch, _ := scanner.peek(); ch == '(' {
|
} else if ch, _ := scanner.peek(); ch == '(' {
|
||||||
scanner.readChar()
|
scanner.readChar()
|
||||||
tk = scanner.makeValueToken(SymFuncCall, txt+"(", txt)
|
tk = scanner.MakeValueToken(SymFuncCall, txt+"(", txt)
|
||||||
} else {
|
} 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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner *scanner) fetchBlockComment() *Token {
|
func (scanner *Scanner) fetchBlockComment() *Token {
|
||||||
return scanner.fetchUntil(SymComment, false, '*', '/')
|
return scanner.fetchUntil(SymComment, false, '*', '/')
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner *scanner) fetchOnLineComment() *Token {
|
func (scanner *Scanner) fetchOnLineComment() *Token {
|
||||||
return scanner.fetchUntil(SymComment, true, '\n')
|
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 err error
|
||||||
var ch byte
|
var ch byte
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
var value string
|
var value string
|
||||||
ring := NewByteSlider(len(endings))
|
ring := util.NewByteSlider(len(endings))
|
||||||
endReached := false
|
endReached := false
|
||||||
for ch, err = scanner.readChar(); err == nil && !endReached; {
|
for ch, err = scanner.readChar(); err == nil && !endReached; {
|
||||||
sb.WriteByte(ch)
|
sb.WriteByte(ch)
|
||||||
@@ -593,14 +598,14 @@ func (scanner *scanner) fetchUntil(sym Symbol, allowEos bool, endings ...byte) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if endReached {
|
if endReached {
|
||||||
tk = scanner.makeValueToken(sym, "", value)
|
tk = scanner.MakeValueToken(sym, "", value)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeErrorToken(err)
|
tk = scanner.makeErrorToken(err)
|
||||||
}
|
}
|
||||||
return
|
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 err error
|
||||||
var ch, prev byte
|
var ch, prev byte
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
@@ -639,15 +644,15 @@ func (scanner *scanner) fetchString(termCh byte, addQuote bool) (tk *Token) {
|
|||||||
} else {
|
} else {
|
||||||
txt := sb.String()
|
txt := sb.String()
|
||||||
if addQuote {
|
if addQuote {
|
||||||
tk = scanner.makeValueToken(SymString, `"`+txt+`"`, txt)
|
tk = scanner.MakeValueToken(SymString, `"`+txt+`"`, txt)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.makeValueToken(SymString, txt, txt)
|
tk = scanner.MakeValueToken(SymString, txt, txt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner *scanner) peek() (next byte, err error) {
|
func (scanner *Scanner) peek() (next byte, err error) {
|
||||||
var one []byte
|
var one []byte
|
||||||
if one, err = scanner.stream.Peek(1); err == nil {
|
if one, err = scanner.stream.Peek(1); err == nil {
|
||||||
next = one[0]
|
next = one[0]
|
||||||
@@ -655,7 +660,7 @@ func (scanner *scanner) peek() (next byte, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner *scanner) skipBlanks() (err error) {
|
func (scanner *Scanner) skipBlanks() (err error) {
|
||||||
var one []byte
|
var one []byte
|
||||||
for one, err = scanner.stream.Peek(1); err == nil && one[0] <= 32; one, err = scanner.stream.Peek(1) {
|
for one, err = scanner.stream.Peek(1); err == nil && one[0] <= 32; one, err = scanner.stream.Peek(1) {
|
||||||
scanner.readChar()
|
scanner.readChar()
|
||||||
@@ -663,7 +668,7 @@ func (scanner *scanner) skipBlanks() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner *scanner) translate(sym Symbol) Symbol {
|
func (scanner *Scanner) translate(sym Symbol) Symbol {
|
||||||
if scanner.translations != nil {
|
if scanner.translations != nil {
|
||||||
if translatedSym, ok := scanner.translations[sym]; ok {
|
if translatedSym, ok := scanner.translations[sym]; ok {
|
||||||
return translatedSym
|
return translatedSym
|
||||||
@@ -672,7 +677,7 @@ func (scanner *scanner) translate(sym Symbol) Symbol {
|
|||||||
return sym
|
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))
|
tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), string(chars))
|
||||||
// for i := 1; i < len(chars); i++ {
|
// for i := 1; i < len(chars); i++ {
|
||||||
if len(chars) > 1 {
|
if len(chars) > 1 {
|
||||||
@@ -682,26 +687,26 @@ func (scanner *scanner) moveOn(sym Symbol, chars ...byte) (tk *Token) {
|
|||||||
return
|
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))
|
tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), string(chars))
|
||||||
return
|
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))
|
tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), string(chars))
|
||||||
return
|
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)
|
tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), upperCaseKeyword)
|
||||||
return
|
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)
|
tk = NewValueToken(scanner.row, scanner.column, scanner.translate(sym), source, value)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner *scanner) makeErrorToken(err error) *Token {
|
func (scanner *Scanner) makeErrorToken(err error) *Token {
|
||||||
return NewErrorToken(scanner.row, scanner.column, err)
|
return NewErrorToken(scanner.row, scanner.column, err)
|
||||||
}
|
}
|
||||||
@@ -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: {"<unknown>", SymClassOther, PosLeaf}, // -1: Unknown symbol
|
||||||
|
SymNone: {"<null>", SymClassOther, PosLeaf}, // 0: Null value for variable of type symbol
|
||||||
|
SymError: {"<error>", SymClassOther, PosLeaf}, // 1: Error reading from stream
|
||||||
|
SymEos: {"<eos>", 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 // <selector> ::= <expr> "?" <selector-case> {":" <selector-case>} ["::" <default-selector-case>]
|
||||||
|
// SymSelectorCase // <selector-case> ::= [<list>] "{" <multi-expr> "}"
|
||||||
|
// // 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("<nothing>")
|
||||||
|
} 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)
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
|
|
||||||
// Symbol.go
|
// Symbol.go
|
||||||
package expr
|
package scan
|
||||||
|
|
||||||
type Symbol int16
|
type Symbol int16
|
||||||
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
|
|
||||||
// t_scanner_test.go
|
// t_scanner_test.go
|
||||||
package expr
|
package scan
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@@ -1,23 +1,23 @@
|
|||||||
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
|
|
||||||
// op-registry.go
|
// term-constructor-registry.go
|
||||||
package expr
|
package scan
|
||||||
|
|
||||||
const initialRegistryCapacity = 10
|
const initialRegistryCapacity = 10
|
||||||
|
|
||||||
type termContructor func(tk *Token) *term
|
type termContructor func(tk *Token) *Term
|
||||||
|
|
||||||
var constructorRegistry map[Symbol]termContructor = nil
|
var constructorRegistry map[Symbol]termContructor = nil
|
||||||
|
|
||||||
func registerTermConstructor(sym Symbol, constructor termContructor) {
|
func RegisterTermConstructor(sym Symbol, constructor termContructor) {
|
||||||
if constructorRegistry == nil {
|
if constructorRegistry == nil {
|
||||||
constructorRegistry = make(map[Symbol]termContructor, initialRegistryCapacity)
|
constructorRegistry = make(map[Symbol]termContructor, initialRegistryCapacity)
|
||||||
}
|
}
|
||||||
constructorRegistry[sym] = constructor
|
constructorRegistry[sym] = constructor
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTerm(tk *Token) (inst *term) {
|
func NewTerm(tk *Token) (inst *Term) {
|
||||||
if constructorRegistry != nil {
|
if constructorRegistry != nil {
|
||||||
if construct, exists := constructorRegistry[tk.Sym]; exists {
|
if construct, exists := constructorRegistry[tk.Sym]; exists {
|
||||||
inst = construct(tk)
|
inst = construct(tk)
|
||||||
+301
@@ -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)
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
|
|
||||||
// token.go
|
// token.go
|
||||||
package expr
|
package scan
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"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)
|
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) {
|
func (tk *Token) Clone() (c *Token) {
|
||||||
return NewValueToken(tk.row, tk.col, tk.Sym, tk.source, tk.Value)
|
return NewValueToken(tk.row, tk.col, tk.Sym, tk.source, tk.Value)
|
||||||
}
|
}
|
||||||
-231
@@ -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: {"<unknown>", symClassOther, posLeaf}, // -1: Unknown symbol
|
|
||||||
SymNone: {"<null>", symClassOther, posLeaf}, // 0: Null value for variable of type symbol
|
|
||||||
SymError: {"<error>", symClassOther, posLeaf}, // 1: Error reading from stream
|
|
||||||
SymEos: {"<eos>", 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 // <selector> ::= <expr> "?" <selector-case> {":" <selector-case>} ["::" <default-selector-case>]
|
|
||||||
// SymSelectorCase // <selector-case> ::= [<list>] "{" <multi-expr> "}"
|
|
||||||
// // 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("<nothing>")
|
|
||||||
} 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)
|
|
||||||
}
|
|
||||||
+17
-15
@@ -7,47 +7,49 @@ package expr
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAstString(t *testing.T) {
|
func TestAstString(t *testing.T) {
|
||||||
tree := NewAst()
|
tree := scan.NewAst()
|
||||||
if gotResult := tree.String(); gotResult != "(nil)" {
|
if gotResult := tree.String(); gotResult != "(nil)" {
|
||||||
t.Errorf(`result: got %q, want "(nil)"`, gotResult)
|
t.Errorf(`result: got %q, want "(nil)"`, gotResult)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddTokensGood(t *testing.T) {
|
func TestAddTokensGood(t *testing.T) {
|
||||||
tk1 := NewValueToken(0, 0, SymInteger, "100", 100)
|
tk1 := scan.NewValueToken(0, 0, scan.SymInteger, "100", 100)
|
||||||
tk2 := NewToken(0, 0, SymPlus, "+")
|
tk2 := scan.NewToken(0, 0, scan.SymPlus, "+")
|
||||||
tk3 := NewValueToken(0, 0, SymInteger, "50", 500)
|
tk3 := scan.NewValueToken(0, 0, scan.SymInteger, "50", 500)
|
||||||
|
|
||||||
tree := NewAst()
|
tree := scan.NewAst()
|
||||||
if gotErr := tree.addTokens(tk1, tk2, tk3); gotErr != nil {
|
if gotErr := tree.AddTokens(tk1, tk2, tk3); gotErr != nil {
|
||||||
t.Errorf("err: got <%v>, want <nil>", gotErr)
|
t.Errorf("err: got <%v>, want <nil>", gotErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddTokensBad(t *testing.T) {
|
func TestAddTokensBad(t *testing.T) {
|
||||||
tk0 := NewValueToken(0, 0, SymInteger, "200", 200)
|
tk0 := scan.NewValueToken(0, 0, scan.SymInteger, "200", 200)
|
||||||
tk1 := NewValueToken(0, 0, SymInteger, "100", 100)
|
tk1 := scan.NewValueToken(0, 0, scan.SymInteger, "100", 100)
|
||||||
tk2 := NewToken(0, 0, SymPlus, "+")
|
tk2 := scan.NewToken(0, 0, scan.SymPlus, "+")
|
||||||
tk3 := NewValueToken(0, 0, SymInteger, "50", 500)
|
tk3 := scan.NewValueToken(0, 0, scan.SymInteger, "50", 500)
|
||||||
|
|
||||||
wantErr := errors.New(`[0:0] two adjacent operators: "200" and "100"`)
|
wantErr := errors.New(`[0:0] two adjacent operators: "200" and "100"`)
|
||||||
|
|
||||||
tree := NewAst()
|
tree := scan.NewAst()
|
||||||
if gotErr := tree.addTokens(tk0, tk1, tk2, tk3); gotErr != nil && gotErr.Error() != wantErr.Error() {
|
if gotErr := tree.AddTokens(tk0, tk1, tk2, tk3); gotErr != nil && gotErr.Error() != wantErr.Error() {
|
||||||
t.Errorf("err: got <%v>, want <nil>", gotErr)
|
t.Errorf("err: got <%v>, want <nil>", gotErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddUnknownTokens(t *testing.T) {
|
func TestAddUnknownTokens(t *testing.T) {
|
||||||
tk0 := NewToken(0, 0, SymPercent, "%")
|
tk0 := scan.NewToken(0, 0, scan.SymPercent, "%")
|
||||||
|
|
||||||
wantErr := errors.New(`unexpected token "%"`)
|
wantErr := errors.New(`unexpected token "%"`)
|
||||||
|
|
||||||
tree := NewAst()
|
tree := scan.NewAst()
|
||||||
if _, gotErr := tree.addToken(tk0); gotErr != nil && gotErr.Error() != wantErr.Error() {
|
if _, gotErr := tree.AddToken(tk0); gotErr != nil && gotErr.Error() != wantErr.Error() {
|
||||||
t.Errorf("err: got <%v>, want <%v>", gotErr, wantErr)
|
t.Errorf("err: got <%v>, want <%v>", gotErr, wantErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -10,6 +10,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
type inputType struct {
|
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) {
|
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 gotResult any
|
||||||
var gotErr error
|
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)
|
logTest(t, count, section, input.source, input.wantResult, wantErr)
|
||||||
|
|
||||||
r := strings.NewReader(input.source)
|
r := strings.NewReader(input.source)
|
||||||
scanner := NewScanner(r, DefaultTranslations())
|
scanner := scan.NewScanner(r, scan.DefaultTranslations())
|
||||||
|
|
||||||
good = true
|
good = true
|
||||||
if ast, gotErr = parser.Parse(scanner); gotErr == nil {
|
if ast, gotErr = parser.Parse(scanner); gotErr == nil {
|
||||||
|
|||||||
+5
-4
@@ -11,6 +11,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDictParser(t *testing.T) {
|
func TestDictParser(t *testing.T) {
|
||||||
@@ -52,7 +53,7 @@ func TestDictParser(t *testing.T) {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
for i, input := range inputs {
|
for i, input := range inputs {
|
||||||
var expr *ast
|
var expr *scan.Ast
|
||||||
var gotResult any
|
var gotResult any
|
||||||
var gotErr error
|
var gotErr error
|
||||||
|
|
||||||
@@ -65,7 +66,7 @@ func TestDictParser(t *testing.T) {
|
|||||||
logTest(t, i+1, "Dict", input.source, input.wantResult, input.wantErr)
|
logTest(t, i+1, "Dict", input.source, input.wantResult, input.wantErr)
|
||||||
|
|
||||||
r := strings.NewReader(input.source)
|
r := strings.NewReader(input.source)
|
||||||
scanner := NewScanner(r, DefaultTranslations())
|
scanner := scan.NewScanner(r, scan.DefaultTranslations())
|
||||||
|
|
||||||
good := true
|
good := true
|
||||||
if expr, gotErr = parser.Parse(scanner); gotErr == nil {
|
if expr, gotErr = parser.Parse(scanner); gotErr == nil {
|
||||||
@@ -124,7 +125,7 @@ func TestDictToStringMultiLine(t *testing.T) {
|
|||||||
"first": 1
|
"first": 1
|
||||||
}`
|
}`
|
||||||
args := map[any]any{
|
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)
|
dict := kern.NewDict(args)
|
||||||
got := dict.ToString(kern.MultiLine)
|
got := dict.ToString(kern.MultiLine)
|
||||||
@@ -146,7 +147,7 @@ func TestDictToString(t *testing.T) {
|
|||||||
section := "dict-ToString-SL"
|
section := "dict-ToString-SL"
|
||||||
want := `{"first": 1}`
|
want := `{"first": 1}`
|
||||||
args := map[any]any{
|
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)
|
dict := kern.NewDict(args)
|
||||||
got := dict.ToString(0)
|
got := dict.ToString(0)
|
||||||
|
|||||||
+2
-1
@@ -8,6 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestOperatorEnding(t *testing.T) {
|
func TestOperatorEnding(t *testing.T) {
|
||||||
@@ -28,7 +29,7 @@ func TestOperatorEnding(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testStringEndingWithOperator(source string) bool {
|
func testStringEndingWithOperator(source string) bool {
|
||||||
return StringEndsWithOperator(source)
|
return scan.StringEndsWithOperator(source)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testStringArrayEndingWithOperatorSpec(t *testing.T, section string, inputs []inputType, spec ...int) {
|
func testStringArrayEndingWithOperatorSpec(t *testing.T, section string, inputs []inputType, spec ...int) {
|
||||||
|
|||||||
+15
-13
@@ -6,15 +6,17 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestString(t *testing.T) {
|
func TestString(t *testing.T) {
|
||||||
tk1 := NewValueToken(0, 0, SymInteger, "100", 100)
|
tk1 := scan.NewValueToken(0, 0, scan.SymInteger, "100", 100)
|
||||||
tk2 := NewToken(0, 0, SymPlus, "+")
|
tk2 := scan.NewToken(0, 0, scan.SymPlus, "+")
|
||||||
tk3 := NewValueToken(0, 0, SymInteger, "50", 500)
|
tk3 := scan.NewValueToken(0, 0, scan.SymInteger, "50", 500)
|
||||||
|
|
||||||
tree := NewAst()
|
tree := scan.NewAst()
|
||||||
if gotErr := tree.addTokens(tk1, tk2, tk3); gotErr == nil {
|
if gotErr := tree.AddTokens(tk1, tk2, tk3); gotErr == nil {
|
||||||
t.Log("Tree:", tree)
|
t.Log("Tree:", tree)
|
||||||
} else {
|
} else {
|
||||||
t.Errorf("err: got <%v>, want <nil>", gotErr)
|
t.Errorf("err: got <%v>, want <nil>", gotErr)
|
||||||
@@ -22,22 +24,22 @@ func TestString(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetRoom(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()
|
tree := scan.NewAst()
|
||||||
if gotErr := tree.addTokens(tk1); gotErr == nil {
|
if gotErr := tree.AddTokens(tk1); gotErr == nil {
|
||||||
t.Log("Tree-root room:", tree.root.getRoom())
|
t.Log("Tree-root room:", tree.Root().GetRoom())
|
||||||
} else {
|
} else {
|
||||||
t.Errorf("err: got <%v>, want <nil>", gotErr)
|
t.Errorf("err: got <%v>, want <nil>", gotErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetChildrenCount(t *testing.T) {
|
func TestGetChildrenCount(t *testing.T) {
|
||||||
tk1 := NewValueToken(0, 0, SymInteger, "100", 100)
|
tk1 := scan.NewValueToken(0, 0, scan.SymInteger, "100", 100)
|
||||||
|
|
||||||
tree := NewAst()
|
tree := scan.NewAst()
|
||||||
if gotErr := tree.addTokens(tk1); gotErr == nil {
|
if gotErr := tree.AddTokens(tk1); gotErr == nil {
|
||||||
t.Log("Tree-root children count:", tree.root.GetChildCount())
|
t.Log("Tree-root children count:", tree.Root().GetChildCount())
|
||||||
} else {
|
} else {
|
||||||
t.Errorf("err: got <%v>, want <nil>", gotErr)
|
t.Errorf("err: got <%v>, want <nil>", gotErr)
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-6
@@ -7,27 +7,29 @@ package expr
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"git.portale-stac.it/go-pkg/expr/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDevString(t *testing.T) {
|
func TestDevString(t *testing.T) {
|
||||||
type inputType struct {
|
type inputType struct {
|
||||||
source string
|
source string
|
||||||
sym Symbol
|
sym scan.Symbol
|
||||||
value any
|
value any
|
||||||
wantResult string
|
wantResult string
|
||||||
}
|
}
|
||||||
|
|
||||||
inputs := []inputType{
|
inputs := []inputType{
|
||||||
/* 1 */ {"100", SymInteger, 100, fmt.Sprintf(`[%d]"100"{100}`, SymInteger)},
|
/* 1 */ {"100", scan.SymInteger, 100, fmt.Sprintf(`[%d]"100"{100}`, scan.SymInteger)},
|
||||||
/* 2 */ {"+", SymPlus, nil, fmt.Sprintf(`[%d]"+"{}`, SymPlus)},
|
/* 2 */ {"+", scan.SymPlus, nil, fmt.Sprintf(`[%d]"+"{}`, scan.SymPlus)},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, input := range inputs {
|
for i, input := range inputs {
|
||||||
var tk *Token
|
var tk *scan.Token
|
||||||
if input.value == nil {
|
if input.value == nil {
|
||||||
tk = NewToken(0, 0, input.sym, input.source)
|
tk = scan.NewToken(0, 0, input.sym, input.source)
|
||||||
} else {
|
} 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)
|
t.Logf("Test nr %2d: %q --> %q", i+1, input.source, input.wantResult)
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
|
|
||||||
// byte-slider.go
|
// byte-slider.go
|
||||||
package expr
|
package util
|
||||||
|
|
||||||
import "bytes"
|
import "bytes"
|
||||||
|
|
||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
//go:build unix
|
|
||||||
|
|
||||||
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
|
|
||||||
|
//go:build unix
|
||||||
|
|
||||||
// utils-unix.go
|
// utils-unix.go
|
||||||
package util
|
package util
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user