From eb8fcaafb9c608e0fa28571f4710d121b0d929af Mon Sep 17 00:00:00 2001 From: Riccardo Azzolini Date: Sun, 11 Aug 2019 21:36:06 +0200 Subject: [PATCH] Keep track of identifiers separately for each SubFunctionPattern object --- .../warppi/math/rules/dsl/Pattern.java | 8 ++-- .../warppi/math/rules/dsl/PatternRule.java | 4 +- .../warppi/math/rules/dsl/PatternUtils.java | 26 ---------- .../warppi/math/rules/dsl/RulesDsl.java | 24 +++++----- .../math/rules/dsl/frontend/Parser.java | 38 +++++++-------- .../rules/dsl/patterns/ArcCosinePattern.java | 4 +- .../rules/dsl/patterns/ArcSinePattern.java | 4 +- .../rules/dsl/patterns/ArcTangentPattern.java | 4 +- .../rules/dsl/patterns/ConstantPattern.java | 7 ++- .../rules/dsl/patterns/CosinePattern.java | 4 +- .../rules/dsl/patterns/DivisionPattern.java | 8 ++-- .../rules/dsl/patterns/EquationPattern.java | 8 ++-- .../dsl/patterns/EquationsSystemPattern.java | 8 ++-- .../rules/dsl/patterns/LogarithmPattern.java | 8 ++-- .../dsl/patterns/MultiplicationPattern.java | 8 ++-- .../rules/dsl/patterns/NegativePattern.java | 4 +- .../rules/dsl/patterns/NumberPattern.java | 7 ++- .../math/rules/dsl/patterns/PowerPattern.java | 8 ++-- .../math/rules/dsl/patterns/RootPattern.java | 8 ++-- .../math/rules/dsl/patterns/SinePattern.java | 4 +- .../dsl/patterns/SubFunctionPattern.java | 7 ++- .../dsl/patterns/SubtractionPattern.java | 8 ++-- .../math/rules/dsl/patterns/SumPattern.java | 8 ++-- .../dsl/patterns/SumSubtractionPattern.java | 8 ++-- .../rules/dsl/patterns/TangentPattern.java | 4 +- .../rules/dsl/patterns/UndefinedPattern.java | 7 ++- .../math/rules/dsl/frontend/ParserTest.java | 47 +++++++++++-------- 27 files changed, 132 insertions(+), 151 deletions(-) delete mode 100644 core/src/main/java/it/cavallium/warppi/math/rules/dsl/PatternUtils.java diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/Pattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/Pattern.java index fca8568a..a24bddc1 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/Pattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/Pattern.java @@ -7,7 +7,7 @@ import it.cavallium.warppi.math.rules.dsl.patterns.SubFunctionPattern; import java.util.HashMap; import java.util.Map; import java.util.Optional; -import java.util.Set; +import java.util.stream.Stream; /** * Recognizes and generates functions of some specific shape. @@ -51,8 +51,10 @@ public interface Pattern { Function replace(MathContext mathContext, Map subFunctions); /** - * @return The (possibly empty) Set of all sub-function patterns + * @return A (possibly empty) Stream of all sub-function patterns * found within this pattern and its children. + * If there are multiple sub-function patterns with the same name, the stream still contains all of them. + * The order of the patterns within the stream is unspecified. */ - Set getSubFunctions(); + Stream getSubFunctions(); } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/PatternRule.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/PatternRule.java index 6124c681..08a94045 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/PatternRule.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/PatternRule.java @@ -52,11 +52,11 @@ public class PatternRule implements Rule { return ruleType; } - Pattern getTarget() { + public Pattern getTarget() { return target; } - List getReplacements() { + public List getReplacements() { return replacements; } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/PatternUtils.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/PatternUtils.java deleted file mode 100644 index 82da67bd..00000000 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/PatternUtils.java +++ /dev/null @@ -1,26 +0,0 @@ -package it.cavallium.warppi.math.rules.dsl; - -import it.cavallium.warppi.math.rules.dsl.patterns.SubFunctionPattern; - -import java.util.*; -import java.util.stream.Collectors; - -/** - * Contains helper methods which are useful for writing patterns. - */ -public class PatternUtils { - private PatternUtils() {} - - /** - * Gathers all sub-function patterns from multiple patterns. - * - * @param patterns The patterns from which sub-functions are gathered. - * @return The union of the return values of {@link Pattern#getSubFunctions()} for each pattern. - */ - public static Set getSubFunctionsFrom(final Pattern... patterns) { - return Arrays.stream(patterns) - .map(Pattern::getSubFunctions) - .flatMap(Set::stream) - .collect(Collectors.toSet()); - } -} diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/RulesDsl.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/RulesDsl.java index 6fbf5fd8..2091a129 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/RulesDsl.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/RulesDsl.java @@ -6,6 +6,8 @@ import it.cavallium.warppi.math.rules.dsl.frontend.Parser; import it.cavallium.warppi.math.rules.dsl.patterns.SubFunctionPattern; import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Implements a domain-specific language (DSL) for the definition of {@link Rule}s. @@ -28,9 +30,10 @@ public class RulesDsl { final List rules = parser.parse(); for (final PatternRule rule : rules) { - undefinedSubFunctions(rule).stream() - .flatMap(subFunc -> parser.getSubFunctionIdentifiers(rule, subFunc).stream()) - .map(UndefinedSubFunction::new) + undefinedSubFunctions(rule) + .map(subFunc -> new UndefinedSubFunction( + parser.getSubFunctionIdentifier(subFunc) + )) .forEach(errors::add); } @@ -46,15 +49,12 @@ public class RulesDsl { * without being defined (captured) in the target pattern. * * @param rule The rule to analyze. - * @return The (possibly empty) set of undefined sub-functions. + * @return A (possibly empty) Stream of undefined sub-functions. */ - private static Set undefinedSubFunctions(final PatternRule rule) { - final Set defined = rule.getTarget().getSubFunctions(); - final Set undefined = new HashSet<>(); - for (final Pattern replacement : rule.getReplacements()) { - undefined.addAll(replacement.getSubFunctions()); - } - undefined.removeAll(defined); - return undefined; + private static Stream undefinedSubFunctions(final PatternRule rule) { + final Set defined = rule.getTarget().getSubFunctions().collect(Collectors.toSet()); + return rule.getReplacements().stream() + .flatMap(Pattern::getSubFunctions) + .filter(subFunc -> !defined.contains(subFunc)); } } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/Parser.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/Parser.java index 8c606665..a9699981 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/Parser.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/Parser.java @@ -32,10 +32,8 @@ public class Parser { private int currentIndex = 0; // For error reporting - private Map> ruleSubFunctionIdentifiers; - // An IdentityHashMap is used to distinguish rules even if they're identical (equal) - private final IdentityHashMap>> subFunctionIdentifiers = - new IdentityHashMap<>(); + // An IdentityHashMap is used to distinguish SubFunctionPatterns even if they're identical (equal) + private final IdentityHashMap subFunctionIdentifiers = new IdentityHashMap<>(); /** * Constructs a Parser that will produce a list of {@link PatternRule}s from the the given list of {@link Token}s. @@ -64,8 +62,21 @@ public class Parser { return rules(); } - public List getSubFunctionIdentifiers(final PatternRule rule, final SubFunctionPattern subFunction) { - return subFunctionIdentifiers.get(rule).get(subFunction); + /** + * Retrieves the IDENTIFIER token which corresponds to the given SubFunctionPattern. + *

+ * The information returned by this method can be used to point out the location of sub-function related errors + * within the DSL source code. + * + * @param subFunction a SubFunctionsPattern from one of the rules returned by this Parser + * instance. While SubFunctionPatterns with the same name are considered equal, + * this method can distinguish between them, in order to return the exact identifier which led + * to the creation of the specified SubFunctionPattern object. + * @return the Token (of type IDENTIFIER) which corresponds to the given + * SubFunctionPattern. + */ + public Token getSubFunctionIdentifier(final SubFunctionPattern subFunction) { + return subFunctionIdentifiers.get(subFunction); } // rules = { rule } , EOF ; @@ -88,14 +99,11 @@ public class Parser { private PatternRule rule() throws SyntaxException { final RuleType type = ruleType(); final String name = matchOrFail(IDENTIFIER).lexeme; - ruleSubFunctionIdentifiers = new HashMap<>(); // Must be initialized before calling pattern() and replacements() matchOrFail(COLON); final Pattern target = pattern(); matchOrFail(ARROW); final List replacements = replacements(); - final PatternRule rule = new PatternRule(name, type, target, replacements); - subFunctionIdentifiers.put(rule, ruleSubFunctionIdentifiers); - return rule; + return new PatternRule(name, type, target, replacements); } // rule type = REDUCTION | EXPANSION | CALCULATION | EXISTENCE ; @@ -247,7 +255,7 @@ public class Parser { return new NumberPattern(new BigDecimal(curToken.lexeme)); case IDENTIFIER: final SubFunctionPattern subFunction = new SubFunctionPattern(curToken.lexeme); - saveSubFunctionIdentifier(subFunction, curToken); + subFunctionIdentifiers.put(subFunction, curToken); return subFunction; case LEFT_PAREN: final Pattern grouped = sum(); @@ -257,14 +265,6 @@ public class Parser { throw new SyntaxException(new UnexpectedToken(curToken)); } - private void saveSubFunctionIdentifier(final SubFunctionPattern subFunction, final Token curToken) { - final List subFunctionList = ruleSubFunctionIdentifiers.computeIfAbsent( - subFunction, - key -> new ArrayList<>() - ); - subFunctionList.add(curToken); - } - private Pattern matchLeftAssoc( final PatternParser operandParser, final Map> operators diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ArcCosinePattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ArcCosinePattern.java index be71da18..58dd1e88 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ArcCosinePattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ArcCosinePattern.java @@ -8,7 +8,7 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates the arccosine of another pattern. @@ -34,7 +34,7 @@ public class ArcCosinePattern extends VisitorPattern { } @Override - public Set getSubFunctions() { + public Stream getSubFunctions() { return argument.getSubFunctions(); } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ArcSinePattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ArcSinePattern.java index 4d338151..75487cd0 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ArcSinePattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ArcSinePattern.java @@ -8,7 +8,7 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates the arcsine of another pattern. @@ -34,7 +34,7 @@ public class ArcSinePattern extends VisitorPattern { } @Override - public Set getSubFunctions() { + public Stream getSubFunctions() { return argument.getSubFunctions(); } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ArcTangentPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ArcTangentPattern.java index d71c8cff..d986f14e 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ArcTangentPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ArcTangentPattern.java @@ -8,7 +8,7 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates the arctangent of another pattern. @@ -34,7 +34,7 @@ public class ArcTangentPattern extends VisitorPattern { } @Override - public Set getSubFunctions() { + public Stream getSubFunctions() { return argument.getSubFunctions(); } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ConstantPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ConstantPattern.java index 47882d50..932639ea 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ConstantPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/ConstantPattern.java @@ -5,10 +5,9 @@ import it.cavallium.warppi.math.MathContext; import it.cavallium.warppi.math.functions.Variable; import it.cavallium.warppi.math.rules.dsl.VisitorPattern; -import java.util.Collections; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates a specific symbolic constant. @@ -32,8 +31,8 @@ public class ConstantPattern extends VisitorPattern { } @Override - public Set getSubFunctions() { - return Collections.emptySet(); + public Stream getSubFunctions() { + return Stream.empty(); } @Override diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/CosinePattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/CosinePattern.java index bcfecad0..3aed3da2 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/CosinePattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/CosinePattern.java @@ -8,7 +8,7 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates the cosine of another pattern. @@ -34,7 +34,7 @@ public class CosinePattern extends VisitorPattern { } @Override - public Set getSubFunctions() { + public Stream getSubFunctions() { return argument.getSubFunctions(); } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/DivisionPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/DivisionPattern.java index 586bb5e0..5973dc0b 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/DivisionPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/DivisionPattern.java @@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function; import it.cavallium.warppi.math.MathContext; import it.cavallium.warppi.math.functions.Division; import it.cavallium.warppi.math.rules.dsl.Pattern; -import it.cavallium.warppi.math.rules.dsl.PatternUtils; import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates a division of two other patterns. @@ -39,8 +38,9 @@ public class DivisionPattern extends VisitorPattern { } @Override - public Set getSubFunctions() { - return PatternUtils.getSubFunctionsFrom(dividend, divisor); + public Stream getSubFunctions() { + return Stream.of(dividend, divisor) + .flatMap(Pattern::getSubFunctions); } @Override diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/EquationPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/EquationPattern.java index 4af796ed..72e5b820 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/EquationPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/EquationPattern.java @@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function; import it.cavallium.warppi.math.MathContext; import it.cavallium.warppi.math.functions.equations.Equation; import it.cavallium.warppi.math.rules.dsl.Pattern; -import it.cavallium.warppi.math.rules.dsl.PatternUtils; import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates an equation of two other patterns. @@ -39,8 +38,9 @@ public class EquationPattern extends VisitorPattern { } @Override - public Set getSubFunctions() { - return PatternUtils.getSubFunctionsFrom(left, right); + public Stream getSubFunctions() { + return Stream.of(left, right) + .flatMap(Pattern::getSubFunctions); } @Override diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/EquationsSystemPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/EquationsSystemPattern.java index e5e8a14d..3999a777 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/EquationsSystemPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/EquationsSystemPattern.java @@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function; import it.cavallium.warppi.math.MathContext; import it.cavallium.warppi.math.functions.equations.EquationsSystem; import it.cavallium.warppi.math.rules.dsl.Pattern; -import it.cavallium.warppi.math.rules.dsl.PatternUtils; import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.util.Arrays; import java.util.Map; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates a system of equations of multiple other patterns. @@ -47,8 +46,9 @@ public class EquationsSystemPattern extends VisitorPattern { } @Override - public Set getSubFunctions() { - return PatternUtils.getSubFunctionsFrom(patterns); + public Stream getSubFunctions() { + return Stream.of(patterns) + .flatMap(Pattern::getSubFunctions); } @Override diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/LogarithmPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/LogarithmPattern.java index 608eb4d0..d24bcf7a 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/LogarithmPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/LogarithmPattern.java @@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function; import it.cavallium.warppi.math.MathContext; import it.cavallium.warppi.math.functions.Logarithm; import it.cavallium.warppi.math.rules.dsl.Pattern; -import it.cavallium.warppi.math.rules.dsl.PatternUtils; import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates a logarithm of base and argument patterns. @@ -39,8 +38,9 @@ public class LogarithmPattern extends VisitorPattern { } @Override - public Set getSubFunctions() { - return PatternUtils.getSubFunctionsFrom(base, argument); + public Stream getSubFunctions() { + return Stream.of(base, argument) + .flatMap(Pattern::getSubFunctions); } @Override diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/MultiplicationPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/MultiplicationPattern.java index fb8ded54..6f5f9f6d 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/MultiplicationPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/MultiplicationPattern.java @@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function; import it.cavallium.warppi.math.MathContext; import it.cavallium.warppi.math.functions.Multiplication; import it.cavallium.warppi.math.rules.dsl.Pattern; -import it.cavallium.warppi.math.rules.dsl.PatternUtils; import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates a multiplication of two other patterns. @@ -39,8 +38,9 @@ public class MultiplicationPattern extends VisitorPattern { } @Override - public Set getSubFunctions() { - return PatternUtils.getSubFunctionsFrom(left, right); + public Stream getSubFunctions() { + return Stream.of(left, right) + .flatMap(Pattern::getSubFunctions); } @Override diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/NegativePattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/NegativePattern.java index 1dc56619..f2d7ca4c 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/NegativePattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/NegativePattern.java @@ -10,7 +10,7 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.math.BigDecimal; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates the negative of another pattern. @@ -52,7 +52,7 @@ public class NegativePattern extends VisitorPattern { } @Override - public Set getSubFunctions() { + public Stream getSubFunctions() { return inner.getSubFunctions(); } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/NumberPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/NumberPattern.java index d5786ef8..c4aad340 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/NumberPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/NumberPattern.java @@ -6,10 +6,9 @@ import it.cavallium.warppi.math.functions.Number; import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.math.BigDecimal; -import java.util.Collections; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates a specific number. @@ -32,8 +31,8 @@ public class NumberPattern extends VisitorPattern { } @Override - public Set getSubFunctions() { - return Collections.emptySet(); + public Stream getSubFunctions() { + return Stream.empty(); } @Override diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/PowerPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/PowerPattern.java index 5f7313bd..baeb0ef4 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/PowerPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/PowerPattern.java @@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function; import it.cavallium.warppi.math.MathContext; import it.cavallium.warppi.math.functions.Power; import it.cavallium.warppi.math.rules.dsl.Pattern; -import it.cavallium.warppi.math.rules.dsl.PatternUtils; import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates a power (exponentiation) of base and exponent patterns. @@ -39,8 +38,9 @@ public class PowerPattern extends VisitorPattern { } @Override - public Set getSubFunctions() { - return PatternUtils.getSubFunctionsFrom(base, exponent); + public Stream getSubFunctions() { + return Stream.of(base, exponent) + .flatMap(Pattern::getSubFunctions); } @Override diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/RootPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/RootPattern.java index 0847c3a7..15a119e3 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/RootPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/RootPattern.java @@ -6,13 +6,12 @@ import it.cavallium.warppi.math.functions.Number; import it.cavallium.warppi.math.functions.Root; import it.cavallium.warppi.math.functions.RootSquare; import it.cavallium.warppi.math.rules.dsl.Pattern; -import it.cavallium.warppi.math.rules.dsl.PatternUtils; import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.math.BigDecimal; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates a root of degree and radicand patterns. @@ -54,8 +53,9 @@ public class RootPattern extends VisitorPattern { } @Override - public Set getSubFunctions() { - return PatternUtils.getSubFunctionsFrom(degree, radicand); + public Stream getSubFunctions() { + return Stream.of(degree, radicand) + .flatMap(Pattern::getSubFunctions); } @Override diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SinePattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SinePattern.java index ec9fa94f..f684ccc1 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SinePattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SinePattern.java @@ -8,7 +8,7 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates the sine of another pattern. @@ -34,7 +34,7 @@ public class SinePattern extends VisitorPattern { } @Override - public Set getSubFunctions() { + public Stream getSubFunctions() { return argument.getSubFunctions(); } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SubFunctionPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SubFunctionPattern.java index ddc442e0..002fc22f 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SubFunctionPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SubFunctionPattern.java @@ -4,10 +4,9 @@ import it.cavallium.warppi.math.Function; import it.cavallium.warppi.math.MathContext; import it.cavallium.warppi.math.rules.dsl.Pattern; -import java.util.Collections; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates any function as a named sub-function. @@ -31,8 +30,8 @@ public class SubFunctionPattern implements Pattern { } @Override - public Set getSubFunctions() { - return Collections.singleton(this); + public Stream getSubFunctions() { + return Stream.of(this); } @Override diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SubtractionPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SubtractionPattern.java index 7a71d397..69cbcfae 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SubtractionPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SubtractionPattern.java @@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function; import it.cavallium.warppi.math.MathContext; import it.cavallium.warppi.math.functions.Subtraction; import it.cavallium.warppi.math.rules.dsl.Pattern; -import it.cavallium.warppi.math.rules.dsl.PatternUtils; import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates a subtraction of two other patterns. @@ -39,8 +38,9 @@ public class SubtractionPattern extends VisitorPattern { } @Override - public Set getSubFunctions() { - return PatternUtils.getSubFunctionsFrom(left, right); + public Stream getSubFunctions() { + return Stream.of(left, right) + .flatMap(Pattern::getSubFunctions); } @Override diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SumPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SumPattern.java index e4f7fbd3..1555a21f 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SumPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SumPattern.java @@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function; import it.cavallium.warppi.math.MathContext; import it.cavallium.warppi.math.functions.Sum; import it.cavallium.warppi.math.rules.dsl.Pattern; -import it.cavallium.warppi.math.rules.dsl.PatternUtils; import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates a sum of two other patterns. @@ -39,8 +38,9 @@ public class SumPattern extends VisitorPattern { } @Override - public Set getSubFunctions() { - return PatternUtils.getSubFunctionsFrom(left, right); + public Stream getSubFunctions() { + return Stream.of(left, right) + .flatMap(Pattern::getSubFunctions); } @Override diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SumSubtractionPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SumSubtractionPattern.java index 8a566804..2270396f 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SumSubtractionPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/SumSubtractionPattern.java @@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function; import it.cavallium.warppi.math.MathContext; import it.cavallium.warppi.math.functions.SumSubtraction; import it.cavallium.warppi.math.rules.dsl.Pattern; -import it.cavallium.warppi.math.rules.dsl.PatternUtils; import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates a sum/subtraction (±) of two other patterns. @@ -39,8 +38,9 @@ public class SumSubtractionPattern extends VisitorPattern { } @Override - public Set getSubFunctions() { - return PatternUtils.getSubFunctionsFrom(left, right); + public Stream getSubFunctions() { + return Stream.of(left, right) + .flatMap(Pattern::getSubFunctions); } @Override diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/TangentPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/TangentPattern.java index ef2a26cc..d0761f65 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/TangentPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/TangentPattern.java @@ -8,7 +8,7 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern; import java.util.Map; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates the tangent of another pattern. @@ -34,7 +34,7 @@ public class TangentPattern extends VisitorPattern { } @Override - public Set getSubFunctions() { + public Stream getSubFunctions() { return argument.getSubFunctions(); } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/UndefinedPattern.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/UndefinedPattern.java index f886ac68..ddd3a082 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/UndefinedPattern.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/patterns/UndefinedPattern.java @@ -5,9 +5,8 @@ import it.cavallium.warppi.math.MathContext; import it.cavallium.warppi.math.functions.Undefined; import it.cavallium.warppi.math.rules.dsl.VisitorPattern; -import java.util.Collections; import java.util.Map; -import java.util.Set; +import java.util.stream.Stream; /** * Matches and generates Undefined. @@ -24,8 +23,8 @@ public class UndefinedPattern extends VisitorPattern { } @Override - public Set getSubFunctions() { - return Collections.emptySet(); + public Stream getSubFunctions() { + return Stream.empty(); } @Override diff --git a/core/src/test/java/it/cavallium/warppi/math/rules/dsl/frontend/ParserTest.java b/core/src/test/java/it/cavallium/warppi/math/rules/dsl/frontend/ParserTest.java index d64a558c..1f75150d 100644 --- a/core/src/test/java/it/cavallium/warppi/math/rules/dsl/frontend/ParserTest.java +++ b/core/src/test/java/it/cavallium/warppi/math/rules/dsl/frontend/ParserTest.java @@ -6,6 +6,7 @@ import it.cavallium.warppi.math.rules.dsl.DslError; import it.cavallium.warppi.math.rules.dsl.Pattern; import it.cavallium.warppi.math.rules.dsl.PatternRule; import it.cavallium.warppi.math.rules.dsl.patterns.*; +import org.apache.commons.lang3.ObjectUtils; import org.junit.Before; import org.junit.Test; @@ -15,6 +16,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import static it.cavallium.warppi.math.rules.dsl.frontend.TokenType.*; import static org.junit.Assert.*; @@ -344,21 +346,11 @@ public class ParserTest { final Parser parser = new Parser(tokens, errors::add); final List rules = parser.parse(); - assertEquals(rule0x, toReferenceEquality( - parser.getSubFunctionIdentifiers(rules.get(0), new SubFunctionPattern("x")) - )); - assertEquals(rule1x, toReferenceEquality( - parser.getSubFunctionIdentifiers(rules.get(1), new SubFunctionPattern("x")) - )); - assertEquals(rule1y, toReferenceEquality( - parser.getSubFunctionIdentifiers(rules.get(1), new SubFunctionPattern("y")) - )); - assertEquals(rule2x, toReferenceEquality( - parser.getSubFunctionIdentifiers(rules.get(2), new SubFunctionPattern("x")) - )); - assertEquals(rule3x, toReferenceEquality( - parser.getSubFunctionIdentifiers(rules.get(3), new SubFunctionPattern("x")) - )); + assertEquals(rule0x, getSubFunctionIdentifiers(parser, rules.get(0), "x")); + assertEquals(rule1x, getSubFunctionIdentifiers(parser, rules.get(1), "x")); + assertEquals(rule1y, getSubFunctionIdentifiers(parser, rules.get(1), "y")); + assertEquals(rule2x, getSubFunctionIdentifiers(parser, rules.get(2), "x")); + assertEquals(rule3x, getSubFunctionIdentifiers(parser, rules.get(3), "x")); } private static Token addIdentifierToken(final List list, final String identifier) { @@ -367,10 +359,22 @@ public class ParserTest { return token; } - private static List toReferenceEquality(final List tokens) { - return tokens.stream() - .map(ReferenceEqualityToken::new) - .collect(Collectors.toList()); + private static List getSubFunctionIdentifiers( + final Parser parser, + final PatternRule rule, + final String subFunctionName + ) { + final SubFunctionPattern exampleSubFunction = new SubFunctionPattern(subFunctionName); + final Stream allSubFunctions = Stream.concat( + rule.getTarget().getSubFunctions(), + rule.getReplacements().stream().flatMap(Pattern::getSubFunctions) + ); + return allSubFunctions + .filter(subFunc -> subFunc.equals(exampleSubFunction)) // Match the name without having access to it directly + .map(subFunc -> new ReferenceEqualityToken( + parser.getSubFunctionIdentifier(subFunc) + )) + .collect(Collectors.toList()); } private static class ReferenceEqualityToken { @@ -387,6 +391,11 @@ public class ParserTest { } return this.token == ((ReferenceEqualityToken) o).token; } + + @Override + public String toString() { + return "ReferenceEqualityToken{" + ObjectUtils.identityToString(token) + '}'; + } } // The EOF token is inserted by the lexer, therefore it can only be missing