Parsing 实施“*&引用;组合GLR解析器中的(lazy“lazy*”regexp模式

Parsing 实施“*&引用;组合GLR解析器中的(lazy“lazy*”regexp模式,parsing,language-agnostic,glr,Parsing,Language Agnostic,Glr,我已经实现了组合GLR解析器。其中包括: char(·)使用指定字符或字符范围的解析器 many(·)combinator,从零到无限次重复指定的解析器 示例:“char('a')。many()”将一个字符串与任意数量的“a”-s匹配 但是,many(·)combinator是贪婪的,因此,例如,char('{')>>char('{')>>char('a'..'z')。many()>>char('}')>>char('}')(其中“>”是解析器的顺序链接)将成功地消耗整个“{{foo}}}}

我已经实现了组合GLR解析器。其中包括:

  • char(·)
    使用指定字符或字符范围的解析器
  • many(·)
    combinator,从零到无限次重复指定的解析器
示例:
“char('a')。many()”
将一个字符串与任意数量的
“a”
-s匹配

但是,
many(·)
combinator是贪婪的,因此,例如,
char('{')>>char('{')>>char('a'..'z')。many()>>char('}')>>char('}')
(其中
“>”
是解析器的顺序链接)将成功地消耗整个
“{{foo}}}}}一些{bar}”字符串

我想实现
many(·)
的惰性版本,在前面的示例中使用该版本时,将只使用
“{{foo}}”
。我该怎么做

编辑:

也许我把你们都弄糊涂了。在我的程序中,解析器是一个函数(或C++中的“函子”),它接受“步骤”并返回“步骤”林。“步骤”可以是OK类型(这意味着解析器成功地使用了部分输入),也可以是FAIL类型(这意味着解析器遇到了错误)。有更多类型的步骤,但它们是辅助的

Parser = f(Step) -> Collection of TreeNodes of Steps.
因此,当我分析输入时,我:

  • 组合简单的预定义语法分析器函数,以获得表示所需语法的复杂语法分析器函数

  • 从输入开始形成初始步骤

  • 给出复杂解析器函数的初始步骤

  • 使用步骤过滤TreeNode,只留下OK(如果输入中有错误,则以最小失败次数)

  • 从剩下的步骤中收集信息


    • GLR解析器不会生成所有可能的输入解析吗?然后,解决歧义就是选择您喜欢的解析。要做到这一点,我认为解析林的元素需要根据产生它们的组合器的类型来标记,无论是渴望的还是懒惰的。(通常,在看到所有输入之前,无法逐步解决歧义。)


      (这个答案基于我的模糊记忆和对GLR解析的模糊可能误解。希望有专家会来。)

      我已经实现并使用GLR解析器作为程序转换系统的语言前端15年了

      我不知道“组合GLR解析器”是什么,而且我不熟悉您的符号,所以我不太确定如何解释它。我想这是某种咖喱函数表示法?我想象你的组合规则相当于用终端字符定义语法,其中“char('a')。many”对应语法规则:

       char = "a" ;
       char = char "a" ;
      
      实际上,GLR解析器生成所有可能的解析。GLR解析的关键洞察是它对所有可能解析的psuedo并行处理。如果您的“组合器”可以提出多个解析(也就是说,它们生成的语法规则类似于上述),并且您确实将它们连接到GLR解析器,那么它们都将得到尝试,并且只有那些平铺文本的生成序列将存活(意味着所有有效的解析,例如,不明确的解析)将存活

      如果您确实实现了GLR解析器,那么您应该非常清楚所有可能的解析器的集合。它不是您所实现的东西这一事实并不是GLR解析器


      与任何其他解析技术一样,使用GLR解析器进行错误恢复也是可能的。我们所做的是在错误点之前保留一组实时解析;当发现错误时,我们尝试(在psuedo并行中,GLR解析机制可以使这变得容易,如果它正确弯曲的话)以下所有操作:a)删除有问题的令牌,b)插入所有基本上跟随(x)的令牌,其中x是活动解析。本质上,删除令牌,或者插入实时解析所期望的令牌。然后我们再次松开GLR解析器。只有有效的解析(例如,修复)将继续存在。如果无法处理当前令牌,则处理已删除令牌的流的解析器仍然有效。在最坏的情况下,GLR解析器错误恢复最终会将所有令牌丢弃给EOF。一个严重的缺点是GLR解析器的运行时间在解析错误时急剧增长;如果一个地方有很多错误,那么错误恢复时间可能非常长。

      考虑正则表达式
      和输入
      bcef
      。这应该可以找到
      ,而没有其他匹配项,对吗

      使用相同的输入,考虑正则表达式<代码> E<代码>。这应该可以找到

      bce
      ,对吗

      这造成了一个两难境地。为了用户的利益,我们希望从两个操作数的角度来理解组合器
      >
      的行为。然而,根据第一个解析器的发现,无法生成第二个解析器的行为


      一个答案是,每个解析器生成一个按优先顺序排列的所有解析器的序列,而不是所有解析器的无序集合。贪婪匹配将返回排序从最长到最短的匹配;非贪婪,从最短到最长。

      非贪婪功能只不过是一种消歧机制。如果您真的有一个通用的解析器(它不需要消除歧义来产生结果),那么“非贪婪”是没有意义的;无论操作符是否“非贪婪”,都将返回相同的结果


      非贪婪消歧行为可以应用于广义解析器提供的完整结果集。从左到右,过滤对应于非贪婪运算符的不明确子组,以使用最短匹配,这仍然导致成功解析剩余输入。

      我还想实现自动错误恢复。如果输入有错误怎么办?这样的算法能合理地从错误中恢复吗?主要投票给“YouC”