添加AST类后C++ Lexer与Parser无输出且卡死问题排查
常见问题原因及解决方法
无限递归解析
大概率是Parser在生成AST时,语法规则处理不当导致无限循环。比如表达式解析的左递归没有消除,或者某个规则的递归调用没有终止条件(比如一直尝试匹配不存在的Token)。
解决:检查Parser的语法规则,把左递归改成迭代实现,或者调整规则结构;给每个递归解析函数加终止判断(比如遇到EOF或不匹配的Token立即返回)。Token流未正确终止
Lexer没在输入结束时输出EOFToken,导致Parser一直等待下一个Token,进入死循环。添加AST后可能不小心修改了Lexer的收尾逻辑。
解决:强制Lexer在输入处理完成后输出EOFToken;在Parser中添加判断,遇到EOF就终止解析流程,不要继续等待。AST节点的循环引用
虽然你排除了shared_ptr的问题,但AST节点之间如果存在双向引用(比如父节点持子节点的shared_ptr,子节点又持父节点的shared_ptr),会导致析构时死锁,或者构造时触发循环依赖的逻辑。
解决:把双向引用中的一侧改成weak_ptr;检查AST节点的构造函数,不要在构造时递归创建父/子节点导致循环。Parser错误处理缺失
解析遇到错误时没有终止逻辑,而是无限重试。比如某个Token不匹配,Parser没有抛出错误或退出,而是一直尝试无效的匹配组合。
解决:给Parser加错误处理,遇到无法匹配的Token立即终止并打印错误;在关键解析步骤加调试日志,看卡死时卡在哪个规则上。输入读取阻塞
如果程序从标准输入读字符串,添加AST后可能修改了输入读取逻辑,导致程序一直等输入(比如误把非阻塞读改成阻塞,或者输入缓冲区没刷新)。
解决:测试时直接硬编码输入字符串,排除输入阻塞;检查输入读取代码,确保读完后正确终止。
调试技巧
- 在Lexer的每个Token生成处加日志,确认Token流是否完整,最后有没有输出
EOF; - 在Parser的每个解析函数入口加日志,定位卡死时正在执行的代码;
- 用调试器(比如
gdb)打断点,查看调用栈,直接找到无限循环的函数。
内容的提问来源于stack exchange,提问作者Pratik S

