rubysolo/dentaku

PrintVisitor incorrectly converts formula

spiree opened this issue · 2 comments

When converting a formule using the PrintVisitor, I get an incorrect result for formula "10 - (0 - 10)".

calculator = Dentaku::Calculator.new ast = calculator.ast("10 - (0 - 10)") result = PrintVisitor.new(ast).to_s

I would expect result to be "10 - (0 - 10)" but it is "10 - 0 - 10". Which is incorrect and evaluates to "0" instead of "20".

I think this is an off by one error in the PrintVisitor’s precedence checking. If the operand is on the right side precedence equality should also qualify it for parentheses.

I believe you’d be able to fix this with the following monkey-patch, although I’m sure making it into a pull-request would be appreciated.

Dentaku::PrintVisitor.class_eval do
  def visit_operation(node)
    if node.left
      visit_operand(node.left, node.class.precedence, suffix: " ", dir: :left)
    end
    @output << node.display_operator
    if node.right
      visit_operand(node.right, node.class.precedence, prefix: " ", dir: :right)
    end
  end

  def visit_operand(node, precedence, prefix: "", suffix: "", dir: :none)
    @output << prefix
    @output << "(" if node.is_a?(Dentaku::AST::Operation) && node.class.precedence < precedence || (node.class.precedence == precedence && dir == :right)
    node.accept(self)
    @output << ")" if node.is_a?(Dentaku::AST::Operation) && node.class.precedence < precedence || (node.class.precedence == precedence && dir == :right)
    @output << suffix
  end
end

Thanks for reporting, and @Boudewijn26 for the fix!