#Scans through a string, moving the "cursor" when a match occurs.
scanner = object.new

#Initialize with string to match against
scanner.init = { str |
  my.str = str
  my.pos = 0
}

scanner.prototype {
  #Scan using either a string or a regex
  my.scan = { matcher |
    when { matcher.string? } { scan_string matcher }
    { matcher.regex? } { scan_regex matcher }
    { true } { throw "Expected string or regex" }
  }

  #Attempt to match string against current position. Advances position
  #when there is a match.
  my.scan_string = { matcher |
    patch = my.str[my.pos, my.pos + matcher.length - 1]

      true? patch == matcher
      { 
        my.pos = my.pos + matcher.length
        patch
      }
  }

  #Attempt to match regex against current position. Advances position
  #when there is a match.
  my.scan_regex = { matcher |
    current = my.pos
    result = my.str.match(matcher, current)

    true? result && { current == result.start_pos }
    {
      my.pos = result.end_pos + 1
      result
    }
  }

  my.rest = {
    my.str[my.pos, -1]
  }

  my.end? = { my.pos >= str.length }

  my.end = { my.pos = str.length }

}

export scanner, :scanner