Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom operator can use external context ! #499

Merged
merged 1 commit into from
May 1, 2020
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
*/
package com.mitchellbosecke.pebble.extension.core;

import static com.mitchellbosecke.pebble.operator.BinaryOperatorType.FILTER;
import static com.mitchellbosecke.pebble.operator.BinaryOperatorType.NORMAL;
import static com.mitchellbosecke.pebble.operator.BinaryOperatorType.TEST;

import com.mitchellbosecke.pebble.extension.AbstractExtension;
import com.mitchellbosecke.pebble.extension.Filter;
import com.mitchellbosecke.pebble.extension.Function;
Expand Down Expand Up @@ -55,7 +59,6 @@
import com.mitchellbosecke.pebble.tokenParser.ParallelTokenParser;
import com.mitchellbosecke.pebble.tokenParser.SetTokenParser;
import com.mitchellbosecke.pebble.tokenParser.TokenParser;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -97,26 +100,26 @@ public List<UnaryOperator> getUnaryOperators() {
@Override
public List<BinaryOperator> getBinaryOperators() {
List<BinaryOperator> operators = new ArrayList<>();
operators.add(new BinaryOperatorImpl("or", 10, OrExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("and", 15, AndExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("is", 20, PositiveTestExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("is not", 20, NegativeTestExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("contains", 20, ContainsExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("==", 30, EqualsExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("equals", 30, EqualsExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("!=", 30, NotEqualsExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl(">", 30, GreaterThanExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("<", 30, LessThanExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl(">=", 30, GreaterThanEqualsExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("<=", 30, LessThanEqualsExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("+", 40, AddExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("-", 40, SubtractExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("*", 60, MultiplyExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("/", 60, DivideExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("%", 60, ModulusExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("|", 100, FilterExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("~", 110, ConcatenateExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("..", 120, RangeExpression.class, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("or", 10, OrExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("and", 15, AndExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("is", 20, PositiveTestExpression::new, TEST, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("is not", 20, NegativeTestExpression::new, TEST, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("contains", 20, ContainsExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("==", 30, EqualsExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("equals", 30, EqualsExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("!=", 30, NotEqualsExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl(">", 30, GreaterThanExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("<", 30, LessThanExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl(">=", 30, GreaterThanEqualsExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("<=", 30, LessThanEqualsExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("+", 40, AddExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("-", 40, SubtractExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("*", 60, MultiplyExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("/", 60, DivideExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("%", 60, ModulusExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("|", 100, FilterExpression::new, FILTER, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("~", 110, ConcatenateExpression::new, NORMAL, Associativity.LEFT));
operators.add(new BinaryOperatorImpl("..", 120, RangeExpression::new, NORMAL, Associativity.LEFT));

return operators;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ public interface BinaryOperator {

String getSymbol();

Class<? extends BinaryExpression<?>> getNodeClass();
BinaryExpression<?> getInstance();

BinaryOperatorType getType();

Associativity getAssociativity();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,51 @@
*/
package com.mitchellbosecke.pebble.operator;

import com.mitchellbosecke.pebble.error.PebbleException;
import com.mitchellbosecke.pebble.node.expression.BinaryExpression;
import com.mitchellbosecke.pebble.node.expression.FilterExpression;
import com.mitchellbosecke.pebble.node.expression.NegativeTestExpression;
import com.mitchellbosecke.pebble.node.expression.PositiveTestExpression;
import java.util.function.Supplier;

public class BinaryOperatorImpl implements BinaryOperator {

private final int precedence;

private final String symbol;

private final Class<? extends BinaryExpression<?>> nodeClass;
private final Supplier<? extends BinaryExpression<?>> nodeSupplier;

private final BinaryOperatorType type;

private final Associativity associativity;

/**
* This constuctor left for backward compatibility with custom extensions
*/
public BinaryOperatorImpl(String symbol, int precedence,
Class<? extends BinaryExpression<?>> nodeClass,
Associativity associativity) {
this(symbol, precedence, () -> {
try {
return nodeClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new PebbleException(e, "Error instantiating class " + nodeClass.getName());
}
}, getDefaultType(nodeClass), associativity);
}

/**
* This constuctor allows you to completely control the instantiation of the expression class
*/
public BinaryOperatorImpl(String symbol, int precedence,
Supplier<? extends BinaryExpression<?>> nodeSupplier,
BinaryOperatorType type,
Associativity associativity) {
this.symbol = symbol;
this.precedence = precedence;
this.nodeClass = nodeClass;
this.nodeSupplier = nodeSupplier;
this.type = type;
this.associativity = associativity;
}

Expand All @@ -40,12 +67,28 @@ public String getSymbol() {
}

@Override
public Class<? extends BinaryExpression<?>> getNodeClass() {
return this.nodeClass;
public BinaryExpression<?> getInstance() {
return this.nodeSupplier.get();
}

@Override
public BinaryOperatorType getType() {
return this.type;
}

@Override
public Associativity getAssociativity() {
return this.associativity;
}

private static BinaryOperatorType getDefaultType(Class<? extends BinaryExpression<?>> nodeClass) {
if (FilterExpression.class.equals(nodeClass)) {
return BinaryOperatorType.FILTER;
} else if (PositiveTestExpression.class.equals(nodeClass) || NegativeTestExpression.class
.equals(nodeClass)) {
return BinaryOperatorType.TEST;
} else {
return BinaryOperatorType.NORMAL;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.mitchellbosecke.pebble.operator;

public enum BinaryOperatorType {
NORMAL, FILTER, TEST
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import com.mitchellbosecke.pebble.node.expression.ConcatenateExpression;
import com.mitchellbosecke.pebble.node.expression.ContextVariableExpression;
import com.mitchellbosecke.pebble.node.expression.Expression;
import com.mitchellbosecke.pebble.node.expression.FilterExpression;
import com.mitchellbosecke.pebble.node.expression.FilterInvocationExpression;
import com.mitchellbosecke.pebble.node.expression.FunctionOrMacroInvocationExpression;
import com.mitchellbosecke.pebble.node.expression.GetAttributeExpression;
Expand All @@ -33,13 +32,12 @@
import com.mitchellbosecke.pebble.node.expression.LiteralNullExpression;
import com.mitchellbosecke.pebble.node.expression.LiteralStringExpression;
import com.mitchellbosecke.pebble.node.expression.MapExpression;
import com.mitchellbosecke.pebble.node.expression.NegativeTestExpression;
import com.mitchellbosecke.pebble.node.expression.ParentFunctionExpression;
import com.mitchellbosecke.pebble.node.expression.PositiveTestExpression;
import com.mitchellbosecke.pebble.node.expression.TernaryExpression;
import com.mitchellbosecke.pebble.node.expression.UnaryExpression;
import com.mitchellbosecke.pebble.operator.Associativity;
import com.mitchellbosecke.pebble.operator.BinaryOperator;
import com.mitchellbosecke.pebble.operator.BinaryOperatorType;
import com.mitchellbosecke.pebble.operator.UnaryOperator;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -177,13 +175,12 @@ else if (token.test(Token.Type.PUNCTUATION, "{")) {

// the right hand expression of the FILTER operator is handled in a
// unique way
if (FilterExpression.class.equals(operator.getNodeClass())) {
if (operator.getType() == BinaryOperatorType.FILTER) {
expressionRight = this.parseFilterInvocationExpression();
}
// the right hand expression of TEST operators is handled in a
// unique way
else if (PositiveTestExpression.class.equals(operator.getNodeClass())
|| NegativeTestExpression.class.equals(operator.getNodeClass())) {
else if (operator.getType() == BinaryOperatorType.TEST) {
expressionRight = this.parseTestInvocationExpression();
} else {
/*
Expand All @@ -201,16 +198,16 @@ else if (PositiveTestExpression.class.equals(operator.getNodeClass())
* expression we are creating.
*/
BinaryExpression<?> finalExpression;
Class<? extends BinaryExpression<?>> operatorNodeClass = operator.getNodeClass();

try {
finalExpression = operatorNodeClass.newInstance();
finalExpression.setLineNumber(this.stream.current().getLineNumber());
} catch (InstantiationException | IllegalAccessException e) {
finalExpression = operator.getInstance();
} catch (RuntimeException e) {
throw new ParserException(e,
"Error instantiating operator node [" + operatorNodeClass.getName() + "]",
"Error instantiating operator node",
token.getLineNumber(), this.stream.getFilename());
}

finalExpression.setLineNumber(this.stream.current().getLineNumber());
finalExpression.setLeft(expression);
finalExpression.setRight(expressionRight);

Expand Down Expand Up @@ -571,7 +568,7 @@ public ArgumentsNode parseArguments(boolean isMacroDefinition) {
throw new ParserException(null,
"Positional arguments must be declared before any named arguments.",
this.stream.current()
.getLineNumber(),
.getLineNumber(),
this.stream.getFilename());
}
positionalArgs.add(new PositionalArgumentNode(argumentValue));
Expand Down