Algorithm 如何创建允许语法错误的AST解析器?
首先,关于解析和构建AST应该阅读什么 如何为将构建AST并允许语法错误的语言(如SQL)创建解析器 例如,对于“3+4*5”: 对于有语法错误的“3+4*+”,解析器会猜测用户的意思是:Algorithm 如何创建允许语法错误的AST解析器?,algorithm,compiler-construction,language-agnostic,abstract-syntax-tree,Algorithm,Compiler Construction,Language Agnostic,Abstract Syntax Tree,首先,关于解析和构建AST应该阅读什么 如何为将构建AST并允许语法错误的语言(如SQL)创建解析器 例如,对于“3+4*5”: 对于有语法错误的“3+4*+”,解析器会猜测用户的意思是: + / \ 3 * / \ 4 + / \ ? ? 从哪里开始 SQL: 对于如何构建解析器(即构建AST)的问题,标准答案是在编译时阅读标准文本。阿霍和厄尔曼的“龙”编译书非常经典。如果你没有耐心得到最好的参考资料,你会有更多的麻烦,因为它们提供了理论和研究细
+
/ \
3 *
/ \
4 +
/ \
? ?
从哪里开始
SQL:
对于如何构建解析器(即构建AST)的问题,标准答案是在编译时阅读标准文本。阿霍和厄尔曼的“龙”编译书非常经典。如果你没有耐心得到最好的参考资料,你会有更多的麻烦,因为它们提供了理论和研究细节。但是对于那些急于构建递归下降解析器的人来说 可以使用内置的错误恢复构建解析器。关于这类事情的论文很多,这是20世纪80年代的一个热门话题。查看谷歌学者,搜索“语法错误修复”。其基本思想是,解析器在遇到解析错误时,会跳转到一些著名的信标(“对于类似C的语言,语句分隔符非常流行,这就是为什么在注释中询问您的语言是否有语句终止符的原因”),或提出各种输入流删除或插入,以克服语法错误。这类计划的种类之多令人惊讶。关键思想通常是尽可能多地考虑错误点周围的信息。我见过的最有趣的想法之一是有两个解析器,一个在另一个之前运行N个令牌,寻找语法错误地雷,第二个解析器是在遇到语法错误之前基于可用的N个令牌进行错误修复。这允许第二个解析器在出现语法错误之前选择不同的操作。如果您没有这个,大多数解析器会丢弃左上下文,从而失去修复的能力。(我从未实施过这样的计划。) 要插入的内容的选择通常可以从用于首先构建解析器的信息(通常是First和Follow集)中派生出来。对于L(AL)R解析器来说,这是相对容易的,因为解析表包含必要的信息,并且在解析器遇到错误时可用。如果您想了解如何做到这一点,您需要了解解析器是如何构造的理论(面向对象的,这又是一本编译器手册)。(我已多次成功实施该计划) 不管您做什么,语法错误修复都没有多大帮助,因为几乎不可能猜测解析文档的编写者的实际意图。这表明,花哨的计划并没有真正的帮助。我坚持简单的原则;人们很高兴得到一个错误报告和一些半优雅的继续解析 为真正的语言运行自己的解析器的一个真正问题是,真正的语言是令人讨厌的、混乱的东西;构建真正的实现的人会因为现有的代码基础而出错并僵化,或者因为语言很酷而坚持弯曲/改进语言(标准是用于WIMP的,好东西是用于营销的)。预计会花费大量时间,对照真实代码的基本事实,重新校准您认为的语法。作为一般规则,如果您想要一个工作的解析器,最好得到一个有跟踪记录的解析器,而不是自己使用它
大多数一心想构建解析器的人没有得到的一个教训是,如果他们想对解析结果或树做任何有用的事情,他们将需要比解析器更基本的机器。查看我的个人简历中的“解析后的生活”。解析器可以做两件事:
然后,为了继续解析,您必须重新同步到错误之外的某个点。正如Ira Baxter在他的回答中提到的,你可以寻找一个标记,比如“;”,这将语句分开。要查找的正确标记取决于您正在解析的语言。另一种可能性是猜测用户的意思(例如,在检测到错误时推断出额外的令牌或不同的令牌),然后继续。如果在接下来的几个标记中遇到另一个语法错误,您可以回溯,做出不同的猜测,然后重试。ASTs始终允许语义错误,这是一个语法错误。修复了有问题的错误类型。谢谢)你的语言有一种界定语句的方法吗?它们都“允许”语法错误,因为这在实践中是不可避免的。您需要的是语法错误恢复/修复。@IraBaxter我已更正。(对不起,在看到您的回复之前,我删除了我的原始评论。)
+
/ \
3 *
/ \
4 +
/ \
? ?
SELECT_________________
/ \ \
. FROM JOIN
/ \ | / \
a city_name people address ON
|
=______________
/ \
.____ .
/ \ / \
p address_id a id