module CommandSearch::Parser

Public Instance Methods

clean!(ast) click to toggle source
# File lib/command_search/parser.rb, line 104
def clean!(ast)
  return unless ast.any?
  if ast[0][:type] == :colon || ast[0][:type] == :compare
    r_merge!(ast, 0)
  end
  if ast[-1][:type] == :colon || ast[-1][:type] == :compare
    l_merge!(ast, ast.length - 1)
  end
  i = 1
  while i < ast.length - 1
    next i += 1 unless ast[i][:type] == :colon || ast[i][:type] == :compare
    if ast[i + 1][:type] == :minus
      r_merge!(ast, i + 1)
    elsif ![:str, :number, :quote].include?(ast[i - 1][:type])
      r_merge!(ast, i)
    elsif ![:str, :number, :quote].include?(ast[i + 1][:type])
      l_merge!(ast, i)
    else
      i += 1
    end
  end
end
cluster_cmds!(ast) click to toggle source
# File lib/command_search/parser.rb, line 29
def cluster_cmds!(ast)
  i = 1
  while i < ast.length - 1
    type = ast[i][:type]
    next i += 1 unless type == :colon || type == :compare
    ast[(i - 1)..(i + 1)] = {
      type: type,
      nest_op: ast[i][:value],
      value: [ast[i - 1], ast[i + 1]]
    }
  end
end
cluster_not!(ast) click to toggle source
# File lib/command_search/parser.rb, line 61
def cluster_not!(ast)
  i = ast.length
  while i > 0
    i -= 1
    type = ast[i][:type]
    cluster_not!(ast[i][:value]) if type == :and
    next unless type == :minus
    if i == ast.length - 1
      ast.delete_at(i)
      next
    end
    ast[i][:type] = :not
    ast[i][:value] = [ast[i + 1]]
    ast.delete_at(i + 1)
  end
end
cluster_or!(ast) click to toggle source
# File lib/command_search/parser.rb, line 42
def cluster_or!(ast)
  i = 0
  while i < ast.length
    type = ast[i][:type]
    cluster_or!(ast[i][:value]) if type == :and || type == :not
    next i += 1 unless type == :pipe
    if i == 0 || i == ast.length - 1
      ast.delete_at(i)
      next
    end
    val = [ast[i - 1], ast[i + 1]]
    cluster_or!(val)
    ast[i][:type] = :or
    ast[i][:value] = val
    ast.delete_at(i + 1)
    ast.delete_at(i - 1)
  end
end
group_parens!(ast) click to toggle source
# File lib/command_search/parser.rb, line 5
def group_parens!(ast)
  i = 0
  opening_idxs = []
  while i < ast.length
    next i += 1 unless ast[i][:type] == :paren
    if ast[i][:value] == '('
      opening_idxs.push(i)
      ast.delete_at(i)
      next
    end
    ast.delete_at(i)
    opening = opening_idxs.pop()
    next unless opening
    val = ast.slice(opening, i - opening)
    if val.count > 1
      ast[opening..(i - 1)] = { type: :and, value: val }
      i -= val.length
      next
    elsif val.count == 1
      ast[opening] = val.first
    end
  end
end
l_merge!(ast, i) click to toggle source
# File lib/command_search/parser.rb, line 97
def l_merge!(ast, i)
  ast[i][:type] = :str
  return unless ast[i - 1] && ast[i - 1][:type] == :str
  ast[i][:value] = ast[i - 1][:value] + ast[i][:value]
  ast.delete_at(i - 1)
end
parse!(ast) click to toggle source
# File lib/command_search/parser.rb, line 127
def parse!(ast)
  clean!(ast)
  unchain!(ast)
  cluster_cmds!(ast)
  group_parens!(ast)
  cluster_not!(ast)
  cluster_or!(ast)
  ast
end
r_merge!(ast, i) click to toggle source
# File lib/command_search/parser.rb, line 90
def r_merge!(ast, i)
  ast[i][:type] = :str
  return unless ast[i + 1] && ast[i + 1][:type] == :str
  ast[i][:value] = ast[i][:value] + ast[i + 1][:value]
  ast.delete_at(i + 1)
end
unchain!(ast) click to toggle source
# File lib/command_search/parser.rb, line 78
def unchain!(ast)
  i = 1
  while i < ast.length - 3
    left = ast[i][:type]
    right = ast[i + 2][:type]
    i += 1
    next unless left == :colon || left == :compare
    next unless right == :colon || right == :compare
    ast.insert(i, ast[i].clone())
  end
end