moved scanner sources to package 'scan'

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