summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--calc.go10
-rw-r--r--calc_test.go20
2 files changed, 26 insertions, 4 deletions
diff --git a/calc.go b/calc.go
index ebfa815..d74a5fa 100644
--- a/calc.go
+++ b/calc.go
@@ -726,6 +726,7 @@ func (f *File) evalInfixExp(sheet, cell string, tokens []efp.Token) (efp.Token,
if isFunctionStartToken(token) {
opfStack.Push(token)
argsStack.Push(list.New().Init())
+ opftStack.Push(token) // to know which operators belong to a function use the function as a separator
continue
}
@@ -738,7 +739,7 @@ func (f *File) evalInfixExp(sheet, cell string, tokens []efp.Token) (efp.Token,
// current token is args or range, skip next token, order required: parse reference first
if token.TSubType == efp.TokenSubTypeRange {
- if !opftStack.Empty() {
+ if opftStack.Peek().(efp.Token) != opfStack.Peek().(efp.Token) {
refTo := f.getDefinedNameRefTo(token.TValue, sheet)
if refTo != "" {
token.TValue = refTo
@@ -783,7 +784,7 @@ func (f *File) evalInfixExp(sheet, cell string, tokens []efp.Token) (efp.Token,
// current token is arg
if token.TType == efp.TokenTypeArgument {
- for !opftStack.Empty() {
+ for opftStack.Peek().(efp.Token) != opfStack.Peek().(efp.Token) {
// calculate trigger
topOpt := opftStack.Peek().(efp.Token)
if err := calculate(opfdStack, topOpt); err != nil {
@@ -826,7 +827,7 @@ func (f *File) evalInfixExpFunc(sheet, cell string, token, nextToken efp.Token,
return nil
}
// current token is function stop
- for !opftStack.Empty() {
+ for opftStack.Peek().(efp.Token) != opfStack.Peek().(efp.Token) {
// calculate trigger
topOpt := opftStack.Peek().(efp.Token)
if err := calculate(opfdStack, topOpt); err != nil {
@@ -847,9 +848,10 @@ func (f *File) evalInfixExpFunc(sheet, cell string, token, nextToken efp.Token,
return errors.New(arg.Value())
}
argsStack.Pop()
+ opftStack.Pop() // remove current function separator
opfStack.Pop()
if opfStack.Len() > 0 { // still in function stack
- if nextToken.TType == efp.TokenTypeOperatorInfix {
+ if nextToken.TType == efp.TokenTypeOperatorInfix || opftStack.Len() > 1 {
// mathematics calculate in formula function
opfdStack.Push(efp.Token{TValue: arg.Value(), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber})
} else {
diff --git a/calc_test.go b/calc_test.go
index 50f8023..a2b1294 100644
--- a/calc_test.go
+++ b/calc_test.go
@@ -3787,3 +3787,23 @@ func TestGetYearDays(t *testing.T) {
assert.Equal(t, data[2], getYearDays(data[0], data[1]))
}
}
+
+func TestNestedFunctionsWithOperators(t *testing.T) {
+ f := NewFile()
+ formulaList := map[string]string{
+ `=LEN("KEEP")`: "4",
+ `=LEN("REMOVEKEEP") - LEN("REMOVE")`: "4",
+ `=RIGHT("REMOVEKEEP", 4)`: "KEEP",
+ `=RIGHT("REMOVEKEEP", 10 - 6))`: "KEEP",
+ `=RIGHT("REMOVEKEEP", LEN("REMOVEKEEP") - 6)`: "KEEP",
+ `=RIGHT("REMOVEKEEP", LEN("REMOVEKEEP") - LEN("REMOV") - 1)`: "KEEP",
+ `=RIGHT("REMOVEKEEP", 10 - LEN("REMOVE"))`: "KEEP",
+ `=RIGHT("REMOVEKEEP", LEN("REMOVEKEEP") - LEN("REMOVE"))`: "KEEP",
+ }
+ for formula, expected := range formulaList {
+ assert.NoError(t, f.SetCellFormula("Sheet1", "E1", formula))
+ result, err := f.CalcCellValue("Sheet1", "E1")
+ assert.NoError(t, err, formula)
+ assert.Equal(t, expected, result, formula)
+ }
+}