MCPcopy
hub / github.com/qax-os/excelize / evalInfixExp

Method evalInfixExp

calc.go:979–1108  ·  view source on GitHub ↗

evalInfixExp evaluate syntax analysis by given infix expression after lexical analysis. Evaluate an infix expression containing formulas by stacks: opd - Operand opt - Operator opf - Operation formula opfd - Operand of the operation formula opft - Operator of the operation formula args - A

(ctx *calcContext, sheet, cell string, tokens []efp.Token)

Source from the content-addressed store, hash-verified

977//
978// TODO: handle subtypes: Nothing, Text, Logical, Error, Concatenation, Intersection, Union
979func (f *File) evalInfixExp(ctx *calcContext, sheet, cell string, tokens []efp.Token) (formulaArg, error) {
980 var (
981 err error
982 inArray, inArrayRow bool
983 formulaArray [][]formulaArg
984 formulaArrayRow []formulaArg
985 opdStack, optStack, opfStack = NewStack(), NewStack(), NewStack()
986 opfdStack, opftStack, argsStack = NewStack(), NewStack(), NewStack()
987 )
988 for i := 0; i < len(tokens); i++ {
989 token := tokens[i]
990
991 // out of function stack
992 if opfStack.Len() == 0 {
993 if err = f.parseToken(ctx, sheet, token, opdStack, optStack); err != nil {
994 return newEmptyFormulaArg(), err
995 }
996 }
997
998 // function start
999 if isFunctionStartToken(token) {
1000 if token.TValue == "ARRAY" {
1001 inArray, formulaArray = true, [][]formulaArg{}
1002 continue
1003 }
1004 if token.TValue == "ARRAYROW" {
1005 inArrayRow, formulaArrayRow = true, []formulaArg{}
1006 continue
1007 }
1008 opfStack.Push(token)
1009 argsStack.Push(list.New().Init())
1010 opftStack.Push(token) // to know which operators belong to a function use the function as a separator
1011 continue
1012 }
1013
1014 // in function stack, walk 2 token at once
1015 if opfStack.Len() > 0 {
1016 var nextToken efp.Token
1017 if i+1 < len(tokens) {
1018 nextToken = tokens[i+1]
1019 }
1020
1021 // current token is args or range, skip next token, order required: parse reference first
1022 if token.TSubType == efp.TokenSubTypeRange {
1023 if opftStack.Peek().(efp.Token) != opfStack.Peek().(efp.Token) {
1024 refTo := f.getDefinedNameRefTo(token.TValue, sheet)
1025 if refTo != "" {
1026 token.TValue = refTo
1027 }
1028 // parse reference: must reference at here
1029 result, err := f.parseReference(ctx, sheet, token.TValue)
1030 if err != nil {
1031 return result, err
1032 }
1033 opfdStack.Push(result)
1034 continue
1035 }
1036 if nextToken.TType == efp.TokenTypeArgument || nextToken.TType == efp.TokenTypeFunction {

Callers 2

calcCellValueMethod · 0.95
TestEvalInfixExpFunction · 0.95

Calls 15

parseTokenMethod · 0.95
getDefinedNameRefToMethod · 0.95
parseReferenceMethod · 0.95
evalInfixExpFuncMethod · 0.95
NewStackFunction · 0.85
newEmptyFormulaArgFunction · 0.85
isFunctionStartTokenFunction · 0.85
calculateFunction · 0.85
newErrorFormulaArgFunction · 0.85
isOperandFunction · 0.85
isFunctionStopTokenFunction · 0.85
newMatrixFormulaArgFunction · 0.85

Tested by 1

TestEvalInfixExpFunction · 0.76