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