This commit was manufactured by cvs2svn to create tag
'GROOVY_1_0_JSR_03'.

git-svn-id: http://svn.codehaus.org/groovy/tags/GROOVY_1_0_JSR_03@2714 a5544e8c-8a19-0410-ba12-f9af4593a198
diff --git a/CVSROOT/checkoutlist b/CVSROOT/checkoutlist
deleted file mode 100644
index d326583..0000000
--- a/CVSROOT/checkoutlist
+++ /dev/null
@@ -1,15 +0,0 @@
-# The "checkoutlist" file is used to support additional version controlled
-# administrative files in $CVSROOT/CVSROOT, such as template files.
-#
-# The first entry on a line is a filename which will be checked out from
-# the corresponding RCS file in the $CVSROOT/CVSROOT directory.
-# The remainder of the line is an error message to use if the file cannot
-# be checked out.
-#
-# File format:
-#
-#	[<whitespace>]<filename><whitespace><error message><end-of-line>
-#
-# comment lines begin with '#'
-passwd
-log_accum.conf
\ No newline at end of file
diff --git a/CVSROOT/commitinfo b/CVSROOT/commitinfo
deleted file mode 100644
index b19e7b7..0000000
--- a/CVSROOT/commitinfo
+++ /dev/null
@@ -1,15 +0,0 @@
-# The "commitinfo" file is used to control pre-commit checks.
-# The filter on the right is invoked with the repository and a list 
-# of files to check.  A non-zero exit of the filter program will 
-# cause the commit to be aborted.
-#
-# The first entry on a line is a regular expression which is tested
-# against the directory that the change is being committed to, relative
-# to the $CVSROOT.  For the first match that is found, then the remainder
-# of the line is the name of the filter to run.
-#
-# If the repository name does not match any of the regular expressions in this
-# file, the "DEFAULT" line is used, if it is specified.
-#
-# If the name "ALL" appears as a regular expression it is always used
-# in addition to the first matching regex or "DEFAULT".
diff --git a/CVSROOT/damagecontrol-groovy.conf b/CVSROOT/damagecontrol-groovy.conf
deleted file mode 100644
index 623fc62..0000000
--- a/CVSROOT/damagecontrol-groovy.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-project_name: Groovy
-scm_spec: ":ext:dcontrol@localhost:/home/projects/groovy/scm:groovy/groovy-core"
-build_command_line: "maven dc"
-nag_email: groovy-dev@groovy.codehaus.org
-...
\ No newline at end of file
diff --git a/CVSROOT/dctrigger.rb b/CVSROOT/dctrigger.rb
deleted file mode 100644
index a6545a5..0000000
--- a/CVSROOT/dctrigger.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-require 'xmlrpc/client'
-
-url = ARGV[0]
-project_name = ARGV[1]
-
-puts "Nudging DamageControl on #{url} to build project #{project_name}"
-client = XMLRPC::Client.new2(url)
-build = client.proxy("build")
-result = build.trig(project_name, Time.now.utc.strftime("%Y%m%d%H%M%S"))
-puts result
diff --git a/CVSROOT/editinfo b/CVSROOT/editinfo
deleted file mode 100644
index d78886c..0000000
--- a/CVSROOT/editinfo
+++ /dev/null
@@ -1,21 +0,0 @@
-# The "editinfo" file is used to allow verification of logging
-# information.  It works best when a template (as specified in the
-# rcsinfo file) is provided for the logging procedure.  Given a
-# template with locations for, a bug-id number, a list of people who
-# reviewed the code before it can be checked in, and an external
-# process to catalog the differences that were code reviewed, the
-# following test can be applied to the code:
-#
-#   Making sure that the entered bug-id number is correct.
-#   Validating that the code that was reviewed is indeed the code being
-#       checked in (using the bug-id number or a seperate review
-#       number to identify this particular code set.).
-#
-# If any of the above test failed, then the commit would be aborted.
-#
-# Actions such as mailing a copy of the report to each reviewer are
-# better handled by an entry in the loginfo file.
-#
-# One thing that should be noted is the the ALL keyword is not
-# supported.  There can be only one entry that matches a given
-# repository.
diff --git a/CVSROOT/log_accum.conf b/CVSROOT/log_accum.conf
deleted file mode 100644
index 6343eb0..0000000
--- a/CVSROOT/log_accum.conf
+++ /dev/null
@@ -1,83 +0,0 @@
-# The "log_accum.conf" file overrides the the defaults hard-coded in
-# the "log_accum.pl" script allowing admins to setup the log_accum.pl
-# once as executable, but not writable.  Each project can then have
-# it's own "log_accum.conf" to configure the behaviour of their own
-# cvs commit messages.
-
-
-# MAIL TO
-#
-# When set, specifies the email address(es) to
-# receive commit messages. When left unset, the
-# script will attempt to guess the correct
-# mailing list using the repository name and
-# the MLISTHOST option.
-#
-MAIL_TO = scm@groovy.codehaus.org
-
-# MAIL FROM
-#
-# When set, specifies the email address that
-# all commit messages will be sent from.
-# Very usefull for setting up a "no reply"
-# address for commit messages.
-#
-# When not set, the script will guess the sender's
-# address by prefixing the cvs user's name to the
-# MLISTHOST option.
-#
-#MAIL_FROM = noreply@codehaus.org
-
-# MAIL HOST ADDRESS
-#
-# The host address to use when guessing either
-# the TO or FROM addresses.
-#MLISTHOST = codehaus.org
-
-# X-SENDER EMAIL HEADER
-#
-# When specified, adds an X-Sender header to the
-# emails sent so that users can use it to more
-# easily filter out cvs messages.  This is very
-# nice for when there is no mailing list
-# dedicated to cvs commit messages.
-#
-XSENDER       = Groovy-CVS
-
-# REPLY-TO EMAIL ADDRESS
-#
-# When REPLYTO is set an SMTP "Reply-To" email
-# header will be added.  This is very useful
-# for keeping development discussion on a
-# dev list even when cvs messages go a cvs list.
-#
-REPLYTO = dev@groovy.codehaus.org
-
-# SUBJECT PREFIX
-#
-# This text, plus a space, will be prepended
-# to the subject line of the commit message.
-# When the option specified with no value, no
-# prefix will be used.
-#
-SUBJECT_PREFIX =
-
-# MESSAGE SIZE LIMIT
-#
-# If the delta info exceeds this threshold, no diff will be
-# mailed/logged; as a replacement for this, URLs pointing
-# to the corresponding ViewCVS diffs will be constructed and
-# included in the mail/log message.
-#
-# 0 = no treshold, unlimited diffs
-# x = maximum size of the diff in kb
-#
-#SIZELIMIT = 100;
-
-# VIEWCVS URL
-#
-# Specify here the URL to ViewCVS (without trailing slash!)
-# If left unset, the script will attempt to guess the correct
-# value.
-#
-VIEWCVS = "http://cvs.groovy.codehaus.org/groovy";
diff --git a/CVSROOT/modules b/CVSROOT/modules
deleted file mode 100644
index cb9e9ef..0000000
--- a/CVSROOT/modules
+++ /dev/null
@@ -1,26 +0,0 @@
-# Three different line formats are valid:
-#	key	-a    aliases...
-#	key [options] directory
-#	key [options] directory files...
-#
-# Where "options" are composed of:
-#	-i prog		Run "prog" on "cvs commit" from top-level of module.
-#	-o prog		Run "prog" on "cvs checkout" of module.
-#	-e prog		Run "prog" on "cvs export" of module.
-#	-t prog		Run "prog" on "cvs rtag" of module.
-#	-u prog		Run "prog" on "cvs update" of module.
-#	-d dir		Place module in directory "dir" instead of module name.
-#	-l		Top-level directory only -- do not recurse.
-#
-# NOTE:  If you change any of the "Run" options above, you'll have to
-# release and re-checkout any working directories of these modules.
-#
-# And "directory" is a path to a directory relative to $CVSROOT.
-#
-# The "-a" option specifies an alias.  An alias is interpreted as if
-# everything on the right of the "-a" had been typed on the command line.
-#
-# You can encode a module within a module by using the special '&'
-# character to interpose another module into the current module.  This
-# can be useful for creating a module that consists of many directories
-# spread out over the entire source repository.
diff --git a/CVSROOT/notify b/CVSROOT/notify
deleted file mode 100644
index 74ae6f9..0000000
--- a/CVSROOT/notify
+++ /dev/null
@@ -1,12 +0,0 @@
-# The "notify" file controls where notifications from watches set by
-# "cvs watch add" or "cvs edit" are sent.  The first entry on a line is
-# a regular expression which is tested against the directory that the
-# change is being made to, relative to the $CVSROOT.  If it matches,
-# then the remainder of the line is a filter program that should contain
-# one occurrence of %s for the user to notify, and information on its
-# standard input.
-#
-# "ALL" or "DEFAULT" can be used in place of the regular expression.
-#
-# For example:
-#ALL mail -s "CVS notification" %s
diff --git a/CVSROOT/rcsinfo b/CVSROOT/rcsinfo
deleted file mode 100644
index 49e59f4..0000000
--- a/CVSROOT/rcsinfo
+++ /dev/null
@@ -1,13 +0,0 @@
-# The "rcsinfo" file is used to control templates with which the editor
-# is invoked on commit and import.
-#
-# The first entry on a line is a regular expression which is tested
-# against the directory that the change is being made to, relative to the
-# $CVSROOT.  For the first match that is found, then the remainder of the
-# line is the name of the file that contains the template.
-#
-# If the repository name does not match any of the regular expressions in this
-# file, the "DEFAULT" line is used, if it is specified.
-#
-# If the name "ALL" appears as a regular expression it is always used
-# in addition to the first matching regex or "DEFAULT".
diff --git a/CVSROOT/taginfo b/CVSROOT/taginfo
deleted file mode 100644
index 274a46d..0000000
--- a/CVSROOT/taginfo
+++ /dev/null
@@ -1,20 +0,0 @@
-# The "taginfo" file is used to control pre-tag checks.
-# The filter on the right is invoked with the following arguments:
-#
-# $1 -- tagname
-# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d
-# $3 -- repository
-# $4->  file revision [file revision ...]
-#
-# A non-zero exit of the filter program will cause the tag to be aborted.
-#
-# The first entry on a line is a regular expression which is tested
-# against the directory that the change is being committed to, relative
-# to the $CVSROOT.  For the first match that is found, then the remainder
-# of the line is the name of the filter to run.
-#
-# If the repository name does not match any of the regular expressions in this
-# file, the "DEFAULT" line is used, if it is specified.
-#
-# If the name "ALL" appears as a regular expression it is always used
-# in addition to the first matching regex or "DEFAULT".
diff --git a/CVSROOT/verifymsg b/CVSROOT/verifymsg
deleted file mode 100644
index 86f747c..0000000
--- a/CVSROOT/verifymsg
+++ /dev/null
@@ -1,21 +0,0 @@
-# The "verifymsg" file is used to allow verification of logging
-# information.  It works best when a template (as specified in the
-# rcsinfo file) is provided for the logging procedure.  Given a
-# template with locations for, a bug-id number, a list of people who
-# reviewed the code before it can be checked in, and an external
-# process to catalog the differences that were code reviewed, the
-# following test can be applied to the code:
-#
-#   Making sure that the entered bug-id number is correct.
-#   Validating that the code that was reviewed is indeed the code being
-#       checked in (using the bug-id number or a seperate review
-#       number to identify this particular code set.).
-#
-# If any of the above test failed, then the commit would be aborted.
-#
-# Actions such as mailing a copy of the report to each reviewer are
-# better handled by an entry in the loginfo file.
-#
-# One thing that should be noted is the the ALL keyword is not
-# supported.  There can be only one entry that matches a given
-# repository.
diff --git a/groovy/groovy-core/project.properties b/groovy/groovy-core/project.properties
index 3e93bf7..fe7fff6 100644
--- a/groovy/groovy-core/project.properties
+++ b/groovy/groovy-core/project.properties
@@ -50,6 +50,18 @@
 
 maven.remote.group = groovy
 
+# Deployment properties
+maven.repo.list=codehaus
+
+maven.repo.codehaus=scp://${pom.distributionSite}
+maven.repo.codehaus.directory=${pom.distributionDirectory}
+maven.repo.codehaus.group=groovy
+
+# The following properties must be set in your build.properties or on the command line
+#maven.repo.codehaus.username=
+#maven.repo.codehaus.privatekey=
+#maven.repo.codehaus.passphrase=
+
 #####################################################
 # emma code coverage
 #####################################################
diff --git a/groovy/groovy-core/src/bin/groovy.bat b/groovy/groovy-core/src/bin/groovy.bat
index 6593c38..7bc3748 100644
--- a/groovy/groovy-core/src/bin/groovy.bat
+++ b/groovy/groovy-core/src/bin/groovy.bat
@@ -66,8 +66,8 @@
 
 @rem Regular WinNT shell
 set CP=
-if "x%1" == "x-cp" set CP=%2
-if "x%1" == "x-classpath" set CP=%2
+if "x%1" == "x-cp" set CP=%~2
+if "x%1" == "x-classpath" set CP=%~2
 if not "x" == "x%CP%" shift /1
 if not "x" == "x%CP%" shift /1
 set CMD_LINE_ARGS=%1 %2 %3 %4 %5 %6 %7 %8 %9
@@ -113,4 +113,3 @@
 
 @rem Optional pause the batch file
 if "%GROOVY_BATCH_PAUSE%" == "on" pause
-
diff --git a/groovy/groovy-core/src/main/groovy/util/Node.java b/groovy/groovy-core/src/main/groovy/util/Node.java
index 41620af..123b88e 100644
--- a/groovy/groovy-core/src/main/groovy/util/Node.java
+++ b/groovy/groovy-core/src/main/groovy/util/Node.java
@@ -66,7 +66,7 @@
  * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
  * @version $Revision$
  */
-public class Node {
+public class Node implements java.io.Serializable {
 
     private Node parent;
     private Object name;
diff --git a/groovy/groovy-core/src/main/org/codehaus/groovy/ant/Groovyc.java b/groovy/groovy-core/src/main/org/codehaus/groovy/ant/Groovyc.java
index ee12c50..da38095 100644
--- a/groovy/groovy-core/src/main/org/codehaus/groovy/ant/Groovyc.java
+++ b/groovy/groovy-core/src/main/org/codehaus/groovy/ant/Groovyc.java
@@ -45,11 +45,16 @@
  */
 package org.codehaus.groovy.ant;
 
+import groovy.lang.GroovyClassLoader;
+
 import java.io.File;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.nio.charset.Charset;
+import java.util.Iterator;
+import java.util.List;
 
+import org.apache.tools.ant.AntClassLoader;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DirectoryScanner;
 import org.apache.tools.ant.Project;
@@ -71,6 +76,7 @@
  * <li>sourcedir
  * <li>destdir
  * <li>classpath
+ * <li>stacktrace
  * </ul>
  * Of these arguments, the <b>sourcedir</b> and <b>destdir</b> are required.
  * <p>
@@ -81,6 +87,7 @@
  * Based heavily on the Javac implementation in Ant
  *
  * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ * @author Hein Meling
  * @version $Revision$ 
  */
 public class Groovyc extends MatchingTask {
@@ -189,6 +196,15 @@
     }
 
     /**
+     * Enable compiler to report stack trace information if a problem occurs
+     * during compilation.
+     * @param stacktrace
+     */
+    public void setStacktrace(boolean stacktrace) {
+        configuration.setDebug(stacktrace);
+    }
+
+    /**
      * Gets the destination directory into which the java source files
      * should be compiled.
      * @return the destination directory
@@ -432,8 +448,10 @@
                     String filename = compileList[i].getAbsolutePath();
 
                     // TODO this logging does not seem to appear in the maven build??
+                    // COMMENT Hein: This is not ant's problem;
+                    // fix it in maven instead if you really need this from maven!
                     log(filename);
-                    System.out.println("compiling: " + filename);
+//                    System.out.println("compiling: " + filename);
                 }
             }
 
@@ -448,9 +466,9 @@
                     configuration.setSourceEncoding(encoding);
                 }
 
-                CompilationUnit unit = new CompilationUnit( configuration );
-                unit.addSources( compileList );
-                unit.compile( );
+                CompilationUnit unit = new CompilationUnit(configuration, null, buildClassLoaderFor());
+                unit.addSources(compileList);
+                unit.compile();
             }
             catch (Exception e) {
 
@@ -468,4 +486,32 @@
             }
         }
     }
+
+    private GroovyClassLoader buildClassLoaderFor() {
+        ClassLoader parent = this.getClass().getClassLoader();
+        if (parent instanceof AntClassLoader) {
+            AntClassLoader antLoader = (AntClassLoader) parent;
+            String[] pathElm = antLoader.getClasspath().split(File.pathSeparator);
+            List classpath = configuration.getClasspath();
+            /*
+             * Iterate over the classpath provided to groovyc, and add any missing path
+             * entries to the AntClassLoader.  This is a workaround, since for some reason
+             * 'directory' classpath entries were not added to the AntClassLoader' classpath. 
+             */
+            for (Iterator iter = classpath.iterator(); iter.hasNext();) {
+                String cpEntry = (String) iter.next();
+                boolean found = false;
+                for (int i = 0; i < pathElm.length; i++) {
+                    if (cpEntry.equals(pathElm[i])) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found)
+                    antLoader.addPathElement(cpEntry);
+            }
+        }
+        return new GroovyClassLoader(parent, configuration);
+    }
+
 }
diff --git a/groovy/groovy-core/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java b/groovy/groovy-core/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
index 63115c6..f36ba85 100644
--- a/groovy/groovy-core/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+++ b/groovy/groovy-core/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
@@ -1395,29 +1395,122 @@
     }
 
     /**
-     * Support the subscript operator for a regex Matcher
+     * Support the subscript operator, e.g. matcher[index], for a regex Matcher.
+     *
+     * For an example using no group match, <code><pre>
+     *    def p = /ab[d|f]/ 
+     *    def m = "abcabdabeabf" =~ p 
+     *    for (i in 0..<m.count) { 
+     *        println( "m.groupCount() = " + m.groupCount())
+     *        println( "  " + i + ": " + m[i] )   // m[i] is a String
+     *    }
+     * </pre></code>
+     *
+     * For an example using group matches, <code><pre>
+     *    def p = /(?:ab([c|d|e|f]))/ `
+     *    def m = "abcabdabeabf" =~ p 
+     *    for (i in 0..<m.count) { 
+     *        println( "m.groupCount() = " + m.groupCount())
+     *        println( "  " + i + ": " + m[i] )   // m[i] is a List
+     *    }
+     * </pre></code>
+     *
+     * For another example using group matches, <code><pre>
+     *    def m = "abcabdabeabfabxyzabx" =~ /(?:ab([d|x-z]+))/
+     *    m.count.times { 
+     *        println( "m.groupCount() = " + m.groupCount())
+     *        println( "  " + it + ": " + m[it] )   // m[it] is a List
+     *    }
+     * </pre></code>
      *
      * @param matcher a Matcher
      * @param idx     an index
-     * @return the group at the given index
+     * @return object a matched String if no groups matched, list of matched groups otherwise.
      */
-    public static String getAt(Matcher matcher, int idx) {
-        matcher.reset();
-        idx = normaliseIndex(idx, matcher.groupCount());
-
-        // are we using groups?
-        if (matcher.groupCount() > 0) {
-            // yes, so return the specified group
-            matcher.find();
-            return matcher.group(idx);
-        } else {
-            // not using groups, so return the nth
-            // occurrence of the pattern
+    public static Object getAt(Matcher matcher, int idx) {
+        try {
+            int count = getCount(matcher);
+            if (idx < -count || idx >= count) {
+                throw new IndexOutOfBoundsException("index is out of range " + (-count) + ".." + (count - 1) + " (index = " + idx + ")");
+            }
+            idx = normaliseIndex(idx, count);
+            matcher.reset();
             for (int i = 0; i <= idx; i++) {
                 matcher.find();
             }
-            return matcher.group();
+
+            if (hasGroup(matcher)) {
+                // are we using groups?
+                // yes, so return the specified group as list
+                ArrayList list = new ArrayList(matcher.groupCount());
+                for (int i = 0; i <= matcher.groupCount(); i++) {
+                    list.add(matcher.group(i));
+                }
+                return list;
+            } else {
+                // not using groups, so return the nth
+                // occurrence of the pattern
+                return matcher.group();
+            }
         }
+        catch (IllegalStateException ex) {
+            return null;
+        }
+    }
+
+    /**
+     * Set the position of the given Matcher to the given index.
+     *
+     * @param matcher a Matcher
+     * @param idx the index number
+     */
+    public static void setIndex(Matcher matcher, int idx) {
+        int count = getCount(matcher);
+        if (idx < -count || idx >= count) {
+            throw new IndexOutOfBoundsException("index is out of range " + (-count) + ".." + (count - 1) + " (index = " + idx + ")");
+        }
+        if (idx == 0) {
+            matcher.reset();
+        }
+        else if (idx > 0) {
+            matcher.reset();
+            for (int i = 0; i < idx; i++) {
+                matcher.find();
+            }
+        }
+        else if (idx < 0) {
+            matcher.reset();
+            idx += getCount(matcher);
+            for (int i = 0; i < idx; i++) {
+                matcher.find();
+            }
+        }
+    }
+
+    /**
+     * Find the number of Strings matched to the given Matcher.
+     *
+     * @param matcher a Matcher
+     * @return int  the number of Strings matched to the given matcher.
+     */
+    public static int getCount(Matcher matcher) {
+        int counter = 0;
+        matcher.reset();
+        while (matcher.find()) {
+            counter++;
+        }
+        matcher.reset();
+        return counter;
+    }
+
+    /**
+     * Check whether a Matcher contains a group or not.
+     *
+     * @param matcher a Matcher
+     * @return boolean  <code>true</code> if matcher contains at least one group.
+     */
+    public static boolean hasGroup(Matcher matcher) {
+        return matcher.groupCount() > 0;
     }
 
     /**
@@ -3790,6 +3883,15 @@
     }
 
     public static void upto(Long self, Number to, Closure closure) {
+        long self1 = self.longValue();
+        long to1 = to.longValue();
+        if (self1 <= to1) {
+            for (long i = self1; i <= to1; i++) {
+                closure.callSpecial(new Long(i));
+            }
+        }
+        else
+            throw new GroovyRuntimeException("Infinite loop in " + self + ".upto(" + to +")");
     }
 
     public static void upto(float self, Number to, Closure closure) {
diff --git a/groovy/groovy-core/src/test/UberTestCase.java b/groovy/groovy-core/src/test/UberTestCase.java
index 0af6a3d..a13b422 100644
--- a/groovy/groovy-core/src/test/UberTestCase.java
+++ b/groovy/groovy-core/src/test/UberTestCase.java
@@ -203,6 +203,7 @@
         suite.addTestSuite(PropertyWithoutDotTest.class);
         suite.addTestSuite(RangeTest.class);
         suite.addTestSuite(ReadLineTest.class);
+        suite.addTestSuite(RegExpGroupMatchTest.class);
         suite.addTestSuite(RegularExpressionsTest.class);
         suite.addTestSuite(ReturnTest.class);
         suite.addTestSuite(RodsBooleanBug.class);
diff --git a/groovy/groovy-core/src/test/groovy/RegExpGroupMatchTest.groovy b/groovy/groovy-core/src/test/groovy/RegExpGroupMatchTest.groovy
new file mode 100644
index 0000000..38c46c3
--- /dev/null
+++ b/groovy/groovy-core/src/test/groovy/RegExpGroupMatchTest.groovy
@@ -0,0 +1,100 @@
+/**
+ * Test for fixing the Jira issue GROOVY-1000
+ *
+ *    Fix an infinite loop when getting after group matching in regular expression.
+ *    Graham Miller has given this idea.
+ *
+ * @author Pilho Kim
+ * @version $Revision$
+ */
+
+import java.util.regex.Matcher
+import java.util.regex.Pattern
+
+class RegExpGroupMatchTest extends GroovyTestCase {
+
+    void testFirst() {
+        assert "cheesecheese" =~ "cheese"
+        assert "cheesecheese" =~ /cheese/
+        assert "cheese" == /cheese/   /*they are both string syntaxes*/
+    }
+
+    void testSecond() {
+        // Lets create a regex Pattern
+        def pattern = ~/foo/
+        assert pattern instanceof Pattern
+        assert pattern.matcher("foo").matches()
+    }
+
+    void testThird() {
+        // Lets create a Matcher
+        def matcher = "cheesecheese" =~ /cheese/
+        assert matcher instanceof Matcher
+
+        def answer = matcher.replaceAll("edam")
+        println answer
+    }
+
+    void testFourth() {
+        // Lets do some replacement
+        def cheese = ("cheesecheese" =~ /cheese/).replaceFirst("nice")
+        assert cheese == "nicecheese"
+    }
+
+    void testFifth() {
+        // Group demo
+        def matcher = "\$abc." =~ "\\\$(.*)\\."
+        matcher.matches();                   // must be invoked
+        assert matcher.group(1) == "abc"     // is one, not zero
+        // assert matcher[1] == "abc"     // This has worked only before jsr-03-release
+        println (matcher[0])
+        assert matcher[0] == ["\$abc.", "abc"]
+        assert matcher[0][1] == "abc"
+    }
+
+    void testSixth() {
+        // Group demo
+        // Avoid having to double all the backslash escaping characters.
+        def matcher = "\$abc." =~ /\$(.*)\./    // no need to double-escape!
+        assert "\\\$(.*)\\." == /\$(.*)\./
+        matcher.matches();                      // must be invoked
+        assert matcher.group(1) == "abc"        // is one, not zero
+        // assert matcher[1] == "abc"     // This has worked only before jsr-03-release
+        println (matcher[0])
+        assert matcher[0] == ["\$abc.", "abc"]
+        assert matcher[0][1] == "abc"
+    }
+
+    // Test no group match.
+    void testNoGroupMatcherAndGet() {
+        def p = /ab[d|f]/
+        def m = "abcabdabeabf" =~ p 
+
+        for (i in 0..<m.count) { 
+            println( "m.groupCount() = " + m.groupCount())
+            println( "  " + i + ": " + m[i] )   // m[i] is a String
+        }
+    }
+
+    // Test group matches.
+    void testGroupMatcherAndGet() {
+        def p = /(?:ab([c|d|e|f]))/
+        def m = "abcabdabeabf" =~ p 
+
+        for (i in 0..<m.count) { 
+            println( "m.groupCount() = " + m.groupCount())
+            println( "  " + i + ": " + m[i] )   // m[i] is a String
+        }
+    }
+
+    // Test group matches.
+    void testAnotherGroupMatcherAndGet() {
+        def m = "abcabdabeabfabxyzabx" =~ /(?:ab([d|x-z]+))/
+
+        m.count.times { 
+            println( "m.groupCount() = " + m.groupCount())
+            println( "  " + it + ": " + m[it] )   // m[it] is a String
+        }
+    }
+}
+