Keep track of identifiers separately for each SubFunctionPattern object

This commit is contained in:
Riccardo Azzolini 2019-08-11 21:36:06 +02:00
parent c8656d1b30
commit eb8fcaafb9
27 changed files with 132 additions and 151 deletions

View File

@ -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<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.
* 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();
}

View File

@ -52,11 +52,11 @@ public class PatternRule implements Rule {
return ruleType;
}
Pattern getTarget() {
public Pattern getTarget() {
return target;
}
List<Pattern> getReplacements() {
public List<Pattern> getReplacements() {
return replacements;
}

View File

@ -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());
}
}

View File

@ -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<PatternRule> 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) <code>Stream</code> of undefined sub-functions.
*/
private static Set<SubFunctionPattern> undefinedSubFunctions(final PatternRule rule) {
final Set<SubFunctionPattern> defined = rule.getTarget().getSubFunctions();
final Set<SubFunctionPattern> undefined = new HashSet<>();
for (final Pattern replacement : rule.getReplacements()) {
undefined.addAll(replacement.getSubFunctions());
}
undefined.removeAll(defined);
return undefined;
private static Stream<SubFunctionPattern> undefinedSubFunctions(final PatternRule rule) {
final Set<SubFunctionPattern> defined = rule.getTarget().getSubFunctions().collect(Collectors.toSet());
return rule.getReplacements().stream()
.flatMap(Pattern::getSubFunctions)
.filter(subFunc -> !defined.contains(subFunc));
}
}

View File

@ -32,10 +32,8 @@ public class Parser {
private int currentIndex = 0;
// For error reporting
private Map<SubFunctionPattern, List<Token>> ruleSubFunctionIdentifiers;
// An IdentityHashMap is used to distinguish rules even if they're identical (equal)
private final IdentityHashMap<PatternRule, Map<SubFunctionPattern, List<Token>>> subFunctionIdentifiers =
new IdentityHashMap<>();
// An IdentityHashMap is used to distinguish SubFunctionPatterns even if they're identical (equal)
private final IdentityHashMap<SubFunctionPattern, 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.
@ -64,8 +62,21 @@ public class Parser {
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 ;
@ -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<Pattern> 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<Token> subFunctionList = ruleSubFunctionIdentifiers.computeIfAbsent(
subFunction,
key -> new ArrayList<>()
);
subFunctionList.add(curToken);
}
private Pattern matchLeftAssoc(
final PatternParser operandParser,
final Map<TokenType, BiFunction<Pattern, Pattern, Pattern>> operators

View File

@ -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<SubFunctionPattern> getSubFunctions() {
public Stream<SubFunctionPattern> getSubFunctions() {
return argument.getSubFunctions();
}

View File

@ -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<SubFunctionPattern> getSubFunctions() {
public Stream<SubFunctionPattern> getSubFunctions() {
return argument.getSubFunctions();
}

View File

@ -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<SubFunctionPattern> getSubFunctions() {
public Stream<SubFunctionPattern> getSubFunctions() {
return argument.getSubFunctions();
}

View File

@ -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<SubFunctionPattern> getSubFunctions() {
return Collections.emptySet();
public Stream<SubFunctionPattern> getSubFunctions() {
return Stream.empty();
}
@Override

View File

@ -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<SubFunctionPattern> getSubFunctions() {
public Stream<SubFunctionPattern> getSubFunctions() {
return argument.getSubFunctions();
}

View File

@ -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<SubFunctionPattern> getSubFunctions() {
return PatternUtils.getSubFunctionsFrom(dividend, divisor);
public Stream<SubFunctionPattern> getSubFunctions() {
return Stream.of(dividend, divisor)
.flatMap(Pattern::getSubFunctions);
}
@Override

View File

@ -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<SubFunctionPattern> getSubFunctions() {
return PatternUtils.getSubFunctionsFrom(left, right);
public Stream<SubFunctionPattern> getSubFunctions() {
return Stream.of(left, right)
.flatMap(Pattern::getSubFunctions);
}
@Override

View File

@ -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<SubFunctionPattern> getSubFunctions() {
return PatternUtils.getSubFunctionsFrom(patterns);
public Stream<SubFunctionPattern> getSubFunctions() {
return Stream.of(patterns)
.flatMap(Pattern::getSubFunctions);
}
@Override

View File

@ -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<SubFunctionPattern> getSubFunctions() {
return PatternUtils.getSubFunctionsFrom(base, argument);
public Stream<SubFunctionPattern> getSubFunctions() {
return Stream.of(base, argument)
.flatMap(Pattern::getSubFunctions);
}
@Override

View File

@ -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<SubFunctionPattern> getSubFunctions() {
return PatternUtils.getSubFunctionsFrom(left, right);
public Stream<SubFunctionPattern> getSubFunctions() {
return Stream.of(left, right)
.flatMap(Pattern::getSubFunctions);
}
@Override

View File

@ -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<SubFunctionPattern> getSubFunctions() {
public Stream<SubFunctionPattern> getSubFunctions() {
return inner.getSubFunctions();
}

View File

@ -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<SubFunctionPattern> getSubFunctions() {
return Collections.emptySet();
public Stream<SubFunctionPattern> getSubFunctions() {
return Stream.empty();
}
@Override

View File

@ -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<SubFunctionPattern> getSubFunctions() {
return PatternUtils.getSubFunctionsFrom(base, exponent);
public Stream<SubFunctionPattern> getSubFunctions() {
return Stream.of(base, exponent)
.flatMap(Pattern::getSubFunctions);
}
@Override

View File

@ -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<SubFunctionPattern> getSubFunctions() {
return PatternUtils.getSubFunctionsFrom(degree, radicand);
public Stream<SubFunctionPattern> getSubFunctions() {
return Stream.of(degree, radicand)
.flatMap(Pattern::getSubFunctions);
}
@Override

View File

@ -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<SubFunctionPattern> getSubFunctions() {
public Stream<SubFunctionPattern> getSubFunctions() {
return argument.getSubFunctions();
}

View File

@ -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<SubFunctionPattern> getSubFunctions() {
return Collections.singleton(this);
public Stream<SubFunctionPattern> getSubFunctions() {
return Stream.of(this);
}
@Override

View File

@ -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<SubFunctionPattern> getSubFunctions() {
return PatternUtils.getSubFunctionsFrom(left, right);
public Stream<SubFunctionPattern> getSubFunctions() {
return Stream.of(left, right)
.flatMap(Pattern::getSubFunctions);
}
@Override

View File

@ -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<SubFunctionPattern> getSubFunctions() {
return PatternUtils.getSubFunctionsFrom(left, right);
public Stream<SubFunctionPattern> getSubFunctions() {
return Stream.of(left, right)
.flatMap(Pattern::getSubFunctions);
}
@Override

View File

@ -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<SubFunctionPattern> getSubFunctions() {
return PatternUtils.getSubFunctionsFrom(left, right);
public Stream<SubFunctionPattern> getSubFunctions() {
return Stream.of(left, right)
.flatMap(Pattern::getSubFunctions);
}
@Override

View File

@ -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<SubFunctionPattern> getSubFunctions() {
public Stream<SubFunctionPattern> getSubFunctions() {
return argument.getSubFunctions();
}

View File

@ -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 <code>Undefined</code>.
@ -24,8 +23,8 @@ public class UndefinedPattern extends VisitorPattern {
}
@Override
public Set<SubFunctionPattern> getSubFunctions() {
return Collections.emptySet();
public Stream<SubFunctionPattern> getSubFunctions() {
return Stream.empty();
}
@Override

View File

@ -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<PatternRule> 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<ReferenceEqualityToken> list, final String identifier) {
@ -367,10 +359,22 @@ public class ParserTest {
return token;
}
private static List<ReferenceEqualityToken> toReferenceEquality(final List<Token> tokens) {
return tokens.stream()
.map(ReferenceEqualityToken::new)
.collect(Collectors.toList());
private static List<ReferenceEqualityToken> getSubFunctionIdentifiers(
final Parser parser,
final PatternRule rule,
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 {
@ -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