为REPL解释器和编译器构建模块化解析器有什么好方法?

时间:2018-05-21 06:29:10

标签: parsing compiler-construction interpreter

为REPL解释器和编译器构建通用解析器有什么好方法?我的解释器是什么意思是一种read-eval-print循环。 为了支持它们,解析器应该支持整个程序解析和逐行解析。 Dragon书籍引入的LALR(1)算法适用于整个程序解析,但它应该被设计为一点点用于同时支持逐行解析。由于解析的两种样式共享编程语言的相同语法,我相信有一种模块化方法可以为这两个目的构建单个解析器,但我无法找到它。你能帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:2)

你想要的是一个GLR解析器(或GLL),你要特别滥用它。

GLR解析器在这里有用的原因是它愿意继续所有可能的解析,直到一个解析为有效答案。 (提供的大多数标准解析器(LL,LALR,递归下降)只追求一个可能的解析,并且通常无法处理由长(例如,不定)前瞻引入的复杂性。

有了这个,你现在调整你的原始语法有一个目标规则G和一组其他非终结者A-Z:

 G -> A;
 A -> B;
 B -> C;
 ...
 Y -> Z;

是:

 G -> A;
 G -> B;
 G -> C;
 ...
 G -> Z
 A -> B
 B -> C
  ...

即,您将每个非终结符添加为其他目标规则。

现在你的解析器将是langauge的任何有效非终结符。 你可以使用“nonterminal reduce to G”作为决定的触发器 如果你想“编译”非原始的,如果原始的顶级 返回非终结符号A,或“解释”非终结符号(如果不是 原始的顶级非终结符,例如B-Z)或者只是忽略那个输入并等待更多,如果你认为解释像if子句这样的东西没有if部分是不感兴趣的。

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

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

要修改GLR解析器并不容易,但它在技术上也不是很难。你必须深入了解解析器,尤其是解析器。 GLR工作,计算细节并将它们联系在一起。