Module: CommandSearch::Parser

Defined in:
lib/command_search/parser.rb

Class Method Summary collapse

Class Method Details

.clean_ununusable!(input) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/command_search/parser.rb', line 98

def clean_ununusable!(input)
  i = 1
  while i < input.length
    next i += 1 unless input[i][:type] == :minus
    next i += 1 unless [:compare, :colon].include?(input[i - 1][:type])
    input[i..i + 1] = merge_strs(input[i..i + 1], [0, 1])
  end
  i = 0
  while i < input.length
    next i += 1 if ![:compare, :colon].include?(input[i][:type])
    next i += 1 if i > 0 &&
      (i < input.count - 1) &&
      [:str, :number, :quote].include?(input[i - 1][:type]) &&
      [:str, :number, :quote].include?(input[i + 1][:type])

    input[i..i + 1] = merge_strs(input[i..i + 1], [0, 1])
    input[i - 1..i] = merge_strs(input[i - 1..i], [1, 0]) if i > 0
  end
end

.cluster_cmds!(input) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/command_search/parser.rb', line 29

def cluster_cmds!(input)
  i = 1
  while i < input.length - 1
    type = input[i][:type]
    next i += 1 unless type == :colon || type == :compare
    input[(i - 1)..(i + 1)] = {
      type: type,
      nest_op: input[i][:value],
      value: [input[i - 1], input[i + 1]]
    }
  end
end

.cluster_not!(input) ⇒ Object



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

def cluster_not!(input)
  i = input.length
  while i > 0
    i -= 1
    type = input[i][:type]
    cluster_not!(input[i][:value]) if type == :and
    next unless type == :minus
    if i == input.length - 1
      input.delete_at(i)
      next
    end
    input[i..(i + 1)] = {
      type: :not,
      value: [input[i + 1]]
    }
  end
end

.cluster_or!(input) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/command_search/parser.rb', line 42

def cluster_or!(input)
  i = 0
  while i < input.length
    type = input[i][:type]
    cluster_or!(input[i][:value]) if type == :and || type == :not
    next i += 1 unless type == :pipe
    if i == 0 || i == input.length - 1
      input.delete_at(i)
      next
    end
    val = [input[i - 1], input[i + 1]]
    cluster_or!(val)
    input[(i - 1)..(i + 1)] = { type: :or, value: val }
  end
end

.group_parens!(input) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/command_search/parser.rb', line 5

def group_parens!(input)
  i = 0
  opening_idxs = []
  while i < input.length
    next i += 1 unless input[i][:type] == :paren
    if input[i][:value] == '('
      opening_idxs.push(i)
      input.delete_at(i)
      next
    end
    input.delete_at(i)
    opening = opening_idxs.pop()
    next unless opening
    val = input.slice(opening, i - opening)
    if val.count > 1
      input[opening..(i - 1)] = { type: :and, value: val }
      i -= val.length
      next
    elsif val.count == 1
      input[opening] = val.first
    end
  end
end

.merge_strs(input, x, y) ⇒ Object



88
89
90
91
92
93
94
95
96
# File 'lib/command_search/parser.rb', line 88

def merge_strs(input, (x, y))
  if input[y] && input[y][:type] == :str
    values = input.map { |x| x[:value] }
    { type: :str, value: values.join() }
  else
    input[x][:type] = :str
    input
  end
end

.parse!(input) ⇒ Object



118
119
120
121
122
123
124
125
126
# File 'lib/command_search/parser.rb', line 118

def parse!(input)
  clean_ununusable!(input)
  unchain!(input, [:colon, :compare])
  cluster_cmds!(input)
  group_parens!(input)
  cluster_not!(input)
  cluster_or!(input)
  input
end

.unchain!(input, types) ⇒ Object



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

def unchain!(input, types)
  i = 0
  while i < input.length - 2
    left = input[i][:type]
    right = input[i + 2][:type]
    if types.include?(left) && types.include?(right)
      input.insert(i + 1, input[i + 1].clone())
    end
    i += 1
  end
end