在我的计算器解释器中实现运算符优先级 [英] Implementing operator precedence in my calculator interpreter

查看:93
本文介绍了在我的计算器解释器中实现运算符优先级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为学习的一部分,Ruby试图实现一个基本的解释器,该解释器读取输入并进行基本的算术计算.到目前为止,基本的算术运算都可以运行,但是运算符优先级存在问题.尚未处理.这是代码.我是初学者.这段代码中的任何错误均归因于我缺乏知识.如何修改此代码以处理运算符优先级. 样本输出

As part of learning Ruby am trying to implement a basic interpreter which reads input and do basic arithmetic calculations. So far basic arithmetic operations are working but having problem in operator precedence. Which is not handled yet. This is the code. Am at a beginner level. Any mistakes in this code are due to my lack of knowledge. How this code can be modified to handle operator precedence. Sample output

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

此解释器的Github存储库

=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

推荐答案

首先,使用分流来处理输入码算法.这应该以反向波兰符号(RPN)给出令牌列表.然后,您可以评估RPN表达式.

First, process the input using the Shunting-yard algorithm. This should give a list of tokens in Reverse Polish notation (RPN). Then you can evaluate the RPN expression.

这篇关于在我的计算器解释器中实现运算符优先级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆