超出最大递归

时间:2013-11-18 19:02:56

标签: python recursion

我有一个错误,声明:

    return mkAddNode(parse(tokens, i + 1), parse(tokens, i + 1))
  File "derpAgain.py", line 14, in parse
    return mkAddNode(parse(tokens, i + 1), parse(tokens, i + 1))
  File "derpAgain.py", line 13, in parse
    if tokens[0] == "+":
RuntimeError: maximum recursion depth exceeded in comparison

我不知道为什么会出现这个错误。我仔细检查,看到它没有错。

from derp_node import *

def parse(tokens, i = 0):
    """parse: tuple(String) * int -> (Node, int)
    From an infix stream of tokens, and the current index into the
    token stream, construct and return the tree, as a collection of Nodes, 
    that represent the expression.

    NOTE:  YOU ARE NOT ALLOWED TO MUTATE 'tokens' (e.g. pop())!!!  YOU
        MUST USE 'i' TO GET THE CURRENT TOKEN OUT OF 'tokens'
    """
    #t = tokens.pop(0)
    if tokens[0] == "+":
        return mkAddNode(parse(tokens, i + 1), parse(tokens, i + 1))
    elif tokens[0] == "-":
        return mkSubstractNode(parse(tokens, i + 1), parse(tokens, i + 1))
    elif tokens[0] == "*":
        return mkMultiplyNode(parse(tokens, i + 1), parse(tokens, i + 1))
    elif tokens[0] == "//":
        return mkDivideNode(parse(tokens, i + 1), parse(tokens, i + 1))
    elif (tokens.pop(0).isdigit()):
        return mkLiteralNode(int(tokens.pop(0)))
    else:
        return mkVariableNode(tokens.pop(0))

def infix(node):
    """infix: Node -> String | TypeError
    Perform an inorder traversal of the node and return a string that
    represents the infix expression."""
    if isinstance(node, MultiplyNode):
        return "(" + infix(node.left) + " * " + infix(node.right) + ")"
    elif isinstance(node, DivideNode):
        return "(" + infix(node.left) + " // " + infix(node.right) + ")"
    elif isinstance(node, AddNode):
        return "(" + infix(node.left) + " + " + infix(node.right) + ")"
    elif isinstance(node, SubtractNode):
        return "(" + infix(node.left) + " - " + infix(node.right) + ")"
    elif isinstance(node, LiteralNode):
        return str(node.val)
    else:
        return node.name

def evaluate(node, symTbl):
    """evaluate: Node * dict(key=String, value=int) -> int | TypeError
    Given the expression at the node, return the integer result of evaluating
    the node.
    Precondition: all variable names must exist in symTbl"""
    if isinstance(node, MultiplyNode):
        return evaluate(node.left, symTbl) * evaluate(node.right, symTbl)
    elif isinstance(node, DivideNode):
        return evaluate(node.left, symTbl) // evaluate(node.right, symTbl)
    elif isinstance(node, AddNode):
        return evaluate(node.left, symTbl) + evaluate(node.right, symTbl)
    elif isinstance(node, SubtractNode):
        return evaluate(node.left, symTbl) - evaluate(node.right, symTbl)
    elif isinstance(node, VariableNode):
        for var in symTbl:
            if var == node.name:
                return symTbl[var]
    else:
        return node.val

def main():
    """main: None -> None
    The main program prompts for the symbol table file, and a prefix
    expression.  It produces the infix expression, and the integer result of
    evaluating the expression"""

    print("Hello Herp, welcome to Derp v1.0 :)")

    inFile = input("Herp, enter symbol table file: ")

    # STUDENT: CONSTRUCT AND DISPLAY THE SYMBOL TABLE HERE
    fileOpen = open(inFile)
    symTbl = {}

    for line in fileOpen:
        lineStrip = line.split()
        symTbl[lineStrip[0]] = int(lineStrip[1])

    for var in sorted(symTbl):
        print("Name: " + var + " => " + str(symTbl[var]))

    print("Herp, enter prefix expressions, e.g.: + 10 20 (RETURN to quit)...")

    # input loop prompts for prefix expressions and produces infix version
    # along with its evaluation
    while True:
        prefixExp = input("derp> ")
        if prefixExp == "":
            break

        prefix = prefixExp.split()
        root = parse(prefix)
        print("Derping the infix expression: " + infix(root))

        print("Derping the evaluation: " + str(evaluate(root, symTbl)))

    print("Goodbye Herp :(")

if __name__ == "__main__":
    main()

当我打开程序时。它将显示此输出:

Hello Herp, welcome to Derp v1.0 :)
Herp, enter symbol table file: vars.txt
Name: x => 10
Name: y => 20
Name: z => 30
Herp, enter prefix expressions, e.g.: + 10 20 (RETURN to quit)...
derp> - 10 20
Derping the infix expression: 10
Derping the evaluation: None
derp> + 10 * x y
Then the error has started...

Vars.txt:

x 10
y 20
z 30

旁注:如果你们好奇derp_node.py中的内容,我不会在这里发布,但是,我把它发布在pastebin上,所以这个页面看起来并不大。 http://pastebin.com/MXuc8Shc任何帮助都会很棒!谢谢。希望我提供了足够的信息,所以你们有一个想法,我在做什么。

4 个答案:

答案 0 :(得分:1)

您继续将相同的引用传递给令牌。

如果你不增加你所指的那个字符,那么

tokens [0]总是'+',这意味着对parse()的递归调用将永远继续。

另外,为什么你有4个if / elif分支都检查/调用完全相同的东西?

此外,.pop()方法实际上更改了基础列表,因此if tokens.pop()。isdigit()实际上是删除标记中的最后一个元素。这可能是你想要在第一个中做的。

答案 1 :(得分:0)

你仍然有一些关于弹出的调用,并且在条件中调用pop特别糟糕,因为当你甚至不确定条件是否适用时你会改变列表:

elif (tokens.pop(0).isdigit()):
    return mkLiteralNode(int(tokens.pop(0)))

应该是:

elif (tokens[0].isdigit()):
    return mkLiteralNode(int(tokens.pop(0)))

答案 2 :(得分:0)

让我们来看看您致电parse(tokens, i)tokens[0] == '+'时会发生什么。 parse的正文将尝试执行:

return mkAddNode(parse(tokens, i + 1), parse(tokens, i + 1))

执行此声明需要评估parse(tokens, i+1),并且在递归调用中tokens[0]仍然是'+',您将再次呼叫parse,另一个呼叫, 这将永远不会结束。我认为您要做的是测试tokens[i] == '+',而不是tokens[0],或者可能将parse(tokens, i+1)更改为parse(tokens[1:], i+1)(为什么当您'{0}时为i不使用它?)

答案 3 :(得分:0)

如果你得到一个标记'+',它会启动一个无限循环:

if tokens[0] == "+":
    return mkAddNode(parse(tokens, i + 1), parse(tokens, i + 1))
elif tokens[0] == "+":
    return mkAddNode(parse(tokens, i + 1), parse(tokens, i + 1))
elif tokens[0] == "+":
    return mkAddNode(parse(tokens, i + 1), parse(tokens, i + 1))
elif tokens[0] == "+":
    return mkAddNode(parse(tokens, i + 1), parse(tokens, i + 1))
elif (tokens.pop(0).isdigit()):
    return mkLiteralNode(int(tokens.pop(0)))
else:
    return mkVariableNode(tokens.pop(0))

你只检查'+'标记,只有当标记不是'+'时才弹出。我希望有帮助

我会用:

aux = tokens.pop(0)
if aux == "+":
    return mkAddNode(parse(tokens, i + 1), parse(tokens, i + 1))
elif aux == "-":
    return mkAddNode(parse(tokens, i + 1), parse(tokens, i + 1))
elif aux == "*":
    return mkAddNode(parse(tokens, i + 1), parse(tokens, i + 1))
elif aux == "/":
    return mkAddNode(parse(tokens, i + 1), parse(tokens, i + 1))
elif (aux.isdigit()):
    return mkLiteralNode(int(aux))
else:
    return mkVariableNode(aux)