Пример #1
0
func EvaluateUnaryExpr(expr *ast.UnaryExpr, context *Context) ast.Value {
	var val ast.Value = nil

	switch t := expr.Expr.(type) {
	case *ast.BinaryExpr:
		val = EvaluateBinaryExpr(t, context)
	case *ast.UnaryExpr:
		val = EvaluateUnaryExpr(t, context)
	case *ast.Variable:
		if varVal, ok := context.GetVariable(t.Name); ok {
			val = varVal.(ast.Expr)
		}
	default:
		val = ast.Value(t)
	}

	switch expr.Op.Type {
	case ast.T_NOP:
		// do nothing
	case ast.T_LOGICAL_NOT:
		if bVal, ok := val.(ast.BooleanValue); ok {
			val = ast.NewBoolean(bVal.Boolean())
		}
	case ast.T_MINUS:
		switch n := val.(type) {
		case *ast.Number:
			n.Value = -n.Value
		}
	}
	return val
}
Пример #2
0
/*
EvaluateBinaryExpr recursively.
*/
func EvaluateBinaryExpr(expr *ast.BinaryExpr, context *Context) ast.Value {
	var lval ast.Value = nil
	var rval ast.Value = nil

	switch expr := expr.Left.(type) {

	case *ast.BinaryExpr:
		lval = EvaluateBinaryExpr(expr, context)

	case *ast.UnaryExpr:
		lval = EvaluateUnaryExpr(expr, context)

	case *ast.Variable:
		if varVal, ok := context.GetVariable(expr.Name); ok {
			lval = varVal.(ast.Expr)
		}

	default:
		lval = ast.Value(expr)
	}

	switch expr := expr.Right.(type) {

	case *ast.UnaryExpr:
		rval = EvaluateUnaryExpr(expr, context)

	case *ast.BinaryExpr:
		rval = EvaluateBinaryExpr(expr, context)

	case *ast.Variable:
		if varVal, ok := context.GetVariable(expr.Name); ok {
			rval = varVal.(ast.Expr)
		}

	default:
		rval = ast.Value(expr)
	}

	if lval != nil && rval != nil {
		return Compute(expr.Op, lval, rval)
	}
	return nil
}
Пример #3
0
/*
EvaluateExpr calls EvaluateBinaryExpr. except EvaluateExpr
prevents calculate css slash as division.  otherwise it's the same as
EvaluateBinaryExpr.
*/
func EvaluateExpr(expr ast.Expr, context *Context) ast.Value {

	switch t := expr.(type) {

	case *ast.BinaryExpr:
		// For binary expression that is a CSS slash, we evaluate the expression as a literal string (unquoted)
		if t.IsCssSlash() {
			// return string object without quote
			return ast.NewString(0, t.Left.(*ast.Number).String()+"/"+t.Right.(*ast.Number).String(), nil)
		}
		return EvaluateBinaryExpr(t, context)

	case *ast.UnaryExpr:
		return EvaluateUnaryExpr(t, context)

	default:
		return ast.Value(expr)

	}

}
Пример #4
0
func EvaluateUnaryExprInBooleanContext(expr *ast.UnaryExpr, context *Context) ast.Value {
	var val ast.Value = nil

	switch t := expr.Expr.(type) {
	case *ast.BinaryExpr:
		val = EvaluateBinaryExpr(t, context)
	case *ast.UnaryExpr:
		val = EvaluateUnaryExpr(t, context)
	default:
		val = ast.Value(t)
	}

	switch expr.Op.Type {
	case ast.T_LOGICAL_NOT:
		if bval, ok := val.(ast.BooleanValue); ok {
			return ast.NewBoolean(bval.Boolean())
		} else {
			panic(fmt.Errorf("BooleanValue interface is not support for %+v", val))
		}
	}
	return val
}