我已经实施了组合GLR解析器。其中有:

  • char(·) 解析器会消耗指定字符或字符范围。
  • many(·) 组合器将指定解析器从零到无限时间重复。

例子: "char('a').many()" 将与任何数字的字符串匹配 "a"-s。

many(·) 组合器很贪婪,例如, char('{') >> char('{') >> char('a'..'z').many() >> char('}') >> char('}') (在哪里 ">>" 是解析器的顺序链接)将成功消耗整体 "{{foo}}some{{bar}}" 细绳。

我想实现懒惰的版本 many(·) 在上一个示例中使用的将消费 "{{foo}}" 只要。我怎样才能做到这一点?

编辑:

我可能会困惑的是。在我的程序中,解析器是一个函数(或C ++方面的“函数”),它接受“步骤”并返回“步骤”的森林。 “步骤”可能是确定的类型(这意味着解析器已成功地消耗了输入的一部分)和失败类型(这意味着解析器遇到了错误)。还有更多类型的步骤,但它们是辅助的。

Parser = f(Step) -> Collection of TreeNodes of Steps.

因此,当我解析输入时,我:

  • 组成简单的预定义解析器功能,以获取代表所需语法的复杂解析器函数。

  • 从输入形成初始步骤。

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

  • 带有步骤的过滤treenodes,仅保留确定的treenodes(如果输入中存在错误,则最小失败-S)。

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

有帮助吗?

解决方案

考虑正则表达式 <.*?> 和输入 <a>bc<d>ef. 。这应该找到 <a>, ,没有其他比赛,对吗?

现在考虑正则表达式 <.*?>e 具有相同的输入。这应该找到 <a>bc<d>e, , 正确的?

这构成了困境。为了用户的缘故,我们想要组合者的行为 >> 可以从它的两个操作数来理解。然而,从第一个发现的角度来看,无法产生第二个解析器的行为。

一个答案是让每个解析器产生一个 序列 在所有解析中,按优先订购,而不是所有解析器的无序集。贪婪的匹配将返回最短的比赛。非绿色,最短到最长。

其他提示

我已经实施并使用GLR解析器已有15年的时间作为程序转换系统的语言前端。

我不知道“组合GLR Parser”是什么,我不熟悉您的符号,所以我不太确定如何解释它。我认为这是某种咖喱功能符号?我想象您的组合规则等于在终端字符方面定义语法,其中“ char('a')。许多”对应语法规则:

 char = "a" ;
 char = char "a" ;

实际上,GLR解析器会产生所有可能的解析。 GLR解析的关键见解是其所有可能解析的伪平行处理。如果您的“组合者”可以提出多个分析(也就是说,它们产生了与上述相等的语法规则),并且您确实将它们连接到GLR解析器,它们都会受到尝试,只有那些瓷砖序列的序列文本将生存(这意味着所有有效的分析,例如,模棱两可的解析)将生存。

如果您确实实施了GLR解析器,那么您所有可能的解析的集合应该对您来说是非常清楚的。这不是您所实现的事实不是GLR解析器。

与其他任何解析技术一样,使用GLR解析器的错误恢复是可能的。我们要做的是在错误点之前保留一组现场解析。当发现错误时,我们尝试(在伪平行的情况下,glr解析机械使它变得容易,如果它正确弯曲的话)所有以下所有内容:a)删除违规令牌,b)插入所有本质上的图表(x)(x) X是活解析的地方。从本质上讲,删除令牌,或插入一个通过现场解析期望的。然后,我们再次将GLR解析器放松。只有有效的解析(例如,维修)才能生存。如果无法处理当前的令牌,则可以将流量的解析器处理为删除的流程。在最坏的情况下,GLR解析器错误恢复最终将所有令牌丢弃到EOF。严重的缺点是GLR解析器的跑步时间在解析错误时逐渐增长。如果一个地方有很多地方,则错误恢复时间可能会通过屋顶。

GLR解析器不会产生输入的所有可能解析吗?然后解决歧义是选择您喜欢的解析的问题。为此,我想需要根据哪种组合制作,渴望或懒惰的组合森林的元素被标记。 (通常,在您看到所有输入之前,您都无法逐步解决歧义。)

(基于我昏暗的记忆和对GLR解析的可能误解的答案。希望有人会通过。)

非绿色功能无非是一种歧义机制。如果您确实有一个广泛的解析器(不需要歧义来产生其结果),那么“非怪兽”是毫无意义的。无论操作员是否是“非怪兽”,都将返回相同的结果。

非绿色歧义行为可以应用于广义解析器提供的完整结果集。从左到右工作,过滤对应于非怪兽操作员的模棱两可的子组,以使用最短的匹配,这仍然导致了其余输入的成功分析。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top