2016-04-10 1 views
0

В рамках обучения Ruby пытается реализовать базовый интерпретатор, который считывает ввод и выполняет основные арифметические вычисления. До сих пор основные арифметические операции работают, но возникают проблемы с приоритетом оператора. Что еще не обрабатывается. Это код. На начальном уровне. Любые ошибки в этом коде из-за моего отсутствия знаний. Как этот код может быть изменен для обработки приоритета оператора. Пример выводаРеализация приоритета оператора в интерпретаторе моего калькулятора

2+2+2 = 6 #correct 
10+10/2 = 10 # incorrect as in irb answer must be 15 

Github Repo of this interpreter

=begin 
Basic calculator Interpreter 
can add, substract, multiply , divide with any number of operands at a time 
Drawback : Lacks operator precedence 
=end 
class Interpreter 
    attr_accessor :input 
    def initialize 
     @input = gets.chomp    
    end 
    def intepret   
     first_operand = []  
     f    = []  
     operator  = '+'   
     array   = Array.new  
     lc    = 0 

     @input.split.join.split("").each_with_index.map do |i, index| 

      if i.is_number? 
       first_operand.push(i) 
       if index == @input.length-1      
        array.push(first_operand.join("").to_i)     
       end 
      elsif i.is_plus?     
       f = first_operand 
       first_operand = nil 
       first_operand = []    
       array.push(f.join("").to_i) 
       array.push("+") 
      elsif i.is_minus?   
       f = first_operand 
       first_operand = nil 
       first_operand = []    
       operator = '-'    
       array.push(f.join("").to_i) 
       array.push("-") 
      elsif i.is_multi?    
       f = first_operand 
       first_operand = nil 
       first_operand = []    
       operator = '*'    
       array.push(f.join("").to_i) 
       array.push("*") 
      elsif i.is_divide?    
       f = first_operand 
       first_operand = nil 
       first_operand = []    
       operator = '/'    
       array.push(f.join("").to_i) 
       array.push("/") 
      else 
       puts "Illegal input exiting.." 
       exit    
      end    

      lc = lc+1 

     end  
     #apply the appropriate operation on the inputs based on the operand   
     #puts "=======TOKENS======"  
     #puts array.inspect 
     result = 0 
     array.each_with_index.map do |x, key| 
      result = x if key == 0   
      if x == '+' 
       if key == 0 
        result = add(result, array[key+1]) 
       else 
        result = add(result, array [key+1]) 
       end 
      elsif x == '-' 
       if key == 0 
        result = minus(result, array[key+1]) 
       else 
        result = minus(result, array [key+1]) 
       end 
      elsif x == '*' 
       if key == 0 
        result = multi(result, array[key+1]) 
       else 
        result = multi(result, array [key+1]) 
       end 
      elsif x == '/' 
       begin 
        if key == 0 
         result = divide(result, array[key+1]) 
        else 
         result = divide(result, array [key+1]) 
        end 
       rescue 
        puts "Zero Divsion error" 
        exit 
       end 
      end 
     end 
     puts "Result is: "+result.to_s 
    end 
    def print_token(type, value) 
     puts type + ' '+ value 
    end 
    def add(f,s) 
     return f.to_i + s.to_i 
    end 
    def minus(f,s) 
     return f.to_i - s.to_i 
    end 
    def multi(f,s) 
     return f.to_i * s.to_i 
    end 
    def divide(f,s) 
     return f.to_i/s.to_i 
    end 
end 
# Override the string class, to directly use methods like obj.is_number? rather than is_number?(obj) 
class String 
    def is_number? 
    true if Float(self) rescue false 
    end 
    def is_plus? 
    true if self == '+' rescue false 
    end 
    def is_minus? 
    true if self == '-' rescue false 
    end 
    def is_multi? 
    true if self == '*' rescue false 
    end 
    def is_divide? 
    true if self == '/' rescue false 
    end 
end 
#continue accepting inputs until exit CTRL + D 
while true 
    print 'pck>:' 
    i_obj = Interpreter.new 
    i_obj.intepret 
end 
+0

Все ваши методы запросов String, за исключением 'is_number?', Могут быть упрощены до 'self == 'operator'', так как они не выдадут ошибку, и вы можете безопасно удалить' rescue'. –

+0

@SilverPhoenix Спасибо за помощь, но это не отвечает на мой вопрос. –

ответ

Смежные вопросы