aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Tsay <jasontsay@google.com>2011-07-01 16:19:15 -0700
committerJason Tsay <jasontsay@google.com>2011-07-11 12:01:57 -0700
commitba3b8414a98c81371cffa65ec8769d29c46d6b8a (patch)
tree14aad5361a861700af3860e13abc44e48910a898
parent7844ba4f55af24adc7a7dd074891b243650e7fca (diff)
downloadprolog-cafe-ba3b8414a98c81371cffa65ec8769d29c46d6b8a.tar.gz
Add regex/2,3 predicate
regex/3 predicate takes a pattern term in the form of a regular expression and either a single term or a list of terms to match the pattern against. Returns each match. regex/2 predicate takes the pattern and term(s) to match and returns true if any match exists. Change-Id: I20e18a84ea22f9c508aac9beb3136798b9c88eee
-rw-r--r--src/builtin/PRED_regex_compile_2.java47
-rw-r--r--src/builtin/PRED_regex_match_3.java108
-rw-r--r--src/builtin/builtins.pl18
3 files changed, 173 insertions, 0 deletions
diff --git a/src/builtin/PRED_regex_compile_2.java b/src/builtin/PRED_regex_compile_2.java
new file mode 100644
index 0000000..142234f
--- /dev/null
+++ b/src/builtin/PRED_regex_compile_2.java
@@ -0,0 +1,47 @@
+package com.googlecode.prolog_cafe.builtin;
+import com.googlecode.prolog_cafe.lang.IllegalTypeException;
+import com.googlecode.prolog_cafe.lang.JavaObjectTerm;
+import com.googlecode.prolog_cafe.lang.Operation;
+import com.googlecode.prolog_cafe.lang.PInstantiationException;
+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.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * <code>regex_compile/2</code><br>
+ *
+ * <pre>
+ * 'regex_compile'(+regex string, -Pattern object)
+ * </pre>
+ */
+public class PRED_regex_compile_2 extends Predicate.P2 {
+
+ public PRED_regex_compile_2(Term a1, Term a2, Operation cont) {
+ arg1 = a1;
+ arg2 = a2;
+ this.cont = cont;
+ }
+
+ public Operation exec(Prolog engine) {
+ engine.setB0();
+ Term a1 = arg1.dereference();
+ Term a2 = arg2.dereference();
+
+ if (a1.isVariable()) {
+ throw new PInstantiationException(this, 1);
+ }
+ if (!a1.isSymbol()) {
+ throw new IllegalTypeException(this, 1, "atom", a1);
+ }
+ Pattern pattern = Pattern.compile(a1.name());
+
+ if (!a2.unify(new JavaObjectTerm(pattern), engine.trail)) {
+ return engine.fail();
+ }
+ return cont;
+ }
+} \ No newline at end of file
diff --git a/src/builtin/PRED_regex_match_3.java b/src/builtin/PRED_regex_match_3.java
new file mode 100644
index 0000000..830d787
--- /dev/null
+++ b/src/builtin/PRED_regex_match_3.java
@@ -0,0 +1,108 @@
+package com.googlecode.prolog_cafe.builtin;
+import com.googlecode.prolog_cafe.lang.IllegalTypeException;
+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.PInstantiationException;
+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.areg1 = new JavaObjectTerm(matcher);
+ engine.areg2 = arg3;
+ return engine.jtry2(regex_check, regex_next);
+ }
+
+ private static final class PRED_regex_check extends Operation {
+ @Override
+ public Operation exec(Prolog engine) {
+ Term a1 = engine.areg1;
+ Term result = engine.areg2;
+ 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.areg1;
+ Matcher matcher = (Matcher)((JavaObjectTerm)a1).object();
+ if (!matcher.find()) {
+ return engine.fail();
+ }
+
+ return engine.jtry2(regex_check, regex_next);
+ }
+ }
+
+ 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;
+ }
+} \ No newline at end of file
diff --git a/src/builtin/builtins.pl b/src/builtin/builtins.pl
index f0e3178..b6dcda6 100644
--- a/src/builtin/builtins.pl
+++ b/src/builtin/builtins.pl
@@ -1693,6 +1693,8 @@ once(G) :- call(G), !.
%:- public char_code/2. written in Java
%:- public number_chars/2, number_codes/2. written in Java
:- public name/2.
+:- public regex/3.
+:- public regex/2.
sub_atom(Atom, Before, Length, After, Sub_atom) :-
atom_concat(AtomL, X, Atom),
@@ -1714,6 +1716,22 @@ name(Constant, Chars) :-
; illarg(type(list(char)), name(Constant,Chars), 2)
).
+regex(_, [], _) :- !, fail.
+regex(Pattern, List, Result) :-
+ List = [_ | _],
+ !,
+ regex_list(Pattern, List, Result).
+regex(Pattern, String, Result) :-
+ atom(String),
+ regex_compile(Pattern, Matcher),
+ regex_match(Matcher, String, Result).
+
+regex(Pattern, String) :-
+ once(regex(Pattern, String, _)).
+
+regex_list(Pattern, [H | _ ], Result) :- regex(Pattern, H, Result).
+regex_list(Pattern, [_ | Ls], Result) :- regex_list(Pattern, Ls, Result).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Implementation defined hooks
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%