Python解析器递归无限参考

时间:2016-02-28 21:38:32

标签: python parsing recursion

我是Parsers的新手,我的Parser有问题,特别是当我称自己来分析函数的主体时。

当它找到另一个功能时,就变得疯狂和凌乱。

基本上,在分析此代码时

fn test (a, b, c):
    fn test2 (c, b, a):
        print("Hello world")
    end
end

它开始将对象指向自身,而不是子函数:

>>> print(ast[0].value.body[9])
<ast.VariableAST object at 0x7f6285540710>  
>>> print(ast[0].value.body[9].value.body[9])
<ast.VariableAST object at 0x7f6285540710>

这是主要的解析器代码:

# Parser Loop
def Parser(tokenList):
    global tokens
    global size
    tokens = tokenList
    size = len(tokens)
    ast = []
    while i < size:
        ast.append(MainParser())
    return ast


# The Main Parser
def MainParser():
    global i
    if tokens[i] == 'fn':
        i += 1
        node = FunctionParser()
    else:
        node = tokens[i]
        i += 1
    return node


# Parse a function
def FunctionParser():
    global i
    checkEnd("function")
    if tokens[i][0].isalpha():
        node = VariableAST()
        node.name = tokens[i]
        i += 1
        node.value = FunctionBodyParser()
    elif tokens[i] == '(':
        node = FunctionBodyParser()
    else:
        syntaxError("Expecting '(' or function name")
    return node


# Parse a function body
def FunctionBodyParser():
    global i
    i += 1
    node = FunctionAST()
    while True:
        checkEnd("function")
        if tokens[i][0].isalpha():
            node.args.append(tokens[i])
            i += 1
        elif tokens[i] == ',':
            i += 1
        elif tokens[i] == ')':
            break
        else:
            syntaxError("Expecting ')' or ',' in function declaration")
    i += 1
    checkEnd("function")
    if tokens[i] != ':' and tokens[i] != '{':
        syntaxError("Expecting '{' or ':'")
    begin = tokens[i]
    while True:
        checkEnd("function")
        if begin == ':' and tokens[i] == 'end':
            break
        elif begin == '{' and tokens[i] == '}':
            break
        else:
            node.body.append(MainParser())
    i += 1
    return node

编辑:我忘了提到这是C版的原型。我避免了与面向对象相关的东西和python中的一些好的实践,以便以后更容易将代码移植到C.

2 个答案:

答案 0 :(得分:1)

在Python https://wiki.python.org/moin/LanguageParsing中实现了许多解析器,例如PyPEG,允许您描述您正在解析的语言,而不是自己解析它,这样更易​​读,更少错误易发。

同样使用global通常是问题的根源,因为您无法控制变量的范围(只有一个变量),从而降低了函数的可重用性。

使用类可能更好,这几乎是一样的,但是你可以同时运行同一个类的多个实例,而不需要变量colisions:

class Parser:
    def __init__(self, tokenList):
        self.tokens = tokenList
        self.size = len(tokenList)
        self.ast = []
        self.position = 0

    def parse(tokenList):
        while self.position < self.size:
            self.ast.append(self.main())
        return self.ast

    def main(self):
        if self.tokens[self.position] == 'fn':
            self.position += 1
            node = self.function()
        else:
            node = self.tokens[self.position]
            self.position += 1
        return node

    # And so on...

从这一点开始,您可以在main中删除self.position + = 1:

    def main(self):
        self.position += 1
        if self.tokens[self.position] == 'fn':
            node = self.function()
        else:
            node = self.tokens[self.position]
        return node

然后删除无用的&#34;节点&#34;变量:

    def main(self):
        self.position += 1
        if self.tokens[self.position] == 'fn':
            return self.function()
        else:
            return self.tokens[self.position]

但真正做到这一点的方法是使用解析器,看看pyPEG,它是一个很好的,但其他人也很好。

哦,最后一点,避免无用的评论,如:

# Parse a function
def FunctionParser():

我们知道&#34; FunctionParser&#34; &#34;解析函数&#34;,谢谢, 信息。最重要的是明智地选择你的函数名称(哦,PEP8告诉我们不要用大写字母开始方法名称),如果你想添加关于函数的元信息,把它放在一个字符串中函数中的第一个语句,如:

def functionParser():
    "Delegates the body parsing to functionBodyParser"

答案 1 :(得分:0)

我找到了解决方案,

实际上,在Python中编程是一个愚蠢的错误,上面的解析器工作正常。

在AST中我正在创建类似结构的类,以便更容易将语言移植到C.但我做错了,例如:

class VariableAST(NodeAST):
    name = None
    value = None

我对Python不了解的是,类中的那些参数不是对象的属性,而是静态变量,当我为一个对象赋值时,只是让我的程序工作变得不可预测,因为我正在向静态变量求助,我也在为所有其他变量做出贡献,而且这是我无限的对象递归。