You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 修复

  1. 修正parseExpression的方法调用:
def parseExpression(self) -> ast.Exp:
    return self.parsePrimaryExpression()  # 添加括号,实际调用方法
  1. 修正notEOF的判断逻辑:
def notEOF(self) -> bool:   
    return self.tokens[0].type != lexer.TokenType.EOF  # 检查token的type属性
  1. 修正异常抛出逻辑:
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 修复

  1. 修正token函数返回值:
def token(value, type) -> Token:
    return Token(value, type)  # 返回Token类实例而非列表
  1. 修正数字处理的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 19:54:54