Skip to content

Commit

Permalink
If prior input is not present, compose tokens into a string.
Browse files Browse the repository at this point in the history
  • Loading branch information
bhare committed Oct 17, 2018
1 parent 9aa4983 commit 4a3eade
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 12 deletions.
23 changes: 21 additions & 2 deletions EvaluableExpression.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,11 +255,30 @@ func (this EvaluableExpression) Tokens() []ExpressionToken {
}

/*
Returns the original expression used to create this EvaluableExpression.
Returns a string representation of this expression.
*/
func (this EvaluableExpression) String() string {
if this.inputExpression != "" {
return this.inputExpression
}

var expressionText string
for _, val := range this.Tokens() {
switch val.Kind {
case VARIABLE:
expressionText += fmt.Sprintf("[%+v]", val.Meta)
case STRING, TIME:
expressionText += fmt.Sprintf("'%+v'", val.Meta)
case COMPARATOR, LOGICALOP, MODIFIER, TERNARY:
expressionText += fmt.Sprintf(" %+v ", val.Meta)
case SEPARATOR:
expressionText += fmt.Sprintf("%+v ", val.Meta)
default:
expressionText += fmt.Sprintf("%+v", val.Meta)
}
}

return this.inputExpression
return expressionText
}

/*
Expand Down
1 change: 1 addition & 0 deletions ExpressionToken.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ package govaluate
type ExpressionToken struct {
Kind TokenKind
Value interface{}
Meta interface{}
}
41 changes: 41 additions & 0 deletions evaluationFailure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,47 @@ var EVALUATION_FAILURE_PARAMETERS = map[string]interface{}{
"bool": true,
}

func TestFullCycle(test *testing.T) {
currentExpressionString := "2 > 1 && " +
"'something' != 'nothing' || (1,2,3) != (3,2,1) || " +
"func1(1337,'leet',sawce) < 'Wed Jul 8 23:07:35 MDT 2015' && " +
"[escapedVariable name with spaces] <= unescaped\\-variableName && " +
"modifierTest + 0xa3a2b3 / 2 > (80 * 100 % 2) && true ? true : false"
extraFuncs := map[string]ExpressionFunction{
"func1": func(args ...interface{}) (interface{}, error) {
return "2014-01-20", nil
},
}

var initialExpression, cycledExpression, finalExpression *EvaluableExpression
initialExpression, err := NewEvaluableExpressionWithFunctions(currentExpressionString, extraFuncs)
if err != nil {
test.Errorf("Failed to build expression from string... ERROR: %+v", err)
}
cycledExpression, err = NewEvaluableExpressionFromTokens(initialExpression.Tokens())
if err != nil {
test.Errorf("Failed to build expression from tokens, from string... ERROR: %+v", err)
}
temp2, err := NewEvaluableExpressionWithFunctions(cycledExpression.String(), extraFuncs)
if err != nil {
test.Errorf("Failed to build expression from string, from tokens, from string... ERROR: %+v", err)
}
finalExpression, err = NewEvaluableExpressionFromTokens(temp2.Tokens())
if err != nil {
test.Errorf("Failed to build expression from tokens, from string, from tokens, from string... ERROR: %+v", err)
}

if finalExpression.String() != cycledExpression.String() {
test.Errorf("The final result string was not synonymous with the initial's... FAILURE:\n\"%+v\"\n !=\n\"%+v\"", finalExpression.String(), initialExpression.String())
}
if len(finalExpression.Vars()) != len(initialExpression.Vars()) {
test.Errorf("The final result variables were not synonymous with the initial's... FAILURE:\n\"%+v\"\n !=\n\"%+v\"", finalExpression.Vars(), initialExpression.Vars())
}
if len(finalExpression.Tokens()) != len(initialExpression.Tokens()) {
test.Errorf("The final result tokens were not synonymous with the initial's... FAILURE:\n\"%+v\"\n !=\n\"%+v\"", finalExpression.Tokens(), initialExpression.Tokens())
}
}

func TestComplexParameter(test *testing.T) {

var expression *EvaluableExpression
Expand Down
27 changes: 17 additions & 10 deletions parsing.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func readToken(stream *lexerStream, state lexerState, functions map[string]Expre
var found bool
var completed bool
var err error
var meta interface{}

// numeric is 0-9, or . or 0x followed by digits
// string starts with '
Expand All @@ -79,6 +80,7 @@ func readToken(stream *lexerStream, state lexerState, functions map[string]Expre
continue
}

meta = character
kind = UNKNOWN

// numeric constant
Expand All @@ -96,6 +98,7 @@ func readToken(stream *lexerStream, state lexerState, functions map[string]Expre
return ExpressionToken{}, errors.New(errorMsg), false
}

meta = "0x" + tokenString
kind = NUMERIC
tokenValue = float64(tokenValueInt)
break
Expand All @@ -111,6 +114,8 @@ func readToken(stream *lexerStream, state lexerState, functions map[string]Expre
errorMsg := fmt.Sprintf("Unable to parse numeric value '%v' to float64\n", tokenString)
return ExpressionToken{}, errors.New(errorMsg), false
}

meta = tokenString
kind = NUMERIC
break
}
Expand All @@ -119,6 +124,7 @@ func readToken(stream *lexerStream, state lexerState, functions map[string]Expre
if character == ',' {

tokenValue = ","
meta = tokenValue
kind = SEPARATOR
break
}
Expand All @@ -127,6 +133,7 @@ func readToken(stream *lexerStream, state lexerState, functions map[string]Expre
if character == '[' {

tokenValue, completed = readUntilFalse(stream, true, false, true, isNotClosingBracket)
meta = tokenValue
kind = VARIABLE

if !completed {
Expand All @@ -142,22 +149,15 @@ func readToken(stream *lexerStream, state lexerState, functions map[string]Expre
if unicode.IsLetter(character) {

tokenString = readTokenUntilFalse(stream, isVariableName)

meta = tokenString
tokenValue = tokenString
kind = VARIABLE

// boolean?
if tokenValue == "true" {
if tokenValue == "true" || tokenValue == "false" {

kind = BOOLEAN
tokenValue = true
} else {

if tokenValue == "false" {

kind = BOOLEAN
tokenValue = false
}
tokenValue = tokenValue == "true"
}

// textual operator?
Expand Down Expand Up @@ -205,6 +205,7 @@ func readToken(stream *lexerStream, state lexerState, functions map[string]Expre

if !isNotQuote(character) {
tokenValue, completed = readUntilFalse(stream, true, false, true, isNotQuote)
meta = tokenValue

if !completed {
return ExpressionToken{}, errors.New("Unclosed string literal"), false
Expand All @@ -225,19 +226,24 @@ func readToken(stream *lexerStream, state lexerState, functions map[string]Expre
}

if character == '(' {

meta = "("
tokenValue = character
kind = CLAUSE
break
}

if character == ')' {

meta = ")"
tokenValue = character
kind = CLAUSE_CLOSE
break
}

// must be a known symbol
tokenString = readTokenUntilFalse(stream, isNotAlphanumeric)
meta = tokenString
tokenValue = tokenString

// quick hack for the case where "-" can mean "prefixed negation" or "minus", which are used
Expand Down Expand Up @@ -284,6 +290,7 @@ func readToken(stream *lexerStream, state lexerState, functions map[string]Expre

ret.Kind = kind
ret.Value = tokenValue
ret.Meta = meta

return ret, nil, (kind != UNKNOWN)
}
Expand Down

0 comments on commit 4a3eade

Please sign in to comment.