Skip to content

Commit

Permalink
Fixes #73 - (MB-33014) Support arithmetic operations
Browse files Browse the repository at this point in the history
  • Loading branch information
nelio2k committed Feb 22, 2019
1 parent f0cb6ab commit 302ae79
Show file tree
Hide file tree
Showing 5 changed files with 287 additions and 29 deletions.
6 changes: 6 additions & 0 deletions constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ const (
MathFuncSin string = "mathSin"
MathFuncSqrt string = "mathSqrt"
MathFuncTan string = "mathTan"
MathFuncAdd string = "mathAdd"
MathFuncSub string = "mathSubract"
MathFuncMul string = "mathMultiply"
MathFuncDiv string = "mathDivide"
MathFuncMod string = "mathModulo"
MathFuncNeg string = "mathNegate"

FuncAbs string = "ABS"
FuncAcos string = "ACOS"
Expand Down
23 changes: 23 additions & 0 deletions fastMatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,29 @@ func (m *FastMatcher) resolveFunc(fn FuncRef, activeLit *FastVal) FastVal {
case DateFunc:
p1 := m.resolveParam(fn.Params[0], activeLit)
return FastValDateFunc(p1)
case MathFuncAdd:
p1 := m.resolveParam(fn.Params[0], activeLit)
p2 := m.resolveParam(fn.Params[1], activeLit)
return FastValMathAdd(p1, p2)
case MathFuncSub:
p1 := m.resolveParam(fn.Params[0], activeLit)
p2 := m.resolveParam(fn.Params[1], activeLit)
return FastValMathSub(p1, p2)
case MathFuncMul:
p1 := m.resolveParam(fn.Params[0], activeLit)
p2 := m.resolveParam(fn.Params[1], activeLit)
return FastValMathMul(p1, p2)
case MathFuncDiv:
p1 := m.resolveParam(fn.Params[0], activeLit)
p2 := m.resolveParam(fn.Params[1], activeLit)
return FastValMathDiv(p1, p2)
case MathFuncMod:
p1 := m.resolveParam(fn.Params[0], activeLit)
p2 := m.resolveParam(fn.Params[1], activeLit)
return FastValMathMod(p1, p2)
case MathFuncNeg:
p1 := m.resolveParam(fn.Params[0], activeLit)
return FastValMathNeg(p1)
default:
panic(fmt.Sprintf("encountered unexpected function name: %v", fn.FuncName))
}
Expand Down
66 changes: 66 additions & 0 deletions fastval_math.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,51 @@ func FastValMathAbs(val FastVal) FastVal {
return NewInvalidFastVal()
}

type intToIntOp func(int64) int64
type int2ToIntOp func(int64, int64) int64
type floatToFloatOp func(float64) float64
type float2ToFloatOp func(float64, float64) float64

func fastValMathAdd(a, b float64) float64 {
return a + b
}

func fastValMathSub(a, b float64) float64 {
return a - b
}

func fastValMathMult(a, b float64) float64 {
return a * b
}

func fastValMathDiv(a, b float64) float64 {
return a / b
}

func fastValMathMod(a, b int64) int64 {
return a % b
}

func fastValNegate(a float64) float64 {
return -1.0 * a
}

func genericFastValIntOp(val FastVal, op intToIntOp) FastVal {
if val.IsNumeric() {
return NewIntFastVal(op(val.AsInt()))
}

return NewInvalidFastVal()
}

func genericFastVal2IntsOp(val, val1 FastVal, op int2ToIntOp) FastVal {
if !val.IsNumeric() || !val1.IsNumeric() {
return NewInvalidFastVal()
}

return NewIntFastVal(op(val.AsInt(), val1.AsInt()))
}

func genericFastValFloatOp(val FastVal, op floatToFloatOp) FastVal {
if val.IsNumeric() {
return NewFloatFastVal(op(val.AsFloat()))
Expand Down Expand Up @@ -131,3 +173,27 @@ func FastValMathDegrees(val FastVal) FastVal {
func FastValMathRadians(val FastVal) FastVal {
return genericFastValFloatOp(val, mathRadiansFunc)
}

func FastValMathAdd(val, val1 FastVal) FastVal {
return genericFastVal2FloatsOp(val, val1, fastValMathAdd)
}

func FastValMathSub(val, val1 FastVal) FastVal {
return genericFastVal2FloatsOp(val, val1, fastValMathSub)
}

func FastValMathMul(val, val1 FastVal) FastVal {
return genericFastVal2FloatsOp(val, val1, fastValMathMult)
}

func FastValMathDiv(val, val1 FastVal) FastVal {
return genericFastVal2FloatsOp(val, val1, fastValMathDiv)
}

func FastValMathMod(val, val1 FastVal) FastVal {
return genericFastVal2IntsOp(val, val1, fastValMathMod)
}

func FastValMathNeg(val FastVal) FastVal {
return genericFastValFloatOp(val, fastValNegate)
}
175 changes: 148 additions & 27 deletions filterExprParser.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import (
// RHS = ConstFuncExpr | Boolean | Value | Field
// CompareOp = "=" | "<>" | ">" | ">=" | "<" | "<="
// CheckOp = "EXISTS" | ( "IS" [ "NOT" ] ( NULL | MISSING ) )
// Field = OnePath { "." OnePath }
// OnePath = ( PathFuncExpression | @String | @Ident | @RawString | @Char ){ ArrayIndex }
// Field = { @"-" } OnePath { "." OnePath } { MathOp MathValue }
// OnePath = ( PathFuncExpression | StringType ){ ArrayIndex }
// StringType = @String | @Ident | @RawString | @Char
// ArrayIndex = "[" [ @"-" ] @Int "]"
// Value = @String
// ConstFuncExpr = ConstFuncNoArg | ConstFuncOneArg | ConstFuncTwoArgs
Expand All @@ -35,6 +36,8 @@ import (
// ConstFuncArgumentRHS = Value
// PathFuncExpression = OnePathFuncNoArg
// OnePathFuncNoArg = OnePathFuncNoArgName "(" ")"
// MathOp = @"+" | @"-" | @"*" | @"/" | @"%"
// MathValue = @Int | @Float
// OnePathFuncNoArgName = "META"
// BooleanFuncExpr = BooleanFuncTwoArgs
// BooleanFuncTwoArgs = BooleanFuncTwoArgsName "(" ConstFuncArgument "," ConstFuncArgumentRHS ")"
Expand Down Expand Up @@ -465,15 +468,30 @@ func (f *FERhs) OutputExpression() (Expression, error) {
}

type FEField struct {
Path []*FEOnePath `@@ { "." @@ }`
MathNeg *bool `{ @"-" }`
Path []*FEOnePath `@@ { "." @@ }`
MathOp *FEMathArithmeticOp `{ ( @@`
MathValue *FEMathValue `@@ ) }`
}

func (fef *FEField) String() string {
output := []string{}
outerOutput := []string{}
for _, onePath := range fef.Path {
output = append(output, onePath.String())
}
return strings.Join(output, ".")
fieldOutput := strings.Join(output, ".")
if fef.MathNeg != nil {
fieldOutput = fmt.Sprintf("%v%v", "-", fieldOutput)
}
outerOutput = append(outerOutput, fieldOutput)
if fef.MathOp != nil {
outerOutput = append(outerOutput, fef.MathOp.String())
}
if fef.MathValue != nil {
outerOutput = append(outerOutput, fef.MathValue.String())
}
return strings.Join(outerOutput, " ")
}

func (f *FEField) OutputExpression() (Expression, error) {
Expand All @@ -493,7 +511,39 @@ func (f *FEField) OutputExpression() (Expression, error) {
outExpr.Path = append(outExpr.Path, arrIdx)
}
}
return outExpr, nil

if f.MathNeg != nil || (f.MathOp != nil && f.MathValue != nil) {
var mathOutExpr FuncExpr
if f.MathOp == nil {
// Only thing is a negation of the field value
mathOutExpr.FuncName = MathFuncNeg
mathOutExpr.Params = append(mathOutExpr.Params, outExpr)
} else {
// {-}field mathOp mathVal
mathOpExpr, err := f.MathOp.OutputExpression()
if err != nil {
return nil, err
}
mathOutExpr = mathOpExpr.(FuncExpr)

if f.MathNeg != nil {
negativeFieldExpr := FuncExpr{FuncName: MathFuncNeg}
negativeFieldExpr.Params = append(negativeFieldExpr.Params, outExpr)
mathOutExpr.Params = append(mathOutExpr.Params, negativeFieldExpr)
} else {
mathOutExpr.Params = append(mathOutExpr.Params, outExpr)
}

valueExpr, err := f.MathValue.OutputExpression()
if err != nil {
return nil, err
}
mathOutExpr.Params = append(mathOutExpr.Params, valueExpr)
}
return mathOutExpr, nil
} else {
return outExpr, nil
}
}

// The problem with this parser is that if FEField is prioritized higher than FEValue, then
Expand All @@ -518,27 +568,39 @@ func (f *FEField) OutputExpressionSpecialAsValue() (Expression, error) {
return ValueExpr{f.Path[0].String()}, nil
}

type FEStringType struct {
EscapedStrVal string `( @String |`
CharVal string `@Char |`
RawStr string `@RawString |`
StrValue string `@Ident )`
}

func (f *FEStringType) String() string {
if len(f.CharVal) > 0 {
return f.CharVal
} else if len(f.RawStr) > 0 {
return f.RawStr
} else if len(f.StrValue) > 0 {
return f.StrValue
} else if len(f.EscapedStrVal) > 0 {
return f.EscapedStrVal
} else {
return ""
}
}

type FEOnePath struct {
OnePathFunc *FEOnePathFuncExpr `( @@ |`
EscapedStrVal string `@String |`
CharVal string `@Char |`
RawStr string `@RawString |`
StrValue string `@Ident )`
ArrayIndexes []*FEArrayIndex `{ @@ }`
OnePathFunc *FEOnePathFuncExpr `( @@ |`
StrValue *FEStringType ` @@ )`
ArrayIndexes []*FEArrayIndex `{ @@ }`
}

func (feop *FEOnePath) String() string {
output := []string{}
if feop.OnePathFunc != nil {
output = append(output, feop.OnePathFunc.String())
} else if len(feop.CharVal) > 0 {
output = append(output, feop.CharVal)
} else if len(feop.RawStr) > 0 {
output = append(output, feop.RawStr)
} else if len(feop.StrValue) > 0 {
output = append(output, feop.StrValue)
} else if len(feop.EscapedStrVal) > 0 {
output = append(output, feop.EscapedStrVal)
} else if len(feop.StrValue.String()) > 0 {
output = append(output, feop.StrValue.String())
} else {
output = append(output, "")
}
Expand All @@ -555,14 +617,8 @@ func (f *FEOnePath) OutputOnePath() (string, []string, error) {
arrayIdx = append(arrayIdx, arr.String())
}

if len(f.EscapedStrVal) > 0 {
return f.EscapedStrVal, arrayIdx, nil
} else if len(f.CharVal) > 0 {
return f.CharVal, arrayIdx, nil
} else if len(f.RawStr) > 0 {
return f.RawStr, arrayIdx, nil
} else if len(f.StrValue) > 0 {
return f.StrValue, arrayIdx, nil
if f.StrValue != nil {
return f.StrValue.String(), arrayIdx, nil
} else if f.OnePathFunc != nil {
return f.OnePathFunc.String(), arrayIdx, nil
} else {
Expand Down Expand Up @@ -622,6 +678,71 @@ func (f *FEOnePathFuncNoArgName) OutputExpression() (Expression, error) {
return nil, fmt.Errorf("Not supported (FEOnePathFuncNoArgName) %v", f.String())
}

type FEMathArithmeticOp struct {
Addition *bool `@"+" |`
Subtraction *bool `@"-" |`
Multiply *bool `@"*" |`
Division *bool `@"/" |`
Modulo *bool `@"%"`
}

func (f *FEMathArithmeticOp) String() string {
if f.Addition != nil {
return "+"
} else if f.Subtraction != nil {
return "-"
} else if f.Multiply != nil {
return "*"
} else if f.Division != nil {
return "/"
} else if f.Modulo != nil {
return "%"
} else {
return "?? (FEMathArithmeticOp)"
}
}

func (f *FEMathArithmeticOp) OutputExpression() (Expression, error) {
if f.Addition != nil {
return FuncExpr{FuncName: MathFuncAdd}, nil
} else if f.Subtraction != nil {
return FuncExpr{FuncName: MathFuncSub}, nil
} else if f.Multiply != nil {
return FuncExpr{FuncName: MathFuncMul}, nil
} else if f.Division != nil {
return FuncExpr{FuncName: MathFuncDiv}, nil
} else if f.Modulo != nil {
return FuncExpr{FuncName: MathFuncMod}, nil
} else {
return nil, fmt.Errorf("Invalid FEMathArithmeticOp %v", f.String())
}
}

type FEMathValue struct {
IntValue *int `@Int |`
FloatValue *float64 `@Float`
}

func (f *FEMathValue) String() string {
if f.IntValue != nil {
return fmt.Sprintf("%v", *f.IntValue)
} else if f.FloatValue != nil {
return fmt.Sprintf("%v", *f.FloatValue)
} else {
return "?? (FEMathValue)"
}
}

func (f *FEMathValue) OutputExpression() (Expression, error) {
if f.IntValue != nil {
return ValueExpr{*f.IntValue}, nil
} else if f.FloatValue != nil {
return ValueExpr{*f.FloatValue}, nil
} else {
return nil, fmt.Errorf("Invalid FEMathValue %v", f.String())
}
}

type FEValue struct {
StrValue *string `@String |`
IntValue *int `@Int |`
Expand Down
Loading

0 comments on commit 302ae79

Please sign in to comment.