Class: MODL::Parser::Evaluator

Inherits:
Object
  • Object
show all
Defined in:
lib/modl/parser/evaluator.rb

Overview

Evaluate a conditional expression

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.evaluate(global, condition) ⇒ Object

Evaluate the given condition



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/modl/parser/evaluator.rb', line 6

def self.evaluate(global, condition)
  return false if global.nil? || !global.is_a?(GlobalParseContext) || !condition.is_a?(MODL::Parser::Parsed::ParsedCondition)

  start = 0
  if condition.text
    value1, success = value(global, condition.text)
  else
    start = 1
    value1, success = value(global, condition.values[0].text)
  end


  # Handle single-value conditions of the form '{x?}'
  if condition.values.length == start
    return false if value1.nil?
    return false if value1.is_a?(FalseClass)
    return true if value1.is_a?(TrueClass)

    return success ? value1 : false
  end

  # Handle the right-hand side, which might have many values and operators, e.g. '{x=a|b|c|d?}'
  i = start
  result = false
  while i < condition.values.length
    item = condition.values[i]
    if item.primitive.constant
      value2 = item.text
    else
      value2, success = value(global, item.text)
    end
    partial = false
    case condition.operator
    when '='
      wild = value2.is_a?(String) && value2.include?('*') ? true : false
      if wild
        regex = '^'
        value2.each_char do |c|
          regex << (c == '*' ? '.*' : c)
        end
        partial |= !value1.match(regex).nil?
      else
        partial |= value1 == value2
      end
    when '>'
      partial |= value1 > value2
    when '<'
      partial |= value1 < value2
    when '>='
      partial |= value1 >= value2
    when '<='
      partial |= value1 <= value2
    end
    i += 1
    result |= partial
  end
  result
end

.value(global, k) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/modl/parser/evaluator.rb', line 65

def self.value(global, k)
  success = false
  if k.is_a?(String) && k.include?('%')
    value1, _ignore = MODL::Parser::RefProcessor.deref(k, global)
    success = true
  elsif k.is_a?(FalseClass)
    value1 = false
    success = true
  elsif k.is_a?(TrueClass)
    value1 = true
    success = true
  elsif k.is_a?(NilClass)
    value1 = nil
  else
    key = k
    ikey = key.to_i
    if ikey.to_s == key
      index_val = global.index[ikey]
      value1 = index_val.respond_to?(:text) ? index_val.text : nil
    else
      pair = global.pair(key)
      return k unless pair

      value1 = pair.text
    end
    success = true
  end
  [value1, success]
end

Instance Method Details

#evaluate_oldObject



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/modl/parser/evaluator.rb', line 95

def evaluate_old
  result = false
  if @key
    if @key.include?('%')
      value1, _ignore = MODL::Parser::RefProcessor.deref(@key, @global)
    else
      key = @key
      ikey = key.to_i
      if ikey.to_s == key
        index_val = @global.index[ikey]
        value1 = index_val.respond_to?(:text) ? index_val.text : nil
      else
        pair = @global.pair(key)
        return false unless pair

        value1 = pair.text
      end
    end

    @values.each do |value|
      value2 = value.text
      value2, _ignore = MODL::Parser::RefProcessor.deref(value2, @global) if value2.is_a?(String) && value2.include?('%')
      value2 = @global.pair(value.text).text if @global.pair(value.text)

      case @operator
      when '='
        wild = value2.is_a?(String) && value2.include?('*') ? true : false
        if wild
          regex = '^'
          value2.each_char do |c|
            regex << (c == '*' ? '.*' : c)
          end
          result |= !value1.match(regex).nil?
        else
          result |= value1 == value2
        end
      when '>'
        result |= value1 > value2
      when '<'
        result |= value1 < value2
      when '>='
        result |= value1 >= value2
      when '<='
        result |= value1 <= value2
      end
      break if result # shortcut if we have a matching value
    end
  elsif @values.length == 1
    key = @values[0].text
    if key.is_a?(String)
      key = key.start_with?('%') ? Sutil.tail(key) : key
    end
    the_pair = @global.pair(key)
    if the_pair
      result = the_pair.text
    else
      return true if @values[0].trueVal
      return false if @values[0].falseVal
      return false if @values[0].string

      result = @values[0].evaluate
    end
  end
  result
end