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
17 changes: 14 additions & 3 deletions sql/src/main/java/io/cloudevents/sql/ParseException.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
public class ParseException extends RuntimeException {

public enum ErrorKind {
RECOGNITION_ERROR,
PARSE_VALUE
RECOGNITION,
PARSE_VALUE,
CONSTANT_EXPRESSION_EVALUATION,
}

private final ErrorKind errorKind;
Expand Down Expand Up @@ -49,12 +50,22 @@ public static ParseException cannotParseValue(ParseTree node, Type target, Throw

public static ParseException recognitionError(RecognitionException e, String msg) {
return new ParseException(
ErrorKind.RECOGNITION_ERROR,
ErrorKind.RECOGNITION,
new Interval(e.getOffendingToken().getStartIndex(), e.getOffendingToken().getStopIndex()),
e.getOffendingToken().getText(),
"Cannot parse: " + msg,
e
);
}

public static ParseException cannotEvaluateConstantExpression(EvaluationException exception) {
return new ParseException(
ErrorKind.CONSTANT_EXPRESSION_EVALUATION,
exception.getExpressionInterval(),
exception.getExpressionText(),
"Cannot evaluate the constant expression: " + exception.getExpressionText(),
exception
);
}

}
15 changes: 15 additions & 0 deletions sql/src/main/java/io/cloudevents/sql/Parser.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.cloudevents.sql;

import io.cloudevents.sql.impl.ParserBuilder;
import io.cloudevents.sql.impl.ParserImpl;

public interface Parser {
Expand All @@ -24,4 +25,18 @@ static Expression parseDefault(String inputExpression) throws ParseException {
return ParserImpl.getInstance().parse(inputExpression);
}

/**
* @return the default instance of the parser
*/
static Parser getDefault() {
return ParserImpl.getInstance();
}

/**
* @return a new {@link ParserBuilder}, to create a customized parser instance
*/
static ParserBuilder builder() {
return new ParserBuilder();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package io.cloudevents.sql.impl;

import io.cloudevents.SpecVersion;
import io.cloudevents.sql.EvaluationRuntime;
import io.cloudevents.sql.impl.expressions.*;

public class ConstantFoldingExpressionVisitor implements ExpressionInternalVisitor<ExpressionInternal> {

@Override
public ExpressionInternal visitExpressionInternal(ExpressionInternal expressionInternal) {
return expressionInternal;
}

@Override
public ExpressionInternal visitBaseBinaryExpression(BaseBinaryExpression baseBinaryExpression) {
ExpressionInternal left = baseBinaryExpression.getLeftOperand().visit(this);
ExpressionInternal right = baseBinaryExpression.getRightOperand().visit(this);

if (left instanceof ValueExpression && right instanceof ValueExpression) {
// I can do constant folding!
return new ValueExpression(
baseBinaryExpression.expressionInterval(),
baseBinaryExpression.expressionText(),
baseBinaryExpression.evaluate(
EvaluationRuntime.getDefault(),
((ValueExpression) left).getValue(),
((ValueExpression) right).getValue(),
FailFastExceptionThrower.getInstance()
)
);
}

baseBinaryExpression.setLeftOperand(left);
baseBinaryExpression.setRightOperand(right);
return baseBinaryExpression;
}

@Override
public ExpressionInternal visitExistsExpression(ExistsExpression existsExpression) {
if (SpecVersion.V1.getMandatoryAttributes().contains(existsExpression.getKey())) {
// If the attribute is a mandatory attribute of the spec, there's no need to check it
return new ValueExpression(existsExpression.expressionInterval(), existsExpression.expressionText(), true);
}
return existsExpression;
}

@Override
public ExpressionInternal visitBaseUnaryExpression(BaseUnaryExpression baseUnaryExpression) {
ExpressionInternal inner = baseUnaryExpression.getOperand().visit(this);

if (inner instanceof ValueExpression) {
return new ValueExpression(
baseUnaryExpression.expressionInterval(),
baseUnaryExpression.expressionText(),
baseUnaryExpression.evaluate(EvaluationRuntime.getDefault(), ((ValueExpression) inner).getValue(), FailFastExceptionThrower.getInstance())
);
}

baseUnaryExpression.setOperand(inner);
return baseUnaryExpression;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
import java.util.ArrayList;
import java.util.List;

class ExceptionsStore implements ExceptionThrower {
class ExceptionStore implements ExceptionThrower {

private List<EvaluationException> exceptions;

ExceptionsStore() {
ExceptionStore() {
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.cloudevents.sql.EvaluationRuntime;
import io.cloudevents.sql.Expression;
import io.cloudevents.sql.Result;
import io.cloudevents.sql.impl.expressions.ExpressionInternal;

public class ExpressionImpl implements Expression {

Expand All @@ -16,7 +17,7 @@ public ExpressionImpl(ExpressionInternal expressionInternal) {

@Override
public Result evaluate(EvaluationRuntime evaluationRuntime, CloudEvent event) {
ExceptionsStore exceptions = new ExceptionsStore();
ExceptionStore exceptions = new ExceptionStore();
Object value = this.expressionInternal.evaluate(evaluationRuntime, event, exceptions);
return new EvaluationResult(value, exceptions.getExceptions());
}
Expand All @@ -25,4 +26,8 @@ public Result evaluate(EvaluationRuntime evaluationRuntime, CloudEvent event) {
public Object tryEvaluate(EvaluationRuntime evaluationRuntime, CloudEvent event) throws EvaluationException {
return this.expressionInternal.evaluate(evaluationRuntime, event, FailFastExceptionThrower.getInstance());
}

protected ExpressionInternal getExpressionInternal() {
return expressionInternal;
}
}
30 changes: 30 additions & 0 deletions sql/src/main/java/io/cloudevents/sql/impl/ParserBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.cloudevents.sql.impl;

import io.cloudevents.sql.Parser;

public class ParserBuilder {

private boolean constantFolding;

public ParserBuilder() {
this.constantFolding = true;
}

/**
* Disable constant folding when parsing.
*
* @return this
*/
public ParserBuilder disableConstantFolding() {
this.constantFolding = false;
return this;
}

/**
* @return the new {@link Parser}
*/
public Parser build() {
return new ParserImpl(this.constantFolding);
}

}
19 changes: 16 additions & 3 deletions sql/src/main/java/io/cloudevents/sql/impl/ParserImpl.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package io.cloudevents.sql.impl;

import io.cloudevents.sql.EvaluationException;
import io.cloudevents.sql.Expression;
import io.cloudevents.sql.ParseException;
import io.cloudevents.sql.Parser;
import io.cloudevents.sql.generated.CESQLParserLexer;
import io.cloudevents.sql.generated.CESQLParserParser;
import io.cloudevents.sql.impl.expressions.ExpressionInternal;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.ATNConfigSet;
import org.antlr.v4.runtime.dfa.DFA;
Expand All @@ -17,17 +19,20 @@
public class ParserImpl implements Parser {

private static class SingletonContainer {
private final static ParserImpl INSTANCE = new ParserImpl();
private final static ParserImpl INSTANCE = new ParserImpl(true);
}

/**
* @return instance of {@link ParserImpl}
* @return default instance of {@link ParserImpl}
*/
public static Parser getInstance() {
return ParserImpl.SingletonContainer.INSTANCE;
}

public ParserImpl() {
private final boolean constantFolding;

ParserImpl(boolean constantFolding) {
this.constantFolding = constantFolding;
}

@Override
Expand Down Expand Up @@ -72,6 +77,14 @@ public void reportContextSensitivity(org.antlr.v4.runtime.Parser recognizer, DFA

ExpressionInternal internal = new ExpressionTranslatorVisitor().visit(tree);

if (this.constantFolding) {
try {
internal = internal.visit(new ConstantFoldingExpressionVisitor());
} catch (EvaluationException e) {
throw ParseException.cannotEvaluateConstantExpression(e);
}
}

return new ExpressionImpl(internal);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,9 @@ public Object evaluate(EvaluationRuntime runtime, CloudEvent event, ExceptionThr
return CloudEventUtils.accessContextAttribute(thrower, expressionInterval(), expressionText(), event, key);
}

@Override
public <T> T visit(ExpressionInternalVisitor<T> visitor) {
return visitor.visitAccessAttributeExpression(this);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import io.cloudevents.sql.EvaluationRuntime;
import io.cloudevents.sql.impl.ExceptionThrower;
import io.cloudevents.sql.impl.ExpressionInternal;
import org.antlr.v4.runtime.misc.Interval;

public class AndExpression extends BaseBinaryExpression {
Expand All @@ -12,7 +11,7 @@ public AndExpression(Interval expressionInterval, String expressionText, Express
}

@Override
Object evaluate(EvaluationRuntime runtime, Object left, Object right, ExceptionThrower exceptions) {
public Object evaluate(EvaluationRuntime runtime, Object left, Object right, ExceptionThrower exceptions) {
boolean x = castToBoolean(runtime, exceptions, left);
if (!x) {
// Short circuit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,48 @@
import io.cloudevents.CloudEvent;
import io.cloudevents.sql.EvaluationRuntime;
import io.cloudevents.sql.impl.ExceptionThrower;
import io.cloudevents.sql.impl.ExpressionInternal;
import org.antlr.v4.runtime.misc.Interval;

public abstract class BaseBinaryExpression extends BaseExpression {

protected final ExpressionInternal leftOperand;
protected final ExpressionInternal rightOperand;
protected ExpressionInternal leftOperand;
protected ExpressionInternal rightOperand;

protected BaseBinaryExpression(Interval expressionInterval, String expressionText, ExpressionInternal leftOperand, ExpressionInternal rightOperand) {
super(expressionInterval, expressionText);
this.leftOperand = leftOperand;
this.rightOperand = rightOperand;
}

abstract Object evaluate(EvaluationRuntime runtime, Object left, Object right, ExceptionThrower exceptions);
public abstract Object evaluate(EvaluationRuntime runtime, Object left, Object right, ExceptionThrower exceptions);

@Override
public Object evaluate(EvaluationRuntime runtime, CloudEvent event, ExceptionThrower thrower) {
Object left = leftOperand.evaluate(runtime, event, thrower);
Object right = rightOperand.evaluate(runtime, event, thrower);
return evaluate(runtime, left, right, thrower);
}

@Override
public <T> T visit(ExpressionInternalVisitor<T> visitor) {
return visitor.visitBaseBinaryExpression(this);
}

public ExpressionInternal getLeftOperand() {
return leftOperand;
}

public ExpressionInternal getRightOperand() {
return rightOperand;
}

public BaseBinaryExpression setLeftOperand(ExpressionInternal leftOperand) {
this.leftOperand = leftOperand;
return this;
}

public BaseBinaryExpression setRightOperand(ExpressionInternal rightOperand) {
this.rightOperand = rightOperand;
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import io.cloudevents.sql.Type;
import io.cloudevents.sql.impl.EvaluationContextImpl;
import io.cloudevents.sql.impl.ExceptionThrower;
import io.cloudevents.sql.impl.ExpressionInternal;
import org.antlr.v4.runtime.misc.Interval;

public abstract class BaseExpression implements ExpressionInternal {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import io.cloudevents.sql.EvaluationRuntime;
import io.cloudevents.sql.impl.ExceptionThrower;
import io.cloudevents.sql.impl.ExpressionInternal;
import org.antlr.v4.runtime.misc.Interval;

public abstract class BaseIntegerBinaryExpression extends BaseBinaryExpression {
Expand All @@ -14,7 +13,7 @@ public BaseIntegerBinaryExpression(Interval expressionInterval, String expressio
abstract Object evaluate(EvaluationRuntime runtime, int left, int right, ExceptionThrower exceptions);

@Override
Object evaluate(EvaluationRuntime runtime, Object left, Object right, ExceptionThrower exceptions) {
public Object evaluate(EvaluationRuntime runtime, Object left, Object right, ExceptionThrower exceptions) {
return this.evaluate(
runtime,
castToInteger(runtime, exceptions, left).intValue(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.cloudevents.sql.impl.expressions;

import io.cloudevents.CloudEvent;
import io.cloudevents.sql.EvaluationRuntime;
import io.cloudevents.sql.impl.ExceptionThrower;
import org.antlr.v4.runtime.misc.Interval;

public abstract class BaseUnaryExpression extends BaseExpression {

protected ExpressionInternal internal;

public BaseUnaryExpression(Interval expressionInterval, String expressionText, ExpressionInternal internal) {
super(expressionInterval, expressionText);
this.internal = internal;
}

public abstract Object evaluate(EvaluationRuntime runtime, Object value, ExceptionThrower exceptions);

@Override
public Object evaluate(EvaluationRuntime runtime, CloudEvent event, ExceptionThrower thrower) {
return evaluate(runtime, internal.evaluate(runtime, event, thrower), thrower);
}

@Override
public <T> T visit(ExpressionInternalVisitor<T> visitor) {
return visitor.visitBaseUnaryExpression(this);
}

public ExpressionInternal getOperand() {
return internal;
}

public BaseUnaryExpression setOperand(ExpressionInternal internal) {
this.internal = internal;
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import io.cloudevents.sql.EvaluationRuntime;
import io.cloudevents.sql.impl.ExceptionThrower;
import io.cloudevents.sql.impl.ExpressionInternal;
import org.antlr.v4.runtime.misc.Interval;

public class DifferenceExpression extends BaseIntegerBinaryExpression {
Expand Down
Loading