diff options
author | Jason Tsay <jasontsay@google.com> | 2011-07-01 16:19:15 -0700 |
---|---|---|
committer | Jason Tsay <jasontsay@google.com> | 2011-07-11 12:01:57 -0700 |
commit | ba3b8414a98c81371cffa65ec8769d29c46d6b8a (patch) | |
tree | 14aad5361a861700af3860e13abc44e48910a898 | |
parent | 7844ba4f55af24adc7a7dd074891b243650e7fca (diff) | |
download | prolog-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.java | 47 | ||||
-rw-r--r-- | src/builtin/PRED_regex_match_3.java | 108 | ||||
-rw-r--r-- | src/builtin/builtins.pl | 18 |
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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |