Python解析器执行函数时程序冻结且输出空错误的技术问询
Python解析器无限循环与空错误问题排查与修复
问题根源分析
1. 程序冻结(无限循环)的原因
- 解析器方法调用错误:
parserdef.py中的parseExpression方法返回的是self.parsePrimaryExpression(方法对象),而非调用该方法self.parsePrimaryExpression()。这导致每次循环都不会实际解析并消耗token,token列表始终保持初始状态,notEOF()一直返回True,程序陷入无限循环,CPU持续高负载导致冻结。 - Token类型判断与生成错误:
lexer.py的token函数返回的是列表[value, type],而非定义好的Token类实例,导致解析器中self.tokens[0]是列表而非Token对象。notEOF方法的判断逻辑错误:应该检查token的type属性是否为EOF,而非判断token对象的类型是否等于TokenType.EOF。两者叠加导致notEOF()永远为True,循环无法终止。
2. 空错误输出的原因
- 异常未正确抛出:
parsePrimaryExpression的else分支仅创建了RuntimeError对象,未使用raise关键字抛出异常。遇到无法识别的token(如+这类BINOP)时,没有触发异常,直到无限循环耗尽资源后,可能抛出未被正确捕获的空异常。 - 词法分析器参数错误:
tokenise方法处理数字时,调用isInt(_source),但isInt函数期望接收单个字符的字符串,实际传入的是整个_source列表,导致内部逻辑出错,但错误未被正确传递,最终表现为空错误信息。
修复方案
parserdef.py 修复
- 修正
parseExpression的方法调用:
def parseExpression(self) -> ast.Exp: return self.parsePrimaryExpression() # 添加括号,实际调用方法
- 修正
notEOF的判断逻辑:
def notEOF(self) -> bool: return self.tokens[0].type != lexer.TokenType.EOF # 检查token的type属性
- 修正异常抛出逻辑:
def parsePrimaryExpression(self) -> ast.Exp: token = self.at().type # 直接取token的type属性 if token == lexer.TokenType.IDENT: return ast.Identifier(self.eat().value) elif token == lexer.TokenType.NUM: return ast.NumericLiteral(float(self.eat().value)) else: raise RuntimeError(f"token: {self.at()}") # 添加raise抛出异常
lexer.py 修复
- 修正
token函数返回值:
def token(value, type) -> Token: return Token(value, type) # 返回Token类实例而非列表
- 修正数字处理的
isInt调用参数:
# Build number token if isInt(_source[0]): num = "" while len(_source) > 0 and isInt(_source[0]): # 传入单个字符而非整个列表 num += shift(_source) tokens.append(token(num, TokenType.NUM))
额外优化(可选但重要)
- main.py中补充
exit分支的退出逻辑:
if source == "exit": break # 退出循环终止程序
- astdef.py中统一使用
NodeType枚举定义节点类型:
class Program(Statement): def __init__(self, body: list): super().__init__(NodeType.PROGRAM) self.body = body class NumericLiteral(Exp): def __init__(self, value: int): super().__init__(NodeType.NUMERICLITERAL) self.value = value
修复后,输入"4 + 5"时,程序不再冻结,会抛出明确的异常RuntimeError: token: Token(value='+', type=TokenType.BINOP),后续可继续实现二元表达式的解析逻辑。
内容的提问来源于stack exchange,提问作者LWB
相关产品推荐
相关产品推荐

