def match(element, first_only = false)
      # Match element if no element name or element name same as element name
      if matched = (!@tag_name or @tag_name == element.name)
        # No match if one of the attribute matches failed
        for attr in @attributes
          if element.attributes[attr[0]] !~ attr[1]
            matched = false
            break
          end
        end
      end

      # Pseudo class matches (nth-child, empty, etc).
      if matched
        for pseudo in @pseudo
          unless pseudo.call(element)
            matched = false
            break
          end
        end
      end

      # Negation. Same rules as above, but we fail if a match is made.
      if matched and @negation
        for negation in @negation
          if negation[:tag_name] == element.name
            matched = false
          else
            for attr in negation[:attributes]
              if element.attributes[attr[0]] =~ attr[1]
                matched = false
                break
              end
            end
          end
          if matched
            for pseudo in negation[:pseudo]
              if pseudo.call(element)
                matched = false
                break
              end
            end
          end
          break unless matched
        end
      end

      # If element matched but depends on another element (child,
      # sibling, etc), apply the dependent matches instead.
      if matched and @depends
        matches = @depends.call(element, first_only)
      else
        matches = matched ? [element] : nil
      end

      # If this selector is part of the group, try all the alternative
      # selectors (unless first_only).
      if @alternates and (!first_only or !matches)
        @alternates.each do |alternate|
          break if matches and first_only
          if subset = alternate.match(element, first_only)
            if matches
              matches.concat subset
            else
              matches = subset
            end
          end
        end
      end

      matches
    end
def match(element, first_only = false)
      # Match element if no element name or element name same as element name
      if matched = (!@tag_name or @tag_name == element.name)
        # No match if one of the attribute matches failed
        for attr in @attributes
          if element.attributes[attr[0]] !~ attr[1]
            matched = false
            break
          end
        end
      end

      # Pseudo class matches (nth-child, empty, etc).
      if matched
        for pseudo in @pseudo
          unless pseudo.call(element)
            matched = false
            break
          end
        end
      end

      # Negation. Same rules as above, but we fail if a match is made.
      if matched and @negation
        for negation in @negation
          if negation[:tag_name] == element.name
            matched = false
          else
            for attr in negation[:attributes]
              if element.attributes[attr[0]] =~ attr[1]
                matched = false
                break
              end
            end
          end
          if matched
            for pseudo in negation[:pseudo]
              if pseudo.call(element)
                matched = false
                break
              end
            end
          end
          break unless matched
        end
      end

      # If element matched but depends on another element (child,
      # sibling, etc), apply the dependent matches instead.
      if matched and @depends
        matches = @depends.call(element, first_only)
      else
        matches = matched ? [element] : nil
      end

      # If this selector is part of the group, try all the alternative
      # selectors (unless first_only).
      if @alternates and (!first_only or !matches)
        @alternates.each do |alternate|
          break if matches and first_only
          if subset = alternate.match(element, first_only)
            if matches
              matches.concat subset
            else
              matches = subset
            end
          end
        end
      end

      matches
    end
:call-seq:
   Selector.new(string, [values ...]) => selector

 Creates a new selector from a CSS 2 selector expression.

 The first argument is the selector expression. All other arguments
 are used for value substitution.

 Throws InvalidSelectorError is the selector expression is invalid.
 :call-seq:
   match(element, first?) => array or nil

 Matches an element against the selector.

 For a simple selector this method returns an array with the
 element if the element matches, nil otherwise.

 For a complex selector (sibling and descendant) this method
 returns an array with all matching elements, nil if no match is
 found.

 Use +first_only=true+ if you are only interested in the first element.

 For example:
   if selector.match(element)
     puts "Element is a login form"
   end