Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-1000

reset call in getAt for Matcher

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Minor
    • Resolution: Fixed
    • 1.0-JSR-2
    • 1.0-JSR-3
    • groovy-jdk
    • None
    • groovy-1.0-jsr-02 on jdk1.5.0_03 on Windows

    Description

      I was hacking away on some regular expression code to use the find method on a Matcher. It wasn't working the way I expect, so I wrote out what I thought to be the equivalent Java code, both shown here:

      //---- Java code ------------
      Pattern pattern = Pattern.compile("(?:ab([c|d]))");
      Matcher matcher = pattern.matcher("abcabd");
      while (matcher.find()) {
      System.out.println(matcher[1]);
      }
      //---------------------------

      //---- Groovy code ----------
      pattern = /(?:ab([c|d]))/
      matcher = "abcabd" =~ pattern;

      while (matcher.find()) {
      println(matcher[1]);
      }
      //---------------------------

      The Java code does what I want (print out "c" then "d" and exit), whereas the groovy code loops infinitely printing "c". (The find method when called repeatedly should start where it left off the last time according to http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Matcher.html) It was then that I noticed that the getAt implementation for Matcher objects calls reset as its first order of business (code below for reference). Calling reset causes find() to start from the beginning the next time.

      I think the simplest solution is to move the matcher.reset() call into the else clause at the bottom of the function, where it's trying do do the find without using groups. I have attached a patch to that effect. For reference the method is copied below.

      // from DefaultGroovyMethods.java
      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
      for (int i = 0; i <= idx; i++)

      { matcher.find(); }

      return matcher.group();
      }
      }

      Attachments

        1. DefaultGroovyMethods.java.patch
          1 kB
          Graham Miller

        Activity

          People

            phkim Kim, Pilho
            gmiller Graham Miller
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: