From 16829d2def82d86178ab5e18ca5268736026ddd9 Mon Sep 17 00:00:00 2001 From: Sidhant Aggarwal <10743214+sidhant92@users.noreply.github.com> Date: Wed, 22 May 2024 14:07:43 +0530 Subject: [PATCH] add support for arithmetic functions --- .gitignore | 3 + build.gradle | 1 + .../ArithmeticExpressionEvaluator.java | 30 +- .../boolparser/constant/FunctionType.java | 28 + .../boolparser/constant/NodeType.java | 1 + .../arithmetic/ArithmeticFunctionNode.java | 30 + .../function/FunctionEvaluatorService.java | 50 ++ .../boolparser/function/FunctionFactory.java | 43 ++ .../function/arithmetic/AbstractFunction.java | 22 + .../function/arithmetic/AvgFunction.java | 47 ++ .../function/arithmetic/IntFunction.java | 42 ++ .../function/arithmetic/LenFunction.java | 37 ++ .../function/arithmetic/MaxFunction.java | 47 ++ .../function/arithmetic/MeanFunction.java | 42 ++ .../function/arithmetic/MedianFunction.java | 45 ++ .../function/arithmetic/MinFunction.java | 47 ++ .../function/arithmetic/ModeFunction.java | 40 ++ .../function/arithmetic/SumFunction.java | 47 ++ .../antlr/BooleanExpressionBaseListener.java | 24 + .../parser/antlr/BooleanExpressionLexer.java | 432 ++++++++------- .../antlr/BooleanExpressionListener.java | 22 + .../parser/antlr/BooleanExpressionParser.java | 517 +++++++++++------- .../parser/antlr/BooleanFilterListener.java | 38 +- .../sidhant92/boolparser/util/ValueUtils.java | 7 + src/main/java/resources/BooleanExpression.g4 | 22 + .../ArithmeticExpressionEvaluatorTest.java | 163 ++++++ .../BooleanExpressionEvaluatorTest.java | 24 + .../antlr/BooleanFilterBoolParserTest.java | 34 ++ 28 files changed, 1487 insertions(+), 398 deletions(-) create mode 100644 src/main/java/com/github/sidhant92/boolparser/constant/FunctionType.java create mode 100644 src/main/java/com/github/sidhant92/boolparser/domain/arithmetic/ArithmeticFunctionNode.java create mode 100644 src/main/java/com/github/sidhant92/boolparser/function/FunctionEvaluatorService.java create mode 100644 src/main/java/com/github/sidhant92/boolparser/function/FunctionFactory.java create mode 100644 src/main/java/com/github/sidhant92/boolparser/function/arithmetic/AbstractFunction.java create mode 100644 src/main/java/com/github/sidhant92/boolparser/function/arithmetic/AvgFunction.java create mode 100644 src/main/java/com/github/sidhant92/boolparser/function/arithmetic/IntFunction.java create mode 100644 src/main/java/com/github/sidhant92/boolparser/function/arithmetic/LenFunction.java create mode 100644 src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MaxFunction.java create mode 100644 src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MeanFunction.java create mode 100644 src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MedianFunction.java create mode 100644 src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MinFunction.java create mode 100644 src/main/java/com/github/sidhant92/boolparser/function/arithmetic/ModeFunction.java create mode 100644 src/main/java/com/github/sidhant92/boolparser/function/arithmetic/SumFunction.java diff --git a/.gitignore b/.gitignore index 3ba01b2..1098d81 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ out/ ` gradle.properties + +*.DS_Store +**/.DS_Store diff --git a/build.gradle b/build.gradle index a922788..05a46f0 100644 --- a/build.gradle +++ b/build.gradle @@ -37,6 +37,7 @@ dependencies { implementation 'io.vavr:vavr:0.10.4' implementation 'com.github.ben-manes.caffeine:caffeine:2.9.3' implementation 'org.projectlombok:lombok:1.18.26' + implementation 'org.apache.commons:commons-math3:3.6.1' annotationProcessor 'org.projectlombok:lombok:1.18.26' testAnnotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess:1.36' diff --git a/src/main/java/com/github/sidhant92/boolparser/application/ArithmeticExpressionEvaluator.java b/src/main/java/com/github/sidhant92/boolparser/application/ArithmeticExpressionEvaluator.java index a8bfa39..f74f160 100644 --- a/src/main/java/com/github/sidhant92/boolparser/application/ArithmeticExpressionEvaluator.java +++ b/src/main/java/com/github/sidhant92/boolparser/application/ArithmeticExpressionEvaluator.java @@ -1,7 +1,11 @@ package com.github.sidhant92.boolparser.application; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.Pair; import com.github.sidhant92.boolparser.constant.ContainerDataType; import com.github.sidhant92.boolparser.constant.DataType; @@ -11,7 +15,9 @@ import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticNode; import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticUnaryNode; import com.github.sidhant92.boolparser.domain.Node; +import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticFunctionNode; import com.github.sidhant92.boolparser.exception.UnsupportedToken; +import com.github.sidhant92.boolparser.function.FunctionEvaluatorService; import com.github.sidhant92.boolparser.operator.OperatorService; import com.github.sidhant92.boolparser.parser.BoolExpressionParser; import com.github.sidhant92.boolparser.util.ValueUtils; @@ -28,9 +34,12 @@ public class ArithmeticExpressionEvaluator { private final OperatorService operatorService; + private final FunctionEvaluatorService functionEvaluatorService; + public ArithmeticExpressionEvaluator(final BoolExpressionParser boolExpressionParser) { this.boolExpressionParser = boolExpressionParser; operatorService = new OperatorService(); + functionEvaluatorService = new FunctionEvaluatorService(); } public Try evaluate(final String expression, final Map data) { @@ -50,6 +59,8 @@ private Object evaluateToken(final Node node, final Map data) { return evaluateArithmeticLeafToken((ArithmeticLeafNode) node, data); case ARITHMETIC_UNARY: return evaluateUnaryArithmeticToken((ArithmeticUnaryNode) node, data); + case ARITHMETIC_FUNCTION: + return evaluateArithmeticFunctionToken((ArithmeticFunctionNode) node, data); case STRING: return evaluateStringToken((StringNode) node, data); default: @@ -63,7 +74,8 @@ private Object evaluateStringToken(final StringNode stringNode, final Map evaluateArithmeticLeafToken(final ArithmeticLeafNode arithmeticLeafNode, final Map data) { - final Optional fetchedValue = ValueUtils.getValueFromMap(arithmeticLeafNode.getOperand().toString(), data); + final Optional fetchedValue = arithmeticLeafNode.getDataType() != DataType.STRING ? Optional.of( + arithmeticLeafNode.getOperand()) : ValueUtils.getValueFromMap(arithmeticLeafNode.getOperand().toString(), data); return fetchedValue .map(o -> Pair.of(o, ValueUtils.getDataType(o))) .orElseGet(() -> Pair.of(arithmeticLeafNode.getOperand(), arithmeticLeafNode.getDataType())); @@ -80,6 +92,22 @@ private Object evaluateUnaryArithmeticToken(final ArithmeticUnaryNode arithmetic return operatorService.evaluateArithmeticOperator(resolvedValue, dataType, null, null, Operator.UNARY, ContainerDataType.PRIMITIVE); } + private Object evaluateArithmeticFunctionToken(final ArithmeticFunctionNode arithmeticFunctionNode, final Map data) { + final List> resolvedValues = arithmeticFunctionNode.getItems() + .stream() + .map(item -> evaluateArithmeticLeafToken(item, data)) + .collect(Collectors.toList()); + final List> flattenedValues = new ArrayList<>(); + resolvedValues.forEach(value -> { + if (value.getKey() instanceof Collection) { + ((Collection) value.getKey()).forEach(v -> flattenedValues.add(Pair.of(v, ValueUtils.getDataType(v)))); + } else { + flattenedValues.add(value); + } + }); + return functionEvaluatorService.evaluateArithmeticFunction(arithmeticFunctionNode.getFunctionType(), flattenedValues); + } + private Object evaluateArithmeticToken(final ArithmeticNode arithmeticNode, final Map data) { final Object leftValue = evaluateToken(arithmeticNode.getLeft(), data); final Object rightValue = evaluateToken(arithmeticNode.getRight(), data); diff --git a/src/main/java/com/github/sidhant92/boolparser/constant/FunctionType.java b/src/main/java/com/github/sidhant92/boolparser/constant/FunctionType.java new file mode 100644 index 0000000..cc731dd --- /dev/null +++ b/src/main/java/com/github/sidhant92/boolparser/constant/FunctionType.java @@ -0,0 +1,28 @@ +package com.github.sidhant92.boolparser.constant; + +import java.util.Arrays; +import java.util.Optional; + +/** + * @author sidhant.aggarwal + * @since 21/05/2024 + */ +public enum FunctionType { + MIN, + MAX, + AVG, + SUM, + MEAN, + MODE, + MEDIAN, + INT, + LEN; + + public static Optional getArrayFunctionFromSymbol(final String symbol) { + final String symbolUpperCase = symbol.toUpperCase(); + return Arrays + .stream(FunctionType.values()) + .filter(function -> function.name().equals(symbolUpperCase)) + .findFirst(); + } +} diff --git a/src/main/java/com/github/sidhant92/boolparser/constant/NodeType.java b/src/main/java/com/github/sidhant92/boolparser/constant/NodeType.java index 53b98f7..567d666 100644 --- a/src/main/java/com/github/sidhant92/boolparser/constant/NodeType.java +++ b/src/main/java/com/github/sidhant92/boolparser/constant/NodeType.java @@ -14,5 +14,6 @@ public enum NodeType { ARITHMETIC, ARITHMETIC_LEAF, ARITHMETIC_UNARY, + ARITHMETIC_FUNCTION, STRING } diff --git a/src/main/java/com/github/sidhant92/boolparser/domain/arithmetic/ArithmeticFunctionNode.java b/src/main/java/com/github/sidhant92/boolparser/domain/arithmetic/ArithmeticFunctionNode.java new file mode 100644 index 0000000..111d90a --- /dev/null +++ b/src/main/java/com/github/sidhant92/boolparser/domain/arithmetic/ArithmeticFunctionNode.java @@ -0,0 +1,30 @@ +package com.github.sidhant92.boolparser.domain.arithmetic; + +import java.util.List; +import com.github.sidhant92.boolparser.constant.FunctionType; +import com.github.sidhant92.boolparser.constant.NodeType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +/** + * @author sidhant.aggarwal + * @since 21/05/2024 + */ +@AllArgsConstructor +@Getter +@Setter +@Builder +public class ArithmeticFunctionNode extends ArithmeticBaseNode { + private FunctionType functionType; + + + private final List items; + + + @Override + public NodeType getTokenType() { + return NodeType.ARITHMETIC_FUNCTION; + } +} diff --git a/src/main/java/com/github/sidhant92/boolparser/function/FunctionEvaluatorService.java b/src/main/java/com/github/sidhant92/boolparser/function/FunctionEvaluatorService.java new file mode 100644 index 0000000..4bdeac9 --- /dev/null +++ b/src/main/java/com/github/sidhant92/boolparser/function/FunctionEvaluatorService.java @@ -0,0 +1,50 @@ +package com.github.sidhant92.boolparser.function; + +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import com.github.sidhant92.boolparser.constant.ContainerDataType; +import com.github.sidhant92.boolparser.constant.DataType; +import com.github.sidhant92.boolparser.constant.FunctionType; +import com.github.sidhant92.boolparser.exception.InvalidContainerTypeException; +import com.github.sidhant92.boolparser.exception.InvalidDataType; +import com.github.sidhant92.boolparser.exception.InvalidExpressionException; +import com.github.sidhant92.boolparser.function.arithmetic.AbstractFunction; +import lombok.extern.slf4j.Slf4j; + +/** + * @author sidhant.aggarwal + * @since 21/05/2024 + */ +@Slf4j +public class FunctionEvaluatorService { + public FunctionEvaluatorService() { + FunctionFactory.initialize(); + } + + public Object evaluateArithmeticFunction(final FunctionType functionType, final List> items) { + final AbstractFunction abstractFunction = FunctionFactory.getArithmeticFunction(functionType); + if (items.isEmpty()) { + log.error("Empty items not allowed"); + throw new InvalidExpressionException(); + } + final ContainerDataType containerDataType = items.size() > 1 ? ContainerDataType.LIST : ContainerDataType.PRIMITIVE; + if (!abstractFunction.getAllowedContainerTypes().contains(containerDataType)) { + log.error("Invalid container type {} for function {}", containerDataType, functionType.name()); + throw new InvalidContainerTypeException(); + } + final boolean validDataType = items + .stream().allMatch(item -> abstractFunction.getAllowedDataTypes().contains(item.getValue())); + if (!validDataType) { + log.error("Invalid data type {} for function {}", items, functionType.name()); + throw new InvalidDataType(); + } + + items.forEach(item -> { + if (!ContainerDataType.PRIMITIVE.isValid(item.getValue(), item.getKey())) { + log.error("Validation failed for the function {} for the operand {}", functionType.name(), item.getKey()); + throw new InvalidDataType(); + } + }); + return abstractFunction.evaluate(items); + } +} diff --git a/src/main/java/com/github/sidhant92/boolparser/function/FunctionFactory.java b/src/main/java/com/github/sidhant92/boolparser/function/FunctionFactory.java new file mode 100644 index 0000000..201e337 --- /dev/null +++ b/src/main/java/com/github/sidhant92/boolparser/function/FunctionFactory.java @@ -0,0 +1,43 @@ +package com.github.sidhant92.boolparser.function; + +import java.util.EnumMap; +import java.util.Map; +import com.github.sidhant92.boolparser.constant.FunctionType; +import com.github.sidhant92.boolparser.function.arithmetic.AbstractFunction; +import com.github.sidhant92.boolparser.function.arithmetic.AvgFunction; +import com.github.sidhant92.boolparser.function.arithmetic.IntFunction; +import com.github.sidhant92.boolparser.function.arithmetic.LenFunction; +import com.github.sidhant92.boolparser.function.arithmetic.MaxFunction; +import com.github.sidhant92.boolparser.function.arithmetic.MeanFunction; +import com.github.sidhant92.boolparser.function.arithmetic.MedianFunction; +import com.github.sidhant92.boolparser.function.arithmetic.MinFunction; +import com.github.sidhant92.boolparser.function.arithmetic.ModeFunction; +import com.github.sidhant92.boolparser.function.arithmetic.SumFunction; + +/** + * @author sidhant.aggarwal + * @since 21/05/2024 + */ +public class FunctionFactory { + private static final Map arithmeticFunctionrMap = new EnumMap<>(FunctionType.class); + + private FunctionFactory() { + super(); + } + + public static void initialize() { + arithmeticFunctionrMap.put(FunctionType.MIN, new MinFunction()); + arithmeticFunctionrMap.put(FunctionType.MAX, new MaxFunction()); + arithmeticFunctionrMap.put(FunctionType.AVG, new AvgFunction()); + arithmeticFunctionrMap.put(FunctionType.SUM, new SumFunction()); + arithmeticFunctionrMap.put(FunctionType.MEAN, new MeanFunction()); + arithmeticFunctionrMap.put(FunctionType.MEDIAN, new MedianFunction()); + arithmeticFunctionrMap.put(FunctionType.MODE, new ModeFunction()); + arithmeticFunctionrMap.put(FunctionType.INT, new IntFunction()); + arithmeticFunctionrMap.put(FunctionType.LEN, new LenFunction()); + } + + public static AbstractFunction getArithmeticFunction(final FunctionType functionType) { + return arithmeticFunctionrMap.get(functionType); + } +} diff --git a/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/AbstractFunction.java b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/AbstractFunction.java new file mode 100644 index 0000000..098d05c --- /dev/null +++ b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/AbstractFunction.java @@ -0,0 +1,22 @@ +package com.github.sidhant92.boolparser.function.arithmetic; + +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import com.github.sidhant92.boolparser.constant.ContainerDataType; +import com.github.sidhant92.boolparser.constant.DataType; +import com.github.sidhant92.boolparser.constant.FunctionType; +import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticFunctionNode; + +/** + * @author sidhant.aggarwal + * @since 21/05/2024 + */ +public abstract class AbstractFunction { + public abstract Object evaluate(final List> items); + + public abstract FunctionType getFunctionType(); + + public abstract List getAllowedContainerTypes(); + + public abstract List getAllowedDataTypes(); +} diff --git a/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/AvgFunction.java b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/AvgFunction.java new file mode 100644 index 0000000..c2b492c --- /dev/null +++ b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/AvgFunction.java @@ -0,0 +1,47 @@ +package com.github.sidhant92.boolparser.function.arithmetic; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import com.github.sidhant92.boolparser.constant.ContainerDataType; +import com.github.sidhant92.boolparser.constant.DataType; +import com.github.sidhant92.boolparser.constant.FunctionType; +import com.github.sidhant92.boolparser.util.ValueUtils; + +/** + * @author sidhant.aggarwal + * @since 21/05/2024 + */ +public class AvgFunction extends AbstractFunction { + @Override + public Object evaluate(final List> items) { + if (items + .stream().anyMatch(a -> a.getValue().equals(DataType.DECIMAL))) { + return ValueUtils.caseDouble(items + .stream().mapToDouble(a -> Double.parseDouble(a.getKey().toString())).average().getAsDouble()); + } + if (items + .stream().anyMatch(a -> a.getValue().equals(DataType.LONG))) { + return ValueUtils.caseDouble(items + .stream().mapToLong(a -> Long.parseLong(a.getKey().toString())).average().getAsDouble()); + } + return ValueUtils.caseDouble(items + .stream().mapToInt(a -> Integer.parseInt(a.getKey().toString())).average().getAsDouble()); + } + + @Override + public FunctionType getFunctionType() { + return FunctionType.AVG; + } + + @Override + public List getAllowedContainerTypes() { + return Collections.singletonList(ContainerDataType.LIST); + } + + @Override + public List getAllowedDataTypes() { + return Arrays.asList(DataType.INTEGER, DataType.LONG, DataType.DECIMAL); + } +} diff --git a/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/IntFunction.java b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/IntFunction.java new file mode 100644 index 0000000..015c9ea --- /dev/null +++ b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/IntFunction.java @@ -0,0 +1,42 @@ +package com.github.sidhant92.boolparser.function.arithmetic; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import com.github.sidhant92.boolparser.constant.ContainerDataType; +import com.github.sidhant92.boolparser.constant.DataType; +import com.github.sidhant92.boolparser.constant.FunctionType; + +/** + * @author sidhant.aggarwal + * @since 21/05/2024 + */ +public class IntFunction extends AbstractFunction { + @Override + public Object evaluate(final List> items) { + final Pair item = items.get(0); + if (item.getValue() == DataType.DECIMAL) { + return ((Double) item.getKey()).intValue(); + } + if (item.getValue() == DataType.LONG) { + return ((Long) item.getKey()).intValue(); + } + return item.getKey(); + } + + @Override + public FunctionType getFunctionType() { + return FunctionType.INT; + } + + @Override + public List getAllowedContainerTypes() { + return Collections.singletonList(ContainerDataType.PRIMITIVE); + } + + @Override + public List getAllowedDataTypes() { + return Arrays.asList(DataType.INTEGER, DataType.LONG, DataType.DECIMAL); + } +} diff --git a/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/LenFunction.java b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/LenFunction.java new file mode 100644 index 0000000..4072fac --- /dev/null +++ b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/LenFunction.java @@ -0,0 +1,37 @@ +package com.github.sidhant92.boolparser.function.arithmetic; + +import java.util.Arrays; +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import com.github.sidhant92.boolparser.constant.ContainerDataType; +import com.github.sidhant92.boolparser.constant.DataType; +import com.github.sidhant92.boolparser.constant.FunctionType; + +/** + * @author sidhant.aggarwal + * @since 21/05/2024 + */ +public class LenFunction extends AbstractFunction { + @Override + public Object evaluate(final List> items) { + if (items.size() == 1 && items.get(0).getKey() instanceof String) { + return ((String) items.get(0).getKey()).length(); + } + return items.size(); + } + + @Override + public FunctionType getFunctionType() { + return FunctionType.LEN; + } + + @Override + public List getAllowedContainerTypes() { + return Arrays.asList(ContainerDataType.values()); + } + + @Override + public List getAllowedDataTypes() { + return Arrays.asList(DataType.values()); + } +} diff --git a/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MaxFunction.java b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MaxFunction.java new file mode 100644 index 0000000..b39b444 --- /dev/null +++ b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MaxFunction.java @@ -0,0 +1,47 @@ +package com.github.sidhant92.boolparser.function.arithmetic; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import com.github.sidhant92.boolparser.constant.ContainerDataType; +import com.github.sidhant92.boolparser.constant.DataType; +import com.github.sidhant92.boolparser.constant.FunctionType; +import com.github.sidhant92.boolparser.util.ValueUtils; + +/** + * @author sidhant.aggarwal + * @since 21/05/2024 + */ +public class MaxFunction extends AbstractFunction { + @Override + public Object evaluate(final List> items) { + if (items + .stream().anyMatch(a -> a.getValue().equals(DataType.DECIMAL))) { + return ValueUtils.caseDouble(items + .stream().mapToDouble(a -> Double.parseDouble(a.getKey().toString())).max().getAsDouble()); + } + if (items + .stream().anyMatch(a -> a.getValue().equals(DataType.LONG))) { + return ValueUtils.caseDouble(items + .stream().mapToLong(a -> Long.parseLong(a.getKey().toString())).max().getAsLong()); + } + return ValueUtils.caseDouble(items + .stream().mapToInt(a -> Integer.parseInt(a.getKey().toString())).max().getAsInt()); + } + + @Override + public FunctionType getFunctionType() { + return FunctionType.MAX; + } + + @Override + public List getAllowedContainerTypes() { + return Collections.singletonList(ContainerDataType.LIST); + } + + @Override + public List getAllowedDataTypes() { + return Arrays.asList(DataType.INTEGER, DataType.LONG, DataType.DECIMAL); + } +} diff --git a/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MeanFunction.java b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MeanFunction.java new file mode 100644 index 0000000..15cc927 --- /dev/null +++ b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MeanFunction.java @@ -0,0 +1,42 @@ +package com.github.sidhant92.boolparser.function.arithmetic; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.math3.stat.StatUtils; +import org.apache.commons.math3.stat.descriptive.moment.Mean; +import com.github.sidhant92.boolparser.constant.ContainerDataType; +import com.github.sidhant92.boolparser.constant.DataType; +import com.github.sidhant92.boolparser.constant.FunctionType; + +/** + * @author sidhant.aggarwal + * @since 21/05/2024 + */ +public class MeanFunction extends AbstractFunction { + @Override + public Object evaluate(final List> items) { + final double mean = StatUtils.mean(items + .stream().mapToDouble(a -> Double.parseDouble(a.getKey().toString())).toArray()); + if ((int) mean == mean) { + return (int) mean; + } + return mean; + } + + @Override + public FunctionType getFunctionType() { + return FunctionType.MEAN; + } + + @Override + public List getAllowedContainerTypes() { + return Collections.singletonList(ContainerDataType.LIST); + } + + @Override + public List getAllowedDataTypes() { + return Arrays.asList(DataType.INTEGER, DataType.LONG, DataType.DECIMAL); + } +} diff --git a/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MedianFunction.java b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MedianFunction.java new file mode 100644 index 0000000..477d924 --- /dev/null +++ b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MedianFunction.java @@ -0,0 +1,45 @@ +package com.github.sidhant92.boolparser.function.arithmetic; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.math3.stat.descriptive.rank.Median; +import com.github.sidhant92.boolparser.constant.ContainerDataType; +import com.github.sidhant92.boolparser.constant.DataType; +import com.github.sidhant92.boolparser.constant.FunctionType; +import com.github.sidhant92.boolparser.util.ValueUtils; + +/** + * @author sidhant.aggarwal + * @since 21/05/2024 + */ +public class MedianFunction extends AbstractFunction { + private final Median median; + + public MedianFunction() { + this.median = new Median(); + } + + @Override + public Object evaluate(final List> items) { + final double res = median.evaluate(items + .stream().mapToDouble(a -> Double.parseDouble(a.getKey().toString())).toArray()); + return ValueUtils.caseDouble(res); + } + + @Override + public FunctionType getFunctionType() { + return FunctionType.MEDIAN; + } + + @Override + public List getAllowedContainerTypes() { + return Collections.singletonList(ContainerDataType.LIST); + } + + @Override + public List getAllowedDataTypes() { + return Arrays.asList(DataType.INTEGER, DataType.LONG, DataType.DECIMAL); + } +} diff --git a/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MinFunction.java b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MinFunction.java new file mode 100644 index 0000000..959433e --- /dev/null +++ b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/MinFunction.java @@ -0,0 +1,47 @@ +package com.github.sidhant92.boolparser.function.arithmetic; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import com.github.sidhant92.boolparser.constant.ContainerDataType; +import com.github.sidhant92.boolparser.constant.DataType; +import com.github.sidhant92.boolparser.constant.FunctionType; +import com.github.sidhant92.boolparser.util.ValueUtils; + +/** + * @author sidhant.aggarwal + * @since 21/05/2024 + */ +public class MinFunction extends AbstractFunction { + @Override + public Object evaluate(final List> items) { + if (items + .stream().anyMatch(a -> a.getValue().equals(DataType.DECIMAL))) { + return ValueUtils.caseDouble(items + .stream().mapToDouble(a -> Double.parseDouble(a.getKey().toString())).min().getAsDouble()); + } + if (items + .stream().anyMatch(a -> a.getValue().equals(DataType.LONG))) { + return ValueUtils.caseDouble(items + .stream().mapToLong(a -> Long.parseLong(a.getKey().toString())).min().getAsLong()); + } + return ValueUtils.caseDouble(items + .stream().mapToInt(a -> Integer.parseInt(a.getKey().toString())).min().getAsInt()); + } + + @Override + public FunctionType getFunctionType() { + return FunctionType.MIN; + } + + @Override + public List getAllowedContainerTypes() { + return Collections.singletonList(ContainerDataType.LIST); + } + + @Override + public List getAllowedDataTypes() { + return Arrays.asList(DataType.INTEGER, DataType.LONG, DataType.DECIMAL); + } +} diff --git a/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/ModeFunction.java b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/ModeFunction.java new file mode 100644 index 0000000..313502b --- /dev/null +++ b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/ModeFunction.java @@ -0,0 +1,40 @@ +package com.github.sidhant92.boolparser.function.arithmetic; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.math3.stat.StatUtils; +import org.apache.commons.math3.stat.descriptive.moment.Mean; +import com.github.sidhant92.boolparser.constant.ContainerDataType; +import com.github.sidhant92.boolparser.constant.DataType; +import com.github.sidhant92.boolparser.constant.FunctionType; +import com.github.sidhant92.boolparser.util.ValueUtils; + +/** + * @author sidhant.aggarwal + * @since 21/05/2024 + */ +public class ModeFunction extends AbstractFunction { + @Override + public Object evaluate(final List> items) { + final double mode = StatUtils.mode(items + .stream().mapToDouble(a -> Double.parseDouble(a.getKey().toString())).toArray())[0]; + return ValueUtils.caseDouble(mode); + } + + @Override + public FunctionType getFunctionType() { + return FunctionType.MODE; + } + + @Override + public List getAllowedContainerTypes() { + return Collections.singletonList(ContainerDataType.LIST); + } + + @Override + public List getAllowedDataTypes() { + return Arrays.asList(DataType.INTEGER, DataType.LONG, DataType.DECIMAL); + } +} diff --git a/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/SumFunction.java b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/SumFunction.java new file mode 100644 index 0000000..077f436 --- /dev/null +++ b/src/main/java/com/github/sidhant92/boolparser/function/arithmetic/SumFunction.java @@ -0,0 +1,47 @@ +package com.github.sidhant92.boolparser.function.arithmetic; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import com.github.sidhant92.boolparser.constant.ContainerDataType; +import com.github.sidhant92.boolparser.constant.DataType; +import com.github.sidhant92.boolparser.constant.FunctionType; +import com.github.sidhant92.boolparser.util.ValueUtils; + +/** + * @author sidhant.aggarwal + * @since 21/05/2024 + */ +public class SumFunction extends AbstractFunction { + @Override + public Object evaluate(final List> items) { + if (items + .stream().anyMatch(a -> a.getValue().equals(DataType.DECIMAL))) { + return ValueUtils.caseDouble(items + .stream().mapToDouble(a -> Double.parseDouble(a.getKey().toString())).sum()); + } + if (items + .stream().anyMatch(a -> a.getValue().equals(DataType.LONG))) { + return ValueUtils.caseDouble(items + .stream().mapToLong(a -> Long.parseLong(a.getKey().toString())).sum()); + } + return ValueUtils.caseDouble(items + .stream().mapToInt(a -> Integer.parseInt(a.getKey().toString())).sum()); + } + + @Override + public FunctionType getFunctionType() { + return FunctionType.SUM; + } + + @Override + public List getAllowedContainerTypes() { + return Collections.singletonList(ContainerDataType.LIST); + } + + @Override + public List getAllowedDataTypes() { + return Arrays.asList(DataType.INTEGER, DataType.LONG, DataType.DECIMAL); + } +} diff --git a/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionBaseListener.java b/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionBaseListener.java index 17548d4..73b6c47 100644 --- a/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionBaseListener.java +++ b/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionBaseListener.java @@ -95,6 +95,18 @@ public class BooleanExpressionBaseListener implements BooleanExpressionListener *

The default implementation does nothing.

*/ @Override public void exitToExpression(BooleanExpressionParser.ToExpressionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterArithmeticFunctionExpression(BooleanExpressionParser.ArithmeticFunctionExpressionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitArithmeticFunctionExpression(BooleanExpressionParser.ArithmeticFunctionExpressionContext ctx) { } /** * {@inheritDoc} * @@ -167,6 +179,18 @@ public class BooleanExpressionBaseListener implements BooleanExpressionListener *

The default implementation does nothing.

*/ @Override public void exitArithmeticOperator(BooleanExpressionParser.ArithmeticOperatorContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterArrayArithmeticFunction(BooleanExpressionParser.ArrayArithmeticFunctionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitArrayArithmeticFunction(BooleanExpressionParser.ArrayArithmeticFunctionContext ctx) { } /** * {@inheritDoc} * diff --git a/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionLexer.java b/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionLexer.java index c943be8..d2c607a 100644 --- a/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionLexer.java +++ b/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionLexer.java @@ -17,10 +17,11 @@ public class BooleanExpressionLexer extends Lexer { new PredictionContextCache(); public static final int T__0=1, IN=2, TO=3, AND=4, OR=5, NOT=6, TRUE=7, FALSE=8, CONTAINS_ALL=9, - CONTAINS_ANY=10, ADD=11, SUBTRACT=12, MULTIPLY=13, DIVIDE=14, MODULUS=15, - EXPONENT=16, NE=17, GT=18, GE=19, LT=20, LE=21, EQ=22, LPAREN=23, RPAREN=24, - DECIMAL=25, APP_VERSION=26, INTEGER=27, WS=28, WORD=29, ALPHANUMERIC=30, - SQ=31, DQ=32; + CONTAINS_ANY=10, MIN=11, MAX=12, AVG=13, SUM=14, MEAN=15, MODE=16, MEDIAN=17, + LEN=18, INT=19, ADD=20, SUBTRACT=21, MULTIPLY=22, DIVIDE=23, MODULUS=24, + EXPONENT=25, NE=26, GT=27, GE=28, LT=29, LE=30, EQ=31, LPAREN=32, RPAREN=33, + DECIMAL=34, APP_VERSION=35, INTEGER=36, WS=37, WORD=38, ALPHANUMERIC=39, + SQ=40, DQ=41; public static String[] channelNames = { "DEFAULT_TOKEN_CHANNEL", "HIDDEN" }; @@ -32,7 +33,8 @@ public class BooleanExpressionLexer extends Lexer { private static String[] makeRuleNames() { return new String[] { "T__0", "IN", "TO", "AND", "OR", "NOT", "TRUE", "FALSE", "CONTAINS_ALL", - "CONTAINS_ANY", "ADD", "SUBTRACT", "MULTIPLY", "DIVIDE", "MODULUS", "EXPONENT", + "CONTAINS_ANY", "MIN", "MAX", "AVG", "SUM", "MEAN", "MODE", "MEDIAN", + "LEN", "INT", "ADD", "SUBTRACT", "MULTIPLY", "DIVIDE", "MODULUS", "EXPONENT", "NE", "GT", "GE", "LT", "LE", "EQ", "LPAREN", "RPAREN", "DECIMAL", "APP_VERSION", "INTEGER", "WS", "WORD", "ALPHANUMERIC", "SQ", "DQ" }; @@ -41,16 +43,18 @@ private static String[] makeRuleNames() { private static String[] makeLiteralNames() { return new String[] { - null, "','", null, null, null, null, null, null, null, null, null, "'+'", - "'-'", "'*'", "'/'", "'%'", "'^'", "'!='", "'>'", "'>='", "'<'", "'<='", - "'='", "'('", "')'" + null, "','", null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, "'+'", "'-'", "'*'", + "'/'", "'%'", "'^'", "'!='", "'>'", "'>='", "'<'", "'<='", "'='", "'('", + "')'" }; } private static final String[] _LITERAL_NAMES = makeLiteralNames(); private static String[] makeSymbolicNames() { return new String[] { null, null, "IN", "TO", "AND", "OR", "NOT", "TRUE", "FALSE", "CONTAINS_ALL", - "CONTAINS_ANY", "ADD", "SUBTRACT", "MULTIPLY", "DIVIDE", "MODULUS", "EXPONENT", + "CONTAINS_ANY", "MIN", "MAX", "AVG", "SUM", "MEAN", "MODE", "MEDIAN", + "LEN", "INT", "ADD", "SUBTRACT", "MULTIPLY", "DIVIDE", "MODULUS", "EXPONENT", "NE", "GT", "GE", "LT", "LE", "EQ", "LPAREN", "RPAREN", "DECIMAL", "APP_VERSION", "INTEGER", "WS", "WORD", "ALPHANUMERIC", "SQ", "DQ" }; @@ -114,7 +118,7 @@ public BooleanExpressionLexer(CharStream input) { public ATN getATN() { return _ATN; } public static final String _serializedATN = - "\u0004\u0000 \u0126\u0006\uffff\uffff\u0002\u0000\u0007\u0000\u0002\u0001"+ + "\u0004\u0000)\u018a\u0006\uffff\uffff\u0002\u0000\u0007\u0000\u0002\u0001"+ "\u0007\u0001\u0002\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004"+ "\u0007\u0004\u0002\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007"+ "\u0007\u0007\u0002\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b"+ @@ -124,189 +128,249 @@ public BooleanExpressionLexer(CharStream input) { "\u0015\u0007\u0015\u0002\u0016\u0007\u0016\u0002\u0017\u0007\u0017\u0002"+ "\u0018\u0007\u0018\u0002\u0019\u0007\u0019\u0002\u001a\u0007\u001a\u0002"+ "\u001b\u0007\u001b\u0002\u001c\u0007\u001c\u0002\u001d\u0007\u001d\u0002"+ - "\u001e\u0007\u001e\u0002\u001f\u0007\u001f\u0001\u0000\u0001\u0000\u0001"+ - "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0001H\b\u0001\u0001"+ - "\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0003\u0002N\b\u0002\u0001"+ + "\u001e\u0007\u001e\u0002\u001f\u0007\u001f\u0002 \u0007 \u0002!\u0007"+ + "!\u0002\"\u0007\"\u0002#\u0007#\u0002$\u0007$\u0002%\u0007%\u0002&\u0007"+ + "&\u0002\'\u0007\'\u0002(\u0007(\u0001\u0000\u0001\u0000\u0001\u0001\u0001"+ + "\u0001\u0001\u0001\u0001\u0001\u0003\u0001Z\b\u0001\u0001\u0002\u0001"+ + "\u0002\u0001\u0002\u0001\u0002\u0003\u0002`\b\u0002\u0001\u0003\u0001"+ "\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001"+ - "\u0003\u0001\u0003\u0003\u0003X\b\u0003\u0001\u0004\u0001\u0004\u0001"+ - "\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0003\u0004`\b\u0004\u0001"+ - "\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0003"+ - "\u0005h\b\u0005\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001"+ - "\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0003\u0006r\b\u0006\u0001"+ + "\u0003\u0003\u0003j\b\u0003\u0001\u0004\u0001\u0004\u0001\u0004\u0001"+ + "\u0004\u0001\u0004\u0001\u0004\u0003\u0004r\b\u0004\u0001\u0005\u0001"+ + "\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0003\u0005z\b"+ + "\u0005\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001"+ + "\u0006\u0001\u0006\u0001\u0006\u0003\u0006\u0084\b\u0006\u0001\u0007\u0001"+ "\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001"+ - "\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0003\u0007~\b\u0007\u0001"+ + "\u0007\u0001\u0007\u0001\u0007\u0003\u0007\u0090\b\u0007\u0001\b\u0001"+ "\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001"+ "\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001"+ - "\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0003\b\u0098\b\b\u0001\t\u0001"+ + "\b\u0001\b\u0001\b\u0001\b\u0001\b\u0003\b\u00aa\b\b\u0001\t\u0001\t\u0001"+ "\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+ "\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+ - "\t\u0001\t\u0001\t\u0001\t\u0001\t\u0003\t\u00b2\b\t\u0001\n\u0001\n\u0001"+ - "\u000b\u0001\u000b\u0001\f\u0001\f\u0001\r\u0001\r\u0001\u000e\u0001\u000e"+ - "\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0011"+ - "\u0001\u0011\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0013\u0001\u0013"+ - "\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0015\u0001\u0015\u0001\u0016"+ - "\u0001\u0016\u0001\u0017\u0001\u0017\u0001\u0018\u0004\u0018\u00d4\b\u0018"+ - "\u000b\u0018\f\u0018\u00d5\u0001\u0018\u0001\u0018\u0004\u0018\u00da\b"+ - "\u0018\u000b\u0018\f\u0018\u00db\u0001\u0019\u0001\u0019\u0001\u0019\u0004"+ - "\u0019\u00e1\b\u0019\u000b\u0019\f\u0019\u00e2\u0001\u001a\u0004\u001a"+ - "\u00e6\b\u001a\u000b\u001a\f\u001a\u00e7\u0001\u001b\u0004\u001b\u00eb"+ - "\b\u001b\u000b\u001b\f\u001b\u00ec\u0001\u001b\u0001\u001b\u0001\u001c"+ - "\u0001\u001c\u0001\u001c\u0004\u001c\u00f4\b\u001c\u000b\u001c\f\u001c"+ - "\u00f5\u0001\u001c\u0001\u001c\u0001\u001c\u0001\u001c\u0005\u001c\u00fc"+ - "\b\u001c\n\u001c\f\u001c\u00ff\t\u001c\u0001\u001c\u0001\u001c\u0003\u001c"+ - "\u0103\b\u001c\u0001\u001c\u0001\u001c\u0001\u001c\u0001\u001c\u0004\u001c"+ - "\u0109\b\u001c\u000b\u001c\f\u001c\u010a\u0001\u001c\u0001\u001c\u0003"+ - "\u001c\u010f\b\u001c\u0003\u001c\u0111\b\u001c\u0001\u001d\u0001\u001d"+ - "\u0001\u001e\u0001\u001e\u0005\u001e\u0117\b\u001e\n\u001e\f\u001e\u011a"+ - "\t\u001e\u0001\u001e\u0001\u001e\u0001\u001f\u0001\u001f\u0005\u001f\u0120"+ - "\b\u001f\n\u001f\f\u001f\u0123\t\u001f\u0001\u001f\u0001\u001f\u0002\u0118"+ - "\u0121\u0000 \u0001\u0001\u0003\u0002\u0005\u0003\u0007\u0004\t\u0005"+ + "\t\u0001\t\u0001\t\u0001\t\u0003\t\u00c4\b\t\u0001\n\u0001\n\u0001\n\u0001"+ + "\n\u0001\n\u0001\n\u0003\n\u00cc\b\n\u0001\u000b\u0001\u000b\u0001\u000b"+ + "\u0001\u000b\u0001\u000b\u0001\u000b\u0003\u000b\u00d4\b\u000b\u0001\f"+ + "\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0003\f\u00dc\b\f\u0001\r\u0001"+ + "\r\u0001\r\u0001\r\u0001\r\u0001\r\u0003\r\u00e4\b\r\u0001\u000e\u0001"+ + "\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001"+ + "\u000e\u0003\u000e\u00ee\b\u000e\u0001\u000f\u0001\u000f\u0001\u000f\u0001"+ + "\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0003\u000f\u00f8"+ + "\b\u000f\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001"+ + "\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001"+ + "\u0010\u0003\u0010\u0106\b\u0010\u0001\u0011\u0001\u0011\u0001\u0011\u0001"+ + "\u0011\u0001\u0011\u0001\u0011\u0003\u0011\u010e\b\u0011\u0001\u0012\u0001"+ + "\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0003\u0012\u0116"+ + "\b\u0012\u0001\u0013\u0001\u0013\u0001\u0014\u0001\u0014\u0001\u0015\u0001"+ + "\u0015\u0001\u0016\u0001\u0016\u0001\u0017\u0001\u0017\u0001\u0018\u0001"+ + "\u0018\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u001a\u0001\u001a\u0001"+ + "\u001b\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001\u001d\u0001"+ + "\u001d\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001f\u0001\u001f\u0001"+ + " \u0001 \u0001!\u0004!\u0138\b!\u000b!\f!\u0139\u0001!\u0001!\u0004!\u013e"+ + "\b!\u000b!\f!\u013f\u0001\"\u0001\"\u0001\"\u0004\"\u0145\b\"\u000b\""+ + "\f\"\u0146\u0001#\u0004#\u014a\b#\u000b#\f#\u014b\u0001$\u0004$\u014f"+ + "\b$\u000b$\f$\u0150\u0001$\u0001$\u0001%\u0001%\u0001%\u0004%\u0158\b"+ + "%\u000b%\f%\u0159\u0001%\u0001%\u0001%\u0001%\u0005%\u0160\b%\n%\f%\u0163"+ + "\t%\u0001%\u0001%\u0003%\u0167\b%\u0001%\u0001%\u0001%\u0001%\u0004%\u016d"+ + "\b%\u000b%\f%\u016e\u0001%\u0001%\u0003%\u0173\b%\u0003%\u0175\b%\u0001"+ + "&\u0001&\u0001\'\u0001\'\u0005\'\u017b\b\'\n\'\f\'\u017e\t\'\u0001\'\u0001"+ + "\'\u0001(\u0001(\u0005(\u0184\b(\n(\f(\u0187\t(\u0001(\u0001(\u0002\u017c"+ + "\u0185\u0000)\u0001\u0001\u0003\u0002\u0005\u0003\u0007\u0004\t\u0005"+ "\u000b\u0006\r\u0007\u000f\b\u0011\t\u0013\n\u0015\u000b\u0017\f\u0019"+ "\r\u001b\u000e\u001d\u000f\u001f\u0010!\u0011#\u0012%\u0013\'\u0014)\u0015"+ "+\u0016-\u0017/\u00181\u00193\u001a5\u001b7\u001c9\u001d;\u001e=\u001f"+ - "? \u0001\u0000\u0005\u0001\u000009\u0003\u0000\t\n\f\r \u0002\u0000."+ - ".__\u0002\u0000-.__\u0003\u000009AZaz\u0145\u0000\u0001\u0001\u0000\u0000"+ - "\u0000\u0000\u0003\u0001\u0000\u0000\u0000\u0000\u0005\u0001\u0000\u0000"+ - "\u0000\u0000\u0007\u0001\u0000\u0000\u0000\u0000\t\u0001\u0000\u0000\u0000"+ - "\u0000\u000b\u0001\u0000\u0000\u0000\u0000\r\u0001\u0000\u0000\u0000\u0000"+ - "\u000f\u0001\u0000\u0000\u0000\u0000\u0011\u0001\u0000\u0000\u0000\u0000"+ - "\u0013\u0001\u0000\u0000\u0000\u0000\u0015\u0001\u0000\u0000\u0000\u0000"+ - "\u0017\u0001\u0000\u0000\u0000\u0000\u0019\u0001\u0000\u0000\u0000\u0000"+ - "\u001b\u0001\u0000\u0000\u0000\u0000\u001d\u0001\u0000\u0000\u0000\u0000"+ - "\u001f\u0001\u0000\u0000\u0000\u0000!\u0001\u0000\u0000\u0000\u0000#\u0001"+ - "\u0000\u0000\u0000\u0000%\u0001\u0000\u0000\u0000\u0000\'\u0001\u0000"+ - "\u0000\u0000\u0000)\u0001\u0000\u0000\u0000\u0000+\u0001\u0000\u0000\u0000"+ - "\u0000-\u0001\u0000\u0000\u0000\u0000/\u0001\u0000\u0000\u0000\u00001"+ - "\u0001\u0000\u0000\u0000\u00003\u0001\u0000\u0000\u0000\u00005\u0001\u0000"+ - "\u0000\u0000\u00007\u0001\u0000\u0000\u0000\u00009\u0001\u0000\u0000\u0000"+ - "\u0000;\u0001\u0000\u0000\u0000\u0000=\u0001\u0000\u0000\u0000\u0000?"+ - "\u0001\u0000\u0000\u0000\u0001A\u0001\u0000\u0000\u0000\u0003G\u0001\u0000"+ - "\u0000\u0000\u0005M\u0001\u0000\u0000\u0000\u0007W\u0001\u0000\u0000\u0000"+ - "\t_\u0001\u0000\u0000\u0000\u000bg\u0001\u0000\u0000\u0000\rq\u0001\u0000"+ - "\u0000\u0000\u000f}\u0001\u0000\u0000\u0000\u0011\u0097\u0001\u0000\u0000"+ - "\u0000\u0013\u00b1\u0001\u0000\u0000\u0000\u0015\u00b3\u0001\u0000\u0000"+ - "\u0000\u0017\u00b5\u0001\u0000\u0000\u0000\u0019\u00b7\u0001\u0000\u0000"+ - "\u0000\u001b\u00b9\u0001\u0000\u0000\u0000\u001d\u00bb\u0001\u0000\u0000"+ - "\u0000\u001f\u00bd\u0001\u0000\u0000\u0000!\u00bf\u0001\u0000\u0000\u0000"+ - "#\u00c2\u0001\u0000\u0000\u0000%\u00c4\u0001\u0000\u0000\u0000\'\u00c7"+ - "\u0001\u0000\u0000\u0000)\u00c9\u0001\u0000\u0000\u0000+\u00cc\u0001\u0000"+ - "\u0000\u0000-\u00ce\u0001\u0000\u0000\u0000/\u00d0\u0001\u0000\u0000\u0000"+ - "1\u00d3\u0001\u0000\u0000\u00003\u00dd\u0001\u0000\u0000\u00005\u00e5"+ - "\u0001\u0000\u0000\u00007\u00ea\u0001\u0000\u0000\u00009\u0110\u0001\u0000"+ - "\u0000\u0000;\u0112\u0001\u0000\u0000\u0000=\u0114\u0001\u0000\u0000\u0000"+ - "?\u011d\u0001\u0000\u0000\u0000AB\u0005,\u0000\u0000B\u0002\u0001\u0000"+ - "\u0000\u0000CD\u0005I\u0000\u0000DH\u0005N\u0000\u0000EF\u0005i\u0000"+ - "\u0000FH\u0005n\u0000\u0000GC\u0001\u0000\u0000\u0000GE\u0001\u0000\u0000"+ - "\u0000H\u0004\u0001\u0000\u0000\u0000IJ\u0005T\u0000\u0000JN\u0005O\u0000"+ - "\u0000KL\u0005t\u0000\u0000LN\u0005o\u0000\u0000MI\u0001\u0000\u0000\u0000"+ - "MK\u0001\u0000\u0000\u0000N\u0006\u0001\u0000\u0000\u0000OP\u0005A\u0000"+ - "\u0000PQ\u0005N\u0000\u0000QX\u0005D\u0000\u0000RS\u0005a\u0000\u0000"+ - "ST\u0005n\u0000\u0000TX\u0005d\u0000\u0000UV\u0005&\u0000\u0000VX\u0005"+ - "&\u0000\u0000WO\u0001\u0000\u0000\u0000WR\u0001\u0000\u0000\u0000WU\u0001"+ - "\u0000\u0000\u0000X\b\u0001\u0000\u0000\u0000YZ\u0005O\u0000\u0000Z`\u0005"+ - "R\u0000\u0000[\\\u0005o\u0000\u0000\\`\u0005r\u0000\u0000]^\u0005|\u0000"+ - "\u0000^`\u0005|\u0000\u0000_Y\u0001\u0000\u0000\u0000_[\u0001\u0000\u0000"+ - "\u0000_]\u0001\u0000\u0000\u0000`\n\u0001\u0000\u0000\u0000ab\u0005N\u0000"+ - "\u0000bc\u0005O\u0000\u0000ch\u0005T\u0000\u0000de\u0005n\u0000\u0000"+ - "ef\u0005o\u0000\u0000fh\u0005t\u0000\u0000ga\u0001\u0000\u0000\u0000g"+ - "d\u0001\u0000\u0000\u0000h\f\u0001\u0000\u0000\u0000ij\u0005T\u0000\u0000"+ - "jk\u0005R\u0000\u0000kl\u0005U\u0000\u0000lr\u0005E\u0000\u0000mn\u0005"+ - "t\u0000\u0000no\u0005r\u0000\u0000op\u0005u\u0000\u0000pr\u0005e\u0000"+ - "\u0000qi\u0001\u0000\u0000\u0000qm\u0001\u0000\u0000\u0000r\u000e\u0001"+ - "\u0000\u0000\u0000st\u0005F\u0000\u0000tu\u0005A\u0000\u0000uv\u0005L"+ - "\u0000\u0000vw\u0005S\u0000\u0000w~\u0005E\u0000\u0000xy\u0005f\u0000"+ - "\u0000yz\u0005a\u0000\u0000z{\u0005l\u0000\u0000{|\u0005s\u0000\u0000"+ - "|~\u0005e\u0000\u0000}s\u0001\u0000\u0000\u0000}x\u0001\u0000\u0000\u0000"+ - "~\u0010\u0001\u0000\u0000\u0000\u007f\u0080\u0005C\u0000\u0000\u0080\u0081"+ - "\u0005O\u0000\u0000\u0081\u0082\u0005N\u0000\u0000\u0082\u0083\u0005T"+ - "\u0000\u0000\u0083\u0084\u0005A\u0000\u0000\u0084\u0085\u0005I\u0000\u0000"+ - "\u0085\u0086\u0005N\u0000\u0000\u0086\u0087\u0005S\u0000\u0000\u0087\u0088"+ - "\u0005_\u0000\u0000\u0088\u0089\u0005A\u0000\u0000\u0089\u008a\u0005L"+ - "\u0000\u0000\u008a\u0098\u0005L\u0000\u0000\u008b\u008c\u0005c\u0000\u0000"+ - "\u008c\u008d\u0005o\u0000\u0000\u008d\u008e\u0005n\u0000\u0000\u008e\u008f"+ - "\u0005t\u0000\u0000\u008f\u0090\u0005a\u0000\u0000\u0090\u0091\u0005i"+ - "\u0000\u0000\u0091\u0092\u0005n\u0000\u0000\u0092\u0093\u0005s\u0000\u0000"+ - "\u0093\u0094\u0005_\u0000\u0000\u0094\u0095\u0005a\u0000\u0000\u0095\u0096"+ - "\u0005l\u0000\u0000\u0096\u0098\u0005l\u0000\u0000\u0097\u007f\u0001\u0000"+ - "\u0000\u0000\u0097\u008b\u0001\u0000\u0000\u0000\u0098\u0012\u0001\u0000"+ - "\u0000\u0000\u0099\u009a\u0005C\u0000\u0000\u009a\u009b\u0005O\u0000\u0000"+ - "\u009b\u009c\u0005N\u0000\u0000\u009c\u009d\u0005T\u0000\u0000\u009d\u009e"+ - "\u0005A\u0000\u0000\u009e\u009f\u0005I\u0000\u0000\u009f\u00a0\u0005N"+ - "\u0000\u0000\u00a0\u00a1\u0005S\u0000\u0000\u00a1\u00a2\u0005_\u0000\u0000"+ - "\u00a2\u00a3\u0005A\u0000\u0000\u00a3\u00a4\u0005N\u0000\u0000\u00a4\u00b2"+ - "\u0005Y\u0000\u0000\u00a5\u00a6\u0005c\u0000\u0000\u00a6\u00a7\u0005o"+ - "\u0000\u0000\u00a7\u00a8\u0005n\u0000\u0000\u00a8\u00a9\u0005t\u0000\u0000"+ - "\u00a9\u00aa\u0005a\u0000\u0000\u00aa\u00ab\u0005i\u0000\u0000\u00ab\u00ac"+ - "\u0005n\u0000\u0000\u00ac\u00ad\u0005s\u0000\u0000\u00ad\u00ae\u0005_"+ - "\u0000\u0000\u00ae\u00af\u0005a\u0000\u0000\u00af\u00b0\u0005n\u0000\u0000"+ - "\u00b0\u00b2\u0005y\u0000\u0000\u00b1\u0099\u0001\u0000\u0000\u0000\u00b1"+ - "\u00a5\u0001\u0000\u0000\u0000\u00b2\u0014\u0001\u0000\u0000\u0000\u00b3"+ - "\u00b4\u0005+\u0000\u0000\u00b4\u0016\u0001\u0000\u0000\u0000\u00b5\u00b6"+ - "\u0005-\u0000\u0000\u00b6\u0018\u0001\u0000\u0000\u0000\u00b7\u00b8\u0005"+ - "*\u0000\u0000\u00b8\u001a\u0001\u0000\u0000\u0000\u00b9\u00ba\u0005/\u0000"+ - "\u0000\u00ba\u001c\u0001\u0000\u0000\u0000\u00bb\u00bc\u0005%\u0000\u0000"+ - "\u00bc\u001e\u0001\u0000\u0000\u0000\u00bd\u00be\u0005^\u0000\u0000\u00be"+ - " \u0001\u0000\u0000\u0000\u00bf\u00c0\u0005!\u0000\u0000\u00c0\u00c1\u0005"+ - "=\u0000\u0000\u00c1\"\u0001\u0000\u0000\u0000\u00c2\u00c3\u0005>\u0000"+ - "\u0000\u00c3$\u0001\u0000\u0000\u0000\u00c4\u00c5\u0005>\u0000\u0000\u00c5"+ - "\u00c6\u0005=\u0000\u0000\u00c6&\u0001\u0000\u0000\u0000\u00c7\u00c8\u0005"+ - "<\u0000\u0000\u00c8(\u0001\u0000\u0000\u0000\u00c9\u00ca\u0005<\u0000"+ - "\u0000\u00ca\u00cb\u0005=\u0000\u0000\u00cb*\u0001\u0000\u0000\u0000\u00cc"+ - "\u00cd\u0005=\u0000\u0000\u00cd,\u0001\u0000\u0000\u0000\u00ce\u00cf\u0005"+ - "(\u0000\u0000\u00cf.\u0001\u0000\u0000\u0000\u00d0\u00d1\u0005)\u0000"+ - "\u0000\u00d10\u0001\u0000\u0000\u0000\u00d2\u00d4\u0007\u0000\u0000\u0000"+ - "\u00d3\u00d2\u0001\u0000\u0000\u0000\u00d4\u00d5\u0001\u0000\u0000\u0000"+ - "\u00d5\u00d3\u0001\u0000\u0000\u0000\u00d5\u00d6\u0001\u0000\u0000\u0000"+ - "\u00d6\u00d7\u0001\u0000\u0000\u0000\u00d7\u00d9\u0005.\u0000\u0000\u00d8"+ - "\u00da\u0007\u0000\u0000\u0000\u00d9\u00d8\u0001\u0000\u0000\u0000\u00da"+ - "\u00db\u0001\u0000\u0000\u0000\u00db\u00d9\u0001\u0000\u0000\u0000\u00db"+ - "\u00dc\u0001\u0000\u0000\u0000\u00dc2\u0001\u0000\u0000\u0000\u00dd\u00e0"+ - "\u0007\u0000\u0000\u0000\u00de\u00df\u0005.\u0000\u0000\u00df\u00e1\u0003"+ - "5\u001a\u0000\u00e0\u00de\u0001\u0000\u0000\u0000\u00e1\u00e2\u0001\u0000"+ - "\u0000\u0000\u00e2\u00e0\u0001\u0000\u0000\u0000\u00e2\u00e3\u0001\u0000"+ - "\u0000\u0000\u00e34\u0001\u0000\u0000\u0000\u00e4\u00e6\u0007\u0000\u0000"+ - "\u0000\u00e5\u00e4\u0001\u0000\u0000\u0000\u00e6\u00e7\u0001\u0000\u0000"+ - "\u0000\u00e7\u00e5\u0001\u0000\u0000\u0000\u00e7\u00e8\u0001\u0000\u0000"+ - "\u0000\u00e86\u0001\u0000\u0000\u0000\u00e9\u00eb\u0007\u0001\u0000\u0000"+ - "\u00ea\u00e9\u0001\u0000\u0000\u0000\u00eb\u00ec\u0001\u0000\u0000\u0000"+ - "\u00ec\u00ea\u0001\u0000\u0000\u0000\u00ec\u00ed\u0001\u0000\u0000\u0000"+ - "\u00ed\u00ee\u0001\u0000\u0000\u0000\u00ee\u00ef\u0006\u001b\u0000\u0000"+ - "\u00ef8\u0001\u0000\u0000\u0000\u00f0\u00f4\u0003;\u001d\u0000\u00f1\u00f4"+ - "\u0003=\u001e\u0000\u00f2\u00f4\u0003?\u001f\u0000\u00f3\u00f0\u0001\u0000"+ - "\u0000\u0000\u00f3\u00f1\u0001\u0000\u0000\u0000\u00f3\u00f2\u0001\u0000"+ - "\u0000\u0000\u00f4\u00f5\u0001\u0000\u0000\u0000\u00f5\u00f3\u0001\u0000"+ - "\u0000\u0000\u00f5\u00f6\u0001\u0000\u0000\u0000\u00f6\u00fd\u0001\u0000"+ - "\u0000\u0000\u00f7\u00fc\u0003;\u001d\u0000\u00f8\u00fc\u0007\u0002\u0000"+ - "\u0000\u00f9\u00fc\u0003=\u001e\u0000\u00fa\u00fc\u0003?\u001f\u0000\u00fb"+ - "\u00f7\u0001\u0000\u0000\u0000\u00fb\u00f8\u0001\u0000\u0000\u0000\u00fb"+ - "\u00f9\u0001\u0000\u0000\u0000\u00fb\u00fa\u0001\u0000\u0000\u0000\u00fc"+ - "\u00ff\u0001\u0000\u0000\u0000\u00fd\u00fb\u0001\u0000\u0000\u0000\u00fd"+ - "\u00fe\u0001\u0000\u0000\u0000\u00fe\u0111\u0001\u0000\u0000\u0000\u00ff"+ - "\u00fd\u0001\u0000\u0000\u0000\u0100\u0103\u0003=\u001e\u0000\u0101\u0103"+ - "\u0003?\u001f\u0000\u0102\u0100\u0001\u0000\u0000\u0000\u0102\u0101\u0001"+ - "\u0000\u0000\u0000\u0103\u0108\u0001\u0000\u0000\u0000\u0104\u0109\u0003"+ - ";\u001d\u0000\u0105\u0109\u0007\u0003\u0000\u0000\u0106\u0109\u0003=\u001e"+ - "\u0000\u0107\u0109\u0003?\u001f\u0000\u0108\u0104\u0001\u0000\u0000\u0000"+ - "\u0108\u0105\u0001\u0000\u0000\u0000\u0108\u0106\u0001\u0000\u0000\u0000"+ - "\u0108\u0107\u0001\u0000\u0000\u0000\u0109\u010a\u0001\u0000\u0000\u0000"+ - "\u010a\u0108\u0001\u0000\u0000\u0000\u010a\u010b\u0001\u0000\u0000\u0000"+ - "\u010b\u010e\u0001\u0000\u0000\u0000\u010c\u010f\u0003=\u001e\u0000\u010d"+ - "\u010f\u0003?\u001f\u0000\u010e\u010c\u0001\u0000\u0000\u0000\u010e\u010d"+ - "\u0001\u0000\u0000\u0000\u010f\u0111\u0001\u0000\u0000\u0000\u0110\u00f3"+ - "\u0001\u0000\u0000\u0000\u0110\u0102\u0001\u0000\u0000\u0000\u0111:\u0001"+ - "\u0000\u0000\u0000\u0112\u0113\u0007\u0004\u0000\u0000\u0113<\u0001\u0000"+ - "\u0000\u0000\u0114\u0118\u0005\'\u0000\u0000\u0115\u0117\t\u0000\u0000"+ - "\u0000\u0116\u0115\u0001\u0000\u0000\u0000\u0117\u011a\u0001\u0000\u0000"+ - "\u0000\u0118\u0119\u0001\u0000\u0000\u0000\u0118\u0116\u0001\u0000\u0000"+ - "\u0000\u0119\u011b\u0001\u0000\u0000\u0000\u011a\u0118\u0001\u0000\u0000"+ - "\u0000\u011b\u011c\u0005\'\u0000\u0000\u011c>\u0001\u0000\u0000\u0000"+ - "\u011d\u0121\u0005\"\u0000\u0000\u011e\u0120\t\u0000\u0000\u0000\u011f"+ - "\u011e\u0001\u0000\u0000\u0000\u0120\u0123\u0001\u0000\u0000\u0000\u0121"+ - "\u0122\u0001\u0000\u0000\u0000\u0121\u011f\u0001\u0000\u0000\u0000\u0122"+ - "\u0124\u0001\u0000\u0000\u0000\u0123\u0121\u0001\u0000\u0000\u0000\u0124"+ - "\u0125\u0005\"\u0000\u0000\u0125@\u0001\u0000\u0000\u0000\u001a\u0000"+ - "GMW_gq}\u0097\u00b1\u00d5\u00db\u00e2\u00e7\u00ec\u00f3\u00f5\u00fb\u00fd"+ - "\u0102\u0108\u010a\u010e\u0110\u0118\u0121\u0001\u0006\u0000\u0000"; + "? A!C\"E#G$I%K&M\'O(Q)\u0001\u0000\u0005\u0001\u000009\u0003\u0000\t\n"+ + "\f\r \u0002\u0000..__\u0002\u0000-.__\u0003\u000009AZaz\u01b2\u0000\u0001"+ + "\u0001\u0000\u0000\u0000\u0000\u0003\u0001\u0000\u0000\u0000\u0000\u0005"+ + "\u0001\u0000\u0000\u0000\u0000\u0007\u0001\u0000\u0000\u0000\u0000\t\u0001"+ + "\u0000\u0000\u0000\u0000\u000b\u0001\u0000\u0000\u0000\u0000\r\u0001\u0000"+ + "\u0000\u0000\u0000\u000f\u0001\u0000\u0000\u0000\u0000\u0011\u0001\u0000"+ + "\u0000\u0000\u0000\u0013\u0001\u0000\u0000\u0000\u0000\u0015\u0001\u0000"+ + "\u0000\u0000\u0000\u0017\u0001\u0000\u0000\u0000\u0000\u0019\u0001\u0000"+ + "\u0000\u0000\u0000\u001b\u0001\u0000\u0000\u0000\u0000\u001d\u0001\u0000"+ + "\u0000\u0000\u0000\u001f\u0001\u0000\u0000\u0000\u0000!\u0001\u0000\u0000"+ + "\u0000\u0000#\u0001\u0000\u0000\u0000\u0000%\u0001\u0000\u0000\u0000\u0000"+ + "\'\u0001\u0000\u0000\u0000\u0000)\u0001\u0000\u0000\u0000\u0000+\u0001"+ + "\u0000\u0000\u0000\u0000-\u0001\u0000\u0000\u0000\u0000/\u0001\u0000\u0000"+ + "\u0000\u00001\u0001\u0000\u0000\u0000\u00003\u0001\u0000\u0000\u0000\u0000"+ + "5\u0001\u0000\u0000\u0000\u00007\u0001\u0000\u0000\u0000\u00009\u0001"+ + "\u0000\u0000\u0000\u0000;\u0001\u0000\u0000\u0000\u0000=\u0001\u0000\u0000"+ + "\u0000\u0000?\u0001\u0000\u0000\u0000\u0000A\u0001\u0000\u0000\u0000\u0000"+ + "C\u0001\u0000\u0000\u0000\u0000E\u0001\u0000\u0000\u0000\u0000G\u0001"+ + "\u0000\u0000\u0000\u0000I\u0001\u0000\u0000\u0000\u0000K\u0001\u0000\u0000"+ + "\u0000\u0000M\u0001\u0000\u0000\u0000\u0000O\u0001\u0000\u0000\u0000\u0000"+ + "Q\u0001\u0000\u0000\u0000\u0001S\u0001\u0000\u0000\u0000\u0003Y\u0001"+ + "\u0000\u0000\u0000\u0005_\u0001\u0000\u0000\u0000\u0007i\u0001\u0000\u0000"+ + "\u0000\tq\u0001\u0000\u0000\u0000\u000by\u0001\u0000\u0000\u0000\r\u0083"+ + "\u0001\u0000\u0000\u0000\u000f\u008f\u0001\u0000\u0000\u0000\u0011\u00a9"+ + "\u0001\u0000\u0000\u0000\u0013\u00c3\u0001\u0000\u0000\u0000\u0015\u00cb"+ + "\u0001\u0000\u0000\u0000\u0017\u00d3\u0001\u0000\u0000\u0000\u0019\u00db"+ + "\u0001\u0000\u0000\u0000\u001b\u00e3\u0001\u0000\u0000\u0000\u001d\u00ed"+ + "\u0001\u0000\u0000\u0000\u001f\u00f7\u0001\u0000\u0000\u0000!\u0105\u0001"+ + "\u0000\u0000\u0000#\u010d\u0001\u0000\u0000\u0000%\u0115\u0001\u0000\u0000"+ + "\u0000\'\u0117\u0001\u0000\u0000\u0000)\u0119\u0001\u0000\u0000\u0000"+ + "+\u011b\u0001\u0000\u0000\u0000-\u011d\u0001\u0000\u0000\u0000/\u011f"+ + "\u0001\u0000\u0000\u00001\u0121\u0001\u0000\u0000\u00003\u0123\u0001\u0000"+ + "\u0000\u00005\u0126\u0001\u0000\u0000\u00007\u0128\u0001\u0000\u0000\u0000"+ + "9\u012b\u0001\u0000\u0000\u0000;\u012d\u0001\u0000\u0000\u0000=\u0130"+ + "\u0001\u0000\u0000\u0000?\u0132\u0001\u0000\u0000\u0000A\u0134\u0001\u0000"+ + "\u0000\u0000C\u0137\u0001\u0000\u0000\u0000E\u0141\u0001\u0000\u0000\u0000"+ + "G\u0149\u0001\u0000\u0000\u0000I\u014e\u0001\u0000\u0000\u0000K\u0174"+ + "\u0001\u0000\u0000\u0000M\u0176\u0001\u0000\u0000\u0000O\u0178\u0001\u0000"+ + "\u0000\u0000Q\u0181\u0001\u0000\u0000\u0000ST\u0005,\u0000\u0000T\u0002"+ + "\u0001\u0000\u0000\u0000UV\u0005I\u0000\u0000VZ\u0005N\u0000\u0000WX\u0005"+ + "i\u0000\u0000XZ\u0005n\u0000\u0000YU\u0001\u0000\u0000\u0000YW\u0001\u0000"+ + "\u0000\u0000Z\u0004\u0001\u0000\u0000\u0000[\\\u0005T\u0000\u0000\\`\u0005"+ + "O\u0000\u0000]^\u0005t\u0000\u0000^`\u0005o\u0000\u0000_[\u0001\u0000"+ + "\u0000\u0000_]\u0001\u0000\u0000\u0000`\u0006\u0001\u0000\u0000\u0000"+ + "ab\u0005A\u0000\u0000bc\u0005N\u0000\u0000cj\u0005D\u0000\u0000de\u0005"+ + "a\u0000\u0000ef\u0005n\u0000\u0000fj\u0005d\u0000\u0000gh\u0005&\u0000"+ + "\u0000hj\u0005&\u0000\u0000ia\u0001\u0000\u0000\u0000id\u0001\u0000\u0000"+ + "\u0000ig\u0001\u0000\u0000\u0000j\b\u0001\u0000\u0000\u0000kl\u0005O\u0000"+ + "\u0000lr\u0005R\u0000\u0000mn\u0005o\u0000\u0000nr\u0005r\u0000\u0000"+ + "op\u0005|\u0000\u0000pr\u0005|\u0000\u0000qk\u0001\u0000\u0000\u0000q"+ + "m\u0001\u0000\u0000\u0000qo\u0001\u0000\u0000\u0000r\n\u0001\u0000\u0000"+ + "\u0000st\u0005N\u0000\u0000tu\u0005O\u0000\u0000uz\u0005T\u0000\u0000"+ + "vw\u0005n\u0000\u0000wx\u0005o\u0000\u0000xz\u0005t\u0000\u0000ys\u0001"+ + "\u0000\u0000\u0000yv\u0001\u0000\u0000\u0000z\f\u0001\u0000\u0000\u0000"+ + "{|\u0005T\u0000\u0000|}\u0005R\u0000\u0000}~\u0005U\u0000\u0000~\u0084"+ + "\u0005E\u0000\u0000\u007f\u0080\u0005t\u0000\u0000\u0080\u0081\u0005r"+ + "\u0000\u0000\u0081\u0082\u0005u\u0000\u0000\u0082\u0084\u0005e\u0000\u0000"+ + "\u0083{\u0001\u0000\u0000\u0000\u0083\u007f\u0001\u0000\u0000\u0000\u0084"+ + "\u000e\u0001\u0000\u0000\u0000\u0085\u0086\u0005F\u0000\u0000\u0086\u0087"+ + "\u0005A\u0000\u0000\u0087\u0088\u0005L\u0000\u0000\u0088\u0089\u0005S"+ + "\u0000\u0000\u0089\u0090\u0005E\u0000\u0000\u008a\u008b\u0005f\u0000\u0000"+ + "\u008b\u008c\u0005a\u0000\u0000\u008c\u008d\u0005l\u0000\u0000\u008d\u008e"+ + "\u0005s\u0000\u0000\u008e\u0090\u0005e\u0000\u0000\u008f\u0085\u0001\u0000"+ + "\u0000\u0000\u008f\u008a\u0001\u0000\u0000\u0000\u0090\u0010\u0001\u0000"+ + "\u0000\u0000\u0091\u0092\u0005C\u0000\u0000\u0092\u0093\u0005O\u0000\u0000"+ + "\u0093\u0094\u0005N\u0000\u0000\u0094\u0095\u0005T\u0000\u0000\u0095\u0096"+ + "\u0005A\u0000\u0000\u0096\u0097\u0005I\u0000\u0000\u0097\u0098\u0005N"+ + "\u0000\u0000\u0098\u0099\u0005S\u0000\u0000\u0099\u009a\u0005_\u0000\u0000"+ + "\u009a\u009b\u0005A\u0000\u0000\u009b\u009c\u0005L\u0000\u0000\u009c\u00aa"+ + "\u0005L\u0000\u0000\u009d\u009e\u0005c\u0000\u0000\u009e\u009f\u0005o"+ + "\u0000\u0000\u009f\u00a0\u0005n\u0000\u0000\u00a0\u00a1\u0005t\u0000\u0000"+ + "\u00a1\u00a2\u0005a\u0000\u0000\u00a2\u00a3\u0005i\u0000\u0000\u00a3\u00a4"+ + "\u0005n\u0000\u0000\u00a4\u00a5\u0005s\u0000\u0000\u00a5\u00a6\u0005_"+ + "\u0000\u0000\u00a6\u00a7\u0005a\u0000\u0000\u00a7\u00a8\u0005l\u0000\u0000"+ + "\u00a8\u00aa\u0005l\u0000\u0000\u00a9\u0091\u0001\u0000\u0000\u0000\u00a9"+ + "\u009d\u0001\u0000\u0000\u0000\u00aa\u0012\u0001\u0000\u0000\u0000\u00ab"+ + "\u00ac\u0005C\u0000\u0000\u00ac\u00ad\u0005O\u0000\u0000\u00ad\u00ae\u0005"+ + "N\u0000\u0000\u00ae\u00af\u0005T\u0000\u0000\u00af\u00b0\u0005A\u0000"+ + "\u0000\u00b0\u00b1\u0005I\u0000\u0000\u00b1\u00b2\u0005N\u0000\u0000\u00b2"+ + "\u00b3\u0005S\u0000\u0000\u00b3\u00b4\u0005_\u0000\u0000\u00b4\u00b5\u0005"+ + "A\u0000\u0000\u00b5\u00b6\u0005N\u0000\u0000\u00b6\u00c4\u0005Y\u0000"+ + "\u0000\u00b7\u00b8\u0005c\u0000\u0000\u00b8\u00b9\u0005o\u0000\u0000\u00b9"+ + "\u00ba\u0005n\u0000\u0000\u00ba\u00bb\u0005t\u0000\u0000\u00bb\u00bc\u0005"+ + "a\u0000\u0000\u00bc\u00bd\u0005i\u0000\u0000\u00bd\u00be\u0005n\u0000"+ + "\u0000\u00be\u00bf\u0005s\u0000\u0000\u00bf\u00c0\u0005_\u0000\u0000\u00c0"+ + "\u00c1\u0005a\u0000\u0000\u00c1\u00c2\u0005n\u0000\u0000\u00c2\u00c4\u0005"+ + "y\u0000\u0000\u00c3\u00ab\u0001\u0000\u0000\u0000\u00c3\u00b7\u0001\u0000"+ + "\u0000\u0000\u00c4\u0014\u0001\u0000\u0000\u0000\u00c5\u00c6\u0005M\u0000"+ + "\u0000\u00c6\u00c7\u0005I\u0000\u0000\u00c7\u00cc\u0005N\u0000\u0000\u00c8"+ + "\u00c9\u0005m\u0000\u0000\u00c9\u00ca\u0005i\u0000\u0000\u00ca\u00cc\u0005"+ + "n\u0000\u0000\u00cb\u00c5\u0001\u0000\u0000\u0000\u00cb\u00c8\u0001\u0000"+ + "\u0000\u0000\u00cc\u0016\u0001\u0000\u0000\u0000\u00cd\u00ce\u0005M\u0000"+ + "\u0000\u00ce\u00cf\u0005A\u0000\u0000\u00cf\u00d4\u0005X\u0000\u0000\u00d0"+ + "\u00d1\u0005m\u0000\u0000\u00d1\u00d2\u0005a\u0000\u0000\u00d2\u00d4\u0005"+ + "x\u0000\u0000\u00d3\u00cd\u0001\u0000\u0000\u0000\u00d3\u00d0\u0001\u0000"+ + "\u0000\u0000\u00d4\u0018\u0001\u0000\u0000\u0000\u00d5\u00d6\u0005A\u0000"+ + "\u0000\u00d6\u00d7\u0005V\u0000\u0000\u00d7\u00dc\u0005G\u0000\u0000\u00d8"+ + "\u00d9\u0005a\u0000\u0000\u00d9\u00da\u0005v\u0000\u0000\u00da\u00dc\u0005"+ + "g\u0000\u0000\u00db\u00d5\u0001\u0000\u0000\u0000\u00db\u00d8\u0001\u0000"+ + "\u0000\u0000\u00dc\u001a\u0001\u0000\u0000\u0000\u00dd\u00de\u0005S\u0000"+ + "\u0000\u00de\u00df\u0005U\u0000\u0000\u00df\u00e4\u0005M\u0000\u0000\u00e0"+ + "\u00e1\u0005s\u0000\u0000\u00e1\u00e2\u0005u\u0000\u0000\u00e2\u00e4\u0005"+ + "m\u0000\u0000\u00e3\u00dd\u0001\u0000\u0000\u0000\u00e3\u00e0\u0001\u0000"+ + "\u0000\u0000\u00e4\u001c\u0001\u0000\u0000\u0000\u00e5\u00e6\u0005M\u0000"+ + "\u0000\u00e6\u00e7\u0005E\u0000\u0000\u00e7\u00e8\u0005A\u0000\u0000\u00e8"+ + "\u00ee\u0005N\u0000\u0000\u00e9\u00ea\u0005m\u0000\u0000\u00ea\u00eb\u0005"+ + "e\u0000\u0000\u00eb\u00ec\u0005a\u0000\u0000\u00ec\u00ee\u0005n\u0000"+ + "\u0000\u00ed\u00e5\u0001\u0000\u0000\u0000\u00ed\u00e9\u0001\u0000\u0000"+ + "\u0000\u00ee\u001e\u0001\u0000\u0000\u0000\u00ef\u00f0\u0005M\u0000\u0000"+ + "\u00f0\u00f1\u0005O\u0000\u0000\u00f1\u00f2\u0005D\u0000\u0000\u00f2\u00f8"+ + "\u0005E\u0000\u0000\u00f3\u00f4\u0005m\u0000\u0000\u00f4\u00f5\u0005o"+ + "\u0000\u0000\u00f5\u00f6\u0005d\u0000\u0000\u00f6\u00f8\u0005e\u0000\u0000"+ + "\u00f7\u00ef\u0001\u0000\u0000\u0000\u00f7\u00f3\u0001\u0000\u0000\u0000"+ + "\u00f8 \u0001\u0000\u0000\u0000\u00f9\u00fa\u0005M\u0000\u0000\u00fa\u00fb"+ + "\u0005E\u0000\u0000\u00fb\u00fc\u0005D\u0000\u0000\u00fc\u00fd\u0005I"+ + "\u0000\u0000\u00fd\u00fe\u0005A\u0000\u0000\u00fe\u0106\u0005N\u0000\u0000"+ + "\u00ff\u0100\u0005m\u0000\u0000\u0100\u0101\u0005e\u0000\u0000\u0101\u0102"+ + "\u0005d\u0000\u0000\u0102\u0103\u0005i\u0000\u0000\u0103\u0104\u0005a"+ + "\u0000\u0000\u0104\u0106\u0005n\u0000\u0000\u0105\u00f9\u0001\u0000\u0000"+ + "\u0000\u0105\u00ff\u0001\u0000\u0000\u0000\u0106\"\u0001\u0000\u0000\u0000"+ + "\u0107\u0108\u0005L\u0000\u0000\u0108\u0109\u0005E\u0000\u0000\u0109\u010e"+ + "\u0005N\u0000\u0000\u010a\u010b\u0005l\u0000\u0000\u010b\u010c\u0005e"+ + "\u0000\u0000\u010c\u010e\u0005n\u0000\u0000\u010d\u0107\u0001\u0000\u0000"+ + "\u0000\u010d\u010a\u0001\u0000\u0000\u0000\u010e$\u0001\u0000\u0000\u0000"+ + "\u010f\u0110\u0005I\u0000\u0000\u0110\u0111\u0005N\u0000\u0000\u0111\u0116"+ + "\u0005T\u0000\u0000\u0112\u0113\u0005i\u0000\u0000\u0113\u0114\u0005n"+ + "\u0000\u0000\u0114\u0116\u0005t\u0000\u0000\u0115\u010f\u0001\u0000\u0000"+ + "\u0000\u0115\u0112\u0001\u0000\u0000\u0000\u0116&\u0001\u0000\u0000\u0000"+ + "\u0117\u0118\u0005+\u0000\u0000\u0118(\u0001\u0000\u0000\u0000\u0119\u011a"+ + "\u0005-\u0000\u0000\u011a*\u0001\u0000\u0000\u0000\u011b\u011c\u0005*"+ + "\u0000\u0000\u011c,\u0001\u0000\u0000\u0000\u011d\u011e\u0005/\u0000\u0000"+ + "\u011e.\u0001\u0000\u0000\u0000\u011f\u0120\u0005%\u0000\u0000\u01200"+ + "\u0001\u0000\u0000\u0000\u0121\u0122\u0005^\u0000\u0000\u01222\u0001\u0000"+ + "\u0000\u0000\u0123\u0124\u0005!\u0000\u0000\u0124\u0125\u0005=\u0000\u0000"+ + "\u01254\u0001\u0000\u0000\u0000\u0126\u0127\u0005>\u0000\u0000\u01276"+ + "\u0001\u0000\u0000\u0000\u0128\u0129\u0005>\u0000\u0000\u0129\u012a\u0005"+ + "=\u0000\u0000\u012a8\u0001\u0000\u0000\u0000\u012b\u012c\u0005<\u0000"+ + "\u0000\u012c:\u0001\u0000\u0000\u0000\u012d\u012e\u0005<\u0000\u0000\u012e"+ + "\u012f\u0005=\u0000\u0000\u012f<\u0001\u0000\u0000\u0000\u0130\u0131\u0005"+ + "=\u0000\u0000\u0131>\u0001\u0000\u0000\u0000\u0132\u0133\u0005(\u0000"+ + "\u0000\u0133@\u0001\u0000\u0000\u0000\u0134\u0135\u0005)\u0000\u0000\u0135"+ + "B\u0001\u0000\u0000\u0000\u0136\u0138\u0007\u0000\u0000\u0000\u0137\u0136"+ + "\u0001\u0000\u0000\u0000\u0138\u0139\u0001\u0000\u0000\u0000\u0139\u0137"+ + "\u0001\u0000\u0000\u0000\u0139\u013a\u0001\u0000\u0000\u0000\u013a\u013b"+ + "\u0001\u0000\u0000\u0000\u013b\u013d\u0005.\u0000\u0000\u013c\u013e\u0007"+ + "\u0000\u0000\u0000\u013d\u013c\u0001\u0000\u0000\u0000\u013e\u013f\u0001"+ + "\u0000\u0000\u0000\u013f\u013d\u0001\u0000\u0000\u0000\u013f\u0140\u0001"+ + "\u0000\u0000\u0000\u0140D\u0001\u0000\u0000\u0000\u0141\u0144\u0007\u0000"+ + "\u0000\u0000\u0142\u0143\u0005.\u0000\u0000\u0143\u0145\u0003G#\u0000"+ + "\u0144\u0142\u0001\u0000\u0000\u0000\u0145\u0146\u0001\u0000\u0000\u0000"+ + "\u0146\u0144\u0001\u0000\u0000\u0000\u0146\u0147\u0001\u0000\u0000\u0000"+ + "\u0147F\u0001\u0000\u0000\u0000\u0148\u014a\u0007\u0000\u0000\u0000\u0149"+ + "\u0148\u0001\u0000\u0000\u0000\u014a\u014b\u0001\u0000\u0000\u0000\u014b"+ + "\u0149\u0001\u0000\u0000\u0000\u014b\u014c\u0001\u0000\u0000\u0000\u014c"+ + "H\u0001\u0000\u0000\u0000\u014d\u014f\u0007\u0001\u0000\u0000\u014e\u014d"+ + "\u0001\u0000\u0000\u0000\u014f\u0150\u0001\u0000\u0000\u0000\u0150\u014e"+ + "\u0001\u0000\u0000\u0000\u0150\u0151\u0001\u0000\u0000\u0000\u0151\u0152"+ + "\u0001\u0000\u0000\u0000\u0152\u0153\u0006$\u0000\u0000\u0153J\u0001\u0000"+ + "\u0000\u0000\u0154\u0158\u0003M&\u0000\u0155\u0158\u0003O\'\u0000\u0156"+ + "\u0158\u0003Q(\u0000\u0157\u0154\u0001\u0000\u0000\u0000\u0157\u0155\u0001"+ + "\u0000\u0000\u0000\u0157\u0156\u0001\u0000\u0000\u0000\u0158\u0159\u0001"+ + "\u0000\u0000\u0000\u0159\u0157\u0001\u0000\u0000\u0000\u0159\u015a\u0001"+ + "\u0000\u0000\u0000\u015a\u0161\u0001\u0000\u0000\u0000\u015b\u0160\u0003"+ + "M&\u0000\u015c\u0160\u0007\u0002\u0000\u0000\u015d\u0160\u0003O\'\u0000"+ + "\u015e\u0160\u0003Q(\u0000\u015f\u015b\u0001\u0000\u0000\u0000\u015f\u015c"+ + "\u0001\u0000\u0000\u0000\u015f\u015d\u0001\u0000\u0000\u0000\u015f\u015e"+ + "\u0001\u0000\u0000\u0000\u0160\u0163\u0001\u0000\u0000\u0000\u0161\u015f"+ + "\u0001\u0000\u0000\u0000\u0161\u0162\u0001\u0000\u0000\u0000\u0162\u0175"+ + "\u0001\u0000\u0000\u0000\u0163\u0161\u0001\u0000\u0000\u0000\u0164\u0167"+ + "\u0003O\'\u0000\u0165\u0167\u0003Q(\u0000\u0166\u0164\u0001\u0000\u0000"+ + "\u0000\u0166\u0165\u0001\u0000\u0000\u0000\u0167\u016c\u0001\u0000\u0000"+ + "\u0000\u0168\u016d\u0003M&\u0000\u0169\u016d\u0007\u0003\u0000\u0000\u016a"+ + "\u016d\u0003O\'\u0000\u016b\u016d\u0003Q(\u0000\u016c\u0168\u0001\u0000"+ + "\u0000\u0000\u016c\u0169\u0001\u0000\u0000\u0000\u016c\u016a\u0001\u0000"+ + "\u0000\u0000\u016c\u016b\u0001\u0000\u0000\u0000\u016d\u016e\u0001\u0000"+ + "\u0000\u0000\u016e\u016c\u0001\u0000\u0000\u0000\u016e\u016f\u0001\u0000"+ + "\u0000\u0000\u016f\u0172\u0001\u0000\u0000\u0000\u0170\u0173\u0003O\'"+ + "\u0000\u0171\u0173\u0003Q(\u0000\u0172\u0170\u0001\u0000\u0000\u0000\u0172"+ + "\u0171\u0001\u0000\u0000\u0000\u0173\u0175\u0001\u0000\u0000\u0000\u0174"+ + "\u0157\u0001\u0000\u0000\u0000\u0174\u0166\u0001\u0000\u0000\u0000\u0175"+ + "L\u0001\u0000\u0000\u0000\u0176\u0177\u0007\u0004\u0000\u0000\u0177N\u0001"+ + "\u0000\u0000\u0000\u0178\u017c\u0005\'\u0000\u0000\u0179\u017b\t\u0000"+ + "\u0000\u0000\u017a\u0179\u0001\u0000\u0000\u0000\u017b\u017e\u0001\u0000"+ + "\u0000\u0000\u017c\u017d\u0001\u0000\u0000\u0000\u017c\u017a\u0001\u0000"+ + "\u0000\u0000\u017d\u017f\u0001\u0000\u0000\u0000\u017e\u017c\u0001\u0000"+ + "\u0000\u0000\u017f\u0180\u0005\'\u0000\u0000\u0180P\u0001\u0000\u0000"+ + "\u0000\u0181\u0185\u0005\"\u0000\u0000\u0182\u0184\t\u0000\u0000\u0000"+ + "\u0183\u0182\u0001\u0000\u0000\u0000\u0184\u0187\u0001\u0000\u0000\u0000"+ + "\u0185\u0186\u0001\u0000\u0000\u0000\u0185\u0183\u0001\u0000\u0000\u0000"+ + "\u0186\u0188\u0001\u0000\u0000\u0000\u0187\u0185\u0001\u0000\u0000\u0000"+ + "\u0188\u0189\u0005\"\u0000\u0000\u0189R\u0001\u0000\u0000\u0000#\u0000"+ + "Y_iqy\u0083\u008f\u00a9\u00c3\u00cb\u00d3\u00db\u00e3\u00ed\u00f7\u0105"+ + "\u010d\u0115\u0139\u013f\u0146\u014b\u0150\u0157\u0159\u015f\u0161\u0166"+ + "\u016c\u016e\u0172\u0174\u017c\u0185\u0001\u0006\u0000\u0000"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionListener.java b/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionListener.java index 0cf661c..f152d69 100644 --- a/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionListener.java +++ b/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionListener.java @@ -88,6 +88,18 @@ public interface BooleanExpressionListener extends ParseTreeListener { * @param ctx the parse tree */ void exitToExpression(BooleanExpressionParser.ToExpressionContext ctx); + /** + * Enter a parse tree produced by the {@code arithmeticFunctionExpression} + * labeled alternative in {@link BooleanExpressionParser#expression}. + * @param ctx the parse tree + */ + void enterArithmeticFunctionExpression(BooleanExpressionParser.ArithmeticFunctionExpressionContext ctx); + /** + * Exit a parse tree produced by the {@code arithmeticFunctionExpression} + * labeled alternative in {@link BooleanExpressionParser#expression}. + * @param ctx the parse tree + */ + void exitArithmeticFunctionExpression(BooleanExpressionParser.ArithmeticFunctionExpressionContext ctx); /** * Enter a parse tree produced by the {@code notExpression} * labeled alternative in {@link BooleanExpressionParser#expression}. @@ -156,6 +168,16 @@ public interface BooleanExpressionListener extends ParseTreeListener { * @param ctx the parse tree */ void exitArithmeticOperator(BooleanExpressionParser.ArithmeticOperatorContext ctx); + /** + * Enter a parse tree produced by {@link BooleanExpressionParser#arrayArithmeticFunction}. + * @param ctx the parse tree + */ + void enterArrayArithmeticFunction(BooleanExpressionParser.ArrayArithmeticFunctionContext ctx); + /** + * Exit a parse tree produced by {@link BooleanExpressionParser#arrayArithmeticFunction}. + * @param ctx the parse tree + */ + void exitArrayArithmeticFunction(BooleanExpressionParser.ArrayArithmeticFunctionContext ctx); /** * Enter a parse tree produced by {@link BooleanExpressionParser#wordlist}. * @param ctx the parse tree diff --git a/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionParser.java b/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionParser.java index e32b2b8..dccc41d 100644 --- a/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionParser.java +++ b/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanExpressionParser.java @@ -17,34 +17,37 @@ public class BooleanExpressionParser extends Parser { new PredictionContextCache(); public static final int T__0=1, IN=2, TO=3, AND=4, OR=5, NOT=6, TRUE=7, FALSE=8, CONTAINS_ALL=9, - CONTAINS_ANY=10, ADD=11, SUBTRACT=12, MULTIPLY=13, DIVIDE=14, MODULUS=15, - EXPONENT=16, NE=17, GT=18, GE=19, LT=20, LE=21, EQ=22, LPAREN=23, RPAREN=24, - DECIMAL=25, APP_VERSION=26, INTEGER=27, WS=28, WORD=29, ALPHANUMERIC=30, - SQ=31, DQ=32; + CONTAINS_ANY=10, MIN=11, MAX=12, AVG=13, SUM=14, MEAN=15, MODE=16, MEDIAN=17, + LEN=18, INT=19, ADD=20, SUBTRACT=21, MULTIPLY=22, DIVIDE=23, MODULUS=24, + EXPONENT=25, NE=26, GT=27, GE=28, LT=29, LE=30, EQ=31, LPAREN=32, RPAREN=33, + DECIMAL=34, APP_VERSION=35, INTEGER=36, WS=37, WORD=38, ALPHANUMERIC=39, + SQ=40, DQ=41; public static final int RULE_parse = 0, RULE_expression = 1, RULE_comparator = 2, RULE_arithmeticOperator = 3, - RULE_wordlist = 4, RULE_arrayOperators = 5, RULE_numericTypes = 6, RULE_types = 7, - RULE_binary = 8, RULE_bool = 9; + RULE_arrayArithmeticFunction = 4, RULE_wordlist = 5, RULE_arrayOperators = 6, + RULE_numericTypes = 7, RULE_types = 8, RULE_binary = 9, RULE_bool = 10; private static String[] makeRuleNames() { return new String[] { - "parse", "expression", "comparator", "arithmeticOperator", "wordlist", - "arrayOperators", "numericTypes", "types", "binary", "bool" + "parse", "expression", "comparator", "arithmeticOperator", "arrayArithmeticFunction", + "wordlist", "arrayOperators", "numericTypes", "types", "binary", "bool" }; } public static final String[] ruleNames = makeRuleNames(); private static String[] makeLiteralNames() { return new String[] { - null, "','", null, null, null, null, null, null, null, null, null, "'+'", - "'-'", "'*'", "'/'", "'%'", "'^'", "'!='", "'>'", "'>='", "'<'", "'<='", - "'='", "'('", "')'" + null, "','", null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, "'+'", "'-'", "'*'", + "'/'", "'%'", "'^'", "'!='", "'>'", "'>='", "'<'", "'<='", "'='", "'('", + "')'" }; } private static final String[] _LITERAL_NAMES = makeLiteralNames(); private static String[] makeSymbolicNames() { return new String[] { null, null, "IN", "TO", "AND", "OR", "NOT", "TRUE", "FALSE", "CONTAINS_ALL", - "CONTAINS_ANY", "ADD", "SUBTRACT", "MULTIPLY", "DIVIDE", "MODULUS", "EXPONENT", + "CONTAINS_ANY", "MIN", "MAX", "AVG", "SUM", "MEAN", "MODE", "MEDIAN", + "LEN", "INT", "ADD", "SUBTRACT", "MULTIPLY", "DIVIDE", "MODULUS", "EXPONENT", "NE", "GT", "GE", "LT", "LE", "EQ", "LPAREN", "RPAREN", "DECIMAL", "APP_VERSION", "INTEGER", "WS", "WORD", "ALPHANUMERIC", "SQ", "DQ" }; @@ -126,9 +129,9 @@ public final ParseContext parse() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(20); + setState(22); expression(0); - setState(21); + setState(23); match(EOF); } } @@ -279,6 +282,26 @@ public void exitRule(ParseTreeListener listener) { } } @SuppressWarnings("CheckReturnValue") + public static class ArithmeticFunctionExpressionContext extends ExpressionContext { + public ArrayArithmeticFunctionContext left; + public WordlistContext data; + public ArrayArithmeticFunctionContext arrayArithmeticFunction() { + return getRuleContext(ArrayArithmeticFunctionContext.class,0); + } + public WordlistContext wordlist() { + return getRuleContext(WordlistContext.class,0); + } + public ArithmeticFunctionExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof BooleanExpressionListener ) ((BooleanExpressionListener)listener).enterArithmeticFunctionExpression(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof BooleanExpressionListener ) ((BooleanExpressionListener)listener).exitArithmeticFunctionExpression(this); + } + } + @SuppressWarnings("CheckReturnValue") public static class NotExpressionContext extends ExpressionContext { public TerminalNode NOT() { return getToken(BooleanExpressionParser.NOT, 0); } public ExpressionContext expression() { @@ -379,7 +402,7 @@ private ExpressionContext expression(int _p) throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(54); + setState(59); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,4,_ctx) ) { case 1: @@ -388,11 +411,11 @@ private ExpressionContext expression(int _p) throws RecognitionException { _ctx = _localctx; _prevctx = _localctx; - setState(24); + setState(26); match(LPAREN); - setState(25); + setState(27); expression(0); - setState(26); + setState(28); match(RPAREN); } break; @@ -401,10 +424,10 @@ private ExpressionContext expression(int _p) throws RecognitionException { _localctx = new NotExpressionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(28); + setState(30); match(NOT); - setState(29); - expression(14); + setState(31); + expression(15); } break; case 3: @@ -412,99 +435,110 @@ private ExpressionContext expression(int _p) throws RecognitionException { _localctx = new UnaryArithmeticExpressionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(30); + setState(32); ((UnaryArithmeticExpressionContext)_localctx).op = match(SUBTRACT); - setState(31); - ((UnaryArithmeticExpressionContext)_localctx).exp = expression(12); + setState(33); + ((UnaryArithmeticExpressionContext)_localctx).exp = expression(13); } break; case 4: + { + _localctx = new ArithmeticFunctionExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(34); + ((ArithmeticFunctionExpressionContext)_localctx).left = arrayArithmeticFunction(); + setState(35); + ((ArithmeticFunctionExpressionContext)_localctx).data = wordlist(); + } + break; + case 5: { _localctx = new TypesExpressionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(32); + setState(37); types(); } break; - case 5: + case 6: { _localctx = new ToExpressionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(34); + setState(39); _errHandler.sync(this); _la = _input.LA(1); if (_la==WORD) { { - setState(33); + setState(38); ((ToExpressionContext)_localctx).field = match(WORD); } } - setState(36); + setState(41); ((ToExpressionContext)_localctx).lower = numericTypes(); - setState(37); + setState(42); match(TO); - setState(38); + setState(43); ((ToExpressionContext)_localctx).upper = numericTypes(); } break; - case 6: + case 7: { _localctx = new InExpressionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(41); + setState(46); _errHandler.sync(this); _la = _input.LA(1); if (_la==WORD) { { - setState(40); + setState(45); ((InExpressionContext)_localctx).field = match(WORD); } } - setState(44); + setState(49); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(43); + setState(48); ((InExpressionContext)_localctx).not = match(NOT); } } - setState(46); + setState(51); match(IN); - setState(47); + setState(52); ((InExpressionContext)_localctx).data = wordlist(); } break; - case 7: + case 8: { _localctx = new ArrayExpressionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(49); + setState(54); _errHandler.sync(this); _la = _input.LA(1); if (_la==WORD) { { - setState(48); + setState(53); ((ArrayExpressionContext)_localctx).field = match(WORD); } } - setState(51); + setState(56); ((ArrayExpressionContext)_localctx).op = arrayOperators(); - setState(52); + setState(57); ((ArrayExpressionContext)_localctx).data = wordlist(); } break; } _ctx.stop = _input.LT(-1); - setState(84); + setState(89); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,6,_ctx); while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { @@ -512,7 +546,7 @@ private ExpressionContext expression(int _p) throws RecognitionException { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(82); + setState(87); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,5,_ctx) ) { case 1: @@ -520,12 +554,12 @@ private ExpressionContext expression(int _p) throws RecognitionException { _localctx = new ComparatorExpressionContext(new ExpressionContext(_parentctx, _parentState)); ((ComparatorExpressionContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(56); - if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)"); - setState(57); + setState(61); + if (!(precpred(_ctx, 14))) throw new FailedPredicateException(this, "precpred(_ctx, 14)"); + setState(62); ((ComparatorExpressionContext)_localctx).op = comparator(); - setState(58); - ((ComparatorExpressionContext)_localctx).right = expression(14); + setState(63); + ((ComparatorExpressionContext)_localctx).right = expression(15); } break; case 2: @@ -533,12 +567,12 @@ private ExpressionContext expression(int _p) throws RecognitionException { _localctx = new ArithmeticExpressionContext(new ExpressionContext(_parentctx, _parentState)); ((ArithmeticExpressionContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(60); - if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)"); - setState(61); + setState(65); + if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); + setState(66); ((ArithmeticExpressionContext)_localctx).op = match(EXPONENT); - setState(62); - ((ArithmeticExpressionContext)_localctx).right = expression(12); + setState(67); + ((ArithmeticExpressionContext)_localctx).right = expression(13); } break; case 3: @@ -546,12 +580,12 @@ private ExpressionContext expression(int _p) throws RecognitionException { _localctx = new ArithmeticExpressionContext(new ExpressionContext(_parentctx, _parentState)); ((ArithmeticExpressionContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(63); - if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); - setState(64); + setState(68); + if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)"); + setState(69); ((ArithmeticExpressionContext)_localctx).op = match(DIVIDE); - setState(65); - ((ArithmeticExpressionContext)_localctx).right = expression(11); + setState(70); + ((ArithmeticExpressionContext)_localctx).right = expression(12); } break; case 4: @@ -559,12 +593,12 @@ private ExpressionContext expression(int _p) throws RecognitionException { _localctx = new ArithmeticExpressionContext(new ExpressionContext(_parentctx, _parentState)); ((ArithmeticExpressionContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(66); - if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); - setState(67); + setState(71); + if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); + setState(72); ((ArithmeticExpressionContext)_localctx).op = match(MULTIPLY); - setState(68); - ((ArithmeticExpressionContext)_localctx).right = expression(10); + setState(73); + ((ArithmeticExpressionContext)_localctx).right = expression(11); } break; case 5: @@ -572,12 +606,12 @@ private ExpressionContext expression(int _p) throws RecognitionException { _localctx = new ArithmeticExpressionContext(new ExpressionContext(_parentctx, _parentState)); ((ArithmeticExpressionContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(69); - if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)"); - setState(70); + setState(74); + if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); + setState(75); ((ArithmeticExpressionContext)_localctx).op = match(MODULUS); - setState(71); - ((ArithmeticExpressionContext)_localctx).right = expression(9); + setState(76); + ((ArithmeticExpressionContext)_localctx).right = expression(10); } break; case 6: @@ -585,12 +619,12 @@ private ExpressionContext expression(int _p) throws RecognitionException { _localctx = new ArithmeticExpressionContext(new ExpressionContext(_parentctx, _parentState)); ((ArithmeticExpressionContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(72); - if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); - setState(73); + setState(77); + if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)"); + setState(78); ((ArithmeticExpressionContext)_localctx).op = match(ADD); - setState(74); - ((ArithmeticExpressionContext)_localctx).right = expression(8); + setState(79); + ((ArithmeticExpressionContext)_localctx).right = expression(9); } break; case 7: @@ -598,12 +632,12 @@ private ExpressionContext expression(int _p) throws RecognitionException { _localctx = new ArithmeticExpressionContext(new ExpressionContext(_parentctx, _parentState)); ((ArithmeticExpressionContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(75); - if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); - setState(76); + setState(80); + if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); + setState(81); ((ArithmeticExpressionContext)_localctx).op = match(SUBTRACT); - setState(77); - ((ArithmeticExpressionContext)_localctx).right = expression(7); + setState(82); + ((ArithmeticExpressionContext)_localctx).right = expression(8); } break; case 8: @@ -611,18 +645,18 @@ private ExpressionContext expression(int _p) throws RecognitionException { _localctx = new BinaryExpressionContext(new ExpressionContext(_parentctx, _parentState)); ((BinaryExpressionContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(78); + setState(83); if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)"); - setState(79); + setState(84); ((BinaryExpressionContext)_localctx).op = binary(); - setState(80); + setState(85); ((BinaryExpressionContext)_localctx).right = expression(6); } break; } } } - setState(86); + setState(91); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,6,_ctx); } @@ -668,9 +702,9 @@ public final ComparatorContext comparator() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(87); + setState(92); _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 8257536L) != 0)) ) { + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 4227858432L) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -720,9 +754,64 @@ public final ArithmeticOperatorContext arithmeticOperator() throws RecognitionEx try { enterOuterAlt(_localctx, 1); { - setState(89); + setState(94); _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 129024L) != 0)) ) { + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 66060288L) != 0)) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ArrayArithmeticFunctionContext extends ParserRuleContext { + public TerminalNode MIN() { return getToken(BooleanExpressionParser.MIN, 0); } + public TerminalNode MAX() { return getToken(BooleanExpressionParser.MAX, 0); } + public TerminalNode SUM() { return getToken(BooleanExpressionParser.SUM, 0); } + public TerminalNode AVG() { return getToken(BooleanExpressionParser.AVG, 0); } + public TerminalNode MEAN() { return getToken(BooleanExpressionParser.MEAN, 0); } + public TerminalNode MODE() { return getToken(BooleanExpressionParser.MODE, 0); } + public TerminalNode LEN() { return getToken(BooleanExpressionParser.LEN, 0); } + public TerminalNode MEDIAN() { return getToken(BooleanExpressionParser.MEDIAN, 0); } + public TerminalNode INT() { return getToken(BooleanExpressionParser.INT, 0); } + public ArrayArithmeticFunctionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_arrayArithmeticFunction; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof BooleanExpressionListener ) ((BooleanExpressionListener)listener).enterArrayArithmeticFunction(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof BooleanExpressionListener ) ((BooleanExpressionListener)listener).exitArrayArithmeticFunction(this); + } + } + + public final ArrayArithmeticFunctionContext arrayArithmeticFunction() throws RecognitionException { + ArrayArithmeticFunctionContext _localctx = new ArrayArithmeticFunctionContext(_ctx, getState()); + enterRule(_localctx, 8, RULE_arrayArithmeticFunction); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(96); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 1046528L) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -775,93 +864,93 @@ public void exitRule(ParseTreeListener listener) { public final WordlistContext wordlist() throws RecognitionException { WordlistContext _localctx = new WordlistContext(_ctx, getState()); - enterRule(_localctx, 8, RULE_wordlist); + enterRule(_localctx, 10, RULE_wordlist); int _la; try { int _alt; enterOuterAlt(_localctx, 1); { - setState(91); + setState(98); match(LPAREN); - setState(95); + setState(102); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,7,_ctx); while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(92); + setState(99); match(WS); } } } - setState(97); + setState(104); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,7,_ctx); } - setState(98); + setState(105); ((WordlistContext)_localctx).first = types(); - setState(102); + setState(109); _errHandler.sync(this); _la = _input.LA(1); while (_la==WS) { { { - setState(99); + setState(106); match(WS); } } - setState(104); + setState(111); _errHandler.sync(this); _la = _input.LA(1); } - setState(121); + setState(128); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__0) { { { - setState(105); + setState(112); match(T__0); - setState(109); + setState(116); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,9,_ctx); while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(106); + setState(113); match(WS); } } } - setState(111); + setState(118); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,9,_ctx); } - setState(112); + setState(119); ((WordlistContext)_localctx).rest = types(); - setState(116); + setState(123); _errHandler.sync(this); _la = _input.LA(1); while (_la==WS) { { { - setState(113); + setState(120); match(WS); } } - setState(118); + setState(125); _errHandler.sync(this); _la = _input.LA(1); } } } - setState(123); + setState(130); _errHandler.sync(this); _la = _input.LA(1); } - setState(124); + setState(131); match(RPAREN); } } @@ -896,12 +985,12 @@ public void exitRule(ParseTreeListener listener) { public final ArrayOperatorsContext arrayOperators() throws RecognitionException { ArrayOperatorsContext _localctx = new ArrayOperatorsContext(_ctx, getState()); - enterRule(_localctx, 10, RULE_arrayOperators); + enterRule(_localctx, 12, RULE_arrayOperators); int _la; try { enterOuterAlt(_localctx, 1); { - setState(126); + setState(133); _la = _input.LA(1); if ( !(_la==CONTAINS_ALL || _la==CONTAINS_ANY) ) { _errHandler.recoverInline(this); @@ -944,12 +1033,12 @@ public void exitRule(ParseTreeListener listener) { public final NumericTypesContext numericTypes() throws RecognitionException { NumericTypesContext _localctx = new NumericTypesContext(_ctx, getState()); - enterRule(_localctx, 12, RULE_numericTypes); + enterRule(_localctx, 14, RULE_numericTypes); int _la; try { enterOuterAlt(_localctx, 1); { - setState(128); + setState(135); _la = _input.LA(1); if ( !(_la==DECIMAL || _la==INTEGER) ) { _errHandler.recoverInline(this); @@ -997,43 +1086,43 @@ public void exitRule(ParseTreeListener listener) { public final TypesContext types() throws RecognitionException { TypesContext _localctx = new TypesContext(_ctx, getState()); - enterRule(_localctx, 14, RULE_types); + enterRule(_localctx, 16, RULE_types); try { - setState(136); + setState(143); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,12,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(130); + setState(137); match(INTEGER); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(131); + setState(138); match(DECIMAL); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(132); + setState(139); match(APP_VERSION); } break; case 4: enterOuterAlt(_localctx, 4); { - setState(133); + setState(140); bool(); } break; case 5: enterOuterAlt(_localctx, 5); { - setState(134); + setState(141); match(WORD); } break; @@ -1075,12 +1164,12 @@ public void exitRule(ParseTreeListener listener) { public final BinaryContext binary() throws RecognitionException { BinaryContext _localctx = new BinaryContext(_ctx, getState()); - enterRule(_localctx, 16, RULE_binary); + enterRule(_localctx, 18, RULE_binary); int _la; try { enterOuterAlt(_localctx, 1); { - setState(138); + setState(145); _la = _input.LA(1); if ( !(_la==AND || _la==OR) ) { _errHandler.recoverInline(this); @@ -1123,12 +1212,12 @@ public void exitRule(ParseTreeListener listener) { public final BoolContext bool() throws RecognitionException { BoolContext _localctx = new BoolContext(_ctx, getState()); - enterRule(_localctx, 18, RULE_bool); + enterRule(_localctx, 20, RULE_bool); int _la; try { enterOuterAlt(_localctx, 1); { - setState(140); + setState(147); _la = _input.LA(1); if ( !(_la==TRUE || _la==FALSE) ) { _errHandler.recoverInline(this); @@ -1161,19 +1250,19 @@ public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { private boolean expression_sempred(ExpressionContext _localctx, int predIndex) { switch (predIndex) { case 0: - return precpred(_ctx, 13); + return precpred(_ctx, 14); case 1: - return precpred(_ctx, 11); + return precpred(_ctx, 12); case 2: - return precpred(_ctx, 10); + return precpred(_ctx, 11); case 3: - return precpred(_ctx, 9); + return precpred(_ctx, 10); case 4: - return precpred(_ctx, 8); + return precpred(_ctx, 9); case 5: - return precpred(_ctx, 7); + return precpred(_ctx, 8); case 6: - return precpred(_ctx, 6); + return precpred(_ctx, 7); case 7: return precpred(_ctx, 5); } @@ -1181,95 +1270,99 @@ private boolean expression_sempred(ExpressionContext _localctx, int predIndex) { } public static final String _serializedATN = - "\u0004\u0001 \u008f\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001\u0002"+ + "\u0004\u0001)\u0096\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001\u0002"+ "\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004\u0007\u0004\u0002"+ "\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007\u0007\u0007\u0002"+ - "\b\u0007\b\u0002\t\u0007\t\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0001"+ + "\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0001\u0000\u0001\u0000\u0001"+ + "\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ - "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0001#\b\u0001"+ - "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0001"+ - "*\b\u0001\u0001\u0001\u0003\u0001-\b\u0001\u0001\u0001\u0001\u0001\u0001"+ + "\u0001\u0001\u0001\u0001\u0001\u0003\u0001(\b\u0001\u0001\u0001\u0001"+ + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0001/\b\u0001\u0001"+ "\u0001\u0003\u00012\b\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003"+ - "\u00017\b\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ + "\u00017\b\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0001<\b\u0001"+ + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ - "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u0001S\b\u0001\n\u0001"+ - "\f\u0001V\t\u0001\u0001\u0002\u0001\u0002\u0001\u0003\u0001\u0003\u0001"+ - "\u0004\u0001\u0004\u0005\u0004^\b\u0004\n\u0004\f\u0004a\t\u0004\u0001"+ - "\u0004\u0001\u0004\u0005\u0004e\b\u0004\n\u0004\f\u0004h\t\u0004\u0001"+ - "\u0004\u0001\u0004\u0005\u0004l\b\u0004\n\u0004\f\u0004o\t\u0004\u0001"+ - "\u0004\u0001\u0004\u0005\u0004s\b\u0004\n\u0004\f\u0004v\t\u0004\u0005"+ - "\u0004x\b\u0004\n\u0004\f\u0004{\t\u0004\u0001\u0004\u0001\u0004\u0001"+ - "\u0005\u0001\u0005\u0001\u0006\u0001\u0006\u0001\u0007\u0001\u0007\u0001"+ - "\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0003\u0007\u0089\b\u0007\u0001"+ - "\b\u0001\b\u0001\t\u0001\t\u0001\t\u0000\u0001\u0002\n\u0000\u0002\u0004"+ - "\u0006\b\n\f\u000e\u0010\u0012\u0000\u0006\u0001\u0000\u0011\u0016\u0001"+ - "\u0000\u000b\u0010\u0001\u0000\t\n\u0002\u0000\u0019\u0019\u001b\u001b"+ - "\u0001\u0000\u0004\u0005\u0001\u0000\u0007\b\u00a0\u0000\u0014\u0001\u0000"+ - "\u0000\u0000\u00026\u0001\u0000\u0000\u0000\u0004W\u0001\u0000\u0000\u0000"+ - "\u0006Y\u0001\u0000\u0000\u0000\b[\u0001\u0000\u0000\u0000\n~\u0001\u0000"+ - "\u0000\u0000\f\u0080\u0001\u0000\u0000\u0000\u000e\u0088\u0001\u0000\u0000"+ - "\u0000\u0010\u008a\u0001\u0000\u0000\u0000\u0012\u008c\u0001\u0000\u0000"+ - "\u0000\u0014\u0015\u0003\u0002\u0001\u0000\u0015\u0016\u0005\u0000\u0000"+ - "\u0001\u0016\u0001\u0001\u0000\u0000\u0000\u0017\u0018\u0006\u0001\uffff"+ - "\uffff\u0000\u0018\u0019\u0005\u0017\u0000\u0000\u0019\u001a\u0003\u0002"+ - "\u0001\u0000\u001a\u001b\u0005\u0018\u0000\u0000\u001b7\u0001\u0000\u0000"+ - "\u0000\u001c\u001d\u0005\u0006\u0000\u0000\u001d7\u0003\u0002\u0001\u000e"+ - "\u001e\u001f\u0005\f\u0000\u0000\u001f7\u0003\u0002\u0001\f 7\u0003\u000e"+ - "\u0007\u0000!#\u0005\u001d\u0000\u0000\"!\u0001\u0000\u0000\u0000\"#\u0001"+ - "\u0000\u0000\u0000#$\u0001\u0000\u0000\u0000$%\u0003\f\u0006\u0000%&\u0005"+ - "\u0003\u0000\u0000&\'\u0003\f\u0006\u0000\'7\u0001\u0000\u0000\u0000("+ - "*\u0005\u001d\u0000\u0000)(\u0001\u0000\u0000\u0000)*\u0001\u0000\u0000"+ - "\u0000*,\u0001\u0000\u0000\u0000+-\u0005\u0006\u0000\u0000,+\u0001\u0000"+ - "\u0000\u0000,-\u0001\u0000\u0000\u0000-.\u0001\u0000\u0000\u0000./\u0005"+ - "\u0002\u0000\u0000/7\u0003\b\u0004\u000002\u0005\u001d\u0000\u000010\u0001"+ - "\u0000\u0000\u000012\u0001\u0000\u0000\u000023\u0001\u0000\u0000\u0000"+ - "34\u0003\n\u0005\u000045\u0003\b\u0004\u000057\u0001\u0000\u0000\u0000"+ - "6\u0017\u0001\u0000\u0000\u00006\u001c\u0001\u0000\u0000\u00006\u001e"+ - "\u0001\u0000\u0000\u00006 \u0001\u0000\u0000\u00006\"\u0001\u0000\u0000"+ - "\u00006)\u0001\u0000\u0000\u000061\u0001\u0000\u0000\u00007T\u0001\u0000"+ - "\u0000\u000089\n\r\u0000\u00009:\u0003\u0004\u0002\u0000:;\u0003\u0002"+ - "\u0001\u000e;S\u0001\u0000\u0000\u0000<=\n\u000b\u0000\u0000=>\u0005\u0010"+ - "\u0000\u0000>S\u0003\u0002\u0001\f?@\n\n\u0000\u0000@A\u0005\u000e\u0000"+ - "\u0000AS\u0003\u0002\u0001\u000bBC\n\t\u0000\u0000CD\u0005\r\u0000\u0000"+ - "DS\u0003\u0002\u0001\nEF\n\b\u0000\u0000FG\u0005\u000f\u0000\u0000GS\u0003"+ - "\u0002\u0001\tHI\n\u0007\u0000\u0000IJ\u0005\u000b\u0000\u0000JS\u0003"+ - "\u0002\u0001\bKL\n\u0006\u0000\u0000LM\u0005\f\u0000\u0000MS\u0003\u0002"+ - "\u0001\u0007NO\n\u0005\u0000\u0000OP\u0003\u0010\b\u0000PQ\u0003\u0002"+ - "\u0001\u0006QS\u0001\u0000\u0000\u0000R8\u0001\u0000\u0000\u0000R<\u0001"+ - "\u0000\u0000\u0000R?\u0001\u0000\u0000\u0000RB\u0001\u0000\u0000\u0000"+ - "RE\u0001\u0000\u0000\u0000RH\u0001\u0000\u0000\u0000RK\u0001\u0000\u0000"+ - "\u0000RN\u0001\u0000\u0000\u0000SV\u0001\u0000\u0000\u0000TR\u0001\u0000"+ - "\u0000\u0000TU\u0001\u0000\u0000\u0000U\u0003\u0001\u0000\u0000\u0000"+ - "VT\u0001\u0000\u0000\u0000WX\u0007\u0000\u0000\u0000X\u0005\u0001\u0000"+ - "\u0000\u0000YZ\u0007\u0001\u0000\u0000Z\u0007\u0001\u0000\u0000\u0000"+ - "[_\u0005\u0017\u0000\u0000\\^\u0005\u001c\u0000\u0000]\\\u0001\u0000\u0000"+ - "\u0000^a\u0001\u0000\u0000\u0000_]\u0001\u0000\u0000\u0000_`\u0001\u0000"+ - "\u0000\u0000`b\u0001\u0000\u0000\u0000a_\u0001\u0000\u0000\u0000bf\u0003"+ - "\u000e\u0007\u0000ce\u0005\u001c\u0000\u0000dc\u0001\u0000\u0000\u0000"+ - "eh\u0001\u0000\u0000\u0000fd\u0001\u0000\u0000\u0000fg\u0001\u0000\u0000"+ - "\u0000gy\u0001\u0000\u0000\u0000hf\u0001\u0000\u0000\u0000im\u0005\u0001"+ - "\u0000\u0000jl\u0005\u001c\u0000\u0000kj\u0001\u0000\u0000\u0000lo\u0001"+ - "\u0000\u0000\u0000mk\u0001\u0000\u0000\u0000mn\u0001\u0000\u0000\u0000"+ - "np\u0001\u0000\u0000\u0000om\u0001\u0000\u0000\u0000pt\u0003\u000e\u0007"+ - "\u0000qs\u0005\u001c\u0000\u0000rq\u0001\u0000\u0000\u0000sv\u0001\u0000"+ - "\u0000\u0000tr\u0001\u0000\u0000\u0000tu\u0001\u0000\u0000\u0000ux\u0001"+ - "\u0000\u0000\u0000vt\u0001\u0000\u0000\u0000wi\u0001\u0000\u0000\u0000"+ - "x{\u0001\u0000\u0000\u0000yw\u0001\u0000\u0000\u0000yz\u0001\u0000\u0000"+ - "\u0000z|\u0001\u0000\u0000\u0000{y\u0001\u0000\u0000\u0000|}\u0005\u0018"+ - "\u0000\u0000}\t\u0001\u0000\u0000\u0000~\u007f\u0007\u0002\u0000\u0000"+ - "\u007f\u000b\u0001\u0000\u0000\u0000\u0080\u0081\u0007\u0003\u0000\u0000"+ - "\u0081\r\u0001\u0000\u0000\u0000\u0082\u0089\u0005\u001b\u0000\u0000\u0083"+ - "\u0089\u0005\u0019\u0000\u0000\u0084\u0089\u0005\u001a\u0000\u0000\u0085"+ - "\u0089\u0003\u0012\t\u0000\u0086\u0089\u0005\u001d\u0000\u0000\u0087\u0089"+ - "\u0001\u0000\u0000\u0000\u0088\u0082\u0001\u0000\u0000\u0000\u0088\u0083"+ - "\u0001\u0000\u0000\u0000\u0088\u0084\u0001\u0000\u0000\u0000\u0088\u0085"+ - "\u0001\u0000\u0000\u0000\u0088\u0086\u0001\u0000\u0000\u0000\u0088\u0087"+ - "\u0001\u0000\u0000\u0000\u0089\u000f\u0001\u0000\u0000\u0000\u008a\u008b"+ - "\u0007\u0004\u0000\u0000\u008b\u0011\u0001\u0000\u0000\u0000\u008c\u008d"+ - "\u0007\u0005\u0000\u0000\u008d\u0013\u0001\u0000\u0000\u0000\r\"),16R"+ - "T_fmty\u0088"; + "\u0001\u0001\u0001\u0001\u0005\u0001X\b\u0001\n\u0001\f\u0001[\t\u0001"+ + "\u0001\u0002\u0001\u0002\u0001\u0003\u0001\u0003\u0001\u0004\u0001\u0004"+ + "\u0001\u0005\u0001\u0005\u0005\u0005e\b\u0005\n\u0005\f\u0005h\t\u0005"+ + "\u0001\u0005\u0001\u0005\u0005\u0005l\b\u0005\n\u0005\f\u0005o\t\u0005"+ + "\u0001\u0005\u0001\u0005\u0005\u0005s\b\u0005\n\u0005\f\u0005v\t\u0005"+ + "\u0001\u0005\u0001\u0005\u0005\u0005z\b\u0005\n\u0005\f\u0005}\t\u0005"+ + "\u0005\u0005\u007f\b\u0005\n\u0005\f\u0005\u0082\t\u0005\u0001\u0005\u0001"+ + "\u0005\u0001\u0006\u0001\u0006\u0001\u0007\u0001\u0007\u0001\b\u0001\b"+ + "\u0001\b\u0001\b\u0001\b\u0001\b\u0003\b\u0090\b\b\u0001\t\u0001\t\u0001"+ + "\n\u0001\n\u0001\n\u0000\u0001\u0002\u000b\u0000\u0002\u0004\u0006\b\n"+ + "\f\u000e\u0010\u0012\u0014\u0000\u0007\u0001\u0000\u001a\u001f\u0001\u0000"+ + "\u0014\u0019\u0001\u0000\u000b\u0013\u0001\u0000\t\n\u0002\u0000\"\"$"+ + "$\u0001\u0000\u0004\u0005\u0001\u0000\u0007\b\u00a7\u0000\u0016\u0001"+ + "\u0000\u0000\u0000\u0002;\u0001\u0000\u0000\u0000\u0004\\\u0001\u0000"+ + "\u0000\u0000\u0006^\u0001\u0000\u0000\u0000\b`\u0001\u0000\u0000\u0000"+ + "\nb\u0001\u0000\u0000\u0000\f\u0085\u0001\u0000\u0000\u0000\u000e\u0087"+ + "\u0001\u0000\u0000\u0000\u0010\u008f\u0001\u0000\u0000\u0000\u0012\u0091"+ + "\u0001\u0000\u0000\u0000\u0014\u0093\u0001\u0000\u0000\u0000\u0016\u0017"+ + "\u0003\u0002\u0001\u0000\u0017\u0018\u0005\u0000\u0000\u0001\u0018\u0001"+ + "\u0001\u0000\u0000\u0000\u0019\u001a\u0006\u0001\uffff\uffff\u0000\u001a"+ + "\u001b\u0005 \u0000\u0000\u001b\u001c\u0003\u0002\u0001\u0000\u001c\u001d"+ + "\u0005!\u0000\u0000\u001d<\u0001\u0000\u0000\u0000\u001e\u001f\u0005\u0006"+ + "\u0000\u0000\u001f<\u0003\u0002\u0001\u000f !\u0005\u0015\u0000\u0000"+ + "!<\u0003\u0002\u0001\r\"#\u0003\b\u0004\u0000#$\u0003\n\u0005\u0000$<"+ + "\u0001\u0000\u0000\u0000%<\u0003\u0010\b\u0000&(\u0005&\u0000\u0000\'"+ + "&\u0001\u0000\u0000\u0000\'(\u0001\u0000\u0000\u0000()\u0001\u0000\u0000"+ + "\u0000)*\u0003\u000e\u0007\u0000*+\u0005\u0003\u0000\u0000+,\u0003\u000e"+ + "\u0007\u0000,<\u0001\u0000\u0000\u0000-/\u0005&\u0000\u0000.-\u0001\u0000"+ + "\u0000\u0000./\u0001\u0000\u0000\u0000/1\u0001\u0000\u0000\u000002\u0005"+ + "\u0006\u0000\u000010\u0001\u0000\u0000\u000012\u0001\u0000\u0000\u0000"+ + "23\u0001\u0000\u0000\u000034\u0005\u0002\u0000\u00004<\u0003\n\u0005\u0000"+ + "57\u0005&\u0000\u000065\u0001\u0000\u0000\u000067\u0001\u0000\u0000\u0000"+ + "78\u0001\u0000\u0000\u000089\u0003\f\u0006\u00009:\u0003\n\u0005\u0000"+ + ":<\u0001\u0000\u0000\u0000;\u0019\u0001\u0000\u0000\u0000;\u001e\u0001"+ + "\u0000\u0000\u0000; \u0001\u0000\u0000\u0000;\"\u0001\u0000\u0000\u0000"+ + ";%\u0001\u0000\u0000\u0000;\'\u0001\u0000\u0000\u0000;.\u0001\u0000\u0000"+ + "\u0000;6\u0001\u0000\u0000\u0000\n\u000e\u0000"+ + "\u0000>?\u0003\u0004\u0002\u0000?@\u0003\u0002\u0001\u000f@X\u0001\u0000"+ + "\u0000\u0000AB\n\f\u0000\u0000BC\u0005\u0019\u0000\u0000CX\u0003\u0002"+ + "\u0001\rDE\n\u000b\u0000\u0000EF\u0005\u0017\u0000\u0000FX\u0003\u0002"+ + "\u0001\fGH\n\n\u0000\u0000HI\u0005\u0016\u0000\u0000IX\u0003\u0002\u0001"+ + "\u000bJK\n\t\u0000\u0000KL\u0005\u0018\u0000\u0000LX\u0003\u0002\u0001"+ + "\nMN\n\b\u0000\u0000NO\u0005\u0014\u0000\u0000OX\u0003\u0002\u0001\tP"+ + "Q\n\u0007\u0000\u0000QR\u0005\u0015\u0000\u0000RX\u0003\u0002\u0001\b"+ + "ST\n\u0005\u0000\u0000TU\u0003\u0012\t\u0000UV\u0003\u0002\u0001\u0006"+ + "VX\u0001\u0000\u0000\u0000W=\u0001\u0000\u0000\u0000WA\u0001\u0000\u0000"+ + "\u0000WD\u0001\u0000\u0000\u0000WG\u0001\u0000\u0000\u0000WJ\u0001\u0000"+ + "\u0000\u0000WM\u0001\u0000\u0000\u0000WP\u0001\u0000\u0000\u0000WS\u0001"+ + "\u0000\u0000\u0000X[\u0001\u0000\u0000\u0000YW\u0001\u0000\u0000\u0000"+ + "YZ\u0001\u0000\u0000\u0000Z\u0003\u0001\u0000\u0000\u0000[Y\u0001\u0000"+ + "\u0000\u0000\\]\u0007\u0000\u0000\u0000]\u0005\u0001\u0000\u0000\u0000"+ + "^_\u0007\u0001\u0000\u0000_\u0007\u0001\u0000\u0000\u0000`a\u0007\u0002"+ + "\u0000\u0000a\t\u0001\u0000\u0000\u0000bf\u0005 \u0000\u0000ce\u0005%"+ + "\u0000\u0000dc\u0001\u0000\u0000\u0000eh\u0001\u0000\u0000\u0000fd\u0001"+ + "\u0000\u0000\u0000fg\u0001\u0000\u0000\u0000gi\u0001\u0000\u0000\u0000"+ + "hf\u0001\u0000\u0000\u0000im\u0003\u0010\b\u0000jl\u0005%\u0000\u0000"+ + "kj\u0001\u0000\u0000\u0000lo\u0001\u0000\u0000\u0000mk\u0001\u0000\u0000"+ + "\u0000mn\u0001\u0000\u0000\u0000n\u0080\u0001\u0000\u0000\u0000om\u0001"+ + "\u0000\u0000\u0000pt\u0005\u0001\u0000\u0000qs\u0005%\u0000\u0000rq\u0001"+ + "\u0000\u0000\u0000sv\u0001\u0000\u0000\u0000tr\u0001\u0000\u0000\u0000"+ + "tu\u0001\u0000\u0000\u0000uw\u0001\u0000\u0000\u0000vt\u0001\u0000\u0000"+ + "\u0000w{\u0003\u0010\b\u0000xz\u0005%\u0000\u0000yx\u0001\u0000\u0000"+ + "\u0000z}\u0001\u0000\u0000\u0000{y\u0001\u0000\u0000\u0000{|\u0001\u0000"+ + "\u0000\u0000|\u007f\u0001\u0000\u0000\u0000}{\u0001\u0000\u0000\u0000"+ + "~p\u0001\u0000\u0000\u0000\u007f\u0082\u0001\u0000\u0000\u0000\u0080~"+ + "\u0001\u0000\u0000\u0000\u0080\u0081\u0001\u0000\u0000\u0000\u0081\u0083"+ + "\u0001\u0000\u0000\u0000\u0082\u0080\u0001\u0000\u0000\u0000\u0083\u0084"+ + "\u0005!\u0000\u0000\u0084\u000b\u0001\u0000\u0000\u0000\u0085\u0086\u0007"+ + "\u0003\u0000\u0000\u0086\r\u0001\u0000\u0000\u0000\u0087\u0088\u0007\u0004"+ + "\u0000\u0000\u0088\u000f\u0001\u0000\u0000\u0000\u0089\u0090\u0005$\u0000"+ + "\u0000\u008a\u0090\u0005\"\u0000\u0000\u008b\u0090\u0005#\u0000\u0000"+ + "\u008c\u0090\u0003\u0014\n\u0000\u008d\u0090\u0005&\u0000\u0000\u008e"+ + "\u0090\u0001\u0000\u0000\u0000\u008f\u0089\u0001\u0000\u0000\u0000\u008f"+ + "\u008a\u0001\u0000\u0000\u0000\u008f\u008b\u0001\u0000\u0000\u0000\u008f"+ + "\u008c\u0001\u0000\u0000\u0000\u008f\u008d\u0001\u0000\u0000\u0000\u008f"+ + "\u008e\u0001\u0000\u0000\u0000\u0090\u0011\u0001\u0000\u0000\u0000\u0091"+ + "\u0092\u0007\u0005\u0000\u0000\u0092\u0013\u0001\u0000\u0000\u0000\u0093"+ + "\u0094\u0007\u0006\u0000\u0000\u0094\u0015\u0001\u0000\u0000\u0000\r\'"+ + ".16;WYfmt{\u0080\u008f"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanFilterListener.java b/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanFilterListener.java index 70de966..0359c64 100644 --- a/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanFilterListener.java +++ b/src/main/java/com/github/sidhant92/boolparser/parser/antlr/BooleanFilterListener.java @@ -9,10 +9,12 @@ import org.antlr.v4.runtime.tree.ParseTree; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; +import com.github.sidhant92.boolparser.constant.FunctionType; import com.github.sidhant92.boolparser.constant.DataType; import com.github.sidhant92.boolparser.constant.LogicalOperationType; import com.github.sidhant92.boolparser.constant.Operator; import com.github.sidhant92.boolparser.domain.StringNode; +import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticFunctionNode; import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticLeafNode; import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticNode; import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticUnaryNode; @@ -54,7 +56,14 @@ public Node getNode() { public void exitComparatorExpression(BooleanExpressionParser.ComparatorExpressionContext ctx) { final String variableName = getField(ctx.left.getText()); final Operator operator = Operator.getOperatorFromSymbol(ctx.op.getText()).orElse(Operator.EQUALS); - if (ctx.right instanceof BooleanExpressionParser.ParentExpressionContext && !currentNodes.isEmpty()) { + /*if ((ctx.right instanceof BooleanExpressionParser.ParentExpressionContext || ctx.right instanceof BooleanExpressionParser.ArithmeticFunctionExpressionContext) && !currentNodes.isEmpty()) { + final Node value = currentNodes.pop(); + currentNodes.add(new ComparisonNode(variableName, value, operator, DataType.INTEGER)); + } else { + final DataType dataType = getDataType(ctx.right.getStart()); + currentNodes.add(new ComparisonNode(variableName, ValueUtils.convertValue(ctx.right.getText(), dataType), operator, dataType)); + }*/ + if (!(ctx.right instanceof BooleanExpressionParser.TypesExpressionContext) && !currentNodes.isEmpty()) { final Node value = currentNodes.pop(); currentNodes.add(new ComparisonNode(variableName, value, operator, DataType.INTEGER)); } else { @@ -132,6 +141,21 @@ public void exitArrayExpression(BooleanExpressionParser.ArrayExpressionContext c super.exitArrayExpression(ctx); } + @Override + public void exitArithmeticFunctionExpression(BooleanExpressionParser.ArithmeticFunctionExpressionContext ctx) { + if (ctx.data.exception != null) { + log.error("Error parsing expression for the string {}", ctx.getText()); + throw new InvalidExpressionException(); + } + final FunctionType functionType = FunctionType.getArrayFunctionFromSymbol(ctx.left.getText()).orElseThrow(() -> { + log.error("Error parsing expression for the string {}", ctx.getText()); + return new InvalidExpressionException(); + }); + final List items = getArithmeticArrayElements(ctx.data.children); + currentNodes.add(new ArithmeticFunctionNode(functionType, items)); + super.exitArithmeticFunctionExpression(ctx); + } + @Override public void exitInExpression(BooleanExpressionParser.InExpressionContext ctx) { validateField(ctx.field, ctx.getText()); @@ -159,6 +183,18 @@ private List> getArrayElements(final List tree .collect(Collectors.toList()); } + private List getArithmeticArrayElements(final List trees) { + return trees + .stream() + .filter(child -> child instanceof BooleanExpressionParser.TypesContext) + .map(child -> { + final DataType dataType = getDataType(((BooleanExpressionParser.TypesContext) child).start); + final Object value = ValueUtils.convertValue(child.getText(), dataType); + return new ArithmeticLeafNode(value, dataType); + }) + .collect(Collectors.toList()); + } + private void validateField(final Token token, final String text) { if (Objects.isNull(token) || (StringUtils.isBlank(token.getText()) && StringUtils.isBlank(this.defaultField))) { log.error("Error parsing expression (missing field) for the string {}", text); diff --git a/src/main/java/com/github/sidhant92/boolparser/util/ValueUtils.java b/src/main/java/com/github/sidhant92/boolparser/util/ValueUtils.java index a82e586..2d37783 100644 --- a/src/main/java/com/github/sidhant92/boolparser/util/ValueUtils.java +++ b/src/main/java/com/github/sidhant92/boolparser/util/ValueUtils.java @@ -54,6 +54,13 @@ public static Object convertValue(final String value, final DataType dataType) { } } + public static Object caseDouble(final double value) { + if ((int) value == value) { + return (int) value; + } + return value; + } + public static DataType getNumericDataType(final String value) { final Optional integerOptional = parseInteger(value); return integerOptional.isPresent() ? DataType.INTEGER : DataType.LONG; diff --git a/src/main/java/resources/BooleanExpression.g4 b/src/main/java/resources/BooleanExpression.g4 index 34b4821..807beeb 100644 --- a/src/main/java/resources/BooleanExpression.g4 +++ b/src/main/java/resources/BooleanExpression.g4 @@ -15,6 +15,7 @@ expression | left=expression op= MODULUS right=expression #arithmeticExpression | left=expression op= ADD right=expression #arithmeticExpression | left=expression op= SUBTRACT right=expression #arithmeticExpression + | left=arrayArithmeticFunction data=wordlist #arithmeticFunctionExpression | left=expression op=binary right=expression #binaryExpression | types #typesExpression | (field=WORD)? lower=numericTypes TO upper=numericTypes #toExpression @@ -35,6 +36,18 @@ arithmeticOperator | EXPONENT ; + arrayArithmeticFunction + : MIN + | MAX + | SUM + | AVG + | MEAN + | MODE + | LEN + | MEDIAN + | INT + ; + wordlist : LPAREN WS* first=types WS* (',' WS* rest=types WS*)* RPAREN @@ -72,6 +85,15 @@ TRUE : 'TRUE' | 'true'; FALSE : 'FALSE' | 'false'; CONTAINS_ALL : 'CONTAINS_ALL' | 'contains_all'; CONTAINS_ANY : 'CONTAINS_ANY' | 'contains_any'; +MIN : 'MIN' | 'min'; +MAX : 'MAX' | 'max'; +AVG : 'AVG' | 'avg'; +SUM : 'SUM' | 'sum'; +MEAN : 'MEAN' | 'mean'; +MODE : 'MODE' | 'mode'; +MEDIAN : 'MEDIAN' | 'median'; +LEN : 'LEN' | 'len'; +INT : 'INT' | 'int'; ADD : '+'; SUBTRACT : '-' ; MULTIPLY : '*' ; diff --git a/src/test/java/com/github/sidhant92/boolparser/application/ArithmeticExpressionEvaluatorTest.java b/src/test/java/com/github/sidhant92/boolparser/application/ArithmeticExpressionEvaluatorTest.java index d8ba8f4..928be3d 100644 --- a/src/test/java/com/github/sidhant92/boolparser/application/ArithmeticExpressionEvaluatorTest.java +++ b/src/test/java/com/github/sidhant92/boolparser/application/ArithmeticExpressionEvaluatorTest.java @@ -234,4 +234,167 @@ public void testDoubleUnaryNode() { assertTrue(resultOptional.isSuccess()); assertEquals(resultOptional.get(), 10); } + + @Test + public void testMinArithmeticFunctionInteger() { + final Map data = new HashMap<>(); + data.put("a", 10); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("min (1,2,3)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 1); + } + + @Test + public void testMinArithmeticFunctionDouble() { + final Map data = new HashMap<>(); + data.put("a", 10); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("min (1,2,3,4.5)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 1); + } + + @Test + public void testMaxArithmeticFunctionInteger() { + final Map data = new HashMap<>(); + data.put("a", 10); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("max (1,2,3)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 3); + } + + @Test + public void testMaxArithmeticFunctionDouble() { + final Map data = new HashMap<>(); + data.put("a", 10); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("max (1,2,3,4.5)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 4.5d); + } + + @Test + public void testAvgArithmeticFunctionInteger() { + final Map data = new HashMap<>(); + data.put("a", 10); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("avg (1,2,3)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 2); + } + + @Test + public void testAvgArithmeticFunctionDouble() { + final Map data = new HashMap<>(); + data.put("a", 10); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("avg (1,2,3,4.5)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 2.625); + } + + @Test + public void testSumArithmeticFunctionInteger() { + final Map data = new HashMap<>(); + data.put("a", 10); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("sum (1,2,3)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 6); + } + + @Test + public void testSumArithmeticFunctionDouble() { + final Map data = new HashMap<>(); + data.put("a", 10); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("sum (1,2,3,4.5)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 10.5); + } + + @Test + public void testMeanArithmeticFunctionInteger() { + final Map data = new HashMap<>(); + data.put("a", 10); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("mean (1,2,3)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 2); + } + + @Test + public void testMeanArithmeticFunctionDouble() { + final Map data = new HashMap<>(); + data.put("a", 10); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("mean (1,2,3,4.5)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 2.625); + } + + @Test + public void testModeArithmeticFunctionIntegerVariable() { + final Map data = new HashMap<>(); + final List numbers = new ArrayList<>(); + numbers.add(1); + numbers.add(1); + numbers.add(2); + numbers.add(3); + data.put("a", numbers); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("mode (a)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 1); + } + + @Test + public void testModeArithmeticFunctionDouble() { + final Map data = new HashMap<>(); + data.put("a", 10); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("mode (1,2,3,4.5)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 1); + } + + @Test + public void testMedianArithmeticFunctionInteger() { + final Map data = new HashMap<>(); + data.put("a", 10); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("median (3, 13, 2, 34, 11, 17, 27, 47)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 15); + } + + @Test + public void testIntArithmeticFunction() { + final Map data = new HashMap<>(); + data.put("a", 10); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("int (2.7)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 2); + } + + @Test + public void testIntArithmeticFunctionWithVariable() { + final Map data = new HashMap<>(); + data.put("a", 2.7); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("int (a)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 2); + } + + @Test + public void testLenArithmeticFunctionString() { + final Map data = new HashMap<>(); + data.put("a", "lorem"); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("len (a)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 5); + } + + @Test + public void testLenArithmeticFunctionIntegerVariable() { + final Map data = new HashMap<>(); + final List numbers = new ArrayList<>(); + numbers.add(1); + numbers.add(1); + numbers.add(2); + numbers.add(3); + data.put("a", numbers); + final Try resultOptional = arithmeticExpressionEvaluator.evaluate("len (a)", data); + assertTrue(resultOptional.isSuccess()); + assertEquals(resultOptional.get(), 4); + } } diff --git a/src/test/java/com/github/sidhant92/boolparser/application/BooleanExpressionEvaluatorTest.java b/src/test/java/com/github/sidhant92/boolparser/application/BooleanExpressionEvaluatorTest.java index 2d6a391..79e0017 100644 --- a/src/test/java/com/github/sidhant92/boolparser/application/BooleanExpressionEvaluatorTest.java +++ b/src/test/java/com/github/sidhant92/boolparser/application/BooleanExpressionEvaluatorTest.java @@ -524,6 +524,30 @@ public void testComparisonWithArithmeticTrueCondition() { assertTrue(booleanOptional.get()); } + @Test + public void testComparisonWithArithmeticFunction() { + final Map data = new HashMap<>(); + data.put("age", "20"); + final Try booleanOptional = booleanExpressionEvaluator.evaluate("age > min (18, 25, 30)", data); + assertTrue(booleanOptional.isSuccess()); + assertTrue(booleanOptional.get()); + } + + @Test + public void testComparisonWithArithmeticVariableFunction() { + final Map data = new HashMap<>(); + final List numbers = new ArrayList<>(); + numbers.add(1); + numbers.add(1); + numbers.add(2); + numbers.add(30); + data.put("age", "20"); + data.put("numbers", numbers); + final Try booleanOptional = booleanExpressionEvaluator.evaluate("age > max (numbers))", data); + assertTrue(booleanOptional.isSuccess()); + assertFalse(booleanOptional.get()); + } + @Test public void testComparisonWithArithmeticFalseCondition() { final Map data = new HashMap<>(); diff --git a/src/test/java/com/github/sidhant92/boolparser/parser/antlr/BooleanFilterBoolParserTest.java b/src/test/java/com/github/sidhant92/boolparser/parser/antlr/BooleanFilterBoolParserTest.java index c1044da..a37141f 100644 --- a/src/test/java/com/github/sidhant92/boolparser/parser/antlr/BooleanFilterBoolParserTest.java +++ b/src/test/java/com/github/sidhant92/boolparser/parser/antlr/BooleanFilterBoolParserTest.java @@ -1,6 +1,7 @@ package com.github.sidhant92.boolparser.parser.antlr; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -10,6 +11,7 @@ import com.github.sidhant92.boolparser.constant.NodeType; import com.github.sidhant92.boolparser.constant.Operator; import com.github.sidhant92.boolparser.domain.StringNode; +import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticFunctionNode; import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticLeafNode; import com.github.sidhant92.boolparser.domain.arithmetic.ArithmeticNode; import com.github.sidhant92.boolparser.domain.ArrayNode; @@ -394,6 +396,38 @@ public void testAddOperatorDecimal() { assertEquals(((ArithmeticNode) nodeOptional.get()).getOperator(), Operator.ADD); } + @Test + public void testArithmeticArrayFunction() { + final Try nodeOptional = boolExpressionBoolParser.parseExpression("min (1,2,3)"); + assertTrue(nodeOptional.isSuccess()); + assertEquals(nodeOptional.get().getTokenType(), NodeType.ARITHMETIC_FUNCTION); + assertEquals(((ArithmeticFunctionNode) nodeOptional.get()).getFunctionType().name(), "MIN"); + assertEquals(((ArithmeticFunctionNode) nodeOptional.get()).getItems().size(), 3); + assertEquals(((ArithmeticFunctionNode) nodeOptional.get()).getItems().get(0).getDataType(), DataType.INTEGER); + assertEquals(((ArithmeticFunctionNode) nodeOptional.get()).getItems().get(0).getOperand(), 1); + assertEquals(((ArithmeticFunctionNode) nodeOptional.get()).getItems().get(1).getDataType(), DataType.INTEGER); + assertEquals(((ArithmeticFunctionNode) nodeOptional.get()).getItems().get(1).getOperand(), 2); + assertEquals(((ArithmeticFunctionNode) nodeOptional.get()).getItems().get(2).getDataType(), DataType.INTEGER); + assertEquals(((ArithmeticFunctionNode) nodeOptional.get()).getItems().get(2).getOperand(), 3); + } + + @Test + public void testArithmeticArrayFunctionWithSubstitution() { + final Try nodeOptional = boolExpressionBoolParser.parseExpression("min(abc)"); + assertTrue(nodeOptional.isSuccess()); + assertEquals(nodeOptional.get().getTokenType(), NodeType.ARITHMETIC_FUNCTION); + assertEquals(((ArithmeticFunctionNode) nodeOptional.get()).getFunctionType().name(), "MIN"); + assertEquals(((ArithmeticFunctionNode) nodeOptional.get()).getItems().size(), 1); + assertEquals(((ArithmeticFunctionNode) nodeOptional.get()).getItems().get(0).getDataType(), DataType.STRING); + assertEquals(((ArithmeticFunctionNode) nodeOptional.get()).getItems().get(0).getOperand(), "abc"); + } + + @Test + public void testArithmeticArrayFunctionWithError() { + final Try nodeOptional = boolExpressionBoolParser.parseExpression("min abc"); + assertTrue(nodeOptional.isFailure()); + } + @Test public void testAddOperatorBool() { final Try nodeOptional = boolExpressionBoolParser.parseExpression("false + 5");