在我的计算器解释器中实现运算符优先级
Implementing operator precedence in my calculator interpreter
作为学习的一部分 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
首先,使用Shunting-yard algorithm. This should give a list of tokens in Reverse Polish notation (RPN) 处理输入。然后就可以计算RPN表达式了。
作为学习的一部分 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
首先,使用Shunting-yard algorithm. This should give a list of tokens in Reverse Polish notation (RPN) 处理输入。然后就可以计算RPN表达式了。