blob: 5d796f5163c93aac93a35aa89f37ca6b5f8d4abc [file] [log] [blame]
package com.googlecode.prolog_cafe.builtin;
import com.googlecode.prolog_cafe.exceptions.IllegalTypeException;
import com.googlecode.prolog_cafe.exceptions.PInstantiationException;
import com.googlecode.prolog_cafe.lang.ChoicePointFrame;
import com.googlecode.prolog_cafe.lang.JavaObjectTerm;
import com.googlecode.prolog_cafe.lang.ListTerm;
import com.googlecode.prolog_cafe.lang.Operation;
import com.googlecode.prolog_cafe.lang.Predicate;
import com.googlecode.prolog_cafe.lang.Prolog;
import com.googlecode.prolog_cafe.lang.SymbolTerm;
import com.googlecode.prolog_cafe.lang.Term;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* <code>regex_match/3</code><br>
*
* <pre>
* 'regex_match'(+Pattern object, +Chars, -Matches)
* </pre>
*/
public class PRED_regex_match_3 extends Predicate.P3 {
private static final Operation regex_check = new PRED_regex_check();
private static final Operation regex_next = new PRED_regex_next();
private static final Operation regex_empty = new PRED_regex_empty();
public PRED_regex_match_3(Term a1, Term a2, Term a3, Operation cont) {
arg1 = a1;
arg2 = a2;
arg3 = a3;
this.cont = cont;
}
public Operation exec(Prolog engine) {
engine.setB0();
engine.cont = cont;
Term a1 = arg1.dereference();
Term a2 = arg2.dereference();
if (a1.isVariable()) {
throw new PInstantiationException(this, 1);
}
Pattern pattern = (Pattern)((JavaObjectTerm)a1).object();
if (a2.isVariable()) {
throw new PInstantiationException(this, 1);
}
if (!a2.isSymbol()) {
throw new IllegalTypeException(this, 1, "atom", a2);
}
Matcher matcher = pattern.matcher(a2.name());
if (!matcher.find()) {
return engine.fail();
}
engine.r1 = new JavaObjectTerm(matcher);
engine.r2 = arg3;
return engine.jtry(regex_check, regex_next, new ChoicePointFrame.S2(engine));
}
private static final class PRED_regex_check extends Operation {
@Override
public Operation exec(Prolog engine) {
Term a1 = engine.r1;
Term result = engine.r2;
Matcher matcher = (Matcher)((JavaObjectTerm)a1).object();
Term matches = getMatches(matcher);
if (matches == Prolog.Nil || !result.unify(matches, engine.trail)) {
return engine.fail();
}
return engine.cont;
}
}
private static final class PRED_regex_next extends Operation {
@Override
public Operation exec(Prolog engine) {
return engine.trust(regex_empty);
}
}
private static final class PRED_regex_empty extends Operation {
@Override
public Operation exec(Prolog engine) {
Term a1 = engine.r1;
Matcher matcher = (Matcher)((JavaObjectTerm)a1).object();
if (!matcher.find()) {
return engine.fail();
}
return engine.jtry(regex_check, regex_next, new ChoicePointFrame.S2(engine));
}
}
private static Term getMatches(Matcher matcher) {
Term list = Prolog.Nil;
for (int i = matcher.groupCount(); i >= 0; i--) {
SymbolTerm match = SymbolTerm.create(matcher.group(i));
list = new ListTerm(match, list);
}
return list;
}
}