主要观点、关键信息和重要细节总结:
- 介绍:作者自青少年时期就对解析感兴趣,设计并实现过编程语言的解析器,对解析器生成技术有深入研究和实践,此文旨在表达关于解析的诸多观点。
上下文无关文法不如期望的那样声明式:
- 上下文无关文法是指定语言语法的标准,但并非总能实现声明式编程的理想,如在 C 语言中编写文法时需考虑实现细节,易出现错误。
- 简单的语法概念写成 CFG 可能变复杂,如 C 语言中
for
语句、if-else
歧义等情况,要写出无歧义的 CFG 需引入额外复杂性。 - CFG 必须适应解析器技术,不同的解析器生成策略对文法规则的写法有不同要求,如 LL 解析工具支持一些正则表达式类似的操作,LR 则需保持多种可能性在最后时刻,且左右递归等写法在不同解析器中含义不同。
可能想手写生产解析器:
- 自动化解析器生成器虽有优势,但对于严肃的工具,如广泛使用的 GCC,最终会切换到手写解析器,因为手写解析器更灵活,能更好地处理语言规范的变化,且能写出更好的错误消息。
- 自动化解析器在生成错误消息方面表现不佳,难以准确指出错误原因,而手写解析器可根据上下文写出更易理解的错误消息。
- 自动化解析器在语言设计阶段很有用,能快速得到解析器,但在生产编译器中通常不使用。
在语言规范中指定解析器生成技术:
- 语言规范中使用上下文无关文法时,应明确说明该文法与哪种解析技术兼容,最好以机器可读的形式提供文法,便于自动转换和测试。
- 测试语言的参考文法可确保文法无错误,也可通过解析器生成测试用例,检查手写解析器的正确性。
在语言设计中使用 LR 解析器生成器:
- LR 解析器生成器在语言设计阶段非常有用,能指出设计错误,如 C 语言中逗号运算符和函数参数的歧义,可通过限制为 LR 文法来避免。
- LR 解析器生成器还能生成测试用例,检查手写解析器的正确性,但
%prec
等特性会影响测试用例的生成。
停止使用 LALR:
- LR 解析技术中的 LALR 会引入“神秘冲突”,其实是生成算法的 bug,David Pager 的 PGM 技术可避免该问题,构造出几乎与 LALR 一样小的解析表且无错误。
- PGM 有弱和强两种算法,弱算法简单但可能保守,强算法更精确但复杂。
文法应兼具合成性和分析性:
- 上下文无关文法的术语暗示其是合成性的,但实际应用中多为分析性的,可通过文法生成测试用例和进行语法到抽象语法树的转换。
- 避免使用歧义文法和
%prec
等特性,以保证文法的合成性和可靠性。
应做的事情:
- 考虑将实际写的文法与用于自动化的无歧义文法分离,用宏库或文法编译器生成繁琐部分,或处理输入文法生成完全不同的无歧义 CFG。
- 扩展上下文无关文法的概念,为每个操作符添加优先级等注释,使 LR 解析器能处理歧义,还可实现动态重配置操作符等功能。
处理非 LR 语言的方法:
- 对于一些不能用正统 LR 策略解析的语言,如 C 语言的类型名歧义、C++的尖括号与移位运算符、有显著空白的语言等,可通过“LR 带属性”的方法或在 lexer 和 parser 之间插入“过滤器”层来处理。
- 结论:上下文无关文法和自动化解析器生成虽有优势,但在实际生产中仍存在不足,很难说应如何改进它们的设计。
总之,作者对上下文无关文法和解析器生成技术进行了深入探讨,指出了它们的优点和不足,并提出了一些改进的想法和方法。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。