cel-cr
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
-
Add the dependency to your
shard.yml:dependencies: cel-cr: github: dsisnero/cel-cr lrama: github: dsisnero/lrama.cr -
Run
shards install -
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
- Fork it (https://github.com/dsisnero/cel-cr/fork)
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'port: Add some feature') - Run quality gates:
make format && make lint && make test - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request
License
MIT — see LICENSE
Contributors
- Dominic Sisneros — creator and maintainer
cel-cr
- 0
- 0
- 0
- 0
- 2
- about 7 hours ago
- June 8, 2026
MIT License
Mon, 08 Jun 2026 20:41:42 GMT