Commit c8626559 authored by Sarah Grebing's avatar Sarah Grebing

Bugfix for emptyMatch on sequent

parent 3fbd814d
Pipeline #12968 failed with stage
in 1 minute and 27 seconds
...@@ -14,15 +14,36 @@ f(..., ...?X...) ...@@ -14,15 +14,36 @@ f(..., ...?X...)
f(..., ... g(x) ...) f(..., ... g(x) ...)
f(_, x, _, y, ... y ...) f(_, x, _, y, ... y ...)
*/ */
sequentPattern : antec=semiSeqPattern? ARROW succ=semiSeqPattern? | anywhere=semiSeqPattern;
semiSeqPattern : termPattern (',' termPattern)*; semiSeqPattern : termPattern (',' termPattern)*;
sequentPattern : antec=semiSeqPattern? ARROW succ=semiSeqPattern?;
termPattern : termPattern :
DONTCARE #dontCare DONTCARE #dontCare
//| STARDONTCARE #starDontCare //| STARDONTCARE #starDontCare
| SID #schemaVar | SID #schemaVar
| STARDONTCARE termPattern STARDONTCARE #anywhere | STARDONTCARE termPattern STARDONTCARE #anywhere
| DIGITS #number
| func=ID ( '(' termPattern (',' termPattern)* ')')? #function | func=ID ( '(' termPattern (',' termPattern)* ')')? #function
| left=termPattern op=(PLUS|MINUS|MUL|LE|GE|LEQ|GEQ|NEQ|EQ| AND|OR|IMP) right=termPattern #binaryOperation
; ;
/*
expression MUL expression #exprMultiplication
| <assoc=right> expression DIV expression #exprDivision
| expression op=(PLUS|MINUS) expression #exprLineOperators
| expression op=(LE|GE|LEQ|GEQ) expression #exprComparison
| expression op=(NEQ|EQ) expression #exprEquality
| expression AND expression #exprAnd
| expression OR expression #exprOr
| expression IMP expression #exprIMP
//| expression EQUIV expression already covered by EQ/NEQ
| expression LBRACKET substExpressionList RBRACKET #exprSubst
| MINUS expression #exprNegate
| NOT expression #exprNot
| '(' expression ')' #exprParen
*/
/* /*
f(x), f(x,y,g(y)), X, ?Y, _, ..., f(... ?X ...), f(..., ?X), f(..., ...?X...), f(..., ... g(x) ...), f(_, x, _, y, ... y ...) f(x), f(x,y,g(y)), X, ?Y, _, ..., f(... ?X ...), f(..., ?X), f(..., ...?X...), f(..., ... g(x) ...), f(_, x, _, y, ... y ...)
*/ */
...@@ -49,6 +70,7 @@ GE : '>' ; ...@@ -49,6 +70,7 @@ GE : '>' ;
LE : '<' ; LE : '<' ;
AND : '&' ; AND : '&' ;
OR: '|' ; OR: '|' ;
IMP: '->';
COMMENT: '//' ~[\n\r]* -> channel(HIDDEN); COMMENT: '//' ~[\n\r]* -> channel(HIDDEN);
WS: [\n\f\r\t ] -> channel(HIDDEN); WS: [\n\f\r\t ] -> channel(HIDDEN);
\ No newline at end of file
...@@ -12,6 +12,23 @@ public abstract class MatchPatternDualVisitor<T, S> extends MatchPatternBaseVisi ...@@ -12,6 +12,23 @@ public abstract class MatchPatternDualVisitor<T, S> extends MatchPatternBaseVisi
return t; return t;
} }
@Override
public final T visitSequentPattern(MatchPatternParser.SequentPatternContext ctx) {
return visitSequentPattern(ctx, stack.peek());
}
@Override
public final T visitSemiSeqPattern(MatchPatternParser.SemiSeqPatternContext ctx) {
return visitSemiSeqPattern(ctx, stack.peek());
}
protected abstract T visitSemiSeqPattern(MatchPatternParser.SemiSeqPatternContext ctx, S peek);
@Override
public T visitNumber(MatchPatternParser.NumberContext ctx) {
return visitNumber(ctx, stack.peek());
}
@Override @Override
public final T visitDontCare(MatchPatternParser.DontCareContext ctx) { public final T visitDontCare(MatchPatternParser.DontCareContext ctx) {
return visitDontCare(ctx, stack.peek()); return visitDontCare(ctx, stack.peek());
...@@ -33,31 +50,28 @@ public abstract class MatchPatternDualVisitor<T, S> extends MatchPatternBaseVisi ...@@ -33,31 +50,28 @@ public abstract class MatchPatternDualVisitor<T, S> extends MatchPatternBaseVisi
protected abstract T visitSchemaVar(MatchPatternParser.SchemaVarContext ctx, S peek); protected abstract T visitSchemaVar(MatchPatternParser.SchemaVarContext ctx, S peek);
@Override
public final T visitAnywhere(MatchPatternParser.AnywhereContext ctx) {
return visitAnywhere(ctx, stack.peek());
}
protected abstract T visitAnywhere(MatchPatternParser.AnywhereContext ctx, S peek);
@Override @Override
public final T visitFunction(MatchPatternParser.FunctionContext ctx) { public final T visitFunction(MatchPatternParser.FunctionContext ctx) {
return visitFunction(ctx, stack.peek()); return visitFunction(ctx, stack.peek());
} }
protected abstract T visitFunction(MatchPatternParser.FunctionContext ctx, S peek);
@Override @Override
public final T visitSemiSeqPattern(MatchPatternParser.SemiSeqPatternContext ctx) { public T visitBinaryOperation(MatchPatternParser.BinaryOperationContext ctx) {
return visitSemiSeqPattern(ctx, stack.peek()); return visitBinaryOperation(ctx, stack.peek());
} }
protected abstract T visitSemiSeqPattern(MatchPatternParser.SemiSeqPatternContext ctx, S peek);
@Override @Override
public final T visitSequentPattern(MatchPatternParser.SequentPatternContext ctx) { public final T visitAnywhere(MatchPatternParser.AnywhereContext ctx) {
return visitSequentPattern(ctx, stack.peek()); return visitAnywhere(ctx, stack.peek());
} }
protected abstract T visitAnywhere(MatchPatternParser.AnywhereContext ctx, S peek);
protected abstract T visitBinaryOperation(MatchPatternParser.BinaryOperationContext ctx, S peek);
protected abstract T visitFunction(MatchPatternParser.FunctionContext ctx, S peek);
protected abstract T visitNumber(MatchPatternParser.NumberContext ctx, S peek);
protected abstract T visitSequentPattern(MatchPatternParser.SequentPatternContext ctx, S peek); protected abstract T visitSequentPattern(MatchPatternParser.SequentPatternContext ctx, S peek);
} }
...@@ -18,8 +18,7 @@ import java.util.stream.Collectors; ...@@ -18,8 +18,7 @@ import java.util.stream.Collectors;
import static edu.kit.formal.psdb.termmatcher.MatchPatternParser.SequentPatternContext; import static edu.kit.formal.psdb.termmatcher.MatchPatternParser.SequentPatternContext;
import static edu.kit.formal.psdb.termmatcher.MatchPatternParser.TermPatternContext; import static edu.kit.formal.psdb.termmatcher.MatchPatternParser.TermPatternContext;
import static edu.kit.formal.psdb.termmatcher.MatcherImpl.MatchInfo; import static edu.kit.formal.psdb.termmatcher.MatcherImpl.*;
import static edu.kit.formal.psdb.termmatcher.MatcherImpl.NO_MATCH;
/** /**
* A facade for capturing everthing we want to do with matchers. * A facade for capturing everthing we want to do with matchers.
...@@ -101,7 +100,7 @@ public class MatcherFacade { ...@@ -101,7 +100,7 @@ public class MatcherFacade {
//BiMap<Pair<SequentFormula, MatchPatternParser.TermPatternContext>, Matchings> formulaToMatchingInfo, //BiMap<Pair<SequentFormula, MatchPatternParser.TermPatternContext>, Matchings> formulaToMatchingInfo,
/** /**
* Reduce all matches to only comaptible matchings * Reduce all matches to only compatible matchings
* @param allMatches * @param allMatches
* @return * @return
*/ */
...@@ -132,20 +131,60 @@ public class MatcherFacade { ...@@ -132,20 +131,60 @@ public class MatcherFacade {
*/ */
public static Matchings matches(String pattern, Sequent sequent) { public static Matchings matches(String pattern, Sequent sequent) {
MatcherImpl matcher = new MatcherImpl(); MatcherImpl matcher = new MatcherImpl();
MatchPatternParser mpp = getParser(pattern); MatchPatternParser mpp = getParser(pattern);
SequentPatternContext ctx = mpp.sequentPattern(); SequentPatternContext ctx = mpp.sequentPattern();
Semisequent antec = sequent.antecedent(); Semisequent antec = sequent.antecedent();
Semisequent succ = sequent.succedent(); Semisequent succ = sequent.succedent();
SemiSeqPatternContext antecPattern = ctx.antec; Matchings newMatching;
SemiSeqPatternContext succPattern = ctx.succ;
if (ctx.anywhere != null) {
//in this case we have a pattern without "==>"
SemiSeqPatternContext patternCtx = ctx.anywhere;
if (antec.isEmpty() & succ.isEmpty()) {
//Sonderbehandlung, falls beide EmptyMatch-> kein thema aber ansonsten bevorzugung von Varzuweisungen
Matchings antecMatches = matches(patternCtx, antec);
Matchings succMatches = matches(patternCtx, succ);
Matchings ret = compareMatchings(antecMatches, succMatches);
newMatching = ret;
} else {
if (antec.isEmpty()) {
newMatching = matches(patternCtx, succ);
} else {
newMatching = matches(patternCtx, antec);
}
Matchings mAntec = antecPattern == null ? MatcherImpl.EMPTY_MATCH : matches(antecPattern, antec); }
Matchings mSucc = succPattern == null ? MatcherImpl.EMPTY_MATCH : matches(succPattern, succ); } else {
SemiSeqPatternContext antecPattern = ctx.antec;
SemiSeqPatternContext succPattern = ctx.succ;
Matchings newMatching = MatcherImpl.reduceConform(mAntec, mSucc); Matchings mAntec = antecPattern == null ? MatcherImpl.EMPTY_MATCH : matches(antecPattern, antec);
Matchings mSucc = succPattern == null ? MatcherImpl.EMPTY_MATCH : matches(succPattern, succ);
newMatching = MatcherImpl.reduceConform(mAntec, mSucc);
}
return newMatching; return newMatching;
} }
private static Matchings compareMatchings(Matchings antecMatches, Matchings succMatches) {
if (antecMatches.equals(EMPTY_MATCH) && succMatches.equals(EMPTY_MATCH)) {
return MatcherImpl.EMPTY_MATCH;
}
if (antecMatches.equals(NO_MATCH)) return succMatches;
if (succMatches.equals(NO_MATCH)) return antecMatches;
//bevorzuge antecmatch atm
if (!antecMatches.equals(EMPTY_MATCH)) {
return antecMatches;
} else {
return succMatches;
}
}
} }
...@@ -2,6 +2,7 @@ package edu.kit.formal.psdb.termmatcher; ...@@ -2,6 +2,7 @@ package edu.kit.formal.psdb.termmatcher;
import de.uka.ilkd.key.logic.SequentFormula; import de.uka.ilkd.key.logic.SequentFormula;
import de.uka.ilkd.key.logic.Term; import de.uka.ilkd.key.logic.Term;
import org.antlr.v4.runtime.Token;
import java.util.*; import java.util.*;
import java.util.stream.IntStream; import java.util.stream.IntStream;
...@@ -31,6 +32,7 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, Term> { ...@@ -31,6 +32,7 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, Term> {
if (!intersection.isEmpty()) continue; if (!intersection.isEmpty()) continue;
HashMap<String, Term> h3 = reduceConform(minfo1.matching, minfo2.matching); HashMap<String, Term> h3 = reduceConform(minfo1.matching, minfo2.matching);
if (h3 != null) { if (h3 != null) {
Set<SequentFormula> union = new HashSet<>(minfo1.matchedForms); Set<SequentFormula> union = new HashSet<>(minfo1.matchedForms);
union.addAll(minfo2.matchedForms); union.addAll(minfo2.matchedForms);
...@@ -45,51 +47,15 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, Term> { ...@@ -45,51 +47,15 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, Term> {
private static HashMap<String, Term> reduceConform(HashMap<String, Term> h1, HashMap<String, Term> h2) { private static HashMap<String, Term> reduceConform(HashMap<String, Term> h1, HashMap<String, Term> h2) {
HashMap<String, Term> h3 = new HashMap<>(h1); HashMap<String, Term> h3 = new HashMap<>(h1);
for (String s1 : h3.keySet()) { for (String s1 : h3.keySet()) {
if (h2.containsKey(s1) && !h2.get(s1).equals(h1.get(s1))) { if (!s1.equals("EMPTY_MATCH") && (h2.containsKey(s1) && !h2.get(s1).equals(h1.get(s1)))) {
return null; return null;
} }
} }
h3.putAll(h2); h3.putAll(h2);
return h3; return h3;
} }
/**
* Reduce the matchings by eliminating non-compatible matchings.
* For example:
* m1: <X, f(y)>, <Y,g> and m2: <X, g> <Y, f(x)>
* @param m1
* @param m2
* @return
*/
protected static Matchings reduceConform(Matchings m1, Matchings m2) {
//shortcuts
if (m1 == NO_MATCH || m2 == NO_MATCH) return NO_MATCH;
if (m1 == EMPTY_MATCH) return m2;
if (m2 == EMPTY_MATCH) return m1;
Matchings m3 = new Matchings();
boolean oneMatch = false;
for (HashMap<String, Term> h1 : m1) {
for (HashMap<String, Term> h2 : m2) {
HashMap<String, Term> h3 = reduceConform(h1, h2);
if (h3 != null) {
m3.add(h3);
oneMatch = true;
}
}
}
return oneMatch ? m3 : NO_MATCH;
}
/*@Override
protected Matchings visitStartDontCare(MatchPatternParser.StarDontCareContext ctx, Term peek) {
if (peek != null) {
return EMPTY_MATCH;
} else {
return NO_MATCH;
}
}*/
/** /**
* Visit '_' * Visit '_'
* *
...@@ -106,6 +72,15 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, Term> { ...@@ -106,6 +72,15 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, Term> {
} }
} }
/*@Override
protected Matchings visitStartDontCare(MatchPatternParser.StarDontCareContext ctx, Term peek) {
if (peek != null) {
return EMPTY_MATCH;
} else {
return NO_MATCH;
}
}*/
/** /**
* Visit a Schema Variable * Visit a Schema Variable
* *
...@@ -138,6 +113,112 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, Term> { ...@@ -138,6 +113,112 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, Term> {
return m; return m;
} }
@Override
protected Matchings visitBinaryOperation(MatchPatternParser.BinaryOperationContext ctx, Term peek) {
Token op = ctx.op;
String opToKeYName = convert(op.getType());
MatchPatternParser.TermPatternContext left = ctx.left;
MatchPatternParser.TermPatternContext right = ctx.right;
if (peek.op().name().toString().equals(opToKeYName) // same name
&& peek.arity() == 2 // we know that we are in binary term
) {
Matchings lM = accept(left, peek.sub(0));
Matchings rM = accept(right, peek.sub(1));
Matchings ret = reduceConform(lM, rM);
return ret;
/*return IntStream.range(0, peek.arity())
.mapToObj(i -> (Matchings) accept(ctx.termPattern(i), peek.sub(i)))
.reduce(MatcherImpl::reduceConform)
.orElse(NO_MATCH);*/
}
return NO_MATCH;
}
private String convert(int op) {
switch (op) {
case MatchPatternParser.PLUS:
return "add";
case MatchPatternParser.MINUS:
return "sub";
case MatchPatternParser.MUL:
return "mul";
case MatchPatternParser.DIV:
return "div";
case MatchPatternParser.LE:
return "lt";
case MatchPatternParser.LEQ:
return "leq";
case MatchPatternParser.EQ:
return "equals";
case MatchPatternParser.GE:
return "gt";
case MatchPatternParser.GEQ:
return "geq";
case MatchPatternParser.IMP:
return "imp";
case MatchPatternParser.AND:
return "and";
case MatchPatternParser.OR:
return "or";
default:
throw new UnsupportedOperationException("The operator " + op + "is not known");
}
}
/**
* Reduce the matchings by eliminating non-compatible matchings.
* For example:
* m1: <X, f(y)>, <Y,g> and m2: <X, g> <Y, f(x)>
*
* @param m1
* @param m2
* @return
*/
protected static Matchings reduceConform(Matchings m1, Matchings m2) {
//shortcuts
if (m1 == NO_MATCH || m2 == NO_MATCH) return NO_MATCH;
if (m1 == EMPTY_MATCH) return m2;
if (m2 == EMPTY_MATCH) return m1;
Matchings m3 = new Matchings();
boolean oneMatch = false;
for (HashMap<String, Term> h1 : m1) {
for (HashMap<String, Term> h2 : m2) {
HashMap<String, Term> h3 = reduceConform(h1, h2);
if (h3 != null) {
m3.add(h3);
oneMatch = true;
}
}
}
return oneMatch ? m3 : NO_MATCH;
}
/** /**
* Visit a function and predicate symbol without a sequent arrow * Visit a function and predicate symbol without a sequent arrow
* @param ctx * @param ctx
...@@ -153,7 +234,7 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, Term> { ...@@ -153,7 +234,7 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, Term> {
return IntStream.range(0, peek.arity()) return IntStream.range(0, peek.arity())
.mapToObj(i -> (Matchings) accept(ctx.termPattern(i), peek.sub(i))) .mapToObj(i -> (Matchings) accept(ctx.termPattern(i), peek.sub(i)))
.reduce(MatcherImpl::reduceConform) .reduce(MatcherImpl::reduceConform)
.orElse(NO_MATCH); .orElse(EMPTY_MATCH);
} }
return NO_MATCH; return NO_MATCH;
} }
...@@ -169,6 +250,11 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, Term> { ...@@ -169,6 +250,11 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, Term> {
return null; return null;
} }
@Override
protected Matchings visitNumber(MatchPatternParser.NumberContext ctx, Term peek) {
return null;
}
/** /**
* Visit a sequent pattern 'f(x) ==> f(x)', 'f(x) ==>' or '==> f(x)' * Visit a sequent pattern 'f(x) ==> f(x)', 'f(x) ==>' or '==> f(x)'
* @param ctx * @param ctx
......
...@@ -44,6 +44,10 @@ public class MatcherFacadeTest { ...@@ -44,6 +44,10 @@ public class MatcherFacadeTest {
shouldMatchForm("pred(a)", "...?X...", "[{?X=pred(a)}, {?X=a}]"); shouldMatchForm("pred(a)", "...?X...", "[{?X=pred(a)}, {?X=a}]");
shouldMatchForm("pred(f(a))", "pred(...?X...)", "[{?X=f(a)}, {?X=a}]"); shouldMatchForm("pred(f(a))", "pred(...?X...)", "[{?X=f(a)}, {?X=a}]");
shouldMatch("i+j", "add(?X,?Y)", "[{?X=i, ?Y=j}]"); shouldMatch("i+j", "add(?X,?Y)", "[{?X=i, ?Y=j}]");
shouldMatch("i+j", "?X+?Y", "[{?X=i, ?Y=j}]");
shouldMatchForm("p & q", "p & ?X", "[{?X=q}]");
//shouldMatchForm("p & q", "?X & q", "[{?X=p}]");
//shouldMatch("1*j", "add(1,?Y)", "[{?Y=j}]");
//shouldMatch("f(a) ==> f(a), f(b)" , "==> f(?X)", [{?X=a}]); //shouldMatch("f(a) ==> f(a), f(b)" , "==> f(?X)", [{?X=a}]);
...@@ -119,13 +123,14 @@ public class MatcherFacadeTest { ...@@ -119,13 +123,14 @@ public class MatcherFacadeTest {
shouldMatchSemiSeq("pred(a), pred(b) ==>", "pred(?X), pred(?X)", "[]"); shouldMatchSemiSeq("pred(a), pred(b) ==>", "pred(?X), pred(?X)", "[]");
shouldMatchSemiSeq("pred(a), pred(f(a)) ==>", "pred(?X), pred(f(?X))", "[{?X=a}]"); shouldMatchSemiSeq("pred(a), pred(f(a)) ==>", "pred(?X), pred(f(?X))", "[{?X=a}]");
shouldMatchSemiSeq("pred(b), pred(f(a)) ==>", "pred(?X), pred(f(?X))", "[]"); shouldMatchSemiSeq("pred(b), pred(f(a)) ==>", "pred(?X), pred(f(?X))", "[]");
shouldMatchSemiSeq("pred(a), pred(b) ==> qpred(a,b)", "pred(a), pred(b)"); shouldMatchSemiSeq("pred(a), pred(b) ==>", "pred(a), pred(b)", "[{EMPTY_MATCH=null}]");
shouldMatchSemiSeq("pred(a), pred(b) ==> qpred(a,b)", "pred(a), pred(b) ==> ", "[{EMPTY_MATCH=null}]");
shouldMatchSemiSeq("pred(a), pred(b) ==> qpred(a,b)", "pred(?X), pred(?Y)", "[{?X=a, ?Y=b}, {?X=b, ?Y=a}]"); shouldMatchSemiSeq("pred(a), pred(b) ==> qpred(a,b)", "pred(?X), pred(?Y)", "[{?X=a, ?Y=b}, {?X=b, ?Y=a}]");
shouldMatchSemiSeq("pred(b), pred(a) ==>", "pred(...?X...), pred(f(?X))", "[]"); shouldMatchSemiSeq("pred(b), pred(a) ==>", "pred(...?X...), pred(f(?X))", "[]");
shouldMatchSemiSeq("pred(b), pred(a) ==>", "pred(...?X...), pred(...?Y...)", "[{?X=b, ?Y=a}, {?X=a, ?Y=b}]"); shouldMatchSemiSeq("pred(b), pred(a) ==>", "pred(...?X...), pred(...?Y...)", "[{?X=b, ?Y=a}, {?X=a, ?Y=b}]");
shouldMatchSemiSeq("intPred(fint(i+j))", "intPred(...add(?X, ?y)...)"); shouldMatchSemiSeq("intPred(fint(i+j)) ==>", "intPred(...add(?X, ?y)...)");
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment