Skip to content

CEL Specification#

This page summarizes the canonical CEL specification. Refer to the official specification for authoritative details.

Grammar#

CEL expressions follow this grammar. Operator precedence is encoded in the production hierarchy, from lowest (conditional) to highest (primary).

Notation#

The grammar uses Extended Backus-Naur Form (EBNF):

Notation Meaning
= Definition
| Alternation
[] Optional (zero or one)
{} Repetition (zero or more)
() Grouping
"x" Terminal string
UPPER Terminal (token)
Lower Non-terminal (production)

Expressions#

An expression is a conditional, which may include a ternary operator.

Expr = ConditionalOr [ "?" ConditionalOr ":" Expr ] ;

Logical operators#

Logical OR has lower precedence than logical AND.

ConditionalOr  = ConditionalAnd { "||" ConditionalAnd } ;
ConditionalAnd = Relation { "&&" Relation } ;

Relational operators#

Comparison and membership operators.

Relation = Addition { Relop Addition } ;
Relop    = "<" | "<=" | ">=" | ">" | "==" | "!=" | "in" ;

Arithmetic operators#

Addition and subtraction have lower precedence than multiplication.

Addition       = Multiplication { ( "+" | "-" ) Multiplication } ;
Multiplication = Unary { ( "*" | "/" | "%" ) Unary } ;

Negation#

Negation and logical NOT.

Unary = Member
      | "!" { "!" } Member
      | "-" { "-" } Member
      ;

Member access#

Field access, indexing, and method calls.

Member = Primary
       | Member "." IDENT [ "(" [ ExprList ] ")" ]
       | Member "[" Expr "]"
       ;

Primary expressions#

Literals, identifiers, parenthesized expressions, and constructors.

Primary = [ "." ] IDENT [ "(" [ ExprList ] ")" ]
        | "(" Expr ")"
        | "[" [ ExprList ] [ "," ] "]"
        | "{" [ MapInits ] [ "," ] "}"
        | [ "." ] IDENT { "." IDENT } "{" [ FieldInits ] [ "," ] "}"
        | LITERAL
        ;
ExprList   = Expr { "," Expr } ;
FieldInits = IDENT ":" Expr { "," IDENT ":" Expr } ;
MapInits   = Expr ":" Expr { "," Expr ":" Expr } ;

Terminals#

IDENT   = letter { letter | digit | "_" } ;
LITERAL = int_lit | uint_lit | float_lit | string_lit | bytes_lit
        | "true" | "false" | "null"
        ;

Reserved words#

as         break      const      continue   else       false
for        function   if         import     in         let
loop       namespace  null       package    return     true
var        void       while

Literals#

int_lit    = DIGIT { DIGIT } | "0x" HEXDIGIT { HEXDIGIT } ;
uint_lit   = int_lit ( "u" | "U" ) ;
float_lit  = DIGIT { DIGIT } "." { DIGIT } [ EXPONENT ]
           | DIGIT { DIGIT } EXPONENT
           | "." DIGIT { DIGIT } [ EXPONENT ]
           ;
EXPONENT   = ( "e" | "E" ) [ "+" | "-" ] DIGIT { DIGIT } ;
string_lit = [ "r" | "R" ] ( RAW_STRING | ESCAPED_STRING ) ;
bytes_lit  = ( "b" | "B" ) string_lit ;

RAW_STRING     = "'" { CHAR } "'" | '"' { CHAR } '"'
               | "'''" { CHAR } "'''" | '"""' { CHAR } '"""'
               ;
ESCAPED_STRING = "'" { CHAR | ESCAPE } "'" | '"' { CHAR | ESCAPE } '"'
               | "'''" { CHAR | ESCAPE } "'''" | '"""' { CHAR | ESCAPE } '"""'
               ;
ESCAPE         = "\" ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | "\" | "'" | '"' | "`" )
               | "\" "x" HEXDIGIT HEXDIGIT
               | "\" "u" HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT
               | "\" "U" HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT
               | "\" OCTALDIGIT OCTALDIGIT OCTALDIGIT
               ;
CHAR       = <any Unicode code point> ;
DIGIT      = "0" ... "9" ;
HEXDIGIT   = "0" ... "9" | "a" ... "f" | "A" ... "F" ;
OCTALDIGIT = "0" ... "7" ;

Comments and whitespace#

CEL supports single-line comments starting with // and extending to the end of the line.

Whitespace (spaces, tabs, carriage returns, newlines) separates tokens but is otherwise ignored. Comments and whitespace may appear anywhere between tokens.

Conformance#

The conformance test suite verifies implementations against the specification.

See also#