class HumanQL::QueryGenerator

Generate a Human Query Language String from an abstract syntax tree (AST). This allows query simplification (e.g. via TreeNormalizer) and re-writing queries.

Attributes

and[RW]

The AND operator (if not default). Default: ' and '

colon[RW]

COLON character used a prefix delimiter. Default: ':'

default_op[RW]

The default operator (:and or :or). If set, will output a :space instead of the operator. Default: nil

lparen[RW]

Left parenthesis character. Default: '('

lquote[RW]

Left quote character for phrases. Default: '“'

not[RW]

The NOT operator. Default: '-'

or[RW]

The OR operator (if not default). Default: ' or '

precedence[RW]

Hash of operators to precedence integer values, as per QueryParser#precedence. If set, outputs parentheses only when precedence dictates that it is necessary. Default: nil

rparen[RW]

Right parenthesis character. Default: ')'

rquote[RW]

Right quote character for phrases. Default: '“'

space[RW]

SPACE delimiter. Default: ' '

Public Class Methods

new(opts = {}) click to toggle source

Construct given options which are interpreted as attribute names to set.

# File lib/human-ql/query_generator.rb, line 80
def initialize(opts = {})
  @and = ' and '.freeze
  @or = ' or '.freeze
  @not = '-'.freeze
  @space = ' '.freeze
  @lquote = @rquote = '"'.freeze
  @colon = ':'.freeze
  @lparen = '('.freeze
  @rparen = ')'.freeze
  @default_op = nil
  @precedence = nil

  opts.each do |name,val|
    send(name.to_s + '=', val)
  end
end

Public Instance Methods

generate(node) click to toggle source

Given the root node of the AST, return a String in Human Query Language syntax.

# File lib/human-ql/query_generator.rb, line 99
def generate(node)
  op,*args = node
  if ! node.is_a?(Array)
    op
  elsif args.empty?
    nil
  else
    case op
    when :and
      terms_join(args, :and)
    when :or
      terms_join(args, :or)
    when :not
      @not + pwrap_gen(args[0], op)
    when :phrase
      @lquote + args.join(@space) + @rquote
    when String
      op + @colon + pwrap_gen(args[0], op)
    else
      raise "Unsupported op: #{node.inspect}"
    end
  end
end
parser=(p) click to toggle source

Set default_op and precedence from the given QueryParser, as a convenience.

# File lib/human-ql/query_generator.rb, line 73
def parser=(p)
  @default_op = p.default_op
  @precedence = p.precedence
end

Protected Instance Methods

precedence_lte?(op1, op2) click to toggle source
# File lib/human-ql/query_generator.rb, line 153
def precedence_lte?(op1, op2)
  if @precedence
    @precedence[op1] <= @precedence[op2]
  else
    false
  end
end
pwrap(inner) click to toggle source
# File lib/human-ql/query_generator.rb, line 149
def pwrap(inner)
  @lparen + inner + @rparen
end
pwrap_gen(node, parent_op) click to toggle source
# File lib/human-ql/query_generator.rb, line 136
def pwrap_gen(node, parent_op)
  if node.is_a?(Array)
    op = node[0]
    if precedence_lte?(parent_op, op)
      generate(node)
    else
      pwrap(generate(node))
    end
  else
    node
  end
end
terms_join(args, op) click to toggle source
# File lib/human-ql/query_generator.rb, line 125
def terms_join(args, op)
  args = args.map { |a| pwrap_gen(a, op) }
  if op == @default_op
    args.join(@space)
  elsif op == :and
    args.join(@and)
  elsif op == :or
    args.join(@or)
  end
end