class Net::LDAP::Filter::FilterParser

:nodoc:
object hierarchies.
Parses RFC 2254-style string representations of LDAP filters into Filter
#

def initialize(str)

def initialize(str)
  require 'strscan' # Don't load strscan until we need it.
  @filter = parse(StringScanner.new(str))
  raise Net::LDAP::FilterSyntaxInvalidError, "Invalid filter syntax." unless @filter
end

def merge_branches(op, scanner)

operation.
merges them into a single Filter tree by calling the provided
This method calls #parse_branches to generate the branch list and then

into a branch array for filter merging using the parent operation.
test1 and test2. Each of these is parsed separately and then pushed
That is, the expression (&(test1)(test2) has two branches:
Join ("&") and intersect ("|") operations are presented in branches.
#
def merge_branches(op, scanner)
  filter = nil
  branches = parse_branches(scanner)
  if branches.size >= 1
    filter = branches.shift
    while not branches.empty?
      filter = filter.__send__(op, branches.shift)
    end
  end
  filter
end

def parse(ldap_filter_string)

Construct a filter tree from the provided string and return it.
#
def parse(ldap_filter_string)
  new(ldap_filter_string).filter
end

def parse(scanner)

to parse a parenthesized expression.
tries to parse a standalone expression first. If that fails, it tries
Parse the string contained in the StringScanner provided. Parsing
#
def parse(scanner)
  parse_filter_branch(scanner) or parse_paren_expression(scanner)
end

def parse_branches(scanner)

objects.
This method parses the branch text out into an array of filter

into a branch array for filter merging using the parent operation.
test1 and test2. Each of these is parsed separately and then pushed
That is, the expression (&(test1)(test2) has two branches:
Join ("&") and intersect ("|") operations are presented in branches.
#
def parse_branches(scanner)
  branches = []
  while branch = parse_paren_expression(scanner)
    branches << branch
  end
  branches
end

def parse_filter_branch(scanner)

This parses a given expression inside of parentheses.
#
def parse_filter_branch(scanner)
  scanner.scan(/\s*/)
  if token = scanner.scan(/[-\w:.;]*[\w]/)
    scanner.scan(/\s*/)
    if op = scanner.scan(/<=|>=|!=|:=|=/)
      scanner.scan(/\s*/)
      if value = scanner.scan(/(?:[-\[\]{}\w*.+\/:@=,#\$%&!'^~\s\xC3\x80-\xCA\xAF]|[^\x00-\x7F]|\\[a-fA-F\d]{2})+/u)
        # 20100313 AZ: Assumes that "(uid=george*)" is the same as
        # "(uid=george* )". The standard doesn't specify, but I can find
        # no examples that suggest otherwise.
        value.strip!
        case op
        when "="
          Net::LDAP::Filter.eq(token, value)
        when "!="
          Net::LDAP::Filter.ne(token, value)
        when "<="
          Net::LDAP::Filter.le(token, value)
        when ">="
          Net::LDAP::Filter.ge(token, value)
        when ":="
          Net::LDAP::Filter.ex(token, value)
        end
      end
    end
  end
end

def parse_paren_expression(scanner)

def parse_paren_expression(scanner)
  if scanner.scan(/\s*\(\s*/)
    expr = if scanner.scan(/\s*\&\s*/)
             merge_branches(:&, scanner)
           elsif scanner.scan(/\s*\|\s*/)
             merge_branches(:|, scanner)
           elsif scanner.scan(/\s*\!\s*/)
             br = parse_paren_expression(scanner)
             ~br if br
           else
             parse_filter_branch(scanner)
           end
    if expr and scanner.scan(/\s*\)\s*/)
      expr
    end
  end
end