代码之家  ›  专栏  ›  技术社区  ›  user3509406

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

  •  1
  • user3509406  · 技术社区  · 7 年前

    为repl解释器和编译器构建通用的解析器的好方法是什么?我所说的口译员是一种阅读评估打印循环。 为了支持这两种方法,解析器应该支持整个程序解析和逐行解析。龙书引入的LALR(1)算法对于整个程序的解析是很好的,但是需要进行一些设计,以便同时支持逐行解析。由于这两种类型的解析在编程语言中共享相同的语法,我相信有一种模块化方法可以为这两个目的构建一个解析器,但是我找不到它。你能帮我解决这个问题吗?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Ira Baxter    6 年前

    你想要的是 GLR 解析器(或GLL),您可以以特定的方式滥用它。

    GLR解析器之所以有用,是因为它愿意追求 全部的 可能的解析,直到一个解析为有效的答案。(大多数提供的标准解析器(ll,lalr,递归下降)只追求一个可能的解析,并且常常无法处理长(例如,不确定)lookaheads引入的复杂性。

    有了这一点,您现在可以调整原始语法,使其具有目标规则G和其他非终端A-Z集:

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

    成为:

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

    也就是说,你补充说 每一个 作为附加目标规则的非终端。

    现在,您的解析器将使用任何有效的语言非终端。 你可以用“非终端降为G”作为触发器来决定 如果要“编译”非终端 返回非终端A,或“解释”该非终端(如果它不是 原始的顶级非终端,例如b-z),或者忽略该输入,如果您认为在没有if部分的情况下解释诸如then子句之类的内容是不有趣的,请等待更多。

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

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

    要修改一个GLR解析器来完成这项工作并不容易,但从技术上来说也不难。您必须深入了解解析器(尤其是GLR)是如何工作的,才能计算出细节并将它们联系在一起。