package org.matheclipse.core.expression;
import java.util.List;
import java.util.Map;
import org.matheclipse.core.eval.EvalEngine;
import org.matheclipse.core.generic.Predicates;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.interfaces.IPatternSequence;
import org.matheclipse.core.interfaces.ISymbol;
import org.matheclipse.core.patternmatching.IPatternMatcher;
import org.matheclipse.core.patternmatching.PatternMatcher;
import org.matheclipse.core.visit.IVisitor;
import org.matheclipse.core.visit.IVisitorBoolean;
import org.matheclipse.core.visit.IVisitorInt;
import com.google.common.base.Predicate;
/**
* A concrete pattern sequence implementation
*
*/
public class PatternSequence extends ExprImpl implements IPatternSequence {
/**
*
*/
private static final long serialVersionUID = 2773651826316158627L;
/**
*
*/
public static PatternSequence valueOf(final ISymbol symbol, final IExpr check, final boolean def) {
PatternSequence p = new PatternSequence();
p.fSymbol = symbol;
p.fCondition = check;
p.fDefault = def;
return p;
}
/**
*
* @param numerator
* @return
*/
public static PatternSequence valueOf(final ISymbol symbol, final IExpr check) {
PatternSequence p = new PatternSequence();
p.fSymbol = symbol;
p.fCondition = check;
return p;
}
public static PatternSequence valueOf(final ISymbol symbol) {
return valueOf(symbol, null);
}
/**
* The expression which should check this pattern sequence
*/
IExpr fCondition;
/**
* The associated symbol for this pattern sequence
*/
ISymbol fSymbol;
/**
* Use default value, if no matching was found
*/
boolean fDefault = false;
/**
* Index for the pattern-matcher
*
* @see org.matheclipse.core.patternmatching.PatternMatcher
*/
int fIndex = -1;
private PatternSequence() {
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof PatternSequence) {
PatternSequence pattern = (PatternSequence) obj;
if (fSymbol == pattern.fSymbol) {
if ((fCondition != null) && (pattern.fCondition != null)) {
return fCondition.equals(pattern.fCondition);
}
return fCondition == pattern.fCondition;
}
}
return false;
}
public IExpr getCondition() {
return fCondition;
}
/**
* @return
*/
public int getIndex() {
return fIndex;
}
/**
* @return
*/
public ISymbol getSymbol() {
return fSymbol;
}
@Override
public int hashCode() {
if (fSymbol == null) {
return 203;
}
return 17 + fSymbol.hashCode();
}
/** {@inheritDoc} */
public int hierarchy() {
return PATTERNID;
}
@Override
public String internalFormString(boolean symbolsAsFactoryMethod, int depth) {
if (symbolsAsFactoryMethod) {
final StringBuffer buffer = new StringBuffer();
buffer.append("$ps(");
if (fSymbol == null) {
buffer.append("(ISymbol)null");
if (fCondition != null) {
buffer.append("," + fCondition.internalFormString(symbolsAsFactoryMethod, 0));
}
if (fDefault) {
if (fCondition == null) {
buffer.append(",null");
}
buffer.append(",true");
}
} else {
buffer.append("\"" + fSymbol.toString() + "\"");
if (fCondition != null) {
buffer.append("," + fCondition.internalFormString(symbolsAsFactoryMethod, 0));
}
if (fDefault) {
buffer.append(",true");
}
}
buffer.append(')');
return buffer.toString();
}
return toString();
}
@Override
public void setIndex(final int i) {
fIndex = i;
}
@Override
public String toString() {
final StringBuffer buffer = new StringBuffer();
if (fSymbol == null) {
buffer.append("__");
if (fDefault) {
buffer.append('.');
}
if (fCondition != null) {
buffer.append(fCondition.toString());
}
} else {
if (fCondition == null) {
buffer.append(fSymbol.toString());
buffer.append("__");
if (fDefault) {
buffer.append('.');
}
} else {
buffer.append(fSymbol.toString());
buffer.append("__");
if (fDefault) {
buffer.append('.');
}
buffer.append(fCondition.toString());
}
}
return buffer.toString();
}
public String fullFormString() {
StringBuffer buf = new StringBuffer();
if (fSymbol == null) {
buf.append("BlankSequence[");
if (fCondition != null) {
buf.append(fCondition.fullFormString());
}
buf.append(']');
} else {
buf.append("PatternSequence[");
buf.append(fSymbol.toString());
buf.append(", ");
buf.append("BlankSequence[");
if (fCondition != null) {
buf.append(fCondition.fullFormString());
}
buf.append("]]");
}
return buf.toString();
}
/**
* Compares this expression with the specified expression for order. Returns
* a negative integer, zero, or a positive integer as this expression is
* canonical less than, equal to, or greater than the specified expression.
*/
public int compareTo(final IExpr obj) {
if (obj instanceof PatternSequence) {
int cp;
if (fSymbol == null) {
if (((PatternSequence) obj).fSymbol == null) {
cp = -1;
} else {
cp = 0;
}
} else if (((PatternSequence) obj).fSymbol == null) {
cp = 1;
} else {
cp = fSymbol.compareTo(((PatternSequence) obj).fSymbol);
}
if (cp != 0) {
return cp;
}
if (fCondition == null) {
if (((PatternSequence) obj).fCondition != null) {
return -1;
}
return 0;
} else {
if (((PatternSequence) obj).fCondition == null) {
return 1;
} else {
return fCondition.compareTo(((PatternSequence) obj).fCondition);
}
}
}
return (hierarchy() - (obj).hierarchy());
}
public ISymbol head() {
return F.PatternHead;
}
public boolean isBlank() {
return (fSymbol == null);
}
public boolean isConditionMatchedSequence(final IAST sequence) {
if (fCondition == null) {
return true;
}
EvalEngine engine = EvalEngine.get();
boolean traceMode = false;
traceMode = engine.isTraceMode();
final Predicate matcher = Predicates.isTrue(engine, fCondition);
try {
for (int i = 1; i < sequence.size(); i++) {
if (sequence.get(i).head().equals(fCondition)) {
continue;
}
engine.setTraceMode(false);
if (matcher.apply(sequence.get(i))) {
continue;
}
return false;
}
return true;
} finally {
if (traceMode) {
engine.setTraceMode(true);
}
}
}
@Override
public IExpr variables2Slots(final Map map, final List variableList) {
return null;
}
/**
* {@inheritDoc}
*/
public T accept(IVisitor visitor) {
return visitor.visit(this);
}
/**
* {@inheritDoc}
*/
public boolean accept(IVisitorBoolean visitor) {
return visitor.visit(this);
}
/**
* {@inheritDoc}
*/
public int accept(IVisitorInt visitor) {
return visitor.visit(this);
}
/**
* Use default value, if no matching was found.
*
* @return
*/
public boolean isDefault() {
return fDefault;
}
/** {@inheritDoc} */
public final boolean isPatternExpr() {
return true;
}
/** {@inheritDoc} */
final public boolean isPatternSequence() {
return true;
}
/**
* Groovy operator overloading
*/
public boolean isCase(IExpr that) {
final IPatternMatcher matcher = new PatternMatcher(this);
if (matcher.apply(that)) {
return true;
}
return false;
}
}
Ads help maintain this website.