cel-cr

Common Expression Language Interpreter in Crystal

cel-cr

Crystal port of https://github.com/cel-rust/cel-rust

A Common Expression Language (CEL) parser and interpreter for Crystal. CEL is a non-Turing complete language designed for simplicity, speed, safety, and portability.

Source of truth: cel-rust v0.13.0 (vendored at vendor/cel-rust/)

Installation

  1. Add the dependency to your shard.yml:

    dependencies:
      cel-cr:
        github: dsisnero/cel-cr
      lrama:
        github: dsisnero/lrama.cr
    
  2. Run shards install

  3. Generate the parser:

    crystal run lib/lrama/src/lrama/main.cr -- src/cel/parser/cel.y -o src/cel/parser/cel_parser.cr
    

Quick Start

require "cel-cr"
require "cel/parser/cel_parser"

# Simple arithmetic
program = Cel::Program.compile("1 + 2 * 3")
result = program.execute(Cel::Context.default)
puts result  # => 7

# With variables
ctx = Cel::Context.default
ctx.add_variable_from_value("x", 42_i64)
ctx.add_variable_from_value("str", "hello")

program = Cel::Program.compile("x > 40 && str.size() == 5")
puts program.execute(ctx).as_bool  # => true

# Map variables and field access
ctx.add_value("foo", Cel::Value.map({
  "bar" => Cel::Value.int(1_i64),
}))
program = Cel::Program.compile("foo.bar == 1")
puts program.execute(ctx).as_bool  # => true

What CEL Looks Like

// Check whether a resource name starts with a group name.
resource.name.startsWith("/groups/" + auth.claims.group)
// Determine whether the request is in the permitted time window.
request.time - resource.age < duration("24h")
// Check whether all resource names in a list match a given filter.
auth.claims.email_verified && resources.all(r, r.startsWith(auth.claims.email))
// These all work in cel-cr:
Cel::Program.compile("resource.name.startsWith('/groups/')")
Cel::Program.compile("[1, 2, 3].exists(v, v > 2)")
Cel::Program.compile("{'a': 1, 'b': 2}.a == 1")

Features

Feature Status
Core types (10 CEL types) Done
Full CEL parser (LALR) Done
Expression evaluation Done
Short-circuit &&, || Done
15 built-in functions Done
Macro expansion (has, exists, all) Done
Comprehension evaluation Done
JSON serialization Done
Duration parsing Done
Cross-type numeric ops Done
User-defined functions Done
Variable scoping Done

Built-in Functions

size, contains, startsWith, endsWith, max, min, matches, duration, string, int, uint, double, bytes, optional.of, optional.none

Macros

has(foo.bar), [1,2,3].exists(v, v > 2), [1,2,3].all(v, v > 0)

Documentation

  • Architecture — Module map, design decisions, dependency table
  • Development — Setup, build, quality gates, upstream update flow
  • Coding Guidelines — Porting rules, numeric widths, error handling
  • Testing — Spec patterns, parity testing, snapshot conventions
  • PR Workflow — Commit format, review checklist, drift checks
  • Changelog — Release history and feature log

Upstream README Highlights

The upstream cel-rust is a Rust implementation of CEL using ANTLR4 for parsing. cel-cr replaces ANTLR with a lrama.cr LALR parser generator while preserving full expression semantics.

See the parity plan for module-by-module tracking and the inventory for the full port ledger (669 items across 11 features).

Contributing

  1. Fork it (https://github.com/dsisnero/cel-cr/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'port: Add some feature')
  4. Run quality gates: make format && make lint && make test
  5. Push to the branch (git push origin my-new-feature)
  6. Create a new Pull Request

License

MIT — see LICENSE

Contributors

Repository

cel-cr

Owner
Statistic
  • 0
  • 0
  • 0
  • 0
  • 2
  • about 7 hours ago
  • June 8, 2026
License

MIT License

Links
Synced at

Mon, 08 Jun 2026 20:41:42 GMT

Languages