我已经实现了分流码算法,如下所示:
#!/usr/bin/env python
import sys
import string
import operator
import signal
class InvalidStackError(Exception): pass
class BadParenError(Exception): pass
def hook_ctrl_c(signal, frame):
print ""
sys.exit(0)
signal.signal(signal.SIGINT, hook_ctrl_c)
ops = {
"*" : [operator.mul, 3, "left"],
"x" : [operator.mul, 3, "left"],
"/" : [operator.div, 3, "left"],
"+" : [operator.add, 2, "left"],
"-" : [operator.sub, 2, "left"],
"^" : [operator.pow, 4, "right"],
"(" : [None, 5, "neither"],
")" : [None, 5, "neither"]
}
def parse(raw):
return raw.split()
def compile_to_rpn(tokens):
operator_stack = []
rpn_code = []
for token in tokens:
try:
current_number = int(token)
rpn_code.append(current_number)
except ValueError:
if token == "(":
operator_stack.append(token)
elif token == ")":
try:
while True:
current_operator = operator_stack.pop()
if current_operator == "(":
break
rpn_code.append(current_operator)
except IndexError:
print "(error) mismatched parens"
elif token in ops:
if len(operator_stack) > 0 and ((ops[token][2] == "left" and ops[token][1] <= ops[operator_stack[-1]][1]) or (ops[token][2] == "right" and ops[token][1] < ops[operator_stack[-1]][1])):
operator = operator_stack.pop()
if operator != "(":
rpn_code.append(operator_stack.pop())
else:
operator_stack.append("(")
operator_stack.append(token)
try:
while len(operator_stack) != 0:
current_operator = operator_stack.pop()
if current_operator in ["(", ")"]:
raise BadParenError
rpn_code.append(current_operator)
except BadParenError:
print "(error) mismatched parens"
return rpn_code
current_token = None
while True:
try:
tokens = parse(raw_input("-> "))
stack = []
if tokens == ["quit"]:
sys.exit(0)
tokens = compile_to_rpn(tokens)
for token in tokens:
current_token = token
if token not in ops:
stack.append(int(token))
else:
rhs, lhs = stack.pop(), stack.pop()
stack.append(ops[token][0](lhs, rhs))
if len(stack) > 1:
raise InvalidStackError
print "Result: %s\n" % stack[0]
except ValueError:
print "(error) token {%s} is a not a number or operator\n" % current_token
except IndexError:
print "(error) expression has insufficient number of values\n"
except InvalidStackError:
print "(error) too many values\n"
它适用于简单的表达式,例如&#34; 3 + 4&#34;但是如果我输入任何复杂的内容,就会发生这种情况:
$ ./rpn.py
- &GT; 4 - 5 * 6 + 3 ^ 2
(错误)值太多
提前致谢,我感谢任何帮助!
答案 0 :(得分:0)
您的代码至少存在一个问题:
if len(operator_stack) > 0 and ((ops[token][2] == "left" and ops[token][1] <= ops[operator_stack[-1]][1]) or (ops[token][2] == "right" and ops[token][1] < ops[operator_stack[-1]][1])):
operator = operator_stack.pop()
if operator != "(":
rpn_code.append(operator_stack.pop())
您从operator_stack
弹出,然后在追加rpn_code
时再次执行此操作。这会触发您的一个例外。用
rpn_code.append(operator)
像5 * 6 + 4
这样的表达式可以正常运行。不幸的是,这不是代码中唯一的错误,因为您提供的示例无法正确评估。也许这是因为您的代码存在另一个问题:在执行算法的这一部分时(维基百科):
如果令牌是运营商,o1,那么:
while there is an operator token, o2, at the top of the operator stack, and either o1 is left-associative and its precedence is less than or equal to that of o2, or o1 is right associative, and has precedence less than that of o2, then pop o2 off the operator stack, onto the output queue; push o1 onto the operator stack.
你只执行一次,而不是只要满足while条件。