Compare commits
	
		
			No commits in common. "723976b37e65e1f6807f5e6496d6d492bacf9133" and "62e16219f71c9441cffc7706c1833e8c2f48986e" have entirely different histories.
		
	
	
		
			723976b37e
			...
			62e16219f7
		
	
		
| @ -1,41 +0,0 @@ | |||||||
| // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 |  | ||||||
| // All rights reserved.
 |  | ||||||
| 
 |  | ||||||
| // context-helpers.go
 |  | ||||||
| package expr |  | ||||||
| 
 |  | ||||||
| func cloneContext(sourceCtx ExprContext) (clonedCtx ExprContext) { |  | ||||||
| 	if sourceCtx != nil { |  | ||||||
| 		clonedCtx = sourceCtx.Clone() |  | ||||||
| 	} |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func exportVar(ctx ExprContext, name string, value any) { |  | ||||||
| 	if name[0] == '@' { |  | ||||||
| 		name = name[1:] |  | ||||||
| 	} |  | ||||||
| 	ctx.setVar(name, value) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func exportFunc(ctx ExprContext, name string, info ExprFunc) { |  | ||||||
| 	if name[0] == '@' { |  | ||||||
| 		name = name[1:] |  | ||||||
| 	} |  | ||||||
| 	ctx.RegisterFunc(name, info.Functor(), info.MinArgs(), info.MaxArgs()) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func exportObjects(destCtx, sourceCtx ExprContext) { |  | ||||||
| 	exportAll := isEnabled(sourceCtx, control_export_all) |  | ||||||
| 	// Export variables
 |  | ||||||
| 	for _, refName := range sourceCtx.EnumVars(func(name string) bool { return exportAll || name[0] == '@' }) { |  | ||||||
| 		refValue, _ := sourceCtx.GetVar(refName) |  | ||||||
| 		exportVar(destCtx, refName, refValue) |  | ||||||
| 	} |  | ||||||
| 	// Export functions
 |  | ||||||
| 	for _, refName := range sourceCtx.EnumFuncs(func(name string) bool { return exportAll || name[0] == '@' }) { |  | ||||||
| 		if info, _ := sourceCtx.GetFuncInfo(refName); info != nil { |  | ||||||
| 			exportFunc(destCtx, refName, info) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @ -1,62 +0,0 @@ | |||||||
| // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 |  | ||||||
| // All rights reserved.
 |  | ||||||
| 
 |  | ||||||
| // data-cursors.go
 |  | ||||||
| package expr |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"io" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| const ( |  | ||||||
| 	initName    = "init" |  | ||||||
| 	nextName    = "next" |  | ||||||
| 	currentName = "current" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| type dataCursor struct { |  | ||||||
| 	ds          map[any]*term |  | ||||||
| 	ctx         ExprContext |  | ||||||
| 	index       int |  | ||||||
| 	resource    any |  | ||||||
| 	nextFunc    Functor |  | ||||||
| 	currentFunc Functor |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func newDataCursor(ctx ExprContext) (dc *dataCursor) { |  | ||||||
| 	dc = &dataCursor{ |  | ||||||
| 		index: -1, |  | ||||||
| 		ctx:   ctx.Clone(), |  | ||||||
| 	} |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (dc *dataCursor) String() string { |  | ||||||
| 	return "$(...)" |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (dc *dataCursor) Current() (item any, err error) { // must return io.EOF at the last item
 |  | ||||||
| 	ctx := cloneContext(dc.ctx) |  | ||||||
| 	if item, err = dc.currentFunc.Invoke(ctx, currentName, []any{}); err == nil && item == nil { |  | ||||||
| 		err = io.EOF |  | ||||||
| 	} |  | ||||||
| 	exportObjects(dc.ctx, ctx) |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (dc *dataCursor) Next() (item any, err error) { // must return io.EOF after the last item
 |  | ||||||
| 	ctx := cloneContext(dc.ctx) |  | ||||||
| 	if item, err = dc.nextFunc.Invoke(ctx, nextName, []any{}); err == nil { |  | ||||||
| 		if item == nil { |  | ||||||
| 			err = io.EOF |  | ||||||
| 		} else { |  | ||||||
| 			dc.index++ |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	exportObjects(dc.ctx, ctx) |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (dc *dataCursor) Index() int { |  | ||||||
| 	return dc.index |  | ||||||
| } |  | ||||||
							
								
								
									
										19
									
								
								expr_test.go
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								expr_test.go
									
									
									
									
									
								
							| @ -27,22 +27,11 @@ func TestExpr(t *testing.T) { | |||||||
| 	succeeded := 0 | 	succeeded := 0 | ||||||
| 	failed := 0 | 	failed := 0 | ||||||
| 
 | 
 | ||||||
| 	inputs1 := []inputType{ | 	// inputs1 := []inputType{
 | ||||||
| 		/*   1 */ {` | 	// 	/*   1 */ {`0?{}`, nil, nil},
 | ||||||
| 		ds={ | 	// }
 | ||||||
| 			"init":func(end){@end=end; @current=0 but true}, |  | ||||||
| 			"current":func(){current}, |  | ||||||
| 			"next":func(){ |  | ||||||
| 				((next=current+1) <= end) ? [true] {@current=next but current} :: {nil} |  | ||||||
| 			} |  | ||||||
| 		}; |  | ||||||
| 		it=$(ds,3); |  | ||||||
| 		it++; |  | ||||||
| 		it++ |  | ||||||
| `, int64(1), nil}, |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	for i, input := range inputs1 { | 	for i, input := range inputs { | ||||||
| 		var expr Expr | 		var expr Expr | ||||||
| 		var gotResult any | 		var gotResult any | ||||||
| 		var gotErr error | 		var gotErr error | ||||||
|  | |||||||
| @ -5,6 +5,10 @@ | |||||||
| package expr | package expr | ||||||
| 
 | 
 | ||||||
| // -------- dict term
 | // -------- dict term
 | ||||||
|  | // func newDictTermA(args ...*term) *term {
 | ||||||
|  | // 	return newDictTerm(args)
 | ||||||
|  | // }
 | ||||||
|  | 
 | ||||||
| func newDictTerm(args map[any]*term) *term { | func newDictTerm(args map[any]*term) *term { | ||||||
| 	return &term{ | 	return &term{ | ||||||
| 		tk:       *NewValueToken(0, 0, SymDict, "{}", args), | 		tk:       *NewValueToken(0, 0, SymDict, "{}", args), | ||||||
|  | |||||||
| @ -27,3 +27,8 @@ func evalExpr(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // init
 | ||||||
|  | // func init() {
 | ||||||
|  | // 	registerTermConstructor(SymExpression, newExprTerm)
 | ||||||
|  | // }
 | ||||||
|  | |||||||
| @ -22,7 +22,7 @@ func newFuncCallTerm(tk *Token, args []*term) *term { | |||||||
| 
 | 
 | ||||||
| // -------- eval func call
 | // -------- eval func call
 | ||||||
| func evalFuncCall(parentCtx ExprContext, self *term) (v any, err error) { | func evalFuncCall(parentCtx ExprContext, self *term) (v any, err error) { | ||||||
| 	ctx := cloneContext(parentCtx) | 	ctx := parentCtx.Clone() | ||||||
| 	name, _ := self.tk.Value.(string) | 	name, _ := self.tk.Value.(string) | ||||||
| 	params := make([]any, len(self.children)) | 	params := make([]any, len(self.children)) | ||||||
| 	for i, tree := range self.children { | 	for i, tree := range self.children { | ||||||
| @ -34,12 +34,37 @@ func evalFuncCall(parentCtx ExprContext, self *term) (v any, err error) { | |||||||
| 	} | 	} | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| 		if v, err = ctx.Call(name, params); err == nil { | 		if v, err = ctx.Call(name, params); err == nil { | ||||||
| 			exportObjects(parentCtx, ctx) | 			exportAll := isEnabled(ctx, control_export_all) | ||||||
|  | 			// Export variables
 | ||||||
|  | 			for _, refName := range ctx.EnumVars(func(name string) bool { return exportAll || name[0] == '@' }) { | ||||||
|  | 				refValue, _ := ctx.GetVar(refName) | ||||||
|  | 				exportVar(parentCtx, refName, refValue) | ||||||
|  | 			} | ||||||
|  | 			// Export functions
 | ||||||
|  | 			for _, refName := range ctx.EnumFuncs(func(name string) bool { return exportAll || name[0] == '@' }) { | ||||||
|  | 				if info, _ := ctx.GetFuncInfo(refName); info != nil { | ||||||
|  | 					exportFunc(parentCtx, refName, info) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func exportVar(ctx ExprContext, name string, value any) { | ||||||
|  | 	if name[0] == '@' { | ||||||
|  | 		name = name[1:] | ||||||
|  | 	} | ||||||
|  | 	ctx.setVar(name, value) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func exportFunc(ctx ExprContext, name string, info ExprFunc) { | ||||||
|  | 	if name[0] == '@' { | ||||||
|  | 		name = name[1:] | ||||||
|  | 	} | ||||||
|  | 	ctx.RegisterFunc(name, info.Functor(), info.MinArgs(), info.MaxArgs()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // -------- function definition term
 | // -------- function definition term
 | ||||||
| func newFuncDefTerm(tk *Token, args []*term) *term { | func newFuncDefTerm(tk *Token, args []*term) *term { | ||||||
| 	return &term{ | 	return &term{ | ||||||
| @ -82,6 +107,12 @@ func evalFuncDef(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 		paramList := make([]string, 0, len(self.children)) | 		paramList := make([]string, 0, len(self.children)) | ||||||
| 		for _, param := range self.children { | 		for _, param := range self.children { | ||||||
| 			paramList = append(paramList, param.source()) | 			paramList = append(paramList, param.source()) | ||||||
|  | 			// if paramName, ok := param.value().(string); ok {
 | ||||||
|  | 			// 	paramList = append(paramList, paramName)
 | ||||||
|  | 			// } else {
 | ||||||
|  | 			// 	err = fmt.Errorf("invalid function definition: formal param nr %d must be an identifier", i+1)
 | ||||||
|  | 			// 	break
 | ||||||
|  | 			// }
 | ||||||
| 		} | 		} | ||||||
| 		v = &funcDefFunctor{ | 		v = &funcDefFunctor{ | ||||||
| 			params: paramList, | 			params: paramList, | ||||||
|  | |||||||
| @ -6,10 +6,58 @@ package expr | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"io" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // -------- iterator term
 | // -------- iterator term
 | ||||||
| 
 | 
 | ||||||
|  | const ( | ||||||
|  | 	initName    = "init" | ||||||
|  | 	nextName    = "next" | ||||||
|  | 	currentName = "current" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type dataCursor struct { | ||||||
|  | 	ds          map[any]*term | ||||||
|  | 	ctx         ExprContext | ||||||
|  | 	index       int | ||||||
|  | 	resource    any | ||||||
|  | 	nextFunc    Functor | ||||||
|  | 	currentFunc Functor | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (dc *dataCursor) String() string { | ||||||
|  | 	var s string | ||||||
|  | 	if item, err := dc.Current(); err == nil { | ||||||
|  | 		s = fmt.Sprintf("%v", item) | ||||||
|  | 	} else { | ||||||
|  | 		s = "(nil)" | ||||||
|  | 	} | ||||||
|  | 	return s | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (dc *dataCursor) Current() (item any, err error) { // must return io.EOF at the last item
 | ||||||
|  | 	if item, err = dc.currentFunc.Invoke(dc.ctx, currentName, []any{}); err == nil && item == nil { | ||||||
|  | 		err = io.EOF | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (dc *dataCursor) Next() (item any, err error) { // must return io.EOF after the last item
 | ||||||
|  | 	if item, err = dc.nextFunc.Invoke(dc.ctx, nextName, []any{}); err == nil { | ||||||
|  | 		if item == nil { | ||||||
|  | 			err = io.EOF | ||||||
|  | 		} else { | ||||||
|  | 			dc.index++ | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (dc *dataCursor) Index() int { | ||||||
|  | 	return dc.index | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func newIteratorTerm(tk *Token, dsTerm *term, args []*term) *term { | func newIteratorTerm(tk *Token, dsTerm *term, args []*term) *term { | ||||||
| 	tk.Sym = SymIterator | 	tk.Sym = SymIterator | ||||||
| 
 | 
 | ||||||
| @ -77,7 +125,10 @@ func evalIterator(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	dc := newDataCursor(ctx) | 	dc := &dataCursor{ | ||||||
|  | 		index: -1, | ||||||
|  | 		ctx:   ctx.Clone(), | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	if initFunc, exists := ds[initName]; exists && initFunc != nil { | 	if initFunc, exists := ds[initName]; exists && initFunc != nil { | ||||||
| 		var args []any | 		var args []any | ||||||
| @ -88,12 +139,9 @@ func evalIterator(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 		} else { | 		} else { | ||||||
| 			args = []any{} | 			args = []any{} | ||||||
| 		} | 		} | ||||||
| 
 | 		if dc.resource, err = initFunc.Invoke(dc.ctx, initName, args); err != nil { | ||||||
| 		initCtx := dc.ctx.Clone() |  | ||||||
| 		if dc.resource, err = initFunc.Invoke(initCtx, initName, args); err != nil { |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		exportObjects(dc.ctx, initCtx) |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	dc.nextFunc, _ = ds[nextName] | 	dc.nextFunc, _ = ds[nextName] | ||||||
|  | |||||||
| @ -1,49 +0,0 @@ | |||||||
| // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 |  | ||||||
| // All rights reserved.
 |  | ||||||
| 
 |  | ||||||
| // operator-context-value.go
 |  | ||||||
| package expr |  | ||||||
| 
 |  | ||||||
| //-------- context term
 |  | ||||||
| 
 |  | ||||||
| func newContextTerm(tk *Token) (inst *term) { |  | ||||||
| 	return &term{ |  | ||||||
| 		tk:       *tk, |  | ||||||
| 		children: make([]*term, 0, 1), |  | ||||||
| 		position: posPrefix, |  | ||||||
| 		priority: priPrePost, |  | ||||||
| 		evalFunc: evalContextValue, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func evalContextValue(ctx ExprContext, self *term) (v any, err error) { |  | ||||||
| 	var childValue any |  | ||||||
| 
 |  | ||||||
| 	var sourceCtx ExprContext |  | ||||||
| 	if len(self.children) == 0 { |  | ||||||
| 		sourceCtx = ctx |  | ||||||
| 	} else if childValue, err = self.evalPrefix(ctx); err == nil { |  | ||||||
| 		if dc, ok := childValue.(*dataCursor); ok { |  | ||||||
| 			sourceCtx = dc.ctx |  | ||||||
| 		} |  | ||||||
| 	} else { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if sourceCtx != nil { |  | ||||||
| 		keys := sourceCtx.EnumVars(func(name string) bool { return name[0] != '_' }) |  | ||||||
| 		d := make(map[string]any) |  | ||||||
| 		for _, key := range keys { |  | ||||||
| 			d[key], _ = sourceCtx.GetVar(key) |  | ||||||
| 		} |  | ||||||
| 		v = d |  | ||||||
| 	} else { |  | ||||||
| 		err = self.errIncompatibleType(childValue) |  | ||||||
| 	} |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // init
 |  | ||||||
| func init() { |  | ||||||
| 	registerTermConstructor(SymDoubleDollar, newContextTerm) |  | ||||||
| } |  | ||||||
| @ -29,8 +29,9 @@ func evalLength(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 	} else if isString(rightValue) { | 	} else if isString(rightValue) { | ||||||
| 		s, _ := rightValue.(string) | 		s, _ := rightValue.(string) | ||||||
| 		v = len(s) | 		v = len(s) | ||||||
| 	} else if it, ok := rightValue.(Iterator); ok { | 		// } else {
 | ||||||
| 		v = it.Index() | 		// 	v = 1
 | ||||||
|  | 		// }
 | ||||||
| 	} else { | 	} else { | ||||||
| 		err = self.errIncompatibleType(rightValue) | 		err = self.errIncompatibleType(rightValue) | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -4,7 +4,65 @@ | |||||||
| // operator-selector.go
 | // operator-selector.go
 | ||||||
| package expr | package expr | ||||||
| 
 | 
 | ||||||
| //-------- selector term
 | // //-------- export all term
 | ||||||
|  | 
 | ||||||
|  | // func newSelectorTerm(tk *Token) (inst *term) {
 | ||||||
|  | // 	return &term{
 | ||||||
|  | // 		tk:       *tk,
 | ||||||
|  | // 		children: make([]*term, 0, 3),
 | ||||||
|  | // 		position: posMultifix,
 | ||||||
|  | // 		priority: priSelector,
 | ||||||
|  | // 		evalFunc: evalSelector,
 | ||||||
|  | // 	}
 | ||||||
|  | // }
 | ||||||
|  | 
 | ||||||
|  | // func isSelectorCase(ctx ExprContext, exprValue, caseSel any, caseIndex int) (selectedValue any, err error) {
 | ||||||
|  | // 	caseData, _ := caseSel.(*selectorCase)
 | ||||||
|  | // 	if caseData.filterList == nil {
 | ||||||
|  | // 		selectedValue, err = caseData.caseExpr.eval(ctx, false)
 | ||||||
|  | // 	} else {
 | ||||||
|  | // 		filterList := caseData.filterList.children
 | ||||||
|  | // 		if len(filterList) == 0 && exprValue == int64(caseIndex) {
 | ||||||
|  | // 			selectedValue, err = caseData.caseExpr.eval(ctx, false)
 | ||||||
|  | // 		} else {
 | ||||||
|  | // 			var caseValue any
 | ||||||
|  | // 			for _, caseTerm := range filterList {
 | ||||||
|  | // 				if caseValue, err = caseTerm.compute(ctx); err != nil || caseValue == exprValue {
 | ||||||
|  | // 					selectedValue, err = caseData.caseExpr.eval(ctx, false)
 | ||||||
|  | // 					break
 | ||||||
|  | // 				}
 | ||||||
|  | // 			}
 | ||||||
|  | // 		}
 | ||||||
|  | // 	}
 | ||||||
|  | // 	return
 | ||||||
|  | // }
 | ||||||
|  | 
 | ||||||
|  | // func evalSelector(ctx ExprContext, self *term) (v any, err error) {
 | ||||||
|  | // 	var exprValue any
 | ||||||
|  | // 	// var caseList []*term
 | ||||||
|  | 
 | ||||||
|  | // 	if err = self.checkOperands(); err != nil {
 | ||||||
|  | // 		return
 | ||||||
|  | // 	}
 | ||||||
|  | // 	exprTerm := self.children[0]
 | ||||||
|  | // 	if exprValue, err = exprTerm.compute(ctx); err != nil {
 | ||||||
|  | // 		return
 | ||||||
|  | // 	}
 | ||||||
|  | 
 | ||||||
|  | // 	caseList := self.children[1:]
 | ||||||
|  | // 	for i, caseTerm := range caseList {
 | ||||||
|  | // 		caseSel := caseTerm.value()
 | ||||||
|  | // 		if v, err = isSelectorCase(ctx, exprValue, caseSel, i); err != nil || v != nil {
 | ||||||
|  | // 			break
 | ||||||
|  | // 		}
 | ||||||
|  | // 	}
 | ||||||
|  | // 	if err == nil && v == nil {
 | ||||||
|  | // 		err = exprTerm.tk.Errorf("no case catches the value (%v) of the selection expression", exprValue)
 | ||||||
|  | // 	}
 | ||||||
|  | // 	return
 | ||||||
|  | // }
 | ||||||
|  | 
 | ||||||
|  | //-------- export all term
 | ||||||
| 
 | 
 | ||||||
| func newSelectorTerm(tk *Token) (inst *term) { | func newSelectorTerm(tk *Token) (inst *term) { | ||||||
| 	return &term{ | 	return &term{ | ||||||
| @ -16,7 +74,7 @@ func newSelectorTerm(tk *Token) (inst *term) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func trySelectorCase(ctx ExprContext, exprValue, caseSel any, caseIndex int) (match bool, selectedValue any, err error) { | func isSelectorCase(ctx ExprContext, exprValue, caseSel any, caseIndex int) (match bool, selectedValue any, err error) { | ||||||
| 	caseData, _ := caseSel.(*selectorCase) | 	caseData, _ := caseSel.(*selectorCase) | ||||||
| 	if caseData.filterList == nil { | 	if caseData.filterList == nil { | ||||||
| 		selectedValue, err = caseData.caseExpr.eval(ctx, false) | 		selectedValue, err = caseData.caseExpr.eval(ctx, false) | ||||||
| @ -55,7 +113,7 @@ func evalSelector(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 	caseList, _ := caseListTerm.value().([]*term) | 	caseList, _ := caseListTerm.value().([]*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 = isSelectorCase(ctx, exprValue, caseSel, i); err != nil || match { | ||||||
| 			break | 			break | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -242,8 +242,6 @@ func (self *scanner) fetchNextToken() (tk *Token) { | |||||||
| 			if next, _ := self.peek(); next == '(' { | 			if next, _ := self.peek(); next == '(' { | ||||||
| 				tk = self.moveOn(SymDollarRound, ch, next) | 				tk = self.moveOn(SymDollarRound, ch, next) | ||||||
| 				tk.source += ")" | 				tk.source += ")" | ||||||
| 			} else if next == '$' { |  | ||||||
| 				tk = self.moveOn(SymDoubleDollar, ch, next) |  | ||||||
| 			} else { | 			} else { | ||||||
| 				tk = self.makeToken(SymDollar, ch) | 				tk = self.makeToken(SymDollar, ch) | ||||||
| 			} | 			} | ||||||
| @ -251,8 +249,8 @@ func (self *scanner) fetchNextToken() (tk *Token) { | |||||||
| 			if next, _ := self.peek(); next == ')' { | 			if next, _ := self.peek(); next == ')' { | ||||||
| 				tk = self.moveOn(SymOpenClosedRound, ch, next) | 				tk = self.moveOn(SymOpenClosedRound, ch, next) | ||||||
| 			} else { | 			} else { | ||||||
| 				tk = self.makeToken(SymOpenRound, ch) | 			tk = self.makeToken(SymOpenRound, ch) | ||||||
| 			} | 		} | ||||||
| 		case ')': | 		case ')': | ||||||
| 			tk = self.makeToken(SymClosedRound, ch) | 			tk = self.makeToken(SymClosedRound, ch) | ||||||
| 		case '[': | 		case '[': | ||||||
|  | |||||||
| @ -63,8 +63,7 @@ const ( | |||||||
| 	SymAppend                            //  52: '<<'
 | 	SymAppend                            //  52: '<<'
 | ||||||
| 	SymCaret                             //  53: '^'
 | 	SymCaret                             //  53: '^'
 | ||||||
| 	SymDollarRound                       //  54: '$('
 | 	SymDollarRound                       //  54: '$('
 | ||||||
| 	SymOpenClosedRound                   //  55: '()'
 | 	SymOpenClosedRound //  55: '()'
 | ||||||
| 	SymDoubleDollar                      //  56: '$$
 |  | ||||||
| 	SymChangeSign | 	SymChangeSign | ||||||
| 	SymUnchangeSign | 	SymUnchangeSign | ||||||
| 	SymIdentifier | 	SymIdentifier | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user