Okay, I'm back to needing Regexp arity, and then some --I also need to know if 
a particular subexpression if a zero-width positive lookahead. Why?

Have a look at this lovely interface:

  class SplitToken < Token
    def_attr :start_token, :end_token
    def_attr :start_pattern, :end_pattern
    def_attr :start_char, :end_char
    def initialize( name, start_token, end_token, start_char=''..'', 
end_char=''..'', opt=[] )
      super( name, opt )
      @start_token = start_token
      @end_token = end_token
      @start_char = start_char
      @end_char = end_char
      @start_pattern = /(#{start_char.first})(#{Regexp.escape(start_token)})
(#{'?=' if start_reuse?}#{start_char.last})/
      @end_pattern = /(#{end_char.first})(#{Regexp.escape(end_token)})(#{'?=' 
if end_reuse?}#{end_char.last})/
    end
    # ...
  end

  class BlockToken < SplitToken
    def initialize( name, start_pattern, opt=[] )
      super( name, start_pattern, '', '\n\s*'..'', ''...'\n\ *\n' , opt | 
[ :NEWLINE ] )
    end
    # ...
  end

Notice the tricky way I use Ranges. #start_reuse? and #end_reuse? actually 
just check @start_char.exclude_end? and @end_char.exclude_end? respectively.

I really don't want to do this. I'd rather just let the interface accept 
Regexps directly, but then I would like to a) check for arity == 3 to make 
sure they are valid and b) need to know if last subexpression is zero-width 
lookahead.

I'll have to work around. But I think this represents the real use case --when 
an interface accepts regexp and it wants to make sure they are valid.

T.