Documentation
¶
Overview ¶
Package parser declares an expression parser with support for macro expansion.
Index ¶
- Constants
- Variables
- func MakeAll(eh ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error)
- func MakeExists(eh ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error)
- func MakeExistsOne(eh ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error)
- func MakeFilter(eh ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error)
- func MakeHas(eh ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error)
- func MakeMap(eh ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error)
- func Parse(source common.Source) (*exprpb.ParsedExpr, *common.Errors)deprecated
- func Unparse(expr *exprpb.Expr, info *exprpb.SourceInfo) (string, error)
- type ExprHelper
- type Macro
- func NewGlobalMacro(function string, argCount int, expander MacroExpander) Macro
- func NewGlobalVarArgMacro(function string, expander MacroExpander) Macro
- func NewReceiverMacro(function string, argCount int, expander MacroExpander) Macro
- func NewReceiverVarArgMacro(function string, expander MacroExpander) Macro
- type MacroExpander
- type Option
- func ErrorRecoveryLimit(limit int) Option
- func ErrorRecoveryLookaheadTokenLimit(limit int) Option
- func ExpressionSizeCodePointLimit(expressionSizeCodePointLimit int) Option
- func Macros(macros ...Macro) Option
- func MaxRecursionDepth(limit int) Option
- func PopulateMacroCalls(populateMacroCalls bool) Option
- type Parser
Constants ¶
const AccumulatorName = "__result__"
AccumulatorName is the traditional variable name assigned to the fold accumulator variable.
Variables ¶
var ( // HasMacro expands "has(m.f)" which tests the presence of a field, avoiding the need to // specify the field as a string. HasMacro = NewGlobalMacro(operators.Has, 1, MakeHas) // AllMacro expands "range.all(var, predicate)" into a comprehension which ensures that all // elements in the range satisfy the predicate. AllMacro = NewReceiverMacro(operators.All, 2, MakeAll) // ExistsMacro expands "range.exists(var, predicate)" into a comprehension which ensures that // some element in the range satisfies the predicate. ExistsMacro = NewReceiverMacro(operators.Exists, 2, MakeExists) // ExistsOneMacro expands "range.exists_one(var, predicate)", which is true if for exactly one // element in range the predicate holds. ExistsOneMacro = NewReceiverMacro(operators.ExistsOne, 2, MakeExistsOne) // MapMacro expands "range.map(var, function)" into a comprehension which applies the function // to each element in the range to produce a new list. MapMacro = NewReceiverMacro(operators.Map, 2, MakeMap) // MapFilterMacro expands "range.map(var, predicate, function)" into a comprehension which // first filters the elements in the range by the predicate, then applies the transform function // to produce a new list. MapFilterMacro = NewReceiverMacro(operators.Map, 3, MakeMap) // FilterMacro expands "range.filter(var, predicate)" into a comprehension which filters // elements in the range, producing a new list from the elements that satisfy the predicate. FilterMacro = NewReceiverMacro(operators.Filter, 2, MakeFilter) // AllMacros includes the list of all spec-supported macros. AllMacros = []Macro{ HasMacro, AllMacro, ExistsMacro, ExistsOneMacro, MapMacro, MapFilterMacro, FilterMacro, } // NoMacros list. NoMacros = []Macro{} )
Functions ¶
func MakeAll ¶ added in v0.12.0
MakeExists expands the input call arguments into a comprehension that returns true if all of the elements in the range match the predicate expressions: <iterRange>.all(<iterVar>, <predicate>)
func MakeExists ¶ added in v0.12.0
func MakeExists(eh ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error)
MakeExists expands the input call arguments into a comprehension that returns true if any of the elements in the range match the predicate expressions: <iterRange>.exists(<iterVar>, <predicate>)
func MakeExistsOne ¶ added in v0.12.0
func MakeExistsOne(eh ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error)
MakeExistsOne expands the input call arguments into a comprehension that returns true if exactly one of the elements in the range match the predicate expressions: <iterRange>.exists_one(<iterVar>, <predicate>)
func MakeFilter ¶ added in v0.12.0
func MakeFilter(eh ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error)
MakeFilter expands the input call arguments into a comprehension which produces a list which contains only elements which match the provided predicate expression: <iterRange>.filter(<iterVar>, <predicate>)
func MakeHas ¶ added in v0.12.0
MakeHas expands the input call arguments into a presence test, e.g. has(<operand>.field)
func MakeMap ¶ added in v0.12.0
MakeMap expands the input call arguments into a comprehension that transforms each element in the input to produce an output list.
There are two call patterns supported by map:
<iterRange>.map(<iterVar>, <transform>) <iterRange>.map(<iterVar>, <predicate>, <transform>)
In the second form only iterVar values which return true when provided to the predicate expression are transformed.
func Unparse ¶ added in v0.3.0
Unparse takes an input expression and source position information and generates a human-readable expression.
Note, unparsing an AST will often generate the same expression as was originally parsed, but some formatting may be lost in translation, notably:
- All quoted literals are doubled quoted. - Byte literals are represented as octal escapes (same as Google SQL). - Floating point values are converted to the small number of digits needed to represent the value. - Spacing around punctuation marks may be lost. - Parentheses will only be applied when they affect operator precedence.
Types ¶
type ExprHelper ¶
type ExprHelper interface {
// LiteralBool creates an Expr value for a bool literal.
LiteralBool(value bool) *exprpb.Expr
// LiteralBytes creates an Expr value for a byte literal.
LiteralBytes(value []byte) *exprpb.Expr
// LiteralDouble creates an Expr value for double literal.
LiteralDouble(value float64) *exprpb.Expr
// LiteralInt creates an Expr value for an int literal.
LiteralInt(value int64) *exprpb.Expr
// LiteralString creates am Expr value for a string literal.
LiteralString(value string) *exprpb.Expr
// LiteralUint creates an Expr value for a uint literal.
LiteralUint(value uint64) *exprpb.Expr
// NewList creates a CreateList instruction where the list is comprised of the optional set
// of elements provided as arguments.
NewList(elems ...*exprpb.Expr) *exprpb.Expr
// NewMap creates a CreateStruct instruction for a map where the map is comprised of the
// optional set of key, value entries.
NewMap(entries ...*exprpb.Expr_CreateStruct_Entry) *exprpb.Expr
// NewMapEntry creates a Map Entry for the key, value pair.
NewMapEntry(key *exprpb.Expr, val *exprpb.Expr) *exprpb.Expr_CreateStruct_Entry
// NewObject creates a CreateStruct instruction for an object with a given type name and
// optional set of field initializers.
NewObject(typeName string, fieldInits ...*exprpb.Expr_CreateStruct_Entry) *exprpb.Expr
// NewObjectFieldInit creates a new Object field initializer from the field name and value.
NewObjectFieldInit(field string, init *exprpb.Expr) *exprpb.Expr_CreateStruct_Entry
// Fold creates a fold comprehension instruction.
//
// - iterVar is the iteration variable name.
// - iterRange represents the expression that resolves to a list or map where the elements or
// keys (respectively) will be iterated over.
// - accuVar is the accumulation variable name, typically parser.AccumulatorName.
// - accuInit is the initial expression whose value will be set for the accuVar prior to
// folding.
// - condition is the expression to test to determine whether to continue folding.
// - step is the expression to evaluation at the conclusion of a single fold iteration.
// - result is the computation to evaluate at the conclusion of the fold.
//
// The accuVar should not shadow variable names that you would like to reference within the
// environment in the step and condition expressions. Presently, the name __result__ is commonly
// used by built-in macros but this may change in the future.
Fold(iterVar string,
iterRange *exprpb.Expr,
accuVar string,
accuInit *exprpb.Expr,
condition *exprpb.Expr,
step *exprpb.Expr,
result *exprpb.Expr) *exprpb.Expr
// Ident creates an identifier Expr value.
Ident(name string) *exprpb.Expr
// AccuIdent returns an accumulator identifier for use with comprehension results.
AccuIdent() *exprpb.Expr
// GlobalCall creates a function call Expr value for a global (free) function.
GlobalCall(function string, args ...*exprpb.Expr) *exprpb.Expr
// ReceiverCall creates a function call Expr value for a receiver-style function.
ReceiverCall(function string, target *exprpb.Expr, args ...*exprpb.Expr) *exprpb.Expr
// PresenceTest creates a Select TestOnly Expr value for modelling has() semantics.
PresenceTest(operand *exprpb.Expr, field string) *exprpb.Expr
// Select create a field traversal Expr value.
Select(operand *exprpb.Expr, field string) *exprpb.Expr
// OffsetLocation returns the Location of the expression identifier.
OffsetLocation(exprID int64) common.Location
}
ExprHelper assists with the manipulation of proto-based Expr values in a manner which is consistent with the source position and expression id generation code leveraged by both the parser and type-checker.
type Macro ¶
type Macro interface {
// Function name to match.
Function() string
// ArgCount for the function call.
//
// When the macro is a var-arg style macro, the return value will be zero, but the MacroKey
// will contain a `*` where the arg count would have been.
ArgCount() int
// IsReceiverStyle returns true if the macro matches a receiver style call.
IsReceiverStyle() bool
// MacroKey returns the macro signatures accepted by this macro.
//
// Format: `<function>:<arg-count>:<is-receiver>`.
//
// When the macros is a var-arg style macro, the `arg-count` value is represented as a `*`.
MacroKey() string
// Expander returns the MacroExpander to apply when the macro key matches the parsed call
// signature.
Expander() MacroExpander
}
Macro interface for describing the function signature to match and the MacroExpander to apply.
Note: when a Macro should apply to multiple overloads (based on arg count) of a given function, a Macro should be created per arg-count.
func NewGlobalMacro ¶
func NewGlobalMacro(function string, argCount int, expander MacroExpander) Macro
NewGlobalMacro creates a Macro for a global function with the specified arg count.
func NewGlobalVarArgMacro ¶
func NewGlobalVarArgMacro(function string, expander MacroExpander) Macro
NewGlobalVarArgMacro creates a Macro for a global function with a variable arg count.
func NewReceiverMacro ¶
func NewReceiverMacro(function string, argCount int, expander MacroExpander) Macro
NewReceiverMacro creates a Macro for a receiver function matching the specified arg count.
func NewReceiverVarArgMacro ¶
func NewReceiverVarArgMacro(function string, expander MacroExpander) Macro
NewReceiverVarArgMacro creates a Macro for a receiver function matching a variable arg count.
type MacroExpander ¶
type MacroExpander func(eh ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error)
MacroExpander converts a call and its associated arguments into a new CEL abstract syntax tree, or an error if the input arguments are not suitable for the expansion requirements for the macro in question.
The MacroExpander accepts as arguments a MacroExprHelper as well as the arguments used in the function call and produces as output an Expr ast node.
Note: when the Macro.IsReceiverStyle() method returns true, the target argument will be nil.
type Option ¶ added in v0.8.0
type Option func(*options) error
Option configures the behavior of the parser.
func ErrorRecoveryLimit ¶ added in v0.8.0
ErrorRecoveryLimit limits the number of attempts the parser will perform to recover from an error.
func ErrorRecoveryLookaheadTokenLimit ¶ added in v0.8.0
ErrorRecoveryLookaheadTokenLimit limits the number of lexer tokens that may be considered during error recovery.
Error recovery often involves looking ahead in the input to determine if there's a point at which parsing may successfully resume. In some pathological cases, the parser can look through quite a large set of input which in turn generates a lot of back-tracking and performance degredation.
The limit must be > 1, and is recommended to be less than the default of 256.
func ExpressionSizeCodePointLimit ¶ added in v0.8.0
ExpressionSizeCodePointLimit is an option which limits the maximum code point count of an expression.
func MaxRecursionDepth ¶ added in v0.8.0
MaxRecursionDepth limits the maximum depth the parser will attempt to parse the expression before giving up.
func PopulateMacroCalls ¶ added in v0.9.0
PopulateMacroCalls ensures that the original call signatures replaced by expanded macros are preserved in the `SourceInfo` of parse result.