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
The AND operator (if not default). Default: ' and '
COLON character used a prefix delimiter. Default: ':'
The default operator (:and or :or). If set, will output a :space instead of the operator. Default: nil
Left parenthesis character. Default: '('
Left quote character for phrases. Default: '“'
The NOT operator. Default: '-'
The OR operator (if not default). Default: ' or '
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
Right parenthesis character. Default: ')'
Right quote character for phrases. Default: '“'
SPACE delimiter. Default: ' '
Public Class Methods
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
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
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
# File lib/human-ql/query_generator.rb, line 153 def precedence_lte?(op1, op2) if @precedence @precedence[op1] <= @precedence[op2] else false end end
# File lib/human-ql/query_generator.rb, line 149 def pwrap(inner) @lparen + inner + @rparen end
# 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
# 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