Copyright (C) 2001, Geert Vernaeve. All Rights Reserved. |
A Matcher is a repository for symbol values and types. Using this information, it can match expressions to patterns. |
symbols to match -> matched value |
keys: symbol (String); values: type of this symbol (Part) patternTypes contains symbol types of the pattern; tomatchTypes contains symbol types of the part tree to match. |
Creates a deep optimized copy of m. Deep: later changes on m do not affect the new Matcher Optimized: if m is a recursive matcher (e.g. a FallbackMatcher), the new Matcher is flattened Caveat emptor: type info of undefined symbols is *not* preserved in the new Matcher. Pattern types are also lost. |
Checks if tomatch matches the pattern |
Returns true if all identifiers in pattern are matched to a value. |
Takes a pattern; returns a copy of the pattern where all symbols are replaced with their values. |
E.g.: match ("x,y,z|-y","L |- a") Calls action.foundMatch() for each match found, until action.foundMatch() returns true (and then the result of match() is also true). When no match is found, or on each match action.foundMatch() returned false, the result of foundMatch() is false. When this method returns, no variable values are modified. |
This method assumes that action!=null |
Do a quick, partial match
If this method returns false, no partial match was found (so don't even
think about finding a full match() ...
This method does not sport a Matched action argument
like match() because quick matches never need to backtrack |
pattern
*has to* match to val
,
// and here we find that it also has to match tomatch
return false; // A match will never be possible!
}
}
// Try to match a currently unmatched symbol
String typename = ((Identifier)typ).getString();
if (typename.equals("List")) {
setMatchedValue(symbolname,tomatch);
return true;
} else if (typename.equals("Term") || typename.equals("Formula")) {
if (!(tomatch instanceof OperatorComma)) {
if (tomatch instanceof Identifier) {
Part tmTyp = getTomatchType((Identifier)tomatch);
if (tmTyp instanceof Identifier) {
String tmt = ((Identifier)tmTyp).getString();
if (tmt.equals("List")) return false;
}
}
setMatchedValue(symbolname,tomatch);
return true;
} else return false;
} else if (typename.equals("Pred")) {
if (tomatch instanceof Identifier) {
setMatchedValue(symbolname,tomatch);
return true;
} else return false;
} else if (typename.equals("Var")) {
if (tomatch instanceof Identifier) {
Part tmTyp = getTomatchType((Identifier)tomatch);
if (tmTyp instanceof Identifier) {
String tmt = ((Identifier)tmTyp).getString();
if (!(tmt.equals("Var"))) return false;
}
setMatchedValue(symbolname,tomatch);
return true;
} else return false;
} else if (typename.equals("Const")) {
if (tomatch instanceof Identifier) {
Part tmTyp = getTomatchType((Identifier)tomatch);
if (tmTyp instanceof Identifier) {
String tmt = ((Identifier)tmTyp).getString();
if (!(tmt.equals("Const"))) return false;
}
setMatchedValue(symbolname,tomatch);
return true;
} else return false;
}
return false;
} else if (pattern instanceof OperatorModel) {
if (!(tomatch instanceof OperatorModel)) return false;
OperatorModel patModel = (OperatorModel)pattern;
OperatorModel tomModel = (OperatorModel)tomatch;
if (!patModel.getName().equals(tomModel.getName())) return false;
// check right argument
if (!(qmatch(tomModel.right,patModel.right))) return false;
// check left argument; we only can check if it is not an OperatorComma
if (patModel.left instanceof OperatorComma) return true;
return qmatch(tomModel.left,patModel.left);
// } else if (pattern instanceof OperatorComma) {
// A match may still be possible, but that we cannot decide quickly
// return true;
} else if (tomatch instanceof Operator && pattern instanceof Operator
&& tomatch.getClass().getName().equals(pattern.getClass().getName())
&& ((Operator)tomatch).getName().equals(((Operator)pattern).getName())) {
// Default action for operators: match two like operators
// Recursively match all children
int count = 0;
while (true) {
Part chTomatch = tomatch.getChild(count);
Part chPattern = pattern.getChild(count);
if (chTomatch == null) break;
if (!qmatch(chTomatch,chPattern)) return false;
count++;
}
return true;
}
return false;
}
public void dump() {
matches.dump();
}
}
class AlwaysTrue implements Matched {
public AlwaysTrue() {}
public boolean foundMatch(Matcher m) {
return true;
}
}
class OperatorModelMatched implements Matched {
private int count = 0;
private OperatorModel tomatch,pattern;
private Matched action; // action to perform if a match is found
public OperatorModelMatched(OperatorModel tomatch,OperatorModel pattern,Matched action) {
this.tomatch = tomatch;
this.pattern = pattern;
this.action = action;
//System.out.println("CREATE "+this);
}
public boolean foundMatch(Matcher m) {
// Match left child with an OperatorCommaMatched (i.e., consider it as a
// list where "a,b" = "b,a"
// and right child in the classic way
count++;
//System.out.println("FOUNDMATCH enter "+count+" "+this);
boolean result = false;
switch (count) {
case 1:
if (pattern.left instanceof OperatorComma)
result = new OperatorCommaMatched(tomatch.left,pattern.left,this,m).match();
else
result = m.match(tomatch.left,pattern.left,this);
break;
case 2:
result = m.match(tomatch.right,pattern.right,this);
break;
case 3: result = action.foundMatch(m);
break;
default: System.out.println("***OperatorModelMatched: this cannot happen.");
}
//System.out.println("FOUNDMATCH leave "+count+" "+this);
count--;
return result;
}
}
Matcher for OperatorComma patterns WARNING: probably malfunctioning on patterns that are not OperatorComma! (e.g. tomatch = "L", pattern = "", this probably always matches successfully |
Returns a bit pattern: bit i is set => tomatch[i] has not been matched bit i is clear => tomatch[i] has been matched by some pattern[j] for some j != except |
Idem as checkmatch(int), but consider *all* pattern[j]'s |
Strategy: First match all Terms. This is relatively inexpensive, since we only have to try to match each Term to each element of tomatch[]. Then, match all Lists. Note that all elements of tomatch[] that weren't matched to an Identifier earlier on, have to be matched with the Lists. The only thing we don't know is which of those Identifiers has to be matched to which of the Lists (except when there's only one List involved) and which of the already matched Terms have to be added to the Lists ... |