class Eqn::Expression

Node class for an expression.

Public Instance Methods

left_associative?() click to toggle source
# File lib/eqn/expression.rb, line 4
def left_associative?
  elements.any? && elements.last.left_associative?
end
value(vars = {}) click to toggle source
# File lib/eqn/expression.rb, line 8
def value(vars = {})
  base = elements.shift.value(vars)

  # Aggressively consume left associative operators to maintain associativity.
  base = consume_while_left_associative(base, vars)

  # Apply next right-associative operator (if any) or return.
  apply_next_operator(base, vars)
end

Private Instance Methods

apply_left_associative(base, vars, operator, num_expr) click to toggle source
# File lib/eqn/expression.rb, line 39
def apply_left_associative(base, vars, operator, num_expr)
  num_expr_operand = num_expr.elements.shift
  elements.push(num_expr.elements.shift) unless num_expr.term?
  base.send(operator, num_expr_operand.value(vars))
end
apply_next_operator(base, vars) click to toggle source
# File lib/eqn/expression.rb, line 27
def apply_next_operator(base, vars)
  return base if term?

  left_associative = elements.last.left_associative?
  op, num_expr = elements.shift.value(vars)
  if left_associative
    apply_left_associative(base, vars, op, num_expr)
  else
    base.send(op, num_expr.value(vars))
  end
end
consume_while_left_associative(base, vars) click to toggle source
# File lib/eqn/expression.rb, line 20
def consume_while_left_associative(base, vars)
  return base unless left_associative?

  base = apply_next_operator(base, vars)
  consume_while_left_associative(base, vars)
end