Module: CommandSearch::Parser

Defined in:
lib/command_search/parser.rb

Class Method Summary collapse

Class Method Details

.clean_ununused_syntax(input) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/command_search/parser.rb', line 60

def clean_ununused_syntax(input)
  out = input.map do |x|
    next if x[:type] == :paren && x[:value].is_a?(String)
    next if x[:nest_type] == :colon && x[:value].empty?
    if x[:nest_type] == :compare && x[:value].length < 2
      x = clean_ununused_syntax(x[:value]).first
    end
    next x unless x && x[:type] == :nest
    x[:value] = clean_ununused_syntax(x[:value])
    x
  end
  out.compact
end

.cluster(type, input, cluster_type = :binary) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/command_search/parser.rb', line 24

def cluster(type, input, cluster_type = :binary)
  binary = (cluster_type == :binary)
  out = input
  out = out[:value] while out.is_a?(Hash)
  out.compact!
  # rindex (vs index) important for nested prefixes
  while (i = out.rindex { |x| x[:type] == type })
    val = [out[i + 1]]
    val.unshift(out[i - 1]) if binary && i > 0
    front_offset = 0
    front_offset = 1 if binary && i > 0
    out[(i - front_offset)..(i + 1)] = {
      type: :nest,
      nest_type: type,
      nest_op: out[i][:value],
      value: val
    }
  end
  out.map do |x|
    next x unless x[:type] == :nest
    x[:value] = cluster(type, x[:value], cluster_type)
    x
  end
end

.group_parens(input) ⇒ Object



14
15
16
17
18
19
20
21
22
# File 'lib/command_search/parser.rb', line 14

def group_parens(input)
  out = input
  while parens_rindex(out)
    (a, b) = parens_rindex(out)
    val = out[(a + 1)..(b - 1)]
    out[a..b] = { type: :nest, nest_type: :paren, value: val }
  end
  out
end

.parens_rindex(input) ⇒ Object



5
6
7
8
9
10
11
12
# File 'lib/command_search/parser.rb', line 5

def parens_rindex(input)
  val_list = input.map { |x| x[:value] }
  open_i = val_list.rindex('(')
  return unless open_i
  close_offset = val_list.drop(open_i).index(')')
  return unless close_offset
  [open_i, close_offset + open_i]
end

.parse(input) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/command_search/parser.rb', line 74

def parse(input)
  out = input
  out = group_parens(out)
  out = cluster(:colon, out)
  out = unchain(:compare, out)
  out = cluster(:compare, out)
  out = cluster(:minus, out, :prefix)
  out = cluster(:pipe, out)
  out = clean_ununused_syntax(out)
  out
end

.unchain(type, input) ⇒ Object



49
50
51
52
53
54
55
56
57
58
# File 'lib/command_search/parser.rb', line 49

def unchain(type, input)
  input.each_index do |i|
    front = input.dig(i, :type)
    mid = input.dig(i + 1, :type)
    back = input.dig(i + 2, :type)
    if front == type && mid != type && back == type
      input.insert(i + 1, input[i + 1])
    end
  end
end