diff --git a/operator-fraction.go b/operator-fraction.go index b979721..9f6f13b 100644 --- a/operator-fraction.go +++ b/operator-fraction.go @@ -7,7 +7,6 @@ package expr //https://www.youmath.it/lezioni/algebra-elementare/lezioni-di-algebra-e-aritmetica-per-scuole-medie/553-dalle-frazioni-a-numeri-decimali.html import ( - "errors" "fmt" ) @@ -41,7 +40,7 @@ func evalFraction(ctx ExprContext, opTerm *term) (v any, err error) { return } if den == 0 { - err = errors.New("division by zero") + err = opTerm.errDivisionByZero() return } diff --git a/operator-prod.go b/operator-prod.go index 6adeadf..1deaf35 100644 --- a/operator-prod.go +++ b/operator-prod.go @@ -5,7 +5,6 @@ package expr import ( - "errors" "strings" ) @@ -69,7 +68,7 @@ func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) { if IsFloat(leftValue) || IsFloat(rightValue) { d := numAsFloat(rightValue) if d == 0.0 { - err = errors.New("division by zero") + err = opTerm.errDivisionByZero() } else { v = numAsFloat(leftValue) / d } @@ -78,11 +77,36 @@ func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) { } else { leftInt, _ := leftValue.(int64) if rightInt, _ := rightValue.(int64); rightInt == 0 { - err = errors.New("division by zero") + err = opTerm.errDivisionByZero() } else { v = leftInt / rightInt } } + } else if IsString(leftValue) && IsString(rightValue) { + source := leftValue.(string) + sep := rightValue.(string) + v = ListFromStrings(strings.Split(source, sep)) + } else if IsString(leftValue) && IsInteger(rightValue) { + source := leftValue.(string) + partSize := int(rightValue.(int64)) + if partSize == 0 { + err = opTerm.errDivisionByZero() + } else { + partCount := len(source) / partSize + remainder := len(source) % partSize + listSize := partCount + if remainder > 0 { + listSize++ + } + parts := make([]any, 0, listSize) + for i := 0; i < partCount; i++ { + parts = append(parts, source[i*partSize:(i+1)*partSize]) + } + if remainder > 0 { + parts = append(parts, source[len(source)-remainder:]) + } + v = newList(parts) + } } else { err = opTerm.errIncompatibleTypes(leftValue, rightValue) } @@ -121,7 +145,7 @@ func evalDivideAsFloat(ctx ExprContext, floatDivTerm *term) (v any, err error) { if isNumOrFract(leftValue) && isNumOrFract(rightValue) { d := numAsFloat(rightValue) if d == 0.0 { - err = errors.New("division by zero") + err = floatDivTerm.errDivisionByZero() } else { v = numAsFloat(leftValue) / d } @@ -146,7 +170,7 @@ func remainderValues(opTerm *term, leftValue, rightValue any) (v any, err error) if IsInteger(leftValue) && IsInteger(rightValue) { rightInt, _ := rightValue.(int64) if rightInt == 0 { - err = errors.New("division by zero") + err = opTerm.errDivisionByZero() } else { leftInt, _ := leftValue.(int64) v = leftInt % rightInt diff --git a/t_fractions_test.go b/t_fractions_test.go index c4c38a1..6d8fc15 100644 --- a/t_fractions_test.go +++ b/t_fractions_test.go @@ -25,7 +25,7 @@ func TestFractionsParser(t *testing.T) { /* 12 */ {`builtin "math.arith"; add(1:2, 1.0, 2)`, float64(3.5), nil}, /* 13 */ {`builtin "math.arith"; mul(1:2, 2:3)`, newFraction(2, 6), nil}, /* 14 */ {`builtin "math.arith"; mul(1:2, 1.0, 2)`, float64(1.0), nil}, - /* 15 */ {`1:0`, nil, `division by zero`}, + /* 15 */ {`1:0`, nil, `[1:3] division by zero`}, /* 16 */ {`fract(-0.5)`, newFraction(-1, 2), nil}, /* 17 */ {`fract("")`, (*FractionType)(nil), `bad syntax`}, /* 18 */ {`fract("-1")`, newFraction(-1, 1), nil}, @@ -34,7 +34,7 @@ func TestFractionsParser(t *testing.T) { /* 21 */ {`fract(1,0)`, nil, `fract(): division by zero`}, /* 22 */ {`string(1:2)`, "1:2", nil}, /* 23 */ {`1+1:2+0.5`, float64(2), nil}, - /* 24 */ {`1:(2-2)`, nil, `division by zero`}, + /* 24 */ {`1:(2-2)`, nil, `[1:3] division by zero`}, /* 25 */ {`[0,1][1-1]:1`, newFraction(0, 1), nil}, } // runTestSuiteSpec(t, section, inputs, 25) diff --git a/t_parser_test.go b/t_parser_test.go index 7d385b2..e9a1aa4 100644 --- a/t_parser_test.go +++ b/t_parser_test.go @@ -78,8 +78,8 @@ func TestGeneralParser(t *testing.T) { /* 64 */ {`"1.5" != `, nil, `[1:8] infix operator "!=" requires two non-nil operands, got 1`}, /* 65 */ {"+1.5", float64(1.5), nil}, /* 66 */ {"+", nil, `[1:2] prefix operator "+" requires one non-nil operand`}, - /* 67 */ {"4 / 0", nil, `division by zero`}, - /* 68 */ {"4.0 / 0", nil, `division by zero`}, + /* 67 */ {"4 / 0", nil, `[1:4] division by zero`}, + /* 68 */ {"4.0 / 0", nil, `[1:6] division by zero`}, /* 69 */ {"4.0 / \n2", float64(2.0), nil}, /* 70 */ {`123`, int64(123), nil}, /* 71 */ {`1.`, float64(1.0), nil}, diff --git a/t_strings_test.go b/t_strings_test.go index 0b8e049..50a05f4 100644 --- a/t_strings_test.go +++ b/t_strings_test.go @@ -16,6 +16,12 @@ func TestStringsParser(t *testing.T) { /* 4 */ {`"uno" * (2+1)`, `unounouno`, nil}, /* 5 */ {`"abc"[1]`, `b`, nil}, /* 6 */ {`#"abc"`, int64(3), nil}, + /* 7 */ {`"192.168.0.240" / "."`, newListA("192", "168", "0", "240"), nil}, + /* 8 */ {`("192.168.0.240" / ".")[1]`, "168", nil}, + /* 9 */ {`"AF3B0Dz" / 2`, newListA("AF", "3B", "0D", "z"), nil}, + /* 10 */ {`"AF3B0Dz" / 0`, nil, "[1:12] division by zero"}, } + + // runTestSuiteSpec(t, "String", inputs, 8) runTestSuite(t, "String", inputs) }