Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ Native-image and package behavior must be verified in the consuming application'
prove Quarkus native-image or package compatibility for every application.

Before using CEL conditions in release-critical authorization paths, run JVM condition tests, the
consuming project's normal build, dependency tree review for protobuf/ANTLR/Jackson conflicts, and
consuming project's normal build, dependency tree review for protobuf/Jackson conflicts, and
package/native-image verification if native execution is part of the release path.

### Not yet implemented
Expand Down
1 change: 0 additions & 1 deletion bom/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ plugins {
dependencies {
constraints {
api(project(":cel-core"))
api(project(":cel-generated-antlr"))
api(project(":cel-generated-pb"))
api(project(":cel-generated-pb3"))
api(project(":cel-conformance"))
Expand Down
1 change: 0 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ idea.project.settings {
afterSync(
":cel-generated-pb:jar",
":cel-generated-pb:testJar",
":cel-generated-antlr:shadowJar",
)
}
}
Expand Down
51 changes: 50 additions & 1 deletion core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,17 @@ plugins {
`java-test-fixtures`
}

val congocc = configurations.create("congocc")

configurations.named("jmhImplementation") { extendsFrom(configurations.testFixturesApi.get()) }

dependencies {
implementation(project(":cel-generated-antlr"))
compileOnly(project(":cel-generated-pb"))

implementation(libs.agrona)

congocc(libs.congocc)

testImplementation(project(":cel-generated-pb"))
testFixturesApi(platform(libs.junit.bom))
testFixturesApi(libs.bundles.junit.testing)
Expand All @@ -46,13 +49,59 @@ dependencies {
jmhAnnotationProcessor(libs.jmh.generator.annprocess)
}

abstract class Generate : JavaExec() {
init {
outputs.cacheIf { true }
}

@get:InputDirectory
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val sourceDir: DirectoryProperty

@get:OutputDirectory abstract val outputDir: DirectoryProperty
}

val generateCelGrammar =
tasks.register<Generate>("generateCelGrammar") {
val generatedDir = layout.buildDirectory.dir("generated/sources/congocc/cel")
val projectDir = layout.projectDirectory

sourceDir = projectDir.dir("src/main/congocc/cel")
outputDir = generatedDir

classpath(congocc)
mainClass = "org.congocc.app.Main"
workingDir(projectDir)

doFirst { generatedDir.get().asFile.deleteRecursively() }

argumentProviders.add(
CommandLineArgumentProvider {
val sourceFile = sourceDir.file("cel-java.ccc").get().asFile.relativeTo(projectDir.asFile)
val base =
listOf(
"-d",
generatedDir.get().asFile.toString(),
"-jdk17",
"-n",
sourceFile.toString(),
)
if (logger.isInfoEnabled) base else base + "-q"
}
)
}

jmh { jmhVersion.set(libs.versions.jmh.get()) }

sourceSets.main { java.srcDir(generateCelGrammar) }

sourceSets.test {
java.srcDir(layout.buildDirectory.dir("generated/source/proto/test/java"))
java.destinationDirectory.set(layout.buildDirectory.dir("classes/java/generatedTest"))
}

tasks.named("compileJava") { dependsOn(generateCelGrammar) }

tasks.named("check") { dependsOn(tasks.named("jmh")) }

tasks.named("assemble") { dependsOn(tasks.named("jmhJar")) }
151 changes: 151 additions & 0 deletions core/src/main/congocc/cel/cel-java.ccc
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*
* Copyright (C) 2026 The Authors of CEL-Java
*
* 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.
*/

PARSER_PACKAGE="org.projectnessie.cel.parser";
PARSER_CLASS=CelGrammarParser;
LEXER_CLASS=CelGrammarLexer;
NODE_PACKAGE="org.projectnessie.cel.parser.ast";

INCLUDE "cel.ccc"

INJECT PARSER_CLASS :
{
private boolean nextTokenStartsExpression() {
TokenType type = getToken(1).getType();
return switch (type) {
case LBRACKET, LBRACE, LPAREN, DOT, MINUS, EXCLAM, TRUE, FALSE, NULL, NUM_UINT, NUM_FLOAT,
NUM_INT, STRING, BYTES, IDENTIFIER -> true;
default -> false;
};
}
}

INJECT ParseException :
{
@SuppressWarnings("unchecked")
public java.util.Set<Token.TokenType> getExpectedTokenTypes() {
java.util.Set x = expectedTypes;
return x;
}
}

INJECT Expr : implements CelExprNode;
INJECT Expr :
{
@Override
public com.google.api.expr.v1alpha1.Expr toCelExpr(CelExprBuilder builder) {
return builder.visitExpr(this);
}
}

INJECT ConditionalOr : implements CelExprNode;
INJECT ConditionalOr :
{
@Override
public com.google.api.expr.v1alpha1.Expr toCelExpr(CelExprBuilder builder) {
return builder.visitBalanced(this, org.projectnessie.cel.common.operators.Operator.LogicalOr);
}
}

INJECT ConditionalAnd : implements CelExprNode;
INJECT ConditionalAnd :
{
@Override
public com.google.api.expr.v1alpha1.Expr toCelExpr(CelExprBuilder builder) {
return builder.visitBalanced(this, org.projectnessie.cel.common.operators.Operator.LogicalAnd);
}
}

INJECT Relation : implements CelExprNode;
INJECT Relation :
{
@Override
public com.google.api.expr.v1alpha1.Expr toCelExpr(CelExprBuilder builder) {
return builder.visitBinary(this);
}
}

INJECT Calc : implements CelExprNode;
INJECT Calc :
{
@Override
public com.google.api.expr.v1alpha1.Expr toCelExpr(CelExprBuilder builder) {
return builder.visitBinary(this);
}
}

INJECT Multiplicative : implements CelExprNode;
INJECT Multiplicative :
{
@Override
public com.google.api.expr.v1alpha1.Expr toCelExpr(CelExprBuilder builder) {
return builder.visitBinary(this);
}
}

INJECT Unary : implements CelExprNode;
INJECT Unary :
{
@Override
public com.google.api.expr.v1alpha1.Expr toCelExpr(CelExprBuilder builder) {
return builder.visitUnary(this);
}
}

INJECT Member : implements CelExprNode;
INJECT Member :
{
@Override
public com.google.api.expr.v1alpha1.Expr toCelExpr(CelExprBuilder builder) {
return builder.visitMember(this);
}
}

INJECT Primary : implements CelExprNode;
INJECT Primary :
{
@Override
public com.google.api.expr.v1alpha1.Expr toCelExpr(CelExprBuilder builder) {
return builder.visitPrimary(this);
}
}

INJECT ConstantLiteral : implements CelExprNode;
INJECT ConstantLiteral :
{
@Override
public com.google.api.expr.v1alpha1.Expr toCelExpr(CelExprBuilder builder) {
return builder.visitLiteral(this);
}
}

INJECT Literal : implements CelExprNode;
INJECT Literal :
{
@Override
public com.google.api.expr.v1alpha1.Expr toCelExpr(CelExprBuilder builder) {
return builder.visitLiteral(this);
}
}

INJECT Identifier : implements CelExprNode;
INJECT Identifier :
{
@Override
public com.google.api.expr.v1alpha1.Expr toCelExpr(CelExprBuilder builder) {
return builder.visitIdentifier(this);
}
}
84 changes: 84 additions & 0 deletions core/src/main/congocc/cel/cel-lexer.ccc
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright (C) 2026 The Authors of CEL-Java
*
* 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.
*/

SKIP : <WHITESPACE : (" " | "\t" | "\r" | "\n" | "\f")+> #Whitespace;

UNPARSED : <COMMENT : "//" (~["\n"])*> #Comment;

TOKEN #Operator :
<EQUALS : "==">
| <NOT_EQUALS : "!=">
| <LESS_EQUALS : "<=">
| <GREATER_EQUALS : ">=">
| <LOGICAL_AND : "&&">
| <LOGICAL_OR : "||">
| <IN : "in">
| <LESS : "<">
| <GREATER : ">">
| <LBRACKET : "[">
| <RBRACKET : "]">
| <LBRACE : "{">
| <RBRACE : "}">
| <LPAREN : "(">
| <RPAREN : ")">
| <DOT : ".">
| <COMMA : ",">
| <MINUS : "-">
| <EXCLAM : "!">
| <QUESTIONMARK : "?">
| <COLON : ":">
| <PLUS : "+">
| <STAR : "*">
| <SLASH : "/">
| <PERCENT : "%">
;

TOKEN #Literal :
<TRUE : "true">
| <FALSE : "false">
| <NULL : "null">
| <#HEXDIGIT : ["0"-"9", "a"-"f", "A"-"F"]>
| <#DIGIT : ["0"-"9"]>
| <#EXPONENT : ["e", "E"] (["+", "-"])? (<DIGIT>)+>
| <NUM_UINT : ((<DIGIT>)+ | "0x" (<HEXDIGIT>)+) ["u", "U"]>
| <NUM_FLOAT : ((<DIGIT>)+ "." (<DIGIT>)+ (<EXPONENT>)? | (<DIGIT>)+ <EXPONENT> | "." (<DIGIT>)+ (<EXPONENT>)?)>
| <NUM_INT : (<DIGIT>)+ | "0x" (<HEXDIGIT>)+>
| <#ESC_CHAR_SEQ : "\\" ["a", "b", "f", "n", "r", "t", "v", "\"", "'", "\\", "?", "`"]>
| <#ESC_OCT_SEQ : "\\" ["0"-"3"] ["0"-"7"] ["0"-"7"]>
| <#ESC_BYTE_SEQ : "\\" ["x", "X"] <HEXDIGIT> <HEXDIGIT>>
| <#ESC_UNI_SEQ : "\\" "u" <HEXDIGIT> <HEXDIGIT> <HEXDIGIT> <HEXDIGIT> | "\\" "U" <HEXDIGIT> <HEXDIGIT> <HEXDIGIT> <HEXDIGIT> <HEXDIGIT> <HEXDIGIT> <HEXDIGIT> <HEXDIGIT>>
| <#ESC_SEQ : <ESC_CHAR_SEQ> | <ESC_BYTE_SEQ> | <ESC_UNI_SEQ> | <ESC_OCT_SEQ>>
| <#DQ_CHAR : <ESC_SEQ> | ~["\\", "\"", "\n", "\r"]>
| <#SQ_CHAR : <ESC_SEQ> | ~["\\", "'", "\n", "\r"]>
| <#TDQ_CHAR : <ESC_SEQ> | ~["\\"]>
| <#TSQ_CHAR : <ESC_SEQ> | ~["\\"]>
| <STRING :
"\"" (<DQ_CHAR>)* "\""
| "'" (<SQ_CHAR>)* "'"
| "\"\"\"" (<TDQ_CHAR>)* "\"\"\""
| "'''" (<TSQ_CHAR>)* "'''"
| ["r", "R"] "\"" (~["\"", "\n", "\r"])* "\""
| ["r", "R"] "'" (~["'", "\n", "\r"])* "'"
| ["r", "R"] "\"\"\"" (~[])* "\"\"\""
| ["r", "R"] "'''" (~[])* "'''"
>
| <BYTES : ["b", "B"] <STRING>>
;

TOKEN #Identifier :
<IDENTIFIER : ["A"-"Z", "a"-"z", "_"] (["A"-"Z", "a"-"z", "0"-"9", "_"])*>
| <ESC_IDENTIFIER : "`" (<ESC_SEQ> | ~["\\", "`", "\n", "\r"])* "`">
;
Loading
Loading