Here's my effort.  I really enjoyed this quiz but spent way more than  
the 1 hour on it (and it's still not correct)!

I tokenized the expression with a regex and then used the Shunting  
Yard Algorithm to do the parsing.  However, I fail some of tests -

1.  Unary minus  [-2+(2-2)]

2.  Order of evaluation in this expression is right-->left as opposed  
to left-->right and gives wrong result  [(1+3)/(2/2)*(10-8)]

3.  The optional efficient storage test.

I'll try to fix these if I have more time.

Thanks

Bob

require "Interpreter.rb"

class Compiler

   @PRECEDENCE = {
     '(' => -1,
     ')' => -1,
     '+' => 0,
     '-' => 0,
     '*' => 1,
     '/' => 1,
     '**' => 3,
     '%' => 3
   }

   @BYTECODE = {
     'CONST' => 0x01,
     'LCONST' => 0x02,
     '+' => 0x0a,
     '-' => 0x0b,
     '*' => 0x0c,
     '**' => 0x0d,
     '/' => 0x0e,
     '%' => 0x0f,
     'SWAP' => 0xa0
   }

   def Compiler.compile(expression)
     te = self.tokenize(expression)
     be = self.parse(te)
     self.to_bytecode(be)
   end

   def Compiler.tokenize(expression)
     tokenized_expression = []

     expression.gsub!(/\s+/, "")
     expression.scan(/(\d+|\(|\)|\+|-|\*\*|\*|\/|\%)/) { |e|  
tokenized_expression.push(e) }
     tokenized_expression
   end

   def Compiler.parse(tokenized_expression)
     output_queue, operator_stack = [], []
     operator = nil

     tokenized_expression.each { |token|

       # If token is a number, place on output queue
       if (token[0] =~ /^\d+$/)
         output_queue.push(token[0].to_i)
       elsif (token[0] == '(')
         operator_stack.push(token[0])
       elsif (token[0] == ')')
         # Pop operators off stack and onto output queue until left
         # bracket encountered
         while (operator != '(')
           if ((operator = operator_stack.pop) != '(')
               output_queue.push(operator)
           end
         end
       else
         # If there are any operators, check precedence of current token
         # against last operator on queue.  If the operator on queue is
         # more important, add it to the output before pushing the  
current
         # operator on
         if (operator_stack.any? && (@PRECEDENCE[token[0]] <=  
@PRECEDENCE[operator_stack.last]))
           output_queue.push(operator_stack.pop)
         end
         operator_stack.push(token[0])
       end
     }

     # Add the remaining operators to end of the output queue
     operator_stack.reverse_each { |operator|
       output_queue.push(operator)
     }

     output_queue
   end

   def Compiler.to_bytecode(bnf_expression)
     stack = []

     bnf_expression.delete("(")
     bnf_expression.each { |token|
       case token
         when Integer
            # If number is small enough, use smaller 2 byte storage

           if ((token >= -32768) && (token <= 32767))
             stack.push(@BYTECODE['CONST'])
             stack.push(token >> 8, token)
           else
             stack.push(@BYTECODE['LCONST'])
             stack.push(token >> 24, token >> 16, token >> 8, token)
           end
         else
           stack.push(@BYTECODE[token])
       end
     }
     stack
   end

end

require "TestByteCode.rb"