// Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package operators defines the internal function names of operators. // // All operators in the expression language are modelled as function calls. package operators // String "names" for CEL operators. const ( // Symbolic operators. Conditional = "_?_:_" LogicalAnd = "_&&_" LogicalOr = "_||_" LogicalNot = "!_" Equals = "_==_" NotEquals = "_!=_" Less = "_<_" LessEquals = "_<=_" Greater = "_>_" GreaterEquals = "_>=_" Add = "_+_" Subtract = "_-_" Multiply = "_*_" Divide = "_/_" Modulo = "_%_" Negate = "-_" Index = "_[_]" OptIndex = "_[?_]" OptSelect = "_?._" // Macros, must have a valid identifier. Has = "has" All = "all" Exists = "exists" ExistsOne = "exists_one" Map = "map" Filter = "filter" // Named operators, must not have be valid identifiers. NotStrictlyFalse = "@not_strictly_false" In = "@in" // Deprecated: named operators with valid identifiers. OldNotStrictlyFalse = "__not_strictly_false__" OldIn = "_in_" ) var ( operators = map[string]string{ "+": Add, "/": Divide, "==": Equals, ">": Greater, ">=": GreaterEquals, "in": In, "<": Less, "<=": LessEquals, "%": Modulo, "*": Multiply, "!=": NotEquals, "-": Subtract, } // operatorMap of the operator symbol which refers to a struct containing the display name, // if applicable, the operator precedence, and the arity. // // If the symbol does not have a display name listed in the map, it is only because it requires // special casing to render properly as text. operatorMap = map[string]struct { displayName string precedence int arity int }{ Conditional: {displayName: "", precedence: 8, arity: 3}, LogicalOr: {displayName: "||", precedence: 7, arity: 2}, LogicalAnd: {displayName: "&&", precedence: 6, arity: 2}, Equals: {displayName: "==", precedence: 5, arity: 2}, Greater: {displayName: ">", precedence: 5, arity: 2}, GreaterEquals: {displayName: ">=", precedence: 5, arity: 2}, In: {displayName: "in", precedence: 5, arity: 2}, Less: {displayName: "<", precedence: 5, arity: 2}, LessEquals: {displayName: "<=", precedence: 5, arity: 2}, NotEquals: {displayName: "!=", precedence: 5, arity: 2}, OldIn: {displayName: "in", precedence: 5, arity: 2}, Add: {displayName: "+", precedence: 4, arity: 2}, Subtract: {displayName: "-", precedence: 4, arity: 2}, Divide: {displayName: "/", precedence: 3, arity: 2}, Modulo: {displayName: "%", precedence: 3, arity: 2}, Multiply: {displayName: "*", precedence: 3, arity: 2}, LogicalNot: {displayName: "!", precedence: 2, arity: 1}, Negate: {displayName: "-", precedence: 2, arity: 1}, Index: {displayName: "", precedence: 1, arity: 2}, OptIndex: {displayName: "", precedence: 1, arity: 2}, OptSelect: {displayName: "", precedence: 1, arity: 2}, } ) // Find the internal function name for an operator, if the input text is one. func Find(text string) (string, bool) { op, found := operators[text] return op, found } // FindReverse returns the unmangled, text representation of the operator. func FindReverse(symbol string) (string, bool) { op, found := operatorMap[symbol] if !found { return "", false } return op.displayName, true } // FindReverseBinaryOperator returns the unmangled, text representation of a binary operator. // // If the symbol does refer to an operator, but the operator does not have a display name the // result is false. func FindReverseBinaryOperator(symbol string) (string, bool) { op, found := operatorMap[symbol] if !found || op.arity != 2 { return "", false } if op.displayName == "" { return "", false } return op.displayName, true } // Precedence returns the operator precedence, where the higher the number indicates // higher precedence operations. func Precedence(symbol string) int { op, found := operatorMap[symbol] if !found { return 0 } return op.precedence } // Arity returns the number of argument the operator takes // -1 is returned if an undefined symbol is provided func Arity(symbol string) int { op, found := operatorMap[symbol] if !found { return -1 } return op.arity }