Parsing 为REPL解释器和编译器构造模块化解析器的好方法是什么?

Parsing 为REPL解释器和编译器构造模块化解析器的好方法是什么?,parsing,compiler-construction,interpreter,Parsing,Compiler Construction,Interpreter,为REPL解释器和编译器构建通用解析器的好方法是什么?我所说的口译员是一种阅读-评估-打印循环。 为了支持两者,解析器应该支持整个程序解析和逐行解析。Dragon book介绍的LALR(1)算法适用于整个程序的解析,但应该对其进行一些设计,以便同时支持逐行解析。由于这两种类型的解析在编程语言中共享相同的语法,我相信会有一种模块化的方法来构建用于这两种目的的单个解析器,但我找不到它。在这件事上你能帮我吗 您需要的是一个解析器(或GLL),您需要以特定的方式滥用它 GLR解析器在这里之所以有用,是

为REPL解释器和编译器构建通用解析器的好方法是什么?我所说的口译员是一种阅读-评估-打印循环。 为了支持两者,解析器应该支持整个程序解析和逐行解析。Dragon book介绍的LALR(1)算法适用于整个程序的解析,但应该对其进行一些设计,以便同时支持逐行解析。由于这两种类型的解析在编程语言中共享相同的语法,我相信会有一种模块化的方法来构建用于这两种目的的单个解析器,但我找不到它。在这件事上你能帮我吗

您需要的是一个解析器(或GLL),您需要以特定的方式滥用它

GLR解析器在这里之所以有用,是因为它愿意进行所有可能的解析,直到一个解析出有效答案为止。(提供的大多数标准解析器(LL、LALR、递归下降)只进行一次可能的解析,通常无法处理长(例如,不确定)lookahead带来的复杂性

有了它,您现在可以调整原始语法,使用目标规则G和一组其他非终结符a-Z:

 G -> A;
 A -> B;
 B -> C;
 ...
 Y -> Z;
将是:

 G -> A;
 G -> B;
 G -> C;
 ...
 G -> Z
 A -> B
 B -> C
  ...
也就是说,将每个非终结符添加为附加的目标规则

现在,您的解析器将处理语言的任何有效非终结符。 您可以使用“nonterminal reduces to G”作为触发器来决定 如果您想“编译”非终结符,如果原始顶级 返回非终结符A,或“解释”该非终结符(如果它不是 如果您认为解释没有if部分的then子句之类的内容是不有趣的,则可以使用原始顶级非终结符(例如,B-Z)或忽略该输入并等待更多信息

您可以显式修改语法(EAIST),也可以弯曲GLR解析器 要在启动状态下启动所有非终端,whcih具有相同的效果

我的公司使用GLR解析源代码模式(作为非终端),而不是“编译”或“解释”,但这使用了完全相同的技巧


要修改GLR解析器来实现这一点并不容易,但这在“技术上”并不容易也很难。你必须深入了解解析器,尤其是GLR的工作原理,才能找出细节并将其联系在一起。

LALR解析根本不适合逐行解析。你应该设计一个构建语法树的解析器,然后编写一个编译后端来处理它,或者编写一个解释它的解释器,或者编写一个both、 语法树本身是两者的接口:而不是解析器。当您运行解释器时,源代码是否可以更改?如果不能,为什么不按照@EJP的建议,对两者都使用AST?是的,我假设用户可以编写解释器将采用并计算的任意新语句。因此,解释器中的抽象语法树我会动态地改变。