Compare commits
	
		
			No commits in common. "c9db4b84e38550d73090dfe85481017e4b198b3b" and "f028485caae5e92a9fe30c63b700c8ce17efb8fa" have entirely different histories.
		
	
	
		
			c9db4b84e3
			...
			f028485caa
		
	
		
@ -26,7 +26,6 @@ func TestDictParser(t *testing.T) {
 | 
			
		||||
		/*  3 */ {`{1:"one",2:"two",3:"three"}`, map[int64]any{int64(1): "one", int64(2): "two", int64(3): "three"}, nil},
 | 
			
		||||
		/*  4 */ {`{1:"one",2:"two",3:"three"}.2`, "three", nil},
 | 
			
		||||
		/*  5 */ {`#{1:"one",2:"two",3:"three"}`, int64(3), nil},
 | 
			
		||||
		/*  6 */ {`{1:"one"} + {2:"two"}`, map[any]any{1: "one", 2: "two"}, nil},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	succeeded := 0
 | 
			
		||||
 | 
			
		||||
@ -68,15 +68,6 @@ func TestFuncs(t *testing.T) {
 | 
			
		||||
		/*  55 */ {`builtin "math.arith"; add(1,2)`, int64(3), nil},
 | 
			
		||||
		/*  56 */ {`fract("2.2(3)")`, newFraction(67, 30), nil},
 | 
			
		||||
		/*  57 */ {`fract("1.21(3)")`, newFraction(91, 75), nil},
 | 
			
		||||
		/*  58 */ {`fract(1.21(3))`, newFraction(91, 75), nil},
 | 
			
		||||
		/*  59 */ {`fract(1.21)`, newFraction(121, 100), nil},
 | 
			
		||||
		/*  60 */ {`dec(2)`, float64(2), nil},
 | 
			
		||||
		/*  61 */ {`dec(2.0)`, float64(2), nil},
 | 
			
		||||
		/*  62 */ {`dec("2.0")`, float64(2), nil},
 | 
			
		||||
		/*  63 */ {`dec(true)`, float64(1), nil},
 | 
			
		||||
		/*  64 */ {`dec(true")`, nil, errors.New("[1:11] missing string termination \"")},
 | 
			
		||||
		/*  65 */ {`builtin "string"; joinStr("-", [1, "two", "three"])`, nil, errors.New(`joinStr() expected string, got int64 (1)`)},
 | 
			
		||||
		// /*  64 */ {`string(true)`, "true", nil},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t.Setenv("EXPR_PATH", ".")
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										32
									
								
								operand-const.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								operand-const.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | 
			
		||||
// All rights reserved.
 | 
			
		||||
 | 
			
		||||
// operand-const.go
 | 
			
		||||
package expr
 | 
			
		||||
 | 
			
		||||
// -------- const term
 | 
			
		||||
func newConstTerm(tk *Token) *term {
 | 
			
		||||
	return &term{
 | 
			
		||||
		tk:       *tk,
 | 
			
		||||
		parent:   nil,
 | 
			
		||||
		children: nil,
 | 
			
		||||
		position: posLeaf,
 | 
			
		||||
		priority: priValue,
 | 
			
		||||
		evalFunc: evalConst,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// -------- eval func
 | 
			
		||||
func evalConst(ctx ExprContext, self *term) (v any, err error) {
 | 
			
		||||
	v = self.tk.Value
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// init
 | 
			
		||||
func init() {
 | 
			
		||||
	registerTermConstructor(SymString, newConstTerm)
 | 
			
		||||
	registerTermConstructor(SymInteger, newConstTerm)
 | 
			
		||||
	registerTermConstructor(SymFloat, newConstTerm)
 | 
			
		||||
	registerTermConstructor(SymBool, newConstTerm)
 | 
			
		||||
	registerTermConstructor(SymKwNil, newConstTerm)
 | 
			
		||||
}
 | 
			
		||||
@ -1,33 +0,0 @@
 | 
			
		||||
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | 
			
		||||
// All rights reserved.
 | 
			
		||||
 | 
			
		||||
// operand-literal.go
 | 
			
		||||
package expr
 | 
			
		||||
 | 
			
		||||
// -------- literal term
 | 
			
		||||
func newLiteralTerm(tk *Token) *term {
 | 
			
		||||
	return &term{
 | 
			
		||||
		tk:       *tk,
 | 
			
		||||
		parent:   nil,
 | 
			
		||||
		children: nil,
 | 
			
		||||
		position: posLeaf,
 | 
			
		||||
		priority: priValue,
 | 
			
		||||
		evalFunc: evalLiteral,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// -------- eval func
 | 
			
		||||
func evalLiteral(ctx ExprContext, self *term) (v any, err error) {
 | 
			
		||||
	v = self.tk.Value
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// init
 | 
			
		||||
func init() {
 | 
			
		||||
	registerTermConstructor(SymString, newLiteralTerm)
 | 
			
		||||
	registerTermConstructor(SymInteger, newLiteralTerm)
 | 
			
		||||
	registerTermConstructor(SymFloat, newLiteralTerm)
 | 
			
		||||
	registerTermConstructor(SymFraction, newLiteralTerm)
 | 
			
		||||
	registerTermConstructor(SymBool, newLiteralTerm)
 | 
			
		||||
	registerTermConstructor(SymKwNil, newLiteralTerm)
 | 
			
		||||
}
 | 
			
		||||
@ -61,14 +61,6 @@ func evalPlus(ctx ExprContext, self *term) (v any, err error) {
 | 
			
		||||
		} else {
 | 
			
		||||
			v, err = sumAnyFract(leftValue, rightValue)
 | 
			
		||||
		}
 | 
			
		||||
	} else if IsDict(leftValue) && IsDict(rightValue) {
 | 
			
		||||
		leftDict, _ := leftValue.(map[any]any)
 | 
			
		||||
		rightDict, _ := rightValue.(map[any]any)
 | 
			
		||||
		c := CloneMap(leftDict)
 | 
			
		||||
		for key, value := range rightDict {
 | 
			
		||||
			c[key] = value
 | 
			
		||||
		}
 | 
			
		||||
		v = c
 | 
			
		||||
	} else {
 | 
			
		||||
		err = self.errIncompatibleTypes(leftValue, rightValue)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										39
									
								
								scanner.go
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								scanner.go
									
									
									
									
									
								
							@ -385,37 +385,20 @@ func (self *scanner) parseNumber(firstCh byte) (tk *Token) {
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			if ch == 'e' || ch == 'E' {
 | 
			
		||||
				sym = SymFloat
 | 
			
		||||
				sb.WriteByte(ch)
 | 
			
		||||
				if ch, err = self.readChar(); err == nil {
 | 
			
		||||
					if ch == '+' || ch == '-' {
 | 
			
		||||
						sb.WriteByte(ch)
 | 
			
		||||
						ch, err = self.readChar()
 | 
			
		||||
					}
 | 
			
		||||
					if ch >= '0' && ch <= '9' {
 | 
			
		||||
						for ; err == nil && (ch >= '0' && ch <= '9'); ch, err = self.readChar() {
 | 
			
		||||
							sb.WriteByte(ch)
 | 
			
		||||
						}
 | 
			
		||||
					} else {
 | 
			
		||||
						err = fmt.Errorf("[%d:%d] expected integer exponent, got %c", self.row, self.column, ch)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			} else if ch == '(' {
 | 
			
		||||
				sym = SymFraction
 | 
			
		||||
				sb.WriteByte(ch)
 | 
			
		||||
				ch, err = self.readChar()
 | 
			
		||||
				for ; err == nil && (ch >= '0' && ch <= '9'); ch, err = self.readChar() {
 | 
			
		||||
		if err == nil && (ch == 'e' || ch == 'E') {
 | 
			
		||||
			sym = SymFloat
 | 
			
		||||
			sb.WriteByte(ch)
 | 
			
		||||
			if ch, err = self.readChar(); err == nil {
 | 
			
		||||
				if ch == '+' || ch == '-' {
 | 
			
		||||
					sb.WriteByte(ch)
 | 
			
		||||
					ch, err = self.readChar()
 | 
			
		||||
				}
 | 
			
		||||
				if err == nil {
 | 
			
		||||
					if ch != ')' {
 | 
			
		||||
						err = fmt.Errorf("[%d:%d] expected ')', got '%c'", self.row, self.column, ch)
 | 
			
		||||
					} else {
 | 
			
		||||
				if ch >= '0' && ch <= '9' {
 | 
			
		||||
					for ; err == nil && (ch >= '0' && ch <= '9'); ch, err = self.readChar() {
 | 
			
		||||
						sb.WriteByte(ch)
 | 
			
		||||
						_, err = self.readChar()
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					err = errors.New("expected integer exponent")
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@ -429,8 +412,6 @@ func (self *scanner) parseNumber(firstCh byte) (tk *Token) {
 | 
			
		||||
		txt := sb.String()
 | 
			
		||||
		if sym == SymFloat {
 | 
			
		||||
			value, err = strconv.ParseFloat(txt, 64)
 | 
			
		||||
		} else if sym == SymFraction {
 | 
			
		||||
			value, err = makeGeneratingFraction(txt)
 | 
			
		||||
		} else {
 | 
			
		||||
			value, err = strconv.ParseInt(txt, numBase, 64)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,6 @@ package expr
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
@ -56,18 +55,15 @@ func TestScanner(t *testing.T) {
 | 
			
		||||
		/* 33 */ {`(`, SymOpenRound, nil, nil},
 | 
			
		||||
		/* 34 */ {`)`, SymClosedRound, nil, nil},
 | 
			
		||||
		/* 35 */ {`1E+2`, SymFloat, float64(100), nil},
 | 
			
		||||
		/* 36 */ {`1E+x`, SymError, errors.New("[1:5] expected integer exponent, got x"), nil},
 | 
			
		||||
		/* 36 */ {`1E+x`, SymError, errors.New("expected integer exponent"), nil},
 | 
			
		||||
		/* 37 */ {`$`, SymDollar, nil, nil},
 | 
			
		||||
		/* 38 */ {`\`, SymError, errors.New("incomplete escape sequence"), nil},
 | 
			
		||||
		/* 39 */ {`"string"`, SymString, "string", nil},
 | 
			
		||||
		/* 40 */ {`identifier`, SymIdentifier, "identifier", nil},
 | 
			
		||||
		/* 41 */ {`1.2(3)`, SymFraction, newFraction(37, 30), nil},
 | 
			
		||||
		/* 39 */ {`identifier`, SymIdentifier, "identifier", nil},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, input := range inputs {
 | 
			
		||||
		// if i != 40 {
 | 
			
		||||
		// 	continue
 | 
			
		||||
		// }
 | 
			
		||||
 | 
			
		||||
		if input.wantErr == nil {
 | 
			
		||||
			t.Log(fmt.Sprintf("[+]Test nr %2d -- %q", i+1, input.source))
 | 
			
		||||
		} else {
 | 
			
		||||
@ -79,8 +75,7 @@ func TestScanner(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
		if tk := scanner.Next(); tk == nil {
 | 
			
		||||
			t.Errorf("%d: %q -> got = (nil), want %v (value %v [%T])", i+1, input.source, input.wantSym, input.wantValue, input.wantValue)
 | 
			
		||||
			// } else if tk.Sym != input.wantSym || tk.Value != input.wantValue {
 | 
			
		||||
		} else if tk.Sym != input.wantSym || !reflect.DeepEqual(tk.Value, input.wantValue) {
 | 
			
		||||
		} else if tk.Sym != input.wantSym || tk.Value != input.wantValue {
 | 
			
		||||
			if tk.Sym == SymError && input.wantSym == tk.Sym {
 | 
			
		||||
				if tkErr, tkOk := tk.Value.(error); tkOk {
 | 
			
		||||
					if inputErr, inputOk := input.wantValue.(error); inputOk {
 | 
			
		||||
@ -91,7 +86,7 @@ func TestScanner(t *testing.T) {
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				t.Errorf("%d: %q -> got = %v (value=%v [%T]), want %v (value=%v [%T])", i+1,
 | 
			
		||||
				t.Errorf("%d: %q -> got = %v (value=%v [%T), want %v (value=%v [%T)", i+1,
 | 
			
		||||
					input.source, tk.Sym, tk.Value, tk.Value, input.wantSym, input.wantValue, input.wantValue)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user