Class: Chutzen::Expression

Inherits:
Object
  • Object
show all
Defined in:
lib/chutzen/expression.rb,
lib/chutzen/expression/lookup_error.rb,
lib/chutzen/expression/syntax_error.rb

Overview

Transforms a Chutzen expression by transforming it and replacing any query expressions with their values.

Defined Under Namespace

Classes: LookupError, SyntaxError

Constant Summary collapse

INTEGER_RE =
/\A\d+\z/.freeze
OPERATIONS =
{
  '=' => ->(left, right) { left == right },
  '&' => ->(left, right) { left & right },
  '|' => ->(left, right) { left | right },
  '<' => ->(left, right) { left & right ? left < right : nil },
  '>' => ->(left, right) { left & right ? left > right : nil }
}.freeze
Transformer =
Parslet::Transform.new do
  rule(undefined: simple(:value)) { nil }
  rule(boolean: simple(:value)) { value.to_s == 'true' }
  rule(integer: simple(:value)) { value.to_i }
  rule(float: simple(:value)) { value.to_f }
  rule(string: simple(:value)) { value.to_s }

  rule(identifier: simple(:name)) do
    path = *Chutzen::Expression.split(name)
    if dictionary.exist?(*path)
      dictionary.dig(*path)
    else
      raise(
        LookupError.new(
          "No value for #{name}", expression: name.to_s, dictionary: dictionary
        )
      )
    end
  end

  rule(search_identifier: simple(:name)) do
    dictionary.dig_deep(*Chutzen::Expression.split(name))
  end

  rule(
    operation: {
      left: simple(:left), operator: simple(:operator), right: simple(:right)
    }
  ) do
    OPERATIONS[operator.to_s].call(left, right)
  end
end

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(expression, dictionary) ⇒ Expression

Returns a new instance of Expression.



54
55
56
57
58
59
60
61
62
# File 'lib/chutzen/expression.rb', line 54

def initialize(expression, dictionary)
  @expression = Chutzen::ExpressionParser.new.parse(expression)
  @dictionary = dictionary
rescue Parslet::ParseFailed => e
  raise Chutzen::Expression::SyntaxError.new(
    e.parse_failure_cause.ascii_tree,
    expression: expression
  )
end

Class Method Details

.split(key) ⇒ Object



68
69
70
71
72
# File 'lib/chutzen/expression.rb', line 68

def self.split(key)
  key.to_s.split('.').map do |segment|
    INTEGER_RE.match(segment) ? segment.to_i : segment
  end
end

Instance Method Details

#resultObject



64
65
66
# File 'lib/chutzen/expression.rb', line 64

def result
  Transformer.apply(@expression, dictionary: @dictionary)
end