On 12/2/07, Daniel Martin <martin / snowplow.org> wrote:
> "Adam Shelly" <adam.shelly / gmail.com> writes:
>
> > This line:
> >>        tok = Token.new(phrase,term.precedence)
> > should read
> >           term = Term.new(phrase, term.precedence)
>
> Even with that cleanup, it doesn't seem to work:
>
> esau:/tmp$ ruby asrq148.rb '2 3 - 5 +'
> +
> esau:/tmp$ ruby asrq148.rb '2 3 -'
> -

I think you only changed 'Token' to Term, and missed the 'tok'=>'term' sub.
That's the only way I get what you show.

Anyway, Here's an updated version wihch handles the associativity test cases.

#postfix to infix
# ruby quix #148
# Adam Shelly
# v2
#  Converts postfix to infix notation
#  uses ruby's operators & precedence rules

$Operators = {
 '&&'=>'0 ', '||'=>'0 ',
 '=='=>'1 ', '==='=>'1 ', '<=>'=>'1 ',
 '<='=>'2 ', '>='=>'2 ',   '<' =>'2 ', '>'=>'2 ',
 '^' =>'3 ',  '|' =>'3 ',
 '&' =>'4 ',
 '<<'=>'5L', '>>'=>'5L',
 '+' =>'6 ',  '-' =>'6L',
 '*' =>'7 ',  '/' =>'7L', '%'=> '7L',
 '**'=>'8R',
 :term=>'10 '
 }

class Term
 attr_reader :precedence, :dir
 def initialize str, groupPrec=nil
  @s = str
  @precedence = $Operators[str]||groupPrec||$Operators[:term]
  @dir = @precedence[-1].chr
  @precedence = @precedence.to_i
  end
 def isOp
  @precedence != $Operators[:term].to_i
 end
 def parenthesize
  @s="(#{@s})"
 end
 def to_s
  @s
 end
end

class Infix
 def initialize rpn
  stack=[]
  rpn.split.each do |t|
    term = Term.new(t)
    if term.isOp
      rval = stack.pop
      lval = stack.pop
      raise "Empty Stack" unless lval && rval
      lval.parenthesize if lval.precedence < term.precedence or
        term.dir=='R'&& lval.precedence == term.precedence
      rval.parenthesize if rval.precedence < term.precedence or
        term.dir=='L'&& rval.precedence == term.precedence
      phrase = "#{lval} #{term} #{rval}"
      term = Term.new(phrase,term.precedence)
      #p term
    end
    stack.push term
  end
  @expr = stack.pop
   raise "Extra terms" unless stack.size==0
 end
 def to_s
  @expr.to_s
 end
end

def test
  puts Infix.new('2 3 +').to_s                 == '2 + 3'
  puts Infix.new('56 34 213.7 + * 678 -').to_s == '56 * (34 + 213.7) - 678'
  puts Infix.new('1 56 35 + 16 9 - / +').to_s  == '1 + (56 + 35) / (16 - 9)'
  puts Infix.new('1 2 + 3 4 + +').to_s         == '1 + 2 + 3 + 4'
  puts Infix.new('1 2 - 3 4 - -') .to_s        == '1 - 2 - (3 - 4)'
  puts Infix.new('2 2 ** 2 **').to_s           == '(2 ** 2) ** 2'
  puts Infix.new('2 2 2 ** **').to_s           == '2 ** 2 ** 2'
  puts Infix.new('1 2 3 4 5 + + + +').to_s     ==  '1 + 2 + 3 + 4 + 5'
  puts Infix.new('1 2 3 4 5 / / - -').to_s     ==  '1 - (2 - 3 / (4 / 5))'
  puts Infix.new('3 5 * 5 8 * /').to_s         ==  '3 * 5 / (5 * 8)'
  puts Infix.new('3 5 + 5 8 + -').to_s         ==  '3 + 5 - (5 + 8)'
  puts Infix.new('a b == c 1 + 2 < &&').to_s   == 'a == b && c + 1 < 2'
  puts Infix.new('1 2 << 4 <<').to_s           == '1 << 2 << 4'
  puts Infix.new('1 2 4 << <<').to_s           == '1 << (2 << 4)'
end

if __FILE__ == $0
  if ARGV.empty?
     test
   else
    puts Infix.new(ARGV.join(' ')).to_s
  end
end