Keep track of identifiers separately for each SubFunctionPattern object
This commit is contained in:
parent
c8656d1b30
commit
eb8fcaafb9
@ -7,7 +7,7 @@ import it.cavallium.warppi.math.rules.dsl.patterns.SubFunctionPattern;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recognizes and generates functions of some specific shape.
|
* Recognizes and generates functions of some specific shape.
|
||||||
@ -51,8 +51,10 @@ public interface Pattern {
|
|||||||
Function replace(MathContext mathContext, Map<String, Function> subFunctions);
|
Function replace(MathContext mathContext, Map<String, Function> subFunctions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The (possibly empty) <code>Set</code> of all sub-function patterns
|
* @return A (possibly empty) <code>Stream</code> of all sub-function patterns
|
||||||
* found within this pattern and its children.
|
* 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<SubFunctionPattern> getSubFunctions();
|
Stream<SubFunctionPattern> getSubFunctions();
|
||||||
}
|
}
|
||||||
|
@ -52,11 +52,11 @@ public class PatternRule implements Rule {
|
|||||||
return ruleType;
|
return ruleType;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pattern getTarget() {
|
public Pattern getTarget() {
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Pattern> getReplacements() {
|
public List<Pattern> getReplacements() {
|
||||||
return replacements;
|
return replacements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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<SubFunctionPattern> getSubFunctionsFrom(final Pattern... patterns) {
|
|
||||||
return Arrays.stream(patterns)
|
|
||||||
.map(Pattern::getSubFunctions)
|
|
||||||
.flatMap(Set::stream)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,6 +6,8 @@ import it.cavallium.warppi.math.rules.dsl.frontend.Parser;
|
|||||||
import it.cavallium.warppi.math.rules.dsl.patterns.SubFunctionPattern;
|
import it.cavallium.warppi.math.rules.dsl.patterns.SubFunctionPattern;
|
||||||
|
|
||||||
import java.util.*;
|
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.
|
* Implements a domain-specific language (DSL) for the definition of {@link Rule}s.
|
||||||
@ -28,9 +30,10 @@ public class RulesDsl {
|
|||||||
final List<PatternRule> rules = parser.parse();
|
final List<PatternRule> rules = parser.parse();
|
||||||
|
|
||||||
for (final PatternRule rule : rules) {
|
for (final PatternRule rule : rules) {
|
||||||
undefinedSubFunctions(rule).stream()
|
undefinedSubFunctions(rule)
|
||||||
.flatMap(subFunc -> parser.getSubFunctionIdentifiers(rule, subFunc).stream())
|
.map(subFunc -> new UndefinedSubFunction(
|
||||||
.map(UndefinedSubFunction::new)
|
parser.getSubFunctionIdentifier(subFunc)
|
||||||
|
))
|
||||||
.forEach(errors::add);
|
.forEach(errors::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,15 +49,12 @@ public class RulesDsl {
|
|||||||
* without being defined (captured) in the target pattern.
|
* without being defined (captured) in the target pattern.
|
||||||
*
|
*
|
||||||
* @param rule The rule to analyze.
|
* @param rule The rule to analyze.
|
||||||
* @return The (possibly empty) set of undefined sub-functions.
|
* @return A (possibly empty) <code>Stream</code> of undefined sub-functions.
|
||||||
*/
|
*/
|
||||||
private static Set<SubFunctionPattern> undefinedSubFunctions(final PatternRule rule) {
|
private static Stream<SubFunctionPattern> undefinedSubFunctions(final PatternRule rule) {
|
||||||
final Set<SubFunctionPattern> defined = rule.getTarget().getSubFunctions();
|
final Set<SubFunctionPattern> defined = rule.getTarget().getSubFunctions().collect(Collectors.toSet());
|
||||||
final Set<SubFunctionPattern> undefined = new HashSet<>();
|
return rule.getReplacements().stream()
|
||||||
for (final Pattern replacement : rule.getReplacements()) {
|
.flatMap(Pattern::getSubFunctions)
|
||||||
undefined.addAll(replacement.getSubFunctions());
|
.filter(subFunc -> !defined.contains(subFunc));
|
||||||
}
|
|
||||||
undefined.removeAll(defined);
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,10 +32,8 @@ public class Parser {
|
|||||||
private int currentIndex = 0;
|
private int currentIndex = 0;
|
||||||
|
|
||||||
// For error reporting
|
// For error reporting
|
||||||
private Map<SubFunctionPattern, List<Token>> ruleSubFunctionIdentifiers;
|
// An IdentityHashMap is used to distinguish SubFunctionPatterns even if they're identical (equal)
|
||||||
// An IdentityHashMap is used to distinguish rules even if they're identical (equal)
|
private final IdentityHashMap<SubFunctionPattern, Token> subFunctionIdentifiers = new IdentityHashMap<>();
|
||||||
private final IdentityHashMap<PatternRule, Map<SubFunctionPattern, List<Token>>> subFunctionIdentifiers =
|
|
||||||
new IdentityHashMap<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a <code>Parser</code> that will produce a list of {@link PatternRule}s from the the given list of {@link Token}s.
|
* Constructs a <code>Parser</code> 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();
|
return rules();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Token> getSubFunctionIdentifiers(final PatternRule rule, final SubFunctionPattern subFunction) {
|
/**
|
||||||
return subFunctionIdentifiers.get(rule).get(subFunction);
|
* Retrieves the <code>IDENTIFIER</code> token which corresponds to the given <code>SubFunctionPattern</code>.
|
||||||
|
* <p>
|
||||||
|
* 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 <code>SubFunctionsPattern</code> from one of the rules returned by this <code>Parser</code>
|
||||||
|
* instance. While <code>SubFunctionPattern</code>s 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 <code>SubFunctionPattern</code> object.
|
||||||
|
* @return the <code>Token</code> (of type <code>IDENTIFIER</code>) which corresponds to the given
|
||||||
|
* <code>SubFunctionPattern</code>.
|
||||||
|
*/
|
||||||
|
public Token getSubFunctionIdentifier(final SubFunctionPattern subFunction) {
|
||||||
|
return subFunctionIdentifiers.get(subFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// rules = { rule } , EOF ;
|
// rules = { rule } , EOF ;
|
||||||
@ -88,14 +99,11 @@ public class Parser {
|
|||||||
private PatternRule rule() throws SyntaxException {
|
private PatternRule rule() throws SyntaxException {
|
||||||
final RuleType type = ruleType();
|
final RuleType type = ruleType();
|
||||||
final String name = matchOrFail(IDENTIFIER).lexeme;
|
final String name = matchOrFail(IDENTIFIER).lexeme;
|
||||||
ruleSubFunctionIdentifiers = new HashMap<>(); // Must be initialized before calling pattern() and replacements()
|
|
||||||
matchOrFail(COLON);
|
matchOrFail(COLON);
|
||||||
final Pattern target = pattern();
|
final Pattern target = pattern();
|
||||||
matchOrFail(ARROW);
|
matchOrFail(ARROW);
|
||||||
final List<Pattern> replacements = replacements();
|
final List<Pattern> replacements = replacements();
|
||||||
final PatternRule rule = new PatternRule(name, type, target, replacements);
|
return new PatternRule(name, type, target, replacements);
|
||||||
subFunctionIdentifiers.put(rule, ruleSubFunctionIdentifiers);
|
|
||||||
return rule;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// rule type = REDUCTION | EXPANSION | CALCULATION | EXISTENCE ;
|
// rule type = REDUCTION | EXPANSION | CALCULATION | EXISTENCE ;
|
||||||
@ -247,7 +255,7 @@ public class Parser {
|
|||||||
return new NumberPattern(new BigDecimal(curToken.lexeme));
|
return new NumberPattern(new BigDecimal(curToken.lexeme));
|
||||||
case IDENTIFIER:
|
case IDENTIFIER:
|
||||||
final SubFunctionPattern subFunction = new SubFunctionPattern(curToken.lexeme);
|
final SubFunctionPattern subFunction = new SubFunctionPattern(curToken.lexeme);
|
||||||
saveSubFunctionIdentifier(subFunction, curToken);
|
subFunctionIdentifiers.put(subFunction, curToken);
|
||||||
return subFunction;
|
return subFunction;
|
||||||
case LEFT_PAREN:
|
case LEFT_PAREN:
|
||||||
final Pattern grouped = sum();
|
final Pattern grouped = sum();
|
||||||
@ -257,14 +265,6 @@ public class Parser {
|
|||||||
throw new SyntaxException(new UnexpectedToken(curToken));
|
throw new SyntaxException(new UnexpectedToken(curToken));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveSubFunctionIdentifier(final SubFunctionPattern subFunction, final Token curToken) {
|
|
||||||
final List<Token> subFunctionList = ruleSubFunctionIdentifiers.computeIfAbsent(
|
|
||||||
subFunction,
|
|
||||||
key -> new ArrayList<>()
|
|
||||||
);
|
|
||||||
subFunctionList.add(curToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Pattern matchLeftAssoc(
|
private Pattern matchLeftAssoc(
|
||||||
final PatternParser operandParser,
|
final PatternParser operandParser,
|
||||||
final Map<TokenType, BiFunction<Pattern, Pattern, Pattern>> operators
|
final Map<TokenType, BiFunction<Pattern, Pattern, Pattern>> operators
|
||||||
|
@ -8,7 +8,7 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates the arccosine of another pattern.
|
* Matches and generates the arccosine of another pattern.
|
||||||
@ -34,7 +34,7 @@ public class ArcCosinePattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return argument.getSubFunctions();
|
return argument.getSubFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates the arcsine of another pattern.
|
* Matches and generates the arcsine of another pattern.
|
||||||
@ -34,7 +34,7 @@ public class ArcSinePattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return argument.getSubFunctions();
|
return argument.getSubFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates the arctangent of another pattern.
|
* Matches and generates the arctangent of another pattern.
|
||||||
@ -34,7 +34,7 @@ public class ArcTangentPattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return argument.getSubFunctions();
|
return argument.getSubFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,10 +5,9 @@ import it.cavallium.warppi.math.MathContext;
|
|||||||
import it.cavallium.warppi.math.functions.Variable;
|
import it.cavallium.warppi.math.functions.Variable;
|
||||||
import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates a specific symbolic constant.
|
* Matches and generates a specific symbolic constant.
|
||||||
@ -32,8 +31,8 @@ public class ConstantPattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return Collections.emptySet();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -8,7 +8,7 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates the cosine of another pattern.
|
* Matches and generates the cosine of another pattern.
|
||||||
@ -34,7 +34,7 @@ public class CosinePattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return argument.getSubFunctions();
|
return argument.getSubFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function;
|
|||||||
import it.cavallium.warppi.math.MathContext;
|
import it.cavallium.warppi.math.MathContext;
|
||||||
import it.cavallium.warppi.math.functions.Division;
|
import it.cavallium.warppi.math.functions.Division;
|
||||||
import it.cavallium.warppi.math.rules.dsl.Pattern;
|
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 it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates a division of two other patterns.
|
* Matches and generates a division of two other patterns.
|
||||||
@ -39,8 +38,9 @@ public class DivisionPattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return PatternUtils.getSubFunctionsFrom(dividend, divisor);
|
return Stream.of(dividend, divisor)
|
||||||
|
.flatMap(Pattern::getSubFunctions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function;
|
|||||||
import it.cavallium.warppi.math.MathContext;
|
import it.cavallium.warppi.math.MathContext;
|
||||||
import it.cavallium.warppi.math.functions.equations.Equation;
|
import it.cavallium.warppi.math.functions.equations.Equation;
|
||||||
import it.cavallium.warppi.math.rules.dsl.Pattern;
|
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 it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates an equation of two other patterns.
|
* Matches and generates an equation of two other patterns.
|
||||||
@ -39,8 +38,9 @@ public class EquationPattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return PatternUtils.getSubFunctionsFrom(left, right);
|
return Stream.of(left, right)
|
||||||
|
.flatMap(Pattern::getSubFunctions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function;
|
|||||||
import it.cavallium.warppi.math.MathContext;
|
import it.cavallium.warppi.math.MathContext;
|
||||||
import it.cavallium.warppi.math.functions.equations.EquationsSystem;
|
import it.cavallium.warppi.math.functions.equations.EquationsSystem;
|
||||||
import it.cavallium.warppi.math.rules.dsl.Pattern;
|
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 it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates a system of equations of multiple other patterns.
|
* Matches and generates a system of equations of multiple other patterns.
|
||||||
@ -47,8 +46,9 @@ public class EquationsSystemPattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return PatternUtils.getSubFunctionsFrom(patterns);
|
return Stream.of(patterns)
|
||||||
|
.flatMap(Pattern::getSubFunctions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function;
|
|||||||
import it.cavallium.warppi.math.MathContext;
|
import it.cavallium.warppi.math.MathContext;
|
||||||
import it.cavallium.warppi.math.functions.Logarithm;
|
import it.cavallium.warppi.math.functions.Logarithm;
|
||||||
import it.cavallium.warppi.math.rules.dsl.Pattern;
|
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 it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates a logarithm of base and argument patterns.
|
* Matches and generates a logarithm of base and argument patterns.
|
||||||
@ -39,8 +38,9 @@ public class LogarithmPattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return PatternUtils.getSubFunctionsFrom(base, argument);
|
return Stream.of(base, argument)
|
||||||
|
.flatMap(Pattern::getSubFunctions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function;
|
|||||||
import it.cavallium.warppi.math.MathContext;
|
import it.cavallium.warppi.math.MathContext;
|
||||||
import it.cavallium.warppi.math.functions.Multiplication;
|
import it.cavallium.warppi.math.functions.Multiplication;
|
||||||
import it.cavallium.warppi.math.rules.dsl.Pattern;
|
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 it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates a multiplication of two other patterns.
|
* Matches and generates a multiplication of two other patterns.
|
||||||
@ -39,8 +38,9 @@ public class MultiplicationPattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return PatternUtils.getSubFunctionsFrom(left, right);
|
return Stream.of(left, right)
|
||||||
|
.flatMap(Pattern::getSubFunctions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -10,7 +10,7 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates the negative of another pattern.
|
* Matches and generates the negative of another pattern.
|
||||||
@ -52,7 +52,7 @@ public class NegativePattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return inner.getSubFunctions();
|
return inner.getSubFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,10 +6,9 @@ import it.cavallium.warppi.math.functions.Number;
|
|||||||
import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates a specific number.
|
* Matches and generates a specific number.
|
||||||
@ -32,8 +31,8 @@ public class NumberPattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return Collections.emptySet();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function;
|
|||||||
import it.cavallium.warppi.math.MathContext;
|
import it.cavallium.warppi.math.MathContext;
|
||||||
import it.cavallium.warppi.math.functions.Power;
|
import it.cavallium.warppi.math.functions.Power;
|
||||||
import it.cavallium.warppi.math.rules.dsl.Pattern;
|
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 it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates a power (exponentiation) of base and exponent patterns.
|
* Matches and generates a power (exponentiation) of base and exponent patterns.
|
||||||
@ -39,8 +38,9 @@ public class PowerPattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return PatternUtils.getSubFunctionsFrom(base, exponent);
|
return Stream.of(base, exponent)
|
||||||
|
.flatMap(Pattern::getSubFunctions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -6,13 +6,12 @@ import it.cavallium.warppi.math.functions.Number;
|
|||||||
import it.cavallium.warppi.math.functions.Root;
|
import it.cavallium.warppi.math.functions.Root;
|
||||||
import it.cavallium.warppi.math.functions.RootSquare;
|
import it.cavallium.warppi.math.functions.RootSquare;
|
||||||
import it.cavallium.warppi.math.rules.dsl.Pattern;
|
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 it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates a root of degree and radicand patterns.
|
* Matches and generates a root of degree and radicand patterns.
|
||||||
@ -54,8 +53,9 @@ public class RootPattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return PatternUtils.getSubFunctionsFrom(degree, radicand);
|
return Stream.of(degree, radicand)
|
||||||
|
.flatMap(Pattern::getSubFunctions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -8,7 +8,7 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates the sine of another pattern.
|
* Matches and generates the sine of another pattern.
|
||||||
@ -34,7 +34,7 @@ public class SinePattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return argument.getSubFunctions();
|
return argument.getSubFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,10 +4,9 @@ import it.cavallium.warppi.math.Function;
|
|||||||
import it.cavallium.warppi.math.MathContext;
|
import it.cavallium.warppi.math.MathContext;
|
||||||
import it.cavallium.warppi.math.rules.dsl.Pattern;
|
import it.cavallium.warppi.math.rules.dsl.Pattern;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates any function as a named sub-function.
|
* Matches and generates any function as a named sub-function.
|
||||||
@ -31,8 +30,8 @@ public class SubFunctionPattern implements Pattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return Collections.singleton(this);
|
return Stream.of(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function;
|
|||||||
import it.cavallium.warppi.math.MathContext;
|
import it.cavallium.warppi.math.MathContext;
|
||||||
import it.cavallium.warppi.math.functions.Subtraction;
|
import it.cavallium.warppi.math.functions.Subtraction;
|
||||||
import it.cavallium.warppi.math.rules.dsl.Pattern;
|
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 it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates a subtraction of two other patterns.
|
* Matches and generates a subtraction of two other patterns.
|
||||||
@ -39,8 +38,9 @@ public class SubtractionPattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return PatternUtils.getSubFunctionsFrom(left, right);
|
return Stream.of(left, right)
|
||||||
|
.flatMap(Pattern::getSubFunctions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function;
|
|||||||
import it.cavallium.warppi.math.MathContext;
|
import it.cavallium.warppi.math.MathContext;
|
||||||
import it.cavallium.warppi.math.functions.Sum;
|
import it.cavallium.warppi.math.functions.Sum;
|
||||||
import it.cavallium.warppi.math.rules.dsl.Pattern;
|
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 it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates a sum of two other patterns.
|
* Matches and generates a sum of two other patterns.
|
||||||
@ -39,8 +38,9 @@ public class SumPattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return PatternUtils.getSubFunctionsFrom(left, right);
|
return Stream.of(left, right)
|
||||||
|
.flatMap(Pattern::getSubFunctions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -4,12 +4,11 @@ import it.cavallium.warppi.math.Function;
|
|||||||
import it.cavallium.warppi.math.MathContext;
|
import it.cavallium.warppi.math.MathContext;
|
||||||
import it.cavallium.warppi.math.functions.SumSubtraction;
|
import it.cavallium.warppi.math.functions.SumSubtraction;
|
||||||
import it.cavallium.warppi.math.rules.dsl.Pattern;
|
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 it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates a sum/subtraction (±) of two other patterns.
|
* Matches and generates a sum/subtraction (±) of two other patterns.
|
||||||
@ -39,8 +38,9 @@ public class SumSubtractionPattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return PatternUtils.getSubFunctionsFrom(left, right);
|
return Stream.of(left, right)
|
||||||
|
.flatMap(Pattern::getSubFunctions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -8,7 +8,7 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates the tangent of another pattern.
|
* Matches and generates the tangent of another pattern.
|
||||||
@ -34,7 +34,7 @@ public class TangentPattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return argument.getSubFunctions();
|
return argument.getSubFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,9 +5,8 @@ import it.cavallium.warppi.math.MathContext;
|
|||||||
import it.cavallium.warppi.math.functions.Undefined;
|
import it.cavallium.warppi.math.functions.Undefined;
|
||||||
import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches and generates <code>Undefined</code>.
|
* Matches and generates <code>Undefined</code>.
|
||||||
@ -24,8 +23,8 @@ public class UndefinedPattern extends VisitorPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubFunctionPattern> getSubFunctions() {
|
public Stream<SubFunctionPattern> getSubFunctions() {
|
||||||
return Collections.emptySet();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -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.Pattern;
|
||||||
import it.cavallium.warppi.math.rules.dsl.PatternRule;
|
import it.cavallium.warppi.math.rules.dsl.PatternRule;
|
||||||
import it.cavallium.warppi.math.rules.dsl.patterns.*;
|
import it.cavallium.warppi.math.rules.dsl.patterns.*;
|
||||||
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -15,6 +16,7 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static it.cavallium.warppi.math.rules.dsl.frontend.TokenType.*;
|
import static it.cavallium.warppi.math.rules.dsl.frontend.TokenType.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
@ -344,21 +346,11 @@ public class ParserTest {
|
|||||||
final Parser parser = new Parser(tokens, errors::add);
|
final Parser parser = new Parser(tokens, errors::add);
|
||||||
final List<PatternRule> rules = parser.parse();
|
final List<PatternRule> rules = parser.parse();
|
||||||
|
|
||||||
assertEquals(rule0x, toReferenceEquality(
|
assertEquals(rule0x, getSubFunctionIdentifiers(parser, rules.get(0), "x"));
|
||||||
parser.getSubFunctionIdentifiers(rules.get(0), new SubFunctionPattern("x"))
|
assertEquals(rule1x, getSubFunctionIdentifiers(parser, rules.get(1), "x"));
|
||||||
));
|
assertEquals(rule1y, getSubFunctionIdentifiers(parser, rules.get(1), "y"));
|
||||||
assertEquals(rule1x, toReferenceEquality(
|
assertEquals(rule2x, getSubFunctionIdentifiers(parser, rules.get(2), "x"));
|
||||||
parser.getSubFunctionIdentifiers(rules.get(1), new SubFunctionPattern("x"))
|
assertEquals(rule3x, getSubFunctionIdentifiers(parser, rules.get(3), "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"))
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Token addIdentifierToken(final List<ReferenceEqualityToken> list, final String identifier) {
|
private static Token addIdentifierToken(final List<ReferenceEqualityToken> list, final String identifier) {
|
||||||
@ -367,10 +359,22 @@ public class ParserTest {
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<ReferenceEqualityToken> toReferenceEquality(final List<Token> tokens) {
|
private static List<ReferenceEqualityToken> getSubFunctionIdentifiers(
|
||||||
return tokens.stream()
|
final Parser parser,
|
||||||
.map(ReferenceEqualityToken::new)
|
final PatternRule rule,
|
||||||
.collect(Collectors.toList());
|
final String subFunctionName
|
||||||
|
) {
|
||||||
|
final SubFunctionPattern exampleSubFunction = new SubFunctionPattern(subFunctionName);
|
||||||
|
final Stream<SubFunctionPattern> 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 {
|
private static class ReferenceEqualityToken {
|
||||||
@ -387,6 +391,11 @@ public class ParserTest {
|
|||||||
}
|
}
|
||||||
return this.token == ((ReferenceEqualityToken) o).token;
|
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
|
// The EOF token is inserted by the lexer, therefore it can only be missing
|
||||||
|
Loading…
Reference in New Issue
Block a user