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